Skip to content

Commit 75777df

Browse files
test: Add tests for the GET api/business/promo/list endpoint.
- Add tests that check different filtering methods - Add tests that check parameter validation - Add some additional parameter validation to the GET api/business/promo/list endpoint
1 parent 00bde29 commit 75777df

File tree

5 files changed

+449
-27
lines changed

5 files changed

+449
-27
lines changed

promo_code/business/pagination.py

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,15 @@ class CustomLimitOffsetPagination(
1212
def get_limit(self, request):
1313
param_limit = request.query_params.get(self.limit_query_param)
1414
if param_limit is not None:
15-
try:
16-
limit = int(param_limit)
17-
if limit < 0:
18-
raise rest_framework.exceptions.ValidationError(
19-
'Limit cannot be negative.',
20-
)
21-
22-
if limit == 0:
23-
return 0
24-
25-
if self.max_limit:
26-
return min(limit, self.max_limit)
27-
28-
return limit
29-
except (TypeError, ValueError):
30-
pass
15+
limit = int(param_limit)
16+
17+
if limit == 0:
18+
return 0
19+
20+
if self.max_limit:
21+
return min(limit, self.max_limit)
22+
23+
return limit
3124

3225
return self.default_limit
3326

promo_code/business/tests/promocodes/base.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ def setUpTestData(cls):
1212
super().setUpTestData()
1313
cls.client = rest_framework.test.APIClient()
1414
cls.promo_create_url = django.urls.reverse('api-business:promo-create')
15+
cls.promo_list_url = django.urls.reverse(
16+
'api-business:company-promo-list',
17+
)
1518
cls.signup_url = django.urls.reverse('api-business:company-sign-up')
1619
cls.signin_url = django.urls.reverse('api-business:company-sign-in')
1720
cls.valid_data = {
Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
import rest_framework.status
2+
import rest_framework.test
3+
4+
import business.models
5+
import business.tests.promocodes.base
6+
7+
8+
class TestPromoEndpoint(
9+
business.tests.promocodes.base.BasePromoCreateTestCase,
10+
):
11+
def _create_additional_promo(self):
12+
self.__class__.promo5_data = {
13+
'description': 'Special offer: bonus reward for loyal customers',
14+
'target': {'country': 'Kz'},
15+
'max_count': 10,
16+
'active_from': '2026-05-01',
17+
'mode': 'COMMON',
18+
'promo_common': 'special-10',
19+
}
20+
response_create = self.client.post(
21+
self.promo_create_url,
22+
self.__class__.promo5_data,
23+
format='json',
24+
)
25+
self.assertEqual(
26+
response_create.status_code,
27+
rest_framework.status.HTTP_201_CREATED,
28+
)
29+
30+
@classmethod
31+
def setUpTestData(cls):
32+
business.tests.promocodes.base.BasePromoCreateTestCase.setUpTestData()
33+
34+
cls.valid_data = {
35+
'name': 'New Digital Marketing Solutions Inc.',
36+
'email': '[email protected]',
37+
'password': 'SecurePass123!',
38+
}
39+
40+
cls.company = business.models.Company.objects.create_company(
41+
**cls.valid_data,
42+
)
43+
44+
response = cls.client.post(
45+
cls.signin_url,
46+
{
47+
'email': cls.valid_data['email'],
48+
'password': cls.valid_data['password'],
49+
},
50+
format='json',
51+
)
52+
cls.new_token = response.data['access']
53+
54+
cls.promo1_data = {
55+
'description': 'Increased cashback 10% for new bank customers!',
56+
'image_url': 'https://cdn2.thecatapi.com/images/3lo.jpg',
57+
'target': {},
58+
'max_count': 10,
59+
'active_from': '2025-01-10',
60+
'mode': 'COMMON',
61+
'promo_common': 'sale-10',
62+
}
63+
cls.promo2_data = {
64+
'description': 'Increased cashback 40% for new bank customers!',
65+
'image_url': 'https://cdn2.thecatapi.com/images/3lo.jpg',
66+
'target': {'age_from': 15, 'country': 'fr'},
67+
'max_count': 100,
68+
'active_from': '2028-12-20',
69+
'mode': 'COMMON',
70+
'promo_common': 'sale-40',
71+
}
72+
cls.promo3_data = {
73+
'description': 'Gift sleep mask when applying for a car loan',
74+
'target': {'age_from': 28, 'age_until': 50, 'country': 'gb'},
75+
'max_count': 1,
76+
'active_from': '2025-01-01',
77+
'active_until': '2028-12-30',
78+
'mode': 'UNIQUE',
79+
'promo_unique': ['uniq1', 'uniq2', 'uniq3'],
80+
}
81+
cls.promo5_data = {
82+
'description': 'Special offer: bonus reward for loyal customers',
83+
'target': {'country': 'Kz'},
84+
'max_count': 10,
85+
'active_from': '2026-05-01',
86+
'mode': 'COMMON',
87+
'promo_common': 'special-10',
88+
}
89+
cls.created_promos = []
90+
91+
for promo_data in [cls.promo1_data, cls.promo2_data, cls.promo3_data]:
92+
promo = business.models.Promo.objects.create(
93+
company=cls.company,
94+
description=promo_data['description'],
95+
image_url=promo_data.get('image_url'),
96+
target=promo_data['target'],
97+
max_count=promo_data['max_count'],
98+
active_from=promo_data.get('active_from'),
99+
active_until=promo_data.get('active_until'),
100+
mode=promo_data['mode'],
101+
)
102+
if promo.mode == 'COMMON':
103+
promo.promo_common = promo_data.get('promo_common')
104+
promo.save()
105+
else:
106+
promo_codes = [
107+
business.models.PromoCode(promo=promo, code=code)
108+
for code in promo_data.get('promo_unique', [])
109+
]
110+
business.models.PromoCode.objects.bulk_create(promo_codes)
111+
112+
cls.created_promos.append(promo)
113+
114+
def setUp(self):
115+
self.client = rest_framework.test.APIClient()
116+
self.client.credentials(HTTP_AUTHORIZATION='Bearer ' + self.new_token)
117+
118+
def test_get_promos_without_token(self):
119+
client = rest_framework.test.APIClient()
120+
response = client.get(self.promo_list_url)
121+
self.assertEqual(
122+
response.status_code,
123+
rest_framework.status.HTTP_401_UNAUTHORIZED,
124+
)
125+
126+
def test_get_all_promos(self):
127+
response = self.client.get(self.promo_list_url)
128+
self.assertEqual(
129+
response.status_code,
130+
rest_framework.status.HTTP_200_OK,
131+
)
132+
data = response.data
133+
134+
self.assertEqual(len(data), 3)
135+
self.assertEqual(data[0]['promo_id'], str(self.created_promos[2].id))
136+
self.assertEqual(data[1]['promo_id'], str(self.created_promos[1].id))
137+
self.assertEqual(data[2]['promo_id'], str(self.created_promos[0].id))
138+
self.assertEqual(response.headers.get('X-Total-Count'), '3')
139+
140+
def test_get_promos_with_pagination_offset_1(self):
141+
response = self.client.get(self.promo_list_url, {'offset': 1})
142+
self.assertEqual(
143+
response.status_code,
144+
rest_framework.status.HTTP_200_OK,
145+
)
146+
data = response.data
147+
148+
self.assertEqual(len(data), 2)
149+
self.assertEqual(data[0]['promo_id'], str(self.created_promos[1].id))
150+
self.assertEqual(data[1]['promo_id'], str(self.created_promos[0].id))
151+
self.assertEqual(response.headers.get('X-Total-Count'), '3')
152+
153+
def test_get_promos_with_pagination_offset_1_limit_1(self):
154+
response = self.client.get(
155+
self.promo_list_url,
156+
{'offset': 1, 'limit': 1},
157+
)
158+
self.assertEqual(
159+
response.status_code,
160+
rest_framework.status.HTTP_200_OK,
161+
)
162+
data = response.data
163+
self.assertEqual(len(data), 1)
164+
self.assertEqual(data[0]['promo_id'], str(self.created_promos[1].id))
165+
self.assertEqual(response.get('X-Total-Count'), '3')
166+
167+
def test_get_promos_with_pagination_offset_100(self):
168+
response = self.client.get(self.promo_list_url, {'offset': 100})
169+
self.assertEqual(
170+
response.status_code,
171+
rest_framework.status.HTTP_200_OK,
172+
)
173+
data = response.data
174+
self.assertEqual(len(data), 0)
175+
self.assertEqual(response.get('X-Total-Count'), '3')
176+
177+
def test_get_promos_filter_country_gb(self):
178+
response = self.client.get(self.promo_list_url, {'country': 'gb'})
179+
self.assertEqual(
180+
response.status_code,
181+
rest_framework.status.HTTP_200_OK,
182+
)
183+
data = response.data
184+
185+
self.assertEqual(len(data), 2)
186+
self.assertEqual(data[0]['promo_id'], str(self.created_promos[2].id))
187+
self.assertEqual(data[1]['promo_id'], str(self.created_promos[0].id))
188+
self.assertEqual(response.get('X-Total-Count'), '2')
189+
190+
def test_get_promos_filter_country_gb_sort_active_until(self):
191+
response = self.client.get(
192+
self.promo_list_url,
193+
{'country': 'gb', 'sort_by': 'active_until'},
194+
)
195+
self.assertEqual(
196+
response.status_code,
197+
rest_framework.status.HTTP_200_OK,
198+
)
199+
data = response.data
200+
201+
self.assertEqual(len(data), 2)
202+
self.assertEqual(data[0]['promo_id'], str(self.created_promos[0].id))
203+
self.assertEqual(data[1]['promo_id'], str(self.created_promos[2].id))
204+
self.assertEqual(response.get('X-Total-Count'), '2')
205+
206+
def test_get_promos_filter_country_gb_fr_sort_active_from_limit_10(self):
207+
response = self.client.get(
208+
self.promo_list_url,
209+
{'country': 'gb,FR', 'sort_by': 'active_from', 'limit': 10},
210+
)
211+
self.assertEqual(
212+
response.status_code,
213+
rest_framework.status.HTTP_200_OK,
214+
)
215+
data = response.data
216+
217+
self.assertEqual(len(data), 3)
218+
self.assertEqual(data[0]['promo_id'], str(self.created_promos[1].id))
219+
self.assertEqual(data[1]['promo_id'], str(self.created_promos[0].id))
220+
self.assertEqual(data[2]['promo_id'], str(self.created_promos[2].id))
221+
self.assertEqual(response.get('X-Total-Count'), '3')
222+
223+
def test_get_promos_filter_country_gb_fr_sort_active_from_limit_2_offset_2(
224+
self,
225+
):
226+
response = self.client.get(
227+
self.promo_list_url,
228+
{
229+
'country': 'gb,FR',
230+
'sort_by': 'active_from',
231+
'limit': 2,
232+
'offset': 2,
233+
},
234+
)
235+
self.assertEqual(
236+
response.status_code,
237+
rest_framework.status.HTTP_200_OK,
238+
)
239+
data = response.data
240+
self.assertEqual(len(data), 1)
241+
self.assertEqual(data[0]['promo_id'], str(self.created_promos[2].id))
242+
self.assertEqual(response.get('X-Total-Count'), '3')
243+
244+
def test_get_promos_filter_country_gb_fr_us_sort_active_from_limit_2(self):
245+
response = self.client.get(
246+
self.promo_list_url,
247+
{'country': 'gb,FR,us', 'sort_by': 'active_from', 'limit': 2},
248+
)
249+
self.assertEqual(
250+
response.status_code,
251+
rest_framework.status.HTTP_200_OK,
252+
)
253+
data = response.data
254+
255+
self.assertEqual(len(data), 2)
256+
self.assertEqual(data[0]['promo_id'], str(self.created_promos[1].id))
257+
self.assertEqual(data[1]['promo_id'], str(self.created_promos[0].id))
258+
self.assertEqual(response.get('X-Total-Count'), '3')
259+
260+
def test_get_promos_limit_zero(self):
261+
response = self.client.get(self.promo_list_url, {'limit': 0})
262+
self.assertEqual(
263+
response.status_code,
264+
rest_framework.status.HTTP_200_OK,
265+
)
266+
data = response.data
267+
self.assertEqual(len(data), 0)
268+
269+
def test_create_and_get_promos(self):
270+
self._create_additional_promo()
271+
272+
response_list = self.client.get(
273+
self.promo_list_url,
274+
{'country': 'gb,FR,Kz', 'sort_by': 'active_from', 'limit': 10},
275+
)
276+
self.assertEqual(
277+
response_list.status_code,
278+
rest_framework.status.HTTP_200_OK,
279+
)
280+
data = response_list.data
281+
282+
self.assertEqual(len(data), 4)
283+
self.assertEqual(response_list.get('X-Total-Count'), '4')
284+
285+
def test_get_promos_filter_gb_kz_fr(self):
286+
self._create_additional_promo()
287+
response = self.client.get(
288+
self.promo_list_url,
289+
{'country': 'gb,Kz,FR', 'sort_by': 'active_from', 'limit': 10},
290+
)
291+
self.assertEqual(
292+
response.status_code,
293+
rest_framework.status.HTTP_200_OK,
294+
)
295+
data = response.data
296+
297+
self.assertEqual(len(data), 4)
298+
self.assertEqual(response.get('X-Total-Count'), '4')
299+
300+
def test_get_promos_filter_kz_sort_active_until(self):
301+
self._create_additional_promo()
302+
response = self.client.get(
303+
self.promo_list_url,
304+
{'country': 'Kz', 'sort_by': 'active_until', 'limit': 10},
305+
)
306+
self.assertEqual(
307+
response.status_code,
308+
rest_framework.status.HTTP_200_OK,
309+
)
310+
data = response.data
311+
312+
self.assertEqual(len(data), 2)
313+
self.assertEqual(response.get('X-Total-Count'), '2')

0 commit comments

Comments
 (0)