Skip to content

Commit 2899373

Browse files
test(user): Add unit tests for user profile
- Cover profile retrieval (GET) and detailed field assertions - Validate error responses for empty names, invalid avatar URLs, and weak passwords - Test full CRUD flow: update name, avatar URL, password change with persistence checks - Ensure legacy JWT remains valid after password update - Verify authentication rejects old password and accepts new password
1 parent aa55b6d commit 2899373

File tree

6 files changed

+208
-0
lines changed

6 files changed

+208
-0
lines changed

promo_code/user/tests/auth/base.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ def setUpTestData(cls):
1414
cls.refresh_url = django.urls.reverse('api-user:user-token-refresh')
1515
cls.signup_url = django.urls.reverse('api-user:sign-up')
1616
cls.signin_url = django.urls.reverse('api-user:sign-in')
17+
cls.user_profile_url = django.urls.reverse('api-user:user-profile')
1718

1819
def tearDown(self):
1920
user.models.User.objects.all().delete()

promo_code/user/tests/user/__init__.py

Whitespace-only changes.

promo_code/user/tests/user/operations/__init__.py

Whitespace-only changes.
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import rest_framework.status
2+
3+
import user.tests.auth.base
4+
5+
6+
class TestUserProfile(user.tests.auth.base.BaseUserAuthTestCase):
7+
def setUp(self):
8+
super().setUp()
9+
signup_data = {
10+
'name': 'Steve',
11+
'surname': 'Wozniak',
12+
'email': '[email protected]',
13+
'password': 'WhoLivesInCalifornia2000!',
14+
'other': {'age': 23, 'country': 'us'},
15+
}
16+
response = self.client.post(
17+
self.signup_url, signup_data, format='json',
18+
)
19+
token = response.data.get('access')
20+
self.client.credentials(HTTP_AUTHORIZATION='Bearer ' + token)
21+
self.initial_token = token
22+
23+
def test_get_profile_initial(self):
24+
response = self.client.get(self.user_profile_url, format='json')
25+
self.assertEqual(
26+
response.status_code, rest_framework.status.HTTP_200_OK,
27+
)
28+
expected = {
29+
'name': 'Steve',
30+
'surname': 'Wozniak',
31+
'email': '[email protected]',
32+
'other': {'age': 23, 'country': 'us'},
33+
}
34+
self.assertEqual(response.json(), expected)
35+
36+
def test_patch_profile_update_name_and_surname(self):
37+
payload = {'name': 'John', 'surname': 'Tsal'}
38+
response = self.client.patch(
39+
self.user_profile_url, payload, format='json',
40+
)
41+
self.assertEqual(
42+
response.status_code, rest_framework.status.HTTP_200_OK,
43+
)
44+
self.assertEqual(response.data.get('name'), 'John')
45+
self.assertEqual(response.data.get('surname'), 'Tsal')
46+
47+
def test_patch_profile_update_avatar_url(self):
48+
payload = {'avatar_url': 'http://nodomain.com/kitten.jpeg'}
49+
response = self.client.patch(
50+
self.user_profile_url, payload, format='json',
51+
)
52+
self.assertEqual(
53+
response.status_code, rest_framework.status.HTTP_200_OK,
54+
)
55+
self.assertEqual(
56+
response.data.get('avatar_url'), 'http://nodomain.com/kitten.jpeg',
57+
)
58+
59+
def test_patch_password_and_check_persistence(self):
60+
new_password = 'MegaGiant88888@dooRuveS'
61+
self.client.patch(
62+
self.user_profile_url,
63+
{'name': 'John', 'surname': 'Tsal'},
64+
format='json',
65+
)
66+
self.client.patch(
67+
self.user_profile_url,
68+
{'avatar_url': 'http://nodomain.com/kitten.jpeg'},
69+
format='json',
70+
)
71+
response = self.client.patch(
72+
self.user_profile_url, {'password': new_password}, format='json',
73+
)
74+
self.assertEqual(
75+
response.status_code, rest_framework.status.HTTP_200_OK,
76+
)
77+
data = response.data
78+
self.assertEqual(data.get('name'), 'John')
79+
self.assertEqual(data.get('surname'), 'Tsal')
80+
self.assertEqual(data.get('email'), '[email protected]')
81+
self.assertEqual(data.get('other'), {'age': 23, 'country': 'us'})
82+
self.assertEqual(
83+
data.get('avatar_url'), 'http://nodomain.com/kitten.jpeg',
84+
)
85+
86+
# test old token still valid
87+
response = self.client.get(self.user_profile_url, format='json')
88+
self.assertEqual(
89+
response.status_code, rest_framework.status.HTTP_200_OK,
90+
)
91+
92+
def test_auth_sign_in_old_password_fails(self):
93+
new_password = 'MegaGiant88888@dooRuveS'
94+
response = self.client.patch(
95+
self.user_profile_url, {'password': new_password}, format='json',
96+
)
97+
self.client.credentials()
98+
response = self.client.post(
99+
self.signin_url,
100+
{
101+
'email': '[email protected]',
102+
'password': 'WhoLivesInCalifornia2000!',
103+
},
104+
format='json',
105+
)
106+
self.assertEqual(
107+
response.status_code, rest_framework.status.HTTP_401_UNAUTHORIZED,
108+
)
109+
110+
def test_auth_sign_in_new_password_succeeds(self):
111+
new_password = 'MegaGiant88888@dooRuveS'
112+
response = self.client.patch(
113+
self.user_profile_url, {'password': new_password}, format='json',
114+
)
115+
self.client.credentials()
116+
response = self.client.post(
117+
self.signin_url,
118+
{
119+
'email': '[email protected]',
120+
'password': 'MegaGiant88888@dooRuveS',
121+
},
122+
format='json',
123+
)
124+
self.assertEqual(
125+
response.status_code, rest_framework.status.HTTP_200_OK,
126+
)

