test(backend): add coverage for services tasks and apis

This commit is contained in:
2026-04-30 12:44:24 +03:30
parent 8774a4d4dc
commit 3152284cf3
15 changed files with 1279 additions and 0 deletions

View File

@@ -0,0 +1 @@

View File

@@ -0,0 +1,67 @@
from django.test import TestCase
from rest_framework.exceptions import ValidationError
from apps.clients.models import Client
from apps.clients.services.clients import create_client, update_client
from apps.users.models import User
from apps.workspaces.models import Workspace, WorkspaceMembership
class ClientServiceTests(TestCase):
@classmethod
def setUpTestData(cls):
cls.owner = User.objects.create_user(mobile="09120000001", password="secret123")
cls.member = User.objects.create_user(mobile="09120000002", password="secret123")
cls.outsider = User.objects.create_user(mobile="09120000003", password="secret123")
cls.workspace = Workspace.objects.create(name="Clients", owner=cls.owner)
WorkspaceMembership.objects.create(
workspace=cls.workspace,
user=cls.member,
role=WorkspaceMembership.Role.MEMBER,
is_active=True,
)
def test_create_client_creates_record_for_workspace_member(self):
client = create_client(
self.member,
self.workspace.id,
"Acme",
notes="Priority account",
)
self.assertEqual(client.name, "Acme")
self.assertEqual(client.notes, "Priority account")
self.assertEqual(client.workspace, self.workspace)
self.assertEqual(client.created_by, self.member)
def test_create_client_rejects_non_member(self):
with self.assertRaises(ValidationError) as exc:
create_client(self.outsider, self.workspace.id, "Acme")
self.assertIn("workspace", exc.exception.detail)
def test_create_client_rejects_duplicate_name_in_workspace(self):
Client.objects.create(workspace=self.workspace, name="Acme")
with self.assertRaises(ValidationError) as exc:
create_client(self.owner, self.workspace.id, "Acme")
self.assertIn("name", exc.exception.detail)
def test_update_client_updates_name_and_notes(self):
client = Client.objects.create(workspace=self.workspace, name="Acme", notes="Old")
updated = update_client(client, name="Globex", notes="New")
self.assertEqual(updated.name, "Globex")
self.assertEqual(updated.notes, "New")
def test_update_client_rejects_duplicate_new_name(self):
Client.objects.create(workspace=self.workspace, name="Globex")
client = Client.objects.create(workspace=self.workspace, name="Acme")
with self.assertRaises(ValidationError) as exc:
update_client(client, name="Globex")
self.assertIn("name", exc.exception.detail)

View File

@@ -0,0 +1,125 @@
from rest_framework.test import APITestCase
from apps.clients.models import Client
from apps.users.models import User
from apps.workspaces.models import Workspace, WorkspaceMembership
class ClientViewTests(APITestCase):
@classmethod
def setUpTestData(cls):
cls.owner = User.objects.create_user(mobile="09120000011", password="secret123")
cls.admin = User.objects.create_user(mobile="09120000012", password="secret123")
cls.second_admin = User.objects.create_user(mobile="09120000013", password="secret123")
cls.member = User.objects.create_user(mobile="09120000014", password="secret123")
cls.guest = User.objects.create_user(mobile="09120000015", password="secret123")
cls.outsider = User.objects.create_user(mobile="09120000016", password="secret123")
cls.workspace = Workspace.objects.create(name="Clients API", owner=cls.owner)
for user, role in (
(cls.admin, WorkspaceMembership.Role.ADMIN),
(cls.second_admin, WorkspaceMembership.Role.ADMIN),
(cls.member, WorkspaceMembership.Role.MEMBER),
(cls.guest, WorkspaceMembership.Role.GUEST),
):
WorkspaceMembership.objects.create(
workspace=cls.workspace,
user=user,
role=role,
is_active=True,
)
cls.other_workspace = Workspace.objects.create(name="Other", owner=cls.outsider)
cls.visible_client = Client.objects.create(workspace=cls.workspace, name="Visible")
cls.hidden_client = Client.objects.create(workspace=cls.other_workspace, name="Hidden")
cls.admin_owned_client = Client.objects.create(
workspace=cls.workspace,
name="Admin Owned",
created_by=cls.admin,
updated_by=cls.admin,
)
def test_list_only_returns_clients_for_member_workspaces(self):
self.client.force_authenticate(user=self.member)
response = self.client.get("/api/clients/")
self.assertEqual(response.status_code, 200)
results = (
response.data
if isinstance(response.data, list)
else response.data.get("results")
or response.data.get("items")
or response.data.get("notifications")
or []
)
names = {item["name"] for item in results}
self.assertIn("Visible", names)
self.assertNotIn("Hidden", names)
def test_owner_can_create_client(self):
self.client.force_authenticate(user=self.owner)
response = self.client.post(
"/api/clients/",
{
"workspace_id": str(self.workspace.id),
"name": "Created",
"notes": "Important",
},
format="json",
)
self.assertEqual(response.status_code, 201)
self.assertEqual(response.data["name"], "Created")
def test_member_cannot_create_client(self):
self.client.force_authenticate(user=self.member)
response = self.client.post(
"/api/clients/",
{
"workspace_id": str(self.workspace.id),
"name": "Created",
},
format="json",
)
self.assertEqual(response.status_code, 403)
def test_admin_can_update_client(self):
self.client.force_authenticate(user=self.admin)
response = self.client.patch(
f"/api/clients/{self.visible_client.id}/",
{"name": "Renamed"},
format="json",
)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data["name"], "Renamed")
def test_admin_can_delete_only_client_they_created(self):
self.client.force_authenticate(user=self.second_admin)
forbidden = self.client.delete(f"/api/clients/{self.admin_owned_client.id}/")
self.assertEqual(forbidden.status_code, 403)
self.client.force_authenticate(user=self.admin)
allowed = self.client.delete(f"/api/clients/{self.admin_owned_client.id}/")
self.assertEqual(allowed.status_code, 204)
self.assertTrue(Client.all_objects.get(id=self.admin_owned_client.id).is_deleted)
def test_owner_can_delete_any_client(self):
client = Client.objects.create(
workspace=self.workspace,
name="Owner Delete",
created_by=self.admin,
updated_by=self.admin,
)
self.client.force_authenticate(user=self.owner)
response = self.client.delete(f"/api/clients/{client.id}/")
self.assertEqual(response.status_code, 204)
self.assertTrue(Client.all_objects.get(id=client.id).is_deleted)