This commit is contained in:
75
backend/modules/crm/tests/test_models.py
Normal file
75
backend/modules/crm/tests/test_models.py
Normal file
@@ -0,0 +1,75 @@
|
||||
import uuid
|
||||
from django.test import TestCase
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import IntegrityError
|
||||
|
||||
from modules.crm.models import Client
|
||||
|
||||
|
||||
class ClientModelTests(TestCase):
|
||||
def setUp(self):
|
||||
# osnovni validni podaci koje ćemo koristiti u testovima
|
||||
self.base_data = {
|
||||
"name": "Test Client",
|
||||
"tax_id": str(uuid.uuid4()), # jedinstveno
|
||||
"email": f"client+{uuid.uuid4()}@example.test",
|
||||
"address": "Ulica 1",
|
||||
"city": "Grad",
|
||||
"postal_code": "10000",
|
||||
}
|
||||
|
||||
def test_create_client_success(self):
|
||||
client = Client.objects.create(
|
||||
client_type="legal",
|
||||
**self.base_data
|
||||
)
|
||||
self.assertIsNotNone(client.pk)
|
||||
self.assertEqual(client.name, "Test Client")
|
||||
self.assertEqual(client.client_type, "legal")
|
||||
# default ordering ili drugi atributi mogu se dodatno provjeriti
|
||||
self.assertTrue(str(client).startswith("Test Client"))
|
||||
self.assertIn(client.tax_id, str(client))
|
||||
|
||||
def test_default_client_type_is_legal(self):
|
||||
# Ako eksplicitno ne pošaljemo client_type, default je 'legal'
|
||||
data = dict(self.base_data)
|
||||
data["tax_id"] = str(uuid.uuid4())
|
||||
data["email"] = f"client+{uuid.uuid4()}@example.test"
|
||||
client = Client.objects.create(**data)
|
||||
self.assertEqual(client.client_type, "legal")
|
||||
|
||||
def test_str_representation_contains_name_and_taxid(self):
|
||||
client = Client.objects.create(client_type="individual", **self.base_data)
|
||||
expected = f"{client.name} ({client.tax_id})"
|
||||
self.assertEqual(str(client), expected)
|
||||
|
||||
def test_unique_tax_id_constraint(self):
|
||||
# Prva kreacija prođe
|
||||
Client.objects.create(client_type="legal", **self.base_data)
|
||||
# Pokušaj dupliciranja tax_id-a treba podići IntegrityError
|
||||
dup = dict(self.base_data)
|
||||
dup["email"] = f"client+{uuid.uuid4()}@example.test" # unique email drugi
|
||||
with self.assertRaises(IntegrityError):
|
||||
Client.objects.create(client_type="legal", **dup)
|
||||
|
||||
def test_unique_email_constraint(self):
|
||||
Client.objects.create(client_type="legal", **self.base_data)
|
||||
dup = dict(self.base_data)
|
||||
dup["tax_id"] = str(uuid.uuid4()) # unique tax_id drugi
|
||||
with self.assertRaises(IntegrityError):
|
||||
Client.objects.create(client_type="legal", **dup)
|
||||
|
||||
def test_full_clean_validates_email_format(self):
|
||||
data = dict(self.base_data)
|
||||
data["email"] = "not-an-email"
|
||||
client = Client(**data)
|
||||
with self.assertRaises(ValidationError):
|
||||
client.full_clean() # EmailField validation je pokrenuta
|
||||
|
||||
def test_full_clean_requires_required_fields(self):
|
||||
# Uklonimo obavezno polje name i očekujemo ValidationError
|
||||
data = dict(self.base_data)
|
||||
data.pop("name")
|
||||
client = Client(**data)
|
||||
with self.assertRaises(ValidationError):
|
||||
client.full_clean()
|
||||
43
backend/modules/crm/tests/test_serializers.py
Normal file
43
backend/modules/crm/tests/test_serializers.py
Normal file
@@ -0,0 +1,43 @@
|
||||
import uuid
|
||||
from django.test import TestCase, RequestFactory
|
||||
from unittest.mock import patch
|
||||
from modules.crm.serializers import ClientSerializer
|
||||
from modules.crm.models import Client
|
||||
|
||||
|
||||
class ClientSerializerTests(TestCase):
|
||||
def setUp(self):
|
||||
self.factory = RequestFactory()
|
||||
self.base_data = {
|
||||
"name": "Ser Client",
|
||||
"client_type": "legal",
|
||||
"tax_id": str(uuid.uuid4()),
|
||||
"email": f"client+{uuid.uuid4()}@example.test",
|
||||
"address": "Street 1",
|
||||
"city": "City",
|
||||
"postal_code": "00000",
|
||||
}
|
||||
|
||||
@patch("modules.crm.serializers.ClientService.create_client")
|
||||
def test_create_calls_service(self, mock_create):
|
||||
# Prepare mock return value
|
||||
mock_instance = Client(**self.base_data)
|
||||
mock_instance.pk = 1
|
||||
mock_create.return_value = mock_instance
|
||||
|
||||
serializer = ClientSerializer(data=self.base_data, context={"request": self.factory.post("/")})
|
||||
self.assertTrue(serializer.is_valid(), serializer.errors)
|
||||
result = serializer.save()
|
||||
mock_create.assert_called_once()
|
||||
self.assertEqual(result.pk, 1)
|
||||
|
||||
@patch("modules.crm.serializers.ClientService.update_client")
|
||||
def test_update_calls_service(self, mock_update):
|
||||
client = Client.objects.create(**self.base_data)
|
||||
mock_update.return_value = client
|
||||
|
||||
serializer = ClientSerializer(instance=client, data={"city": "UpdatedCity"}, partial=True, context={"request": self.factory.put("/")})
|
||||
self.assertTrue(serializer.is_valid(), serializer.errors)
|
||||
result = serializer.save()
|
||||
mock_update.assert_called_once()
|
||||
self.assertEqual(result, client)
|
||||
36
backend/modules/crm/tests/test_services.py
Normal file
36
backend/modules/crm/tests/test_services.py
Normal file
@@ -0,0 +1,36 @@
|
||||
import uuid
|
||||
from django.test import TestCase
|
||||
from rest_framework.exceptions import ValidationError
|
||||
from modules.crm.services import ClientService
|
||||
from modules.crm.models import Client
|
||||
|
||||
|
||||
class ClientServiceTests(TestCase):
|
||||
def setUp(self):
|
||||
self.base_data = {
|
||||
"name": "Service Client",
|
||||
"client_type": "legal",
|
||||
"tax_id": str(uuid.uuid4()),
|
||||
"email": f"client+{uuid.uuid4()}@example.test",
|
||||
"address": "Street 1",
|
||||
"city": "City",
|
||||
"postal_code": "00000",
|
||||
}
|
||||
|
||||
def test_create_client_success(self):
|
||||
client = ClientService.create_client(self.base_data)
|
||||
self.assertIsNotNone(client.pk)
|
||||
self.assertEqual(client.name, "Service Client")
|
||||
|
||||
def test_create_client_duplicate_tax_id_raises(self):
|
||||
# create first
|
||||
Client.objects.create(**self.base_data)
|
||||
dup = dict(self.base_data)
|
||||
dup["email"] = f"client+{uuid.uuid4()}@example.test"
|
||||
with self.assertRaises(ValidationError):
|
||||
ClientService.create_client(dup)
|
||||
|
||||
def test_update_client_success(self):
|
||||
client = Client.objects.create(**self.base_data)
|
||||
updated = ClientService.update_client(client, {"city": "NewCity"})
|
||||
self.assertEqual(updated.city, "NewCity")
|
||||
62
backend/modules/crm/tests/test_views.py
Normal file
62
backend/modules/crm/tests/test_views.py
Normal file
@@ -0,0 +1,62 @@
|
||||
import uuid
|
||||
from django.test import TestCase, RequestFactory
|
||||
from django.contrib.auth import get_user_model
|
||||
from unittest.mock import patch
|
||||
from modules.crm.serializers import ClientSerializer
|
||||
from modules.crm.views import ClientViewSet
|
||||
from modules.crm.models import Client
|
||||
|
||||
|
||||
class ClientViewSetTests(TestCase):
|
||||
def setUp(self):
|
||||
User = get_user_model()
|
||||
self.user = User.objects.create_user(username=f"user_{uuid.uuid4().hex[:6]}", email=f"user+{uuid.uuid4()}@example.test", password="pass")
|
||||
self.factory = RequestFactory()
|
||||
self.view = ClientViewSet()
|
||||
self.view.request = self.factory.post("/")
|
||||
self.view.request.user = self.user
|
||||
|
||||
self.base_data = {
|
||||
"name": "View Client",
|
||||
"client_type": "legal",
|
||||
"tax_id": str(uuid.uuid4()),
|
||||
"email": f"client+{uuid.uuid4()}@example.test",
|
||||
"address": "Street 1",
|
||||
"city": "City",
|
||||
"postal_code": "00000",
|
||||
}
|
||||
|
||||
@patch("modules.crm.views.ClientService.create_client")
|
||||
def test_perform_create_delegates_to_service(self, mock_create):
|
||||
# make serializer valid
|
||||
serializer = ClientSerializer(data=self.base_data, context={"request": self.view.request})
|
||||
self.assertTrue(serializer.is_valid(), serializer.errors)
|
||||
|
||||
mock_inst = Client(**self.base_data)
|
||||
mock_inst.pk = 1
|
||||
mock_create.return_value = mock_inst
|
||||
|
||||
self.view.request = self.factory.post("/")
|
||||
self.view.request.user = self.user
|
||||
|
||||
# perform_create should call serializer.save() which delegates to service
|
||||
self.view.perform_create(serializer)
|
||||
mock_create.assert_called_once()
|
||||
|
||||
@patch("modules.crm.views.ClientService.update_client")
|
||||
def test_perform_update_delegates_to_service(self, mock_update):
|
||||
client = Client.objects.create(**self.base_data)
|
||||
serializer = ClientSerializer(instance=client, data={"city": "UpdatedCity"}, partial=True, context={"request": self.view.request})
|
||||
self.assertTrue(serializer.is_valid(), serializer.errors)
|
||||
|
||||
mock_update.return_value = client
|
||||
|
||||
self.view.request = self.factory.put("/")
|
||||
self.view.request.user = self.user
|
||||
serializer.instance = client
|
||||
|
||||
self.view.perform_update(serializer)
|
||||
mock_update.assert_called_once()
|
||||
client.refresh_from_db()
|
||||
# serializer.perform_update causes serializer.save() which we delegated; check instance still exists
|
||||
self.assertIsNotNone(client.pk)
|
||||
Reference in New Issue
Block a user