From 9d83c3b30fc1585f2de8feb3e2303ede29823a33 Mon Sep 17 00:00:00 2001 From: Pablo Moreno Date: Mon, 13 May 2024 12:35:58 +0200 Subject: [PATCH] feat: added lots of tests --- config/api/v1/permissions.py | 0 config/tests/mixins.py | 53 ++++++++++ shop/tests/test_api_customers.py | 66 +++++++++++++ shop/tests/test_api_product_batches.py | 60 ++++++++++++ shop/tests/test_api_product_prices.py | 117 ++++++++++++++++++++++ shop/tests/test_api_products.py | 129 +++++++++++++++++++++++++ shop/tests/test_api_providers.py | 66 +++++++++++++ shop/tests/test_api_taxes.py | 54 +++++++++++ 8 files changed, 545 insertions(+) create mode 100644 config/api/v1/permissions.py create mode 100644 config/tests/mixins.py create mode 100644 shop/tests/test_api_customers.py create mode 100644 shop/tests/test_api_product_batches.py create mode 100644 shop/tests/test_api_product_prices.py create mode 100644 shop/tests/test_api_products.py create mode 100644 shop/tests/test_api_providers.py create mode 100644 shop/tests/test_api_taxes.py diff --git a/config/api/v1/permissions.py b/config/api/v1/permissions.py new file mode 100644 index 0000000..e69de29 diff --git a/config/tests/mixins.py b/config/tests/mixins.py new file mode 100644 index 0000000..f25a6d3 --- /dev/null +++ b/config/tests/mixins.py @@ -0,0 +1,53 @@ +import string +import random +from django.contrib.auth.models import User, Permission + + +class TestUserAuthenticationMixin: + model_name = "" + + def create_user(self): + self.password = "".join( + [random.choice(string.ascii_letters) for _ in range(16)] + ) + self.user = User.objects.create( + username="vader", + email="darth@vader.com", + is_staff=True, + is_active=True, + ) + self.user.set_password(self.password) + self.user.save() + self.setup_user_permissions() + + def login(self): + response = self.client.post( + "/api/v1/auth/login/", + { + "username": self.user.username, + "password": self.password, + }, + ) + + jwt_token = response.data.get("access") + self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {jwt_token}") + + def setup_user_permissions(self): + self.create_permission = Permission.objects.get( + codename=f"add_{self.model_name}" + ) + self.delete_permission = Permission.objects.get( + codename=f"delete_{self.model_name}" + ) + self.list_permission = Permission.objects.get( + codename=f"view_{self.model_name}" + ) + self.update_permission = Permission.objects.get( + codename=f"change_{self.model_name}" + ) + + # Grant access and permissions + self.user.user_permissions.add(self.create_permission) + self.user.user_permissions.add(self.delete_permission) + self.user.user_permissions.add(self.list_permission) + self.user.user_permissions.add(self.update_permission) diff --git a/shop/tests/test_api_customers.py b/shop/tests/test_api_customers.py new file mode 100644 index 0000000..85b8da3 --- /dev/null +++ b/shop/tests/test_api_customers.py @@ -0,0 +1,66 @@ +from rest_framework import status +from rest_framework.test import APITestCase + +from config.tests.mixins import TestUserAuthenticationMixin + + +class TestCustomersAPI(APITestCase, TestUserAuthenticationMixin): + model_name = "customer" + + def setUp(self): + self.create_user() + + def test_create_retrieve_customer(self): + self.login() + response = self.client.post( + f"/api/v1/shop/customers/", + { + "vat_id": "11111111H", + "first_name": "Darth", + "last_name": "Maull", + "email": "darth@maul.com", + "address": "Dathomir", + "city": "Dathomir", + "state": "Dathomir", + "country": "Dathomir", + "zip": "00001", + }, + ) + + assert response.status_code == status.HTTP_201_CREATED + pk = response.data.get("id") + response = self.client.get(f"/api/v1/shop/customers/{pk}/") + assert response.status_code == status.HTTP_200_OK + + def test_create_update_customer(self): + self.login() + response = self.client.post( + f"/api/v1/shop/customers/", + { + "vat_id": "11111111H", + "first_name": "Darth", + "last_name": "Maull", + "email": "darth@maul.com", + "address": "Dathomir", + "city": "Dathomir", + "state": "Dathomir", + "country": "Dathomir", + "zip": "00001", + }, + ) + + assert response.status_code == status.HTTP_201_CREATED + pk = response.data.get("id") + response = self.client.get(f"/api/v1/shop/customers/{pk}/") + assert response.status_code == status.HTTP_200_OK + + response = self.client.patch( + f"/api/v1/shop/customers/{pk}/", + { + "address": "Mandalore", + }, + ) + assert response.status_code == status.HTTP_200_OK + response = self.client.get(f"/api/v1/shop/customers/{pk}/") + assert response.status_code == status.HTTP_200_OK + assert response.data.get("address") == "Mandalore" diff --git a/shop/tests/test_api_product_batches.py b/shop/tests/test_api_product_batches.py new file mode 100644 index 0000000..9d34c4b --- /dev/null +++ b/shop/tests/test_api_product_batches.py @@ -0,0 +1,60 @@ +from decimal import Decimal + +from rest_framework import status +from rest_framework.test import APITestCase + +from config.tests.mixins import TestUserAuthenticationMixin +from shop.models import Product, ProductBatch + + +class TestProductBatchesAPI(APITestCase, TestUserAuthenticationMixin): + model_name = "productbatch" + + def setUp(self): + self.create_user() + + def create_product(self): + self.product = Product.objects.create( + name="Papafritas", + description="Las mejores papafritas", + is_digital_asset=False, + url="", + ) + + def test_create_retrieve_product_batch(self): + self.login() + self.create_product() + response = self.client.post( + "/api/v1/shop/product-batches/", + {"code": "B00001", "product": self.product.pk, "quantity": "5"}, + ) + assert response.status_code == status.HTTP_201_CREATED + pk = response.data.get("id") + + response = self.client.get(f"/api/v1/shop/product-batches/{pk}/") + assert response.status_code == status.HTTP_200_OK + + def test_create_update_tax(self): + self.login() + self.create_product() + response = self.client.post( + "/api/v1/shop/product-batches/", + {"code": "B00001", "product": self.product.pk, "quantity": "5"}, + ) + assert response.status_code == status.HTTP_201_CREATED + pk = response.data.get("id") + + response = self.client.get(f"/api/v1/shop/product-batches/{pk}/") + assert response.status_code == status.HTTP_200_OK + + response = self.client.patch( + f"/api/v1/shop/product-batches/{pk}/", + { + "quantity": "10", + }, + ) + assert response.status_code == status.HTTP_200_OK + + response = self.client.get(f"/api/v1/shop/product-batches/{pk}/") + assert response.status_code == status.HTTP_200_OK + assert Decimal(response.data.get("quantity")) == Decimal("10") diff --git a/shop/tests/test_api_product_prices.py b/shop/tests/test_api_product_prices.py new file mode 100644 index 0000000..f33598e --- /dev/null +++ b/shop/tests/test_api_product_prices.py @@ -0,0 +1,117 @@ +from decimal import Decimal + +from rest_framework import status +from rest_framework.test import APITestCase +from django.utils import timezone + +from config.tests.mixins import TestUserAuthenticationMixin +from shop.models import Product, ProductPrice, Tax, ProductBatch + + +class TestProductPricessAPI(APITestCase, TestUserAuthenticationMixin): + model_name = "productprice" + + def setUp(self): + self.create_user() + self.tax = Tax.objects.create( + code="IVA", + value=21, + ) + + def create_products(self): + self.product = Product.objects.create( + name="Papafritas", + description="Las mejores papafritas", + is_digital_asset=False, + url="", + ) + + ProductPrice.objects.create( + product=self.product, + price=Decimal("1.20"), + tax=self.tax, + ) + + def test_fetch_product_prices(self): + self.login() + self.create_products() + response = self.client.get(f"/api/v1/shop/products/{self.product.pk}/prices/") + assert response.status_code == status.HTTP_200_OK + assert len(response.data.get("results")) == 1 + + def test_create_product_prices(self): + self.login() + + product = Product.objects.create( + name="Papafritas", + description="Las mejores papafritas", + is_digital_asset=False, + url="", + ) + response = self.client.post( + f"/api/v1/shop/products/{product.pk}/prices/", + { + "price": "1.20", + "tax": self.tax.pk, + }, + ) + assert response.status_code == status.HTTP_201_CREATED + response = self.client.get(f"/api/v1/shop/products/{product.pk}/prices/") + + assert response.status_code == status.HTTP_200_OK + assert len(response.data.get("results")) == 1 + + def test_create_update_product_prices(self): + self.login() + + product = Product.objects.create( + name="Papafritas", + description="Las mejores papafritas", + is_digital_asset=False, + url="", + ) + response = self.client.post( + f"/api/v1/shop/products/{product.pk}/prices/", + { + "price": "1.20", + "tax": self.tax.pk, + }, + ) + assert response.status_code == status.HTTP_201_CREATED + pk = response.data.get("id") + response = self.client.patch( + f"/api/v1/shop/products/{product.pk}/prices/{pk}/", + { + "price": "1.10", + }, + ) + assert response.status_code == status.HTTP_200_OK + response = self.client.get(f"/api/v1/shop/products/{product.pk}/prices/{pk}/") + assert response.data.get("price") == "1.10" + + def test_create_delete_product_prices(self): + self.login() + + product = Product.objects.create( + name="Papafritas", + description="Las mejores papafritas", + is_digital_asset=False, + url="", + ) + response = self.client.post( + f"/api/v1/shop/products/{product.pk}/prices/", + { + "price": "1.20", + "tax": self.tax.pk, + }, + ) + assert response.status_code == status.HTTP_201_CREATED + pk = response.data.get("id") + + response = self.client.delete( + f"/api/v1/shop/products/{product.pk}/prices/{pk}/" + ) + assert response.status_code == status.HTTP_204_NO_CONTENT + + response = self.client.get(f"/api/v1/shop/products/{product.pk}/prices/{pk}/") + assert response.status_code == status.HTTP_404_NOT_FOUND diff --git a/shop/tests/test_api_products.py b/shop/tests/test_api_products.py new file mode 100644 index 0000000..2bf88e4 --- /dev/null +++ b/shop/tests/test_api_products.py @@ -0,0 +1,129 @@ +from decimal import Decimal + +from rest_framework import status +from rest_framework.test import APITestCase +from django.utils import timezone + +from config.tests.mixins import TestUserAuthenticationMixin +from shop.models import Product, ProductPrice, Tax, ProductBatch + + +class TestProductsAPI(APITestCase, TestUserAuthenticationMixin): + model_name = "product" + + def setUp(self): + self.create_user() + self.tax = Tax.objects.create( + code="IVA", + value=21, + ) + + def create_products(self): + self.product = Product.objects.create( + name="Papafritas", + description="Las mejores papafritas", + is_digital_asset=False, + url="", + ) + + self.product_price = ProductPrice.objects.create( + product=self.product, + price=Decimal("1.20"), + tax=self.tax, + date=timezone.now(), + ) + + self.batch = ProductBatch.objects.create( + code="B0001", + product=self.product, + quantity=Decimal("10"), + ) + + def test_fetch_products(self): + self.login() + self.create_products() + response = self.client.get("/api/v1/shop/products/") + assert response.status_code == status.HTTP_200_OK + assert len(response.data.get("results")) == 1 + + def test_create_product(self): + self.login() + response = self.client.post( + "/api/v1/shop/products/", + { + "name": "Papafritas", + "description": "Las mejores papafritas", + "is_digital_asset": False, + "url": "", + "price": "1.20", + "stock": "100", + "tax": self.tax.pk, + }, + ) + assert response.status_code == status.HTTP_201_CREATED + pk = response.data.get("id") + + response = self.client.get(f"/api/v1/shop/products/{pk}/") + assert response.status_code == status.HTTP_200_OK + + def test_create_update_product(self): + self.login() + response = self.client.post( + "/api/v1/shop/products/", + { + "name": "Papafritas", + "description": "Las mejores papafritas", + "is_digital_asset": False, + "url": "", + "price": "1.20", + "stock": "100", + "tax": self.tax.pk, + }, + ) + assert response.status_code == status.HTTP_201_CREATED + pk = response.data.get("id") + + response = self.client.get(f"/api/v1/shop/products/{pk}/") + assert response.status_code == status.HTTP_200_OK + + response = self.client.patch( + f"/api/v1/shop/products/{pk}/", {"name": "Papafritas pafritas"} + ) + assert response.status_code == status.HTTP_200_OK + response = self.client.get(f"/api/v1/shop/products/{pk}/") + assert response.data.get("name") == "Papafritas pafritas" + + def test_create_delete_product(self): + self.login() + response = self.client.post( + "/api/v1/shop/products/", + { + "name": "Papafritas", + "description": "Las mejores papafritas", + "is_digital_asset": False, + "url": "", + "price": "1.20", + "stock": "100", + "tax": self.tax.pk, + }, + ) + assert response.status_code == status.HTTP_201_CREATED + pk = response.data.get("id") + + response = self.client.get(f"/api/v1/shop/products/{pk}/") + assert response.status_code == status.HTTP_200_OK + + response = self.client.delete(f"/api/v1/shop/products/{pk}/") + assert response.status_code == status.HTTP_204_NO_CONTENT + response = self.client.get(f"/api/v1/shop/products/{pk}/") + assert response.status_code == status.HTTP_404_NOT_FOUND + + def test_create_cannot_delete_product_with_a_batch(self): + self.login() + self.create_products() + + response = self.client.get(f"/api/v1/shop/products/{self.product.pk}/") + assert response.status_code == status.HTTP_200_OK + + response = self.client.delete(f"/api/v1/shop/products/{self.product.pk}/") + assert response.status_code == status.HTTP_400_BAD_REQUEST diff --git a/shop/tests/test_api_providers.py b/shop/tests/test_api_providers.py new file mode 100644 index 0000000..72dbfbd --- /dev/null +++ b/shop/tests/test_api_providers.py @@ -0,0 +1,66 @@ +from rest_framework import status +from rest_framework.test import APITestCase + +from config.tests.mixins import TestUserAuthenticationMixin + + +class TestProvidersAPI(APITestCase, TestUserAuthenticationMixin): + model_name = "provider" + + def setUp(self): + self.create_user() + + def test_create_retrieve_provider(self): + self.login() + response = self.client.post( + f"/api/v1/shop/providers/", + { + "vat_id": "11111111H", + "name": "Darth Maul", + "email": "darth@maul.com", + "address": "Dathomir", + "city": "Dathomir", + "state": "Dathomir", + "country": "Dathomir", + "zip": "00001", + }, + ) + + assert response.status_code == status.HTTP_201_CREATED + pk = response.data.get("id") + + response = self.client.get(f"/api/v1/shop/providers/{pk}/") + assert response.status_code == status.HTTP_200_OK + + def test_create_update_provider(self): + self.login() + response = self.client.post( + f"/api/v1/shop/providers/", + { + "vat_id": "11111111H", + "name": "Darth Maul", + "email": "darth@maul.com", + "address": "Dathomir", + "city": "Dathomir", + "state": "Dathomir", + "country": "Dathomir", + "zip": "00001", + }, + ) + + assert response.status_code == status.HTTP_201_CREATED + pk = response.data.get("id") + response = self.client.get(f"/api/v1/shop/providers/{pk}/") + assert response.status_code == status.HTTP_200_OK + + response = self.client.patch( + f"/api/v1/shop/providers/{pk}/", + { + "address": "Mandalore", + }, + ) + assert response.status_code == status.HTTP_200_OK + response = self.client.get(f"/api/v1/shop/providers/{pk}/") + + assert response.status_code == status.HTTP_200_OK + assert response.data.get("address") == "Mandalore" diff --git a/shop/tests/test_api_taxes.py b/shop/tests/test_api_taxes.py new file mode 100644 index 0000000..ea948d2 --- /dev/null +++ b/shop/tests/test_api_taxes.py @@ -0,0 +1,54 @@ +from rest_framework import status +from rest_framework.test import APITestCase + +from config.tests.mixins import TestUserAuthenticationMixin +from shop.models import Tax + + +class TestTaxesAPI(APITestCase, TestUserAuthenticationMixin): + model_name = "tax" + + def setUp(self): + self.create_user() + + def create_taxes(self): + Tax.objects.create( + code="IVA", + value=21, + ) + + def test_fetch_taxes(self): + self.create_taxes() + self.login() + response = self.client.get("/api/v1/shop/taxes/") + assert response.status_code == status.HTTP_200_OK + assert len(response.data.get("results")) == 1 + + def test_create_retrieve_tax(self): + self.login() + response = self.client.post("/api/v1/shop/taxes/", {"code": "IVA5", "value": 5}) + assert response.status_code == status.HTTP_201_CREATED + pk = response.data.get("id") + + response = self.client.get(f"/api/v1/shop/taxes/{pk}/") + assert response.status_code == status.HTTP_200_OK + + def test_create_update_tax(self): + self.login() + response = self.client.post("/api/v1/shop/taxes/", {"code": "IVA5", "value": 5}) + assert response.status_code == status.HTTP_201_CREATED + pk = response.data.get("id") + + response = self.client.get(f"/api/v1/shop/taxes/{pk}/") + assert response.status_code == status.HTTP_200_OK + + response = self.client.patch( + f"/api/v1/shop/taxes/{pk}/", {"code": "IVA10", "value": 10} + ) + assert response.status_code == status.HTTP_200_OK + + response = self.client.get(f"/api/v1/shop/taxes/{pk}/") + assert response.status_code == status.HTTP_200_OK + + assert response.data.get("code") == "IVA10" + assert response.data.get("value") == 10