bottleneckcrm/backend/cases/tests/test_case_solutions.py
Ashwin bd79a7a4cc Refactor code style and improve error handling in analytics API
- Cleaned up admin.py by removing unnecessary dictionary wrapping for fields.
- Adjusted migration files to maintain consistent formatting and removed redundant lines.
- Updated models.py and tests to remove unnecessary blank lines and improve readability.
- Enhanced error handling in the analytics API to properly forward upstream status and messages.
- Added comprehensive tests for the analytics proxy to ensure correct status and body forwarding.
- Updated contributing guidelines to clarify the use of ruff for code style enforcement.
2026-08-07 15:58:35 +05:30

101 lines
3.7 KiB
Python

"""Tests for Case detail solutions inclusion and link/unlink endpoints."""
import pytest
from cases.models import Solution
from conftest import rls_org
@pytest.mark.django_db
class TestCaseDetailSolutions:
def test_detail_includes_linked_solutions(
self, admin_client, case_a, org_a, admin_user
):
sol = Solution.objects.create(
title="Reset password steps",
description="1. Click forgot password...",
org=org_a,
status="approved",
is_published=True,
created_by=admin_user,
)
sol.cases.add(case_a)
response = admin_client.get(f"/api/cases/{case_a.pk}/")
assert response.status_code == 200
data = response.json()
assert "solutions" in data
assert len(data["solutions"]) == 1
assert data["solutions"][0]["title"] == "Reset password steps"
def test_detail_solutions_excludes_other_org(
self, admin_client, case_a, org_b, admin_user
):
# Seeded into another tenant: the insert-check policy compares
# against `app.current_org`, so writing this row means being that
# tenant for the length of the write.
with rls_org(org_b):
Solution.objects.create(
title="Other org solution",
description="...",
org=org_b,
created_by=admin_user,
)
response = admin_client.get(f"/api/cases/{case_a.pk}/")
assert response.status_code == 200
assert response.json()["solutions"] == []
@pytest.mark.django_db
class TestCaseSolutionLinking:
def _solution(self, org, user, **kwargs):
# Seeded into another tenant: the insert-check policy compares
# against `app.current_org`, so writing this row means being that
# tenant for the length of the write.
with rls_org(org):
return Solution.objects.create(
title=kwargs.get("title", "S"),
description="x",
org=org,
status=kwargs.get("status", "approved"),
is_published=kwargs.get("is_published", True),
created_by=user,
)
def test_link_solution(self, admin_client, case_a, org_a, admin_user):
sol = self._solution(org_a, admin_user)
response = admin_client.post(
f"/api/cases/{case_a.pk}/solutions/",
{"solution_id": str(sol.pk)},
content_type="application/json",
)
assert response.status_code == 201
assert sol in case_a.solutions.all()
def test_link_idempotent(self, admin_client, case_a, org_a, admin_user):
sol = self._solution(org_a, admin_user)
case_a.solutions.add(sol)
response = admin_client.post(
f"/api/cases/{case_a.pk}/solutions/",
{"solution_id": str(sol.pk)},
content_type="application/json",
)
assert response.status_code == 200
assert case_a.solutions.count() == 1
def test_link_cross_org_404(self, admin_client, case_a, org_b, admin_user):
sol = self._solution(org_b, admin_user)
response = admin_client.post(
f"/api/cases/{case_a.pk}/solutions/",
{"solution_id": str(sol.pk)},
content_type="application/json",
)
assert response.status_code == 404
def test_unlink_solution(self, admin_client, case_a, org_a, admin_user):
sol = self._solution(org_a, admin_user)
case_a.solutions.add(sol)
response = admin_client.delete(f"/api/cases/{case_a.pk}/solutions/{sol.pk}/")
assert response.status_code == 204
assert sol not in case_a.solutions.all()