Skip to content

Commit 850f20d

Browse files
committed
Updated tests, added usermanager, tested model relationships
1 parent 187c26a commit 850f20d

10 files changed

+175
-56
lines changed

app/core/admin.py

-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ class UserAdmin(DefaultUserAdmin):
7373
"practice_area_primary",
7474
"practice_area_secondary",
7575
"practice_area_target_intake",
76-
"referred_by",
7776
"email_cognito",
7877
)
7978
},

app/core/api/serializers.py

-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ class Meta:
9494
"practice_area_primary",
9595
"practice_area_secondary",
9696
"practice_area_target_intake",
97-
"referred_by",
9897
"email_cognito",
9998
)
10099
read_only_fields = (

app/core/migrations/0034_alter_user_email_intake.py

-18
This file was deleted.

app/core/migrations/0033_rename_gmail_user_email_gmail_and_more.py renamed to app/core/migrations/0034_alter_user_managers_rename_gmail_user_email_gmail_and_more.py

+12-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
1-
# Generated by Django 4.2.16 on 2025-03-05 21:36
1+
# Generated by Django 4.2.16 on 2025-03-14 21:22
22

3+
import core.models
34
from django.db import migrations, models
45

56

67
class Migration(migrations.Migration):
78

89
dependencies = [
9-
('core', '0032_projectprogramareaxref_project_program_areas'),
10+
('core', '0033_projectstatus_project_current_status'),
1011
]
1112

1213
operations = [
14+
migrations.AlterModelManagers(
15+
name='user',
16+
managers=[
17+
('objects', core.models.UserManager()),
18+
],
19+
),
1320
migrations.RenameField(
1421
model_name='user',
1522
old_name='gmail',
@@ -57,16 +64,16 @@ class Migration(migrations.Migration):
5764
migrations.AddField(
5865
model_name='user',
5966
name='practice_area_primary',
60-
field=models.ManyToManyField(related_name='primary_users', to='core.practicearea'),
67+
field=models.ManyToManyField(blank=True, related_name='primary_users', to='core.practicearea'),
6168
),
6269
migrations.AddField(
6370
model_name='user',
6471
name='practice_area_secondary',
65-
field=models.ManyToManyField(related_name='secondary_users', to='core.practicearea'),
72+
field=models.ManyToManyField(blank=True, related_name='secondary_users', to='core.practicearea'),
6673
),
6774
migrations.AddField(
6875
model_name='user',
6976
name='practice_area_target_intake',
70-
field=models.ManyToManyField(related_name='target_intake_users', to='core.practicearea'),
77+
field=models.ManyToManyField(blank=True, related_name='target_intake_users', to='core.practicearea'),
7178
),
7279
]

app/core/migrations/0035_alter_user_email_intake.py

-19
This file was deleted.

app/core/migrations/max_migration.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0033_projectstatus_project_current_status
1+
0034_alter_user_managers_rename_gmail_user_email_gmail_and_more

app/core/models.py

+57-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import uuid
22

3+
from django.apps import apps
34
from django.contrib.auth.base_user import AbstractBaseUser
5+
from django.contrib.auth.base_user import BaseUserManager
46
from django.contrib.auth.models import PermissionsMixin
5-
from django.contrib.auth.models import UserManager
67
from django.contrib.auth.validators import UnicodeUsernameValidator
78
from django.db import models
89
from phonenumber_field.modelfields import PhoneNumberField
@@ -27,6 +28,49 @@ def __repr__(self):
2728
return f"<{self.__class__.__name__} {self.uuid}>"
2829

2930

31+
class UserManager(BaseUserManager):
32+
"""
33+
This is based on the UserManager from django 4.2
34+
"""
35+
36+
use_in_migrations = True
37+
38+
def _create_user(self, username, password, **extra_fields):
39+
"""
40+
Create and save a user with the given username, email, and password.
41+
"""
42+
43+
# Lookup the real model class from the global app registry so this
44+
# manager method can be used in migrations. This is fine because
45+
# managers are by definition working on the real model.
46+
if not username:
47+
raise ValueError("The given username must be set")
48+
global_user_model = apps.get_model(
49+
self.model._meta.app_label, self.model._meta.object_name
50+
)
51+
username = global_user_model.normalize_username(username)
52+
user = self.model(username=username, **extra_fields)
53+
user.set_password(password)
54+
user.save(using=self._db)
55+
return user
56+
57+
def create_user(self, username, password=None, **extra_fields):
58+
extra_fields.setdefault("is_staff", False)
59+
extra_fields.setdefault("is_superuser", False)
60+
return self._create_user(username, password, **extra_fields)
61+
62+
def create_superuser(self, username, password, **extra_fields):
63+
extra_fields.setdefault("is_staff", True)
64+
extra_fields.setdefault("is_superuser", True)
65+
66+
if extra_fields.get("is_staff") is not True:
67+
raise ValueError("Superuser must have is_staff=True.")
68+
if extra_fields.get("is_superuser") is not True:
69+
raise ValueError("Superuser must have is_superuser=True.")
70+
71+
return self._create_user(username, password, **extra_fields)
72+
73+
3074
class User(PermissionsMixin, AbstractBaseUser, AbstractBaseModel):
3175
"""
3276
Table contains cognito-users & django-users.
@@ -61,7 +105,9 @@ class User(PermissionsMixin, AbstractBaseUser, AbstractBaseModel):
61105

62106
# Django-user related fields #
63107
# password is inherited from AbstractBaseUser
64-
email_intake = models.EmailField("Email address", blank=True) # allow non-unique emails
108+
email_intake = models.EmailField(
109+
"Email address", blank=True
110+
) # allow non-unique emails
65111
is_staff = models.BooleanField(
66112
"staff status",
67113
default=False,
@@ -78,11 +124,15 @@ class User(PermissionsMixin, AbstractBaseUser, AbstractBaseModel):
78124
"UserStatusType", null=True, on_delete=models.PROTECT
79125
)
80126
# current_practice_area = models.ManyToManyField("PracticeArea")
81-
# target_practice_area = models.ManyToManyField("PracticeArea")
82-
practice_area_primary = models.ManyToManyField("PracticeArea", related_name="primary_users")
83-
practice_area_secondary = models.ManyToManyField("PracticeArea", related_name="secondary_users")
84-
practice_area_target_intake = models.ManyToManyField("PracticeArea", related_name="target_intake_users")
85-
127+
practice_area_primary = models.ManyToManyField(
128+
"PracticeArea", related_name="primary_users", blank=True
129+
)
130+
practice_area_secondary = models.ManyToManyField(
131+
"PracticeArea", related_name="secondary_users", blank=True
132+
)
133+
practice_area_target_intake = models.ManyToManyField(
134+
"PracticeArea", related_name="target_intake_users", blank=True
135+
)
86136

87137
job_title_current_intake = models.CharField(max_length=255, blank=True)
88138
job_title_target_intake = models.CharField(max_length=255, blank=True)

app/core/tests/conftest.py

+18-4
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,20 @@
3131
def user_superuser_admin():
3232
return User.objects.create_user(
3333
username="AdminUser",
34-
email_intake="[email protected]",
34+
# email_intake="[email protected]",
3535
password="adminuser",
3636
is_superuser=True,
3737
)
3838

3939

4040
@pytest.fixture
4141
def user_permissions():
42-
user1 = User.objects.create(username="TestUser1", email_intake="[email protected]")
43-
user2 = User.objects.create(username="TestUser2", email_intake="[email protected]")
42+
user1 = User.objects.create(
43+
username="TestUser1", email_intake="[email protected]"
44+
)
45+
user2 = User.objects.create(
46+
username="TestUser2", email_intake="[email protected]"
47+
)
4448
project = Project.objects.create(name="Test Project")
4549
permission_type = PermissionType.objects.first()
4650
practice_area = PracticeArea.objects.first()
@@ -62,7 +66,8 @@ def user_permissions():
6266
@pytest.fixture
6367
def user_permission_admin_project():
6468
user = User.objects.create(
65-
username="TestUser Admin Project", email_intake="[email protected]"
69+
username="TestUser Admin Project",
70+
email_intake="[email protected]",
6671
)
6772
project = Project.objects.create(name="Test Project Admin Project")
6873
permission_type = PermissionType.objects.filter(name=admin_project).first()
@@ -112,6 +117,15 @@ def user2(django_user_model):
112117
)
113118

114119

120+
@pytest.fixture
121+
def user3(django_user_model):
122+
return django_user_model.objects.create_user(
123+
username="TestUser3",
124+
email_intake="[email protected]",
125+
password="testpass",
126+
)
127+
128+
115129
@pytest.fixture
116130
def admin(django_user_model):
117131
return django_user_model.objects.create_user(

app/core/tests/test_api.py

+6
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,12 @@ def test_user_actions(client_name, action, endpoint, payload, expected_status, r
165165
action_fn = getattr(client, action)
166166
url = request.getfixturevalue(endpoint)
167167
res = action_fn(url, payload)
168+
print(f"Status Code: {res.status_code}")
169+
print(f"Response Content: {res.content.decode()}") # If response is not JSON
170+
try:
171+
print(f"Response JSON: {res.json()}") # If response is JSON
172+
except Exception:
173+
pass
168174
assert res.status_code == expected_status
169175

170176

app/core/tests/test_models.py

+81
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
import pytest
44

55
from ..models import Event
6+
from ..models import PracticeArea
67
from ..models import ProgramArea
78
from ..models import ProjectProgramAreaXref
89
from ..models import ProjectSdgXref
910
from ..models import ProjectStatus
1011
from ..models import Sdg
12+
from ..models import User
13+
from ..models import UserStatusType
1114

1215
pytestmark = pytest.mark.django_db
1316

@@ -224,3 +227,81 @@ def test_url_type(url_type):
224227

225228
def test_user_status_type(user_status_type):
226229
assert str(user_status_type) == "Test User Status Type"
230+
231+
232+
def test_user_model_old_names():
233+
"""
234+
Test that accessing old field names raises AttributeError.
235+
"""
236+
with pytest.raises(AttributeError) as excinfo:
237+
old_fields = [
238+
"current_job_title",
239+
"email",
240+
"first_name",
241+
"gmail",
242+
"is_active",
243+
"last_name",
244+
"preferred_email",
245+
"target_job_title",
246+
]
247+
for field in old_fields:
248+
_ = getattr(User, field)
249+
assert f"has no attribute {field}" in str(excinfo)
250+
251+
252+
def test_user_has_a_user_status_relationship(user, user2):
253+
active_user_status = UserStatusType.objects.get(name="Active")
254+
inactive_user_status = UserStatusType.objects.get(name="Inactive")
255+
active_user_status.user_set.add(user)
256+
active_user_status.user_set.add(user2)
257+
258+
assert active_user_status.user_set.count() == 2
259+
260+
assert user.user_status == active_user_status
261+
assert user2.user_status == active_user_status
262+
263+
active_user_status.user_set.remove(user)
264+
inactive_user_status.user_set.add(user)
265+
266+
assert active_user_status.user_set.count() == 1
267+
assert inactive_user_status.user_set.count() == 1
268+
269+
assert user.user_status == inactive_user_status
270+
271+
272+
def test_user_practice_area_relationship(user, user2, user3):
273+
development_practice_area = PracticeArea.objects.get(name="Development")
274+
project_management_practice_area = PracticeArea.objects.get(
275+
name="Project Management"
276+
)
277+
design_practice_area = PracticeArea.objects.get(name="Design")
278+
279+
user.practice_area_primary.add(development_practice_area)
280+
assert user.practice_area_primary.count() == 1
281+
assert user.practice_area_primary.contains(development_practice_area)
282+
assert development_practice_area.primary_users.contains(user)
283+
284+
user.practice_area_primary.remove(development_practice_area)
285+
assert user.practice_area_primary.count() == 0
286+
assert not user.practice_area_primary.contains(development_practice_area)
287+
assert not development_practice_area.primary_users.contains(user)
288+
289+
user2.practice_area_secondary.add(project_management_practice_area)
290+
assert user2.practice_area_secondary.count() == 1
291+
assert user2.practice_area_secondary.contains(project_management_practice_area)
292+
assert project_management_practice_area.secondary_users.contains(user2)
293+
294+
user2.practice_area_secondary.remove(project_management_practice_area)
295+
assert user2.practice_area_secondary.count() == 0
296+
assert not user2.practice_area_secondary.contains(project_management_practice_area)
297+
assert not project_management_practice_area.secondary_users.contains(user2)
298+
299+
user3.practice_area_target_intake.add(design_practice_area)
300+
assert user3.practice_area_target_intake.count() == 1
301+
assert user3.practice_area_target_intake.contains(design_practice_area)
302+
assert design_practice_area.target_intake_users.contains(user3)
303+
304+
user3.practice_area_target_intake.remove(design_practice_area)
305+
assert user3.practice_area_target_intake.count() == 0
306+
assert not user3.practice_area_target_intake.contains(design_practice_area)
307+
assert not design_practice_area.target_intake_users.contains(user3)

0 commit comments

Comments
 (0)