diff --git a/.flake8 b/.flake8 index a3a7fb2..2a6fa7d 100644 --- a/.flake8 +++ b/.flake8 @@ -1,6 +1,6 @@ [flake8] max-line-length = 79 -application_import_names = promo_code, user, core +application_import_names = promo_code, user, core, business import-order-style = google exclude = */migrations/, venv/, verdict.py, .venv/, env/, venv, .git, __pycache__ max-complexity = 10 diff --git a/.isort.cfg b/.isort.cfg index 6bc408b..0f5f77b 100644 --- a/.isort.cfg +++ b/.isort.cfg @@ -1,7 +1,7 @@ [settings] profile = black skip = migrations, venv/, venv -known_first_party = promo_code, user, core +known_first_party = promo_code, user, core, business default_section = THIRDPARTY force_sort_within_sections = true line_length = 79 \ No newline at end of file diff --git a/promo_code/business/permissions.py b/promo_code/business/permissions.py index bc5519b..99da2d3 100644 --- a/promo_code/business/permissions.py +++ b/promo_code/business/permissions.py @@ -1,6 +1,7 @@ -import business.models import rest_framework.permissions +import business.models + class IsCompanyUser(rest_framework.permissions.BasePermission): def has_permission(self, request, view): diff --git a/promo_code/business/serializers.py b/promo_code/business/serializers.py index 7f3af8d..c0badca 100644 --- a/promo_code/business/serializers.py +++ b/promo_code/business/serializers.py @@ -1,5 +1,3 @@ -import business.models as business_models -import business.validators import django.contrib.auth.password_validation import django.core.exceptions import django.core.validators @@ -12,6 +10,9 @@ import rest_framework_simplejwt.tokens import rest_framework_simplejwt.views +import business.models as business_models +import business.validators + class CompanySignUpSerializer(rest_framework.serializers.ModelSerializer): password = rest_framework.serializers.CharField( @@ -147,6 +148,8 @@ class TargetSerializer(rest_framework.serializers.Serializer): allow_null=True, ) country = rest_framework.serializers.CharField( + max_length=2, + min_length=2, required=False, allow_null=True, allow_blank=True, @@ -173,7 +176,6 @@ def validate(self, data): {'age_until': 'Must be greater than or equal to age_from.'}, ) - # change validation country = data.get('country') if country: country = country.strip().upper() @@ -189,6 +191,18 @@ def validate(self, data): class PromoCreateSerializer(rest_framework.serializers.ModelSerializer): + description = rest_framework.serializers.CharField( + min_length=10, + max_length=300, + required=True, + ) + image_url = rest_framework.serializers.CharField( + required=False, + max_length=350, + validators=[ + django.core.validators.URLValidator(schemes=['http', 'https']), + ], + ) target = TargetSerializer(required=True) promo_common = rest_framework.serializers.CharField( min_length=5, @@ -220,10 +234,6 @@ class Meta: 'promo_common', 'promo_unique', ) - extra_kwargs = { - 'description': {'min_length': 10, 'max_length': 300}, - 'image_url': {'max_length': 350}, - } def validate(self, data): mode = data.get('mode') diff --git a/promo_code/business/tests/auth/base.py b/promo_code/business/tests/auth/base.py index bd1ced8..ba8dee5 100644 --- a/promo_code/business/tests/auth/base.py +++ b/promo_code/business/tests/auth/base.py @@ -1,9 +1,10 @@ -import business.models import django.urls import rest_framework import rest_framework.status import rest_framework.test +import business.models + class BaseBusinessAuthTestCase(rest_framework.test.APITestCase): @classmethod diff --git a/promo_code/business/tests/auth/test_authentication.py b/promo_code/business/tests/auth/test_authentication.py index 46d43ae..e5bd1b7 100644 --- a/promo_code/business/tests/auth/test_authentication.py +++ b/promo_code/business/tests/auth/test_authentication.py @@ -1,8 +1,9 @@ -import business.models -import business.tests.auth.base import rest_framework.status import rest_framework.test +import business.models +import business.tests.auth.base + class AuthenticationTests(business.tests.auth.base.BaseBusinessAuthTestCase): def test_signin_success(self): diff --git a/promo_code/business/tests/auth/test_registration.py b/promo_code/business/tests/auth/test_registration.py index 44e87c1..f6762b1 100644 --- a/promo_code/business/tests/auth/test_registration.py +++ b/promo_code/business/tests/auth/test_registration.py @@ -1,8 +1,9 @@ -import business.models -import business.tests.auth.base import rest_framework.status import rest_framework.test +import business.models +import business.tests.auth.base + class TestCompanyRegistration( business.tests.auth.base.BaseBusinessAuthTestCase, diff --git a/promo_code/business/tests/auth/test_tokens.py b/promo_code/business/tests/auth/test_tokens.py index c500c25..a041b24 100644 --- a/promo_code/business/tests/auth/test_tokens.py +++ b/promo_code/business/tests/auth/test_tokens.py @@ -1,9 +1,9 @@ -import business.models -import business.tests.auth.base import rest_framework.status import rest_framework.test import rest_framework_simplejwt.tokens +import business.models +import business.tests.auth.base import user.models diff --git a/promo_code/business/tests/auth/test_validation.py b/promo_code/business/tests/auth/test_validation.py index e8a37af..8f3f8d6 100644 --- a/promo_code/business/tests/auth/test_validation.py +++ b/promo_code/business/tests/auth/test_validation.py @@ -1,9 +1,10 @@ -import business.models -import business.tests.auth.base import parameterized import rest_framework.status import rest_framework.test +import business.models +import business.tests.auth.base + class InvalidCompanyRegistrationTestCase( business.tests.auth.base.BaseBusinessAuthTestCase, diff --git a/promo_code/business/tests/promocodes/__init__.py b/promo_code/business/tests/promocodes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/promo_code/business/tests/promocodes/base.py b/promo_code/business/tests/promocodes/base.py new file mode 100644 index 0000000..dbdd851 --- /dev/null +++ b/promo_code/business/tests/promocodes/base.py @@ -0,0 +1,41 @@ +import django.urls +import rest_framework +import rest_framework.status +import rest_framework.test + +import business.models + + +class BasePromoCreateTestCase(rest_framework.test.APITestCase): + @classmethod + def setUpTestData(cls): + super().setUpTestData() + cls.client = rest_framework.test.APIClient() + cls.promo_create_url = django.urls.reverse('api-business:promo-create') + cls.signup_url = django.urls.reverse('api-business:company-sign-up') + cls.signin_url = django.urls.reverse('api-business:company-sign-in') + cls.valid_data = { + 'name': 'Digital Marketing Solutions Inc.', + 'email': 'testcompany@example.com', + 'password': 'SecurePass123!', + } + business.models.Company.objects.create_company( + name=cls.valid_data['name'], + email=cls.valid_data['email'], + password=cls.valid_data['password'], + ) + + response = cls.client.post( + cls.signin_url, + { + 'email': cls.valid_data['email'], + 'password': cls.valid_data['password'], + }, + format='json', + ) + cls.token = response.data['access'] + + def tearDown(self): + business.models.Company.objects.all().delete() + business.models.Promo.objects.all().delete() + business.models.PromoCode.objects.all().delete() diff --git a/promo_code/business/tests/promocodes/operations/__init__.py b/promo_code/business/tests/promocodes/operations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/promo_code/business/tests/promocodes/operations/test_create.py b/promo_code/business/tests/promocodes/operations/test_create.py new file mode 100644 index 0000000..a41dced --- /dev/null +++ b/promo_code/business/tests/promocodes/operations/test_create.py @@ -0,0 +1,171 @@ +import rest_framework.status + +import business.tests.promocodes.base + + +class TestSuccessfulPromoCreation( + business.tests.promocodes.base.BasePromoCreateTestCase, +): + def test_successful_promo_creation_1(self): + payload = { + 'description': 'Increased cashback 10% for new bank clients!', + 'image_url': 'https://cdn2.thecatapi.com/images/3lo.jpg', + 'target': {}, + 'max_count': 10, + 'active_from': '2025-01-10', + 'mode': 'COMMON', + 'promo_common': 'sale-10', + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_201_CREATED, + ) + + def test_successful_promo_creation_2(self): + payload = { + 'description': 'Increased cashback 40% for new bank clients!', + 'image_url': 'https://cdn2.thecatapi.com/images/3lo.jpg', + 'target': {'age_from': 15, 'country': 'fr'}, + 'max_count': 100, + 'active_from': '2028-12-20', + 'mode': 'COMMON', + 'promo_common': 'sale-40', + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_201_CREATED, + ) + + def test_successful_promo_creation_3(self): + payload = { + 'description': 'Gift sleeping mask with car loan application', + 'target': {'age_from': 28, 'age_until': 50, 'country': 'us'}, + 'max_count': 1, + 'active_from': '2025-01-01', + 'active_until': '2028-12-30', + 'mode': 'UNIQUE', + 'promo_unique': ['uniq1', 'uniq2', 'uniq3'], + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_201_CREATED, + ) + + def test_successful_promo_creation_4(self): + payload = { + 'description': 'We gift a globe when ordering for 30000!', + 'target': {'age_from': 28, 'age_until': 50, 'country': 'us'}, + 'max_count': 1, + 'active_until': '2025-01-10', + 'mode': 'UNIQUE', + 'promo_unique': ['only_youuuu', 'not_only_you'], + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_201_CREATED, + ) + + def test_successful_promo_creation_5(self): + payload = { + 'description': 'Increased cashback 10% for new bank clients!', + 'image_url': 'http://cdn2.thecatapi.com/', + 'target': {}, + 'max_count': 10, + 'active_from': '1950-01-01', + 'mode': 'COMMON', + 'promo_common': 'sale-10', + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_201_CREATED, + ) + + def test_successful_promo_creation_6_country_lower(self): + payload = { + 'description': 'Increased cashback 10% for new bank clients!', + 'image_url': 'http://cdn2.thecatapi.com/', + 'target': {'country': 'Us'}, + 'max_count': 10, + 'mode': 'COMMON', + 'promo_common': 'sale-10', + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_201_CREATED, + ) + + def test_successful_promo_creation_6_country_upper(self): + payload = { + 'description': 'Increased cashback 10% for new bank clients!', + 'image_url': 'http://cdn2.thecatapi.com/', + 'target': {'country': 'US'}, + 'max_count': 10, + 'mode': 'COMMON', + 'promo_common': 'sale-10', + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_201_CREATED, + ) + + def test_successful_promo_creation_7(self): + payload = { + 'description': 'Increased cashback 10% for new bank clients!', + 'image_url': 'http://cdn2.thecatapi.com/', + 'target': {'age_from': 100, 'age_until': 100}, + 'max_count': 10, + 'mode': 'COMMON', + 'promo_common': 'sale-10', + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_201_CREATED, + ) diff --git a/promo_code/business/tests/promocodes/test_permissions.py b/promo_code/business/tests/promocodes/test_permissions.py new file mode 100644 index 0000000..e525d01 --- /dev/null +++ b/promo_code/business/tests/promocodes/test_permissions.py @@ -0,0 +1,47 @@ +import django.contrib.auth +import rest_framework.status +import rest_framework.test + +import business.models +import business.permissions +import business.tests.promocodes.base +import user.models + + +class TestIsCompanyUserPermission( + business.tests.promocodes.base.BasePromoCreateTestCase, +): + def setUp(self): + self.factory = rest_framework.test.APIRequestFactory() + self.permission = business.permissions.IsCompanyUser() + get_user_model = django.contrib.auth.get_user_model + self.regular_user = get_user_model().objects.create_user( + name='regular', + password='testpass123', + surname='adadioa', + email='example@gmail.com', + ) + self.company_user = business.models.Company.objects.create_company( + password='testpass123', + name='Test Company', + email='exampl3e@gmail.com', + ) + + def tearDown(self): + business.models.Company.objects.all().delete() + user.models.User.objects.all().delete() + + def test_has_permission_for_company_user(self): + request = self.factory.get(self.promo_create_url) + request.user = self.company_user + self.assertTrue(self.permission.has_permission(request, None)) + + def test_has_permission_for_regular_user(self): + request = self.factory.get(self.promo_create_url) + request.user = self.regular_user + self.assertFalse(self.permission.has_permission(request, None)) + + def test_has_permission_for_anonymous_user(self): + request = self.factory.get(self.promo_create_url) + request.user = None + self.assertFalse(self.permission.has_permission(request, None)) diff --git a/promo_code/business/tests/promocodes/validations/__init__.py b/promo_code/business/tests/promocodes/validations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/promo_code/business/tests/promocodes/validations/test_create_validation.py b/promo_code/business/tests/promocodes/validations/test_create_validation.py new file mode 100644 index 0000000..894f4f3 --- /dev/null +++ b/promo_code/business/tests/promocodes/validations/test_create_validation.py @@ -0,0 +1,421 @@ +import parameterized +import rest_framework.status + +import business.tests.promocodes.base + + +class TestPromoCodeCreation( + business.tests.promocodes.base.BasePromoCreateTestCase, +): + def test_create_promo_with_old_token(self): + registration_data = { + 'name': 'Someone', + 'email': 'mail@mail.com', + 'password': 'SuperStrongPassword2000!', + } + reg_response = self.client.post( + self.signup_url, + registration_data, + format='json', + ) + old_token = reg_response.data.get('token') + self.client.post( + self.signin_url, + { + 'email': registration_data['email'], + 'password': registration_data['password'], + }, + format='json', + ) + payload = { + 'description': 'Test promo code', + 'target': {}, + 'max_count': 10, + 'active_from': '2025-01-10', + 'mode': 'COMMON', + 'promo_common': 'sale-10', + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + str(old_token), + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_401_UNAUTHORIZED, + ) + + @parameterized.parameterized.expand( + [ + ( + 'missing_description', + { + # 'description' is missing + 'target': {}, + 'max_count': 10, + 'active_from': '2025-01-10', + 'mode': 'COMMON', + 'promo_common': 'sale-10', + }, + ), + ( + 'missing_target', + { + 'description': ( + 'Increased cashback 40% for new bank clients!', + ), + 'max_count': 100, + 'active_from': '2028-12-20', + 'mode': 'COMMON', + 'promo_common': 'sale-40', + # 'target' is missing + }, + ), + ( + 'missing_promo_common', + { + 'description': ( + 'Increased cashback 40% for new bank clients!', + ), + 'max_count': 100, + 'target': {}, + 'active_from': '2028-12-20', + 'mode': 'COMMON', + # 'promo_common' is missing + }, + ), + ], + ) + def test_missing_fields(self, name, payload): + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_400_BAD_REQUEST, + ) + + def test_invalid_mode(self): + payload = { + 'description': 'Gift sleeping mask with car loan application', + 'target': {'age_from': 28, 'age_until': 50, 'country': 'us'}, + 'max_count': 1, + 'active_from': '2025-01-01', + 'active_until': '2028-12-30', + 'mode': 'EMINEM', # invalid mode + 'promo_unique': ['uniq1', 'uniq2', 'uniq3'], + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_400_BAD_REQUEST, + ) + + def test_invalid_max_count_for_unique_mode(self): + payload = { + 'description': 'Gift sleeping mask with car loan application', + 'target': {'age_from': 28, 'age_until': 50, 'country': 'us'}, + 'max_count': 3, # invalid for UNIQUE mode + 'active_from': '2025-01-01', + 'active_until': '2028-12-30', + 'mode': 'UNIQUE', + 'promo_unique': ['uniq1', 'uniq2', 'uniq3'], + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_400_BAD_REQUEST, + ) + + def test_short_description(self): + payload = { + 'description': 'small', # too short description + 'target': {'age_from': 28, 'age_until': 50, 'country': 'US'}, + 'max_count': 1, + 'active_until': '2025-01-10', + 'mode': 'UNIQUE', + 'promo_unique': ['only_youuuu', 'not_only_you'], + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_400_BAD_REQUEST, + ) + + @parameterized.parameterized.expand([('Vietnam'), ('XX')]) + def test_invalid_country(self, invalid_country): + payload = { + 'description': 'A valid description with sufficient length', + 'target': { + 'age_from': 28, + 'age_until': 50, + 'country': invalid_country, + }, + 'max_count': 1, + 'active_until': '2025-01-10', + 'mode': 'UNIQUE', + 'promo_unique': ['only_youuuu', 'not_only_you'], + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_400_BAD_REQUEST, + ) + + def test_nonexistent_country(self): + payload = { + 'description': 'Increased cashback 40% for new bank clients!', + 'max_count': 100, + 'target': {'country': 'aa'}, # non-existent country + 'active_from': '2028-12-20', + 'mode': 'COMMON', + 'promo_common': 'sale-40', + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_400_BAD_REQUEST, + ) + + def test_invalid_age_range(self): + payload = { + 'description': 'Increased cashback 40% for new bank clients!', + 'max_count': 100, + 'target': { + 'age_from': 50, + 'age_until': 49, # invalid: from > until + }, + 'active_from': '2028-12-20', + 'mode': 'COMMON', + 'promo_common': 'sale-40', + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_400_BAD_REQUEST, + ) + + def test_common_with_promo_unique_provided(self): + payload = { + 'description': 'Increased cashback 40% for new bank clients!', + 'max_count': 100, + 'target': {}, + 'active_from': '2028-12-20', + 'mode': 'COMMON', + 'promo_unique': ['sale-40'], + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_400_BAD_REQUEST, + ) + + def test_unique_with_promo_common_provided(self): + payload = { + 'description': 'Increased cashback 40% for new bank clients!', + 'max_count': 1, + 'target': {}, + 'active_from': '2028-12-20', + 'mode': 'UNIQUE', + 'promo_common': 'sale-40', + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_400_BAD_REQUEST, + ) + + def test_both_promo_common_and_promo_unique_provided(self): + payload = { + 'description': 'Increased cashback 40% for new bank clients!', + 'max_count': 1, + 'target': {}, + 'active_from': '2028-12-20', + 'mode': 'UNIQUE', + 'promo_common': 'sale-40', + 'promo_unique': ['opa'], + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_400_BAD_REQUEST, + ) + + def test_too_short_promo_common(self): + payload = { + 'description': 'Increased cashback 40% for new bank clients!', + 'max_count': 100, + 'target': {}, + 'active_from': '2028-12-20', + 'mode': 'COMMON', + 'promo_common': 'str', # too short + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_400_BAD_REQUEST, + ) + + @parameterized.parameterized.expand( + [ + ( + 'invalid_type_for_promo_unique', + { + 'description': ( + 'Increased cashback 40% for new bank clients!' + ), + 'max_count': 1, + 'target': {}, + 'active_from': '2028-12-20', + 'mode': 'UNIQUE', + 'promo_unique': 123, # invalid type, should be a list + }, + ), + ( + 'invalid_type_for_max_count', + { + 'description': ( + 'Increased cashback 40% for new bank clients!' + ), + 'max_count': 'fifty', # invalid type + 'target': {}, + 'active_from': '2028-12-20', + 'mode': 'COMMON', + 'promo_common': 'sale-40', + }, + ), + ( + 'invalid_type_for_target', + { + 'description': ( + 'Increased cashback 40% for new bank clients!' + ), + 'max_count': 1, + 'target': 123, # invalid type + 'active_from': '2028-12-20', + 'mode': 'UNIQUE', + 'promo_unique': ['opa'], + }, + ), + ], + ) + def test_invalid_type_payloads(self, name, payload): + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_400_BAD_REQUEST, + ) + + @parameterized.parameterized.expand( + [ + (-1), + (100000001), + (1000000000001), + ], + ) + def test_invalid_max_count(self, max_count): + payload = { + 'description': 'Increased cashback 40% for new bank clients!', + 'max_count': max_count, + 'target': {}, + 'mode': 'COMMON', + 'promo_common': 'something-here', + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_400_BAD_REQUEST, + ) + + @parameterized.parameterized.expand( + [ + ('itsnotalink'), + ('hello@com'), + (''), + ('https://'), + (f'https://cdn2.thecatapi.com/images/3lo{"1" * 350}.jpg'), + ], + ) + def test_invalid_image_url(self, url): + payload = { + 'description': 'Increased cashback 40% for new bank clients!', + 'image_url': url, + 'max_count': 1000, + 'target': {}, + 'mode': 'COMMON', + 'promo_common': 'something-here', + } + response = self.client.post( + self.promo_create_url, + payload, + format='json', + HTTP_AUTHORIZATION='Bearer ' + self.token, + ) + self.assertEqual( + response.status_code, + rest_framework.status.HTTP_400_BAD_REQUEST, + ) diff --git a/promo_code/business/urls.py b/promo_code/business/urls.py index d634f05..7e8f753 100644 --- a/promo_code/business/urls.py +++ b/promo_code/business/urls.py @@ -1,6 +1,7 @@ -import business.views import django.urls +import business.views + app_name = 'api-business' diff --git a/promo_code/business/validators.py b/promo_code/business/validators.py index 819c64c..755ac01 100644 --- a/promo_code/business/validators.py +++ b/promo_code/business/validators.py @@ -1,6 +1,7 @@ -import business.models import rest_framework.exceptions +import business.models + class UniqueEmailValidator: def __init__(self, default_detail=None, default_code=None): diff --git a/promo_code/business/views.py b/promo_code/business/views.py index 041a8f8..9c269ec 100644 --- a/promo_code/business/views.py +++ b/promo_code/business/views.py @@ -1,6 +1,3 @@ -import business.models -import business.permissions -import business.serializers import rest_framework.exceptions import rest_framework.generics import rest_framework.permissions @@ -11,6 +8,9 @@ import rest_framework_simplejwt.tokens import rest_framework_simplejwt.views +import business.models +import business.permissions +import business.serializers import core.views diff --git a/promo_code/user/authentication.py b/promo_code/user/authentication.py index 7140a3e..c42fa37 100644 --- a/promo_code/user/authentication.py +++ b/promo_code/user/authentication.py @@ -1,7 +1,7 @@ -import business.models import rest_framework_simplejwt.authentication import rest_framework_simplejwt.exceptions +import business.models import user.models as user_models