from typing import TYPE_CHECKING import pytest from pytest import fixture from rest_framework import status from rest_framework.utils import json from outbo.apps.projects.models import Project from tests import utils if TYPE_CHECKING: from outbo.apps.authentication.models import User from rest_framework.authtoken.models import Token @pytest.mark.django_db class ProjectCreationE2ETests: @fixture(autouse=True) def product_stages(self, product_stages): pass BASE_FIELDS = ( "brand", "category", "description", "name", "printing_files_date", "promo_date", ) CREATE_FIELDS = BASE_FIELDS + ("products_amount",) RETRIEVE_FIELDS = BASE_FIELDS + ("slug", "publishable", "published", "products") FIELD_REQUIRED_MESSAGE = "This field is required." AT_LEAST_ONE_PRODUCT = "Ensure this value is greater than or equal to 1." def test_anonymous_user_is_not_authorized(self, client): response = client.post("/projects/", content_type="application/json") # Assert assert ( response.status_code == status.HTTP_401_UNAUTHORIZED ), "Wrong HTTP response code." def test_agency_user_not_allowed_to_create_project( self, client, agency_user, token_factory, unauthorized_message ): token: "Token" = token_factory(user=agency_user) response = client.post( path="/projects/", content_type="application/json", HTTP_AUTHORIZATION=f"Bearer {token.key}", ) data = response.json() # Assert assert ( response.status_code == status.HTTP_403_FORBIDDEN ), "Invalid HTTP response code." assert data["detail"] == unauthorized_message, "Invalid error message." def test_client_user_not_allowed_to_create_project( self, client, client_user, token_factory, unauthorized_message ): # Arrange token: "Token" = token_factory(user=client_user) # Act response = client.post( path="/projects/", content_type="application/json", HTTP_AUTHORIZATION=f"Bearer {token.key}", ) data = response.json() # Assert assert response.status_code == status.HTTP_403_FORBIDDEN assert data["detail"] == unauthorized_message def test_admin_user_not_allowed_to_create_project( self, client, user_factory, token_factory, unauthorized_message ): # Arrange user: "User" = user_factory(is_staff=True) token: "Token" = token_factory(user=user) # Act response = client.post( path="/projects/", content_type="application/json", HTTP_AUTHORIZATION=f"Bearer {token.key}", ) data = response.json() # Assert assert response.status_code == status.HTTP_403_FORBIDDEN assert data["detail"] == unauthorized_message def test_supplier_user_fails_to_create_project_with_empty_data( self, client, supplier_user, token_factory, ): # Arrange token: "Token" = token_factory(user=supplier_user) # Act response = client.post( path="/projects/", content_type="application/json", HTTP_AUTHORIZATION=f"Bearer {token.key}", ) data = response.json() # Assert assert ( response.status_code == status.HTTP_400_BAD_REQUEST ), "Invalid HTTP response code." assert Project.objects.count() == 0, "Product was created and should not be." for item in self.CREATE_FIELDS: assert item in data assert data[item] == [ self.FIELD_REQUIRED_MESSAGE ], f"""Invalid error message for field "{item}".""" def test_supplier_user_creates_project_with_valid_data( self, client, supplier_user, category_factory, brand_factory, token_factory, ): # Arrange token: "Token" = token_factory(user=supplier_user) category = category_factory(name="Sample category") brand = brand_factory(name="Sample brand") project_data = { "name": "Sample name", "description": "Sample description", "products_amount": 1, "category": category.pk, "brand": brand.pk, "printing_files_date": "2019-10-30", "promo_date": "2020-01-01", } expected_data = { "name": "Sample name", "description": "Sample description", "products": "http://testserver/products/?project=1", "category": category.pk, "brand": brand.pk, "printing_files_date": "2019-10-30", "promo_date": "2020-01-01", "slug": "#SASA1-0020", "publishable": False, "published": False, } # Act response = client.post( path="/projects/", data=json.dumps(project_data), content_type="application/json", HTTP_AUTHORIZATION=f"Bearer {token.key}", ) data = response.json() # Assert assert response.status_code == status.HTTP_201_CREATED assert utils.is_subset(subset=expected_data, superset=data) @pytest.mark.parametrize("products_amount", [1, 2, 4]) def test_supplier_user_creates_products_for_project( self, client, supplier_user, category_factory, brand_factory, token_factory, products_amount, ): # Arrange token: "Token" = token_factory(user=supplier_user) category = category_factory(name="Sample category") brand = brand_factory(name="Sample brand") project_data = { "name": "Sample name", "description": "Sample description", "products_amount": products_amount, "category": category.pk, "brand": brand.pk, "printing_files_date": "2019-10-30", "promo_date": "2020-01-01", } # Act response = client.post( path="/projects/", data=json.dumps(project_data), content_type="application/json", HTTP_AUTHORIZATION=f"Bearer {token.key}", ) # Assert assert response.status_code == status.HTTP_201_CREATED assert Project.objects.count() == 1 project = Project.objects.first() assert project.products.count() == products_amount def test_supplier_user_fails_when_zero_products( self, client, supplier_user, category_factory, brand_factory, token_factory, ): # Arrange token: "Token" = token_factory(user=supplier_user) category = category_factory(name="Sample category") brand = brand_factory(name="Sample brand") project_data = { "name": "Sample name", "description": "Sample description", "products_amount": 0, "category": category.pk, "brand": brand.pk, "printing_files_date": "2019-10-30", "promo_date": "2020-01-01", } expected_data = {"products_amount": [self.AT_LEAST_ONE_PRODUCT]} # Act response = client.post( path="/projects/", data=json.dumps(project_data), content_type="application/json", HTTP_AUTHORIZATION=f"Bearer {token.key}", ) data = response.json() # Assert assert ( response.status_code == status.HTTP_400_BAD_REQUEST ), "Invalid HTTP response code." assert data == expected_data, "Error message is invalid." assert Project.objects.count() == 0, "Product was created and should not be." @pytest.mark.parametrize("products_amount", [1, 2, 4]) def test_supplier_user_products_in_project_have_valid_stage( self, client, supplier_user, category_factory, brand_factory, token_factory, products_amount, ): # Arrange token: "Token" = token_factory(user=supplier_user) category = category_factory(name="Sample category") brand = brand_factory(name="Sample brand") project_data = { "name": "Sample name", "description": "Sample description", "products_amount": products_amount, "category": category.pk, "brand": brand.pk, "printing_files_date": "2019-10-30", "promo_date": "2020-01-01", } # Act response = client.post( path="/projects/", data=json.dumps(project_data), content_type="application/json", HTTP_AUTHORIZATION=f"Bearer {token.key}", ) # Assert assert response.status_code == status.HTTP_201_CREATED assert Project.objects.count() == 1 project = Project.objects.first() for product in project.products.all(): assert ( product.stage_id == "waiting_for_brief" ), f"""Product "{product}" has invalid stage."""