Skip to content

Commit 3ec8a5d

Browse files
test(user): Add DRF unit tests for user promo detail endpoint
- Cover GET /user/promo/{id} for: • matching target • non-matching target (returns description) • does not contain forbidden fields • invalid token (401) • nonexistent promo (404)
1 parent 2e0a80f commit 3ec8a5d

File tree

5 files changed

+204
-5
lines changed

5 files changed

+204
-5
lines changed

promo_code/user/tests/auth/base.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ 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')
1817

1918
def tearDown(self):
2019
user.models.User.objects.all().delete()

promo_code/user/tests/user/base.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import django.urls
2+
import rest_framework.test
3+
import rest_framework_simplejwt.token_blacklist.models as tb_models
4+
5+
import business.models
6+
import user.models
7+
8+
9+
class BaseUserTestCase(rest_framework.test.APITestCase):
10+
@classmethod
11+
def setUpTestData(cls):
12+
super().setUpTestData()
13+
cls.client = rest_framework.test.APIClient()
14+
cls.signup_url = django.urls.reverse('api-user:sign-up')
15+
cls.signin_url = django.urls.reverse('api-user:sign-in')
16+
cls.user_profile_url = django.urls.reverse('api-user:user-profile')
17+
cls.promo_list_create_url = django.urls.reverse(
18+
'api-business:promo-list-create',
19+
)
20+
21+
company1_data = {
22+
'name': 'Digital Marketing Solutions Inc.',
23+
'email': '[email protected]',
24+
'password': 'SecurePass123!',
25+
}
26+
business.models.Company.objects.create_company(**company1_data)
27+
cls.company1 = business.models.Company.objects.get(
28+
email=company1_data['email'],
29+
)
30+
response1 = cls.client.post(
31+
django.urls.reverse(
32+
'api-business:company-sign-in',
33+
),
34+
{
35+
'email': company1_data['email'],
36+
'password': company1_data['password'],
37+
},
38+
format='json',
39+
)
40+
cls.company1_token = response1.data['access']
41+
42+
def tearDown(self):
43+
business.models.Company.objects.all().delete()
44+
business.models.Promo.objects.all().delete()
45+
business.models.PromoCode.objects.all().delete()
46+
user.models.User.objects.all().delete()
47+
tb_models.BlacklistedToken.objects.all().delete()
48+
tb_models.OutstandingToken.objects.all().delete()
49+
super().tearDown()
50+
51+
@classmethod
52+
def promo_detail_url(cls, promo_id):
53+
return django.urls.reverse(
54+
'api-user:user-promo-detail',
55+
kwargs={'id': promo_id},
56+
)
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
import uuid
2+
3+
import parameterized
4+
import rest_framework.status
5+
6+
import user.tests.user.base
7+
8+
9+
class TestUserPromoDetail(user.tests.user.base.BaseUserTestCase):
10+
def setUp(self):
11+
super().setUp()
12+
signup_payload = {
13+
'name': 'Leslie',
14+
'surname': 'Lamport',
15+
'email': '[email protected]',
16+
'password': 'Everyth1ngIsDistributed!',
17+
'other': {'age': 80, 'country': 'sg'},
18+
}
19+
response = self.client.post(
20+
self.signup_url,
21+
signup_payload,
22+
format='json',
23+
)
24+
self.user_token = response.data.get('access')
25+
26+
self.client.credentials(
27+
HTTP_AUTHORIZATION='Bearer ' + self.company1_token,
28+
)
29+
30+
promo_kz = {
31+
'description': 'Live COMMON voucher for Kazakhstani users',
32+
'target': {'country': 'kz'},
33+
'max_count': 10,
34+
'active_from': '2025-01-10',
35+
'mode': 'COMMON',
36+
'promo_common': 'sale-10',
37+
}
38+
resp1 = self.client.post(
39+
self.promo_list_create_url,
40+
promo_kz,
41+
format='json',
42+
)
43+
self.promo_kz_id = resp1.data.get('id')
44+
45+
promo_sg = {
46+
'description': 'Live COMMON voucher for Singapore residents',
47+
'target': {'country': 'sg'},
48+
'max_count': 1000,
49+
'active_from': '2023-01-10',
50+
'mode': 'COMMON',
51+
'promo_common': 'sale-10',
52+
}
53+
resp2 = self.client.post(
54+
self.promo_list_create_url,
55+
promo_sg,
56+
format='json',
57+
)
58+
self.promo_sg_id = resp2.data.get('id')
59+
60+
promo_us = {
61+
'description': 'Gift sleeping mask with car loan application',
62+
'target': {'age_from': 28, 'age_until': 50, 'country': 'us'},
63+
'max_count': 1,
64+
'active_from': '2025-01-01',
65+
'active_until': '2028-12-30',
66+
'mode': 'UNIQUE',
67+
'promo_unique': ['uniq1', 'uniq2', 'uniq3'],
68+
}
69+
70+
resp3 = self.client.post(
71+
self.promo_list_create_url,
72+
promo_us,
73+
format='json',
74+
)
75+
self.promo_us_id = resp3.data.get('id')
76+
77+
self.client.credentials(HTTP_AUTHORIZATION='Bearer ' + self.user_token)
78+
79+
def test_get_promo_matching_target(self):
80+
url = self.promo_detail_url(self.promo_sg_id)
81+
response = self.client.get(url)
82+
self.assertEqual(
83+
response.status_code,
84+
rest_framework.status.HTTP_200_OK,
85+
)
86+
self.assertEqual(
87+
str(response.data.get('promo_id')),
88+
str(self.promo_sg_id),
89+
)
90+
91+
def test_get_promo_non_matching_target(self):
92+
url = self.promo_detail_url(self.promo_kz_id)
93+
response = self.client.get(url)
94+
self.assertEqual(
95+
response.status_code,
96+
rest_framework.status.HTTP_200_OK,
97+
)
98+
self.assertEqual(
99+
str(response.data.get('promo_id')),
100+
str(self.promo_kz_id),
101+
)
102+
self.assertEqual(
103+
response.data.get('description'),
104+
'Live COMMON voucher for Kazakhstani users',
105+
)
106+
107+
@parameterized.parameterized.expand(
108+
[
109+
('promo_sg_id', 'promo_common'),
110+
('promo_kz_id', 'promo_common'),
111+
('promo_us_id', 'promo_unique'),
112+
],
113+
)
114+
def test_user_promo_detail(self, promo_attr, forbidden_field):
115+
promo_id = getattr(self, promo_attr)
116+
url = self.promo_detail_url(promo_id)
117+
response = self.client.get(url, format='json')
118+
self.assertEqual(
119+
response.status_code,
120+
rest_framework.status.HTTP_200_OK,
121+
)
122+
123+
self.assertNotContains(
124+
response,
125+
forbidden_field,
126+
)
127+
128+
def test_get_promo_invalid_token(self):
129+
self.client.credentials(HTTP_AUTHORIZATION='Bearer invalid.jwt.token')
130+
url = self.promo_detail_url(self.promo_kz_id)
131+
response = self.client.get(url)
132+
self.assertEqual(
133+
response.status_code,
134+
rest_framework.status.HTTP_401_UNAUTHORIZED,
135+
)
136+
137+
def test_get_promo_not_found(self):
138+
random_uuid = uuid.UUID('550e8400-e29b-41d4-a716-446655440000')
139+
url = self.promo_detail_url(random_uuid)
140+
response = self.client.get(url)
141+
self.assertEqual(
142+
response.status_code,
143+
rest_framework.status.HTTP_404_NOT_FOUND,
144+
)

promo_code/user/tests/user/operations/test_profile.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import rest_framework.status
22

3-
import user.tests.auth.base
3+
import user.tests.user.base
44

55

6-
class TestUserProfile(user.tests.auth.base.BaseUserAuthTestCase):
6+
class TestUserProfile(user.tests.user.base.BaseUserTestCase):
77
def setUp(self):
88
super().setUp()
99
signup_data = {

promo_code/user/tests/user/validations/test_profile_validation.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import parameterized
22
import rest_framework.status
33

4-
import user.tests.auth.base
4+
import user.tests.user.base
55

66

7-
class ProfileAPITestCase(user.tests.auth.base.BaseUserAuthTestCase):
7+
class ProfileAPITestCase(user.tests.user.base.BaseUserTestCase):
88
def setUp(self):
99
super().setUp()
1010
signup_data = {

0 commit comments

Comments
 (0)