promo_code/user/tests/user/validations/__init__.py

Whitespace-only changes.
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import parameterized
2+
import rest_framework.status
3+
4+
import user.tests.auth.base
5+
6+
7+
class ProfileAPITestCase(user.tests.auth.base.BaseUserAuthTestCase):
8+
def setUp(self):
9+
super().setUp()
10+
signup_data = {
11+
'name': 'Jack',
12+
'surname': 'Sparrow',
13+
'email': '[email protected]',
14+
'password': 'WhoLivesInTheOcean100500!',
15+
'other': {'age': 48, 'country': 'gb'},
16+
}
17+
response = self.client.post(
18+
self.signup_url, signup_data, format='json',
19+
)
20+
token = response.data.get('access')
21+
self.client.credentials(HTTP_AUTHORIZATION='Bearer ' + token)
22+
23+
def test_update_profile_empty_name_and_surname(self):
24+
payload = {'name': '', 'surname': ''}
25+
response = self.client.patch(
26+
self.user_profile_url, payload, format='json',
27+
)
28+
self.assertEqual(
29+
response.status_code, rest_framework.status.HTTP_400_BAD_REQUEST,
30+
)
31+
32+
@parameterized.parameterized.expand(
33+
[
34+
('no_scheme', 'notURLcom'),
35+
('only_scheme', 'https://'),
36+
('no_domain', 'https://.com'),
37+
],
38+
)
39+
def test_update_profile_invalid_avatar_url(self, name, url):
40+
payload = {'avatar_url': url}
41+
response = self.client.patch(
42+
self.user_profile_url, payload, format='json',
43+
)
44+
self.assertEqual(
45+
response.status_code, rest_framework.status.HTTP_400_BAD_REQUEST,
46+
)
47+
48+
@parameterized.parameterized.expand(
49+
[
50+
('simple_alpha_num', 'pro100'),
51+
('only_symbols', '!!!!!'),
52+
('only_nums', '1234567890'),
53+
('only_lowercase_chars', 'abcdefghijklmno'),
54+
('only_uppercase-chars', 'ABCDEFGHIJKLMNO'),
55+
('only_symbols_and_nums', '1234567890!@#$%^&*()_+{}|:"<>?'),
56+
('repetitive_chars', 'onlyYOUOOOO!'),
57+
('mixed_short', 'yOu!@1'),
58+
('repeating_pattern', '11111@@@@@aaaaa'),
59+
],
60+
)
61+
def test_update_profile_weak_password(self, name, pwd):
62+
payload = {'password': pwd}
63+
response = self.client.patch(
64+
self.user_profile_url, payload, format='json',
65+
)
66+
self.assertEqual(
67+
response.status_code, rest_framework.status.HTTP_400_BAD_REQUEST,
68+
)
69+
70+
def test_get_profile(self):
71+
response = self.client.get(self.user_profile_url, format='json')
72+
self.assertEqual(
73+
response.status_code, rest_framework.status.HTTP_200_OK,
74+
)
75+
expected = {
76+
'name': 'Jack',
77+
'surname': 'Sparrow',
78+
'email': '[email protected]',
79+
'other': {'age': 48, 'country': 'gb'},
80+
}
81+
self.assertEqual(response.json(), expected)

0 commit comments

Comments
 (0)