Two issues from the whole-branch review: 1. (Important) Observation detail's can_respond_to_department context var did not include is_department_manager, so even though Task 2 let dept managers pass the view's permission check, the 'Submit Response' button stayed hidden from them. Now the context var matches the view predicate. Regression test added. 2. (Minor) appreciation_list had no guard against now-invalid status query params (?status=acknowledged from an old bookmark would show an unexplained empty list). Unknown values are now silently reset to 'all statuses'.
110 lines
4.7 KiB
Python
110 lines
4.7 KiB
Python
"""Tests for the observation workflow realignment."""
|
|
from django.contrib.auth.models import Group
|
|
|
|
import pytest
|
|
from django.test import TestCase
|
|
from django.urls import reverse
|
|
|
|
from apps.accounts.models import User
|
|
from apps.organizations.models import Department, Hospital
|
|
from apps.observations.models import Observation
|
|
|
|
|
|
def _ensure_group(name):
|
|
"""Get or create a role group (pytest runs with --nomigrations, so seeded
|
|
groups may not exist in the test DB)."""
|
|
grp, _ = Group.objects.get_or_create(name=name)
|
|
return grp
|
|
|
|
|
|
@pytest.mark.django_db
|
|
class TestObservationDepartmentResponsePermission(TestCase):
|
|
"""A department manager of the assigned department can respond.
|
|
|
|
Uses self.client (full middleware incl. django.contrib.messages) — the
|
|
view calls messages.error() on the permission-denied path. The project's
|
|
root conftest.py disables ManifestStaticFilesStorage for all tests.
|
|
"""
|
|
|
|
def setUp(self):
|
|
self.hospital = Hospital.objects.create(name="Test Hospital", code="TH02")
|
|
self.dept = Department.objects.create(name="Dept A", hospital=self.hospital, code="OA")
|
|
self.other_dept = Department.objects.create(name="Dept B", hospital=self.hospital, code="OB")
|
|
|
|
_ensure_group("Department Manager")
|
|
self.dept_manager = User.objects.create_user(
|
|
username="odmgr", email="odmgr@test", password="x", department=self.dept
|
|
)
|
|
self.dept_manager.groups.add(Group.objects.get(name="Department Manager"))
|
|
|
|
self.other_manager = User.objects.create_user(
|
|
username="oother", email="oo@test", password="x", department=self.other_dept
|
|
)
|
|
self.other_manager.groups.add(Group.objects.get(name="Department Manager"))
|
|
|
|
self.observation = Observation.objects.create(
|
|
description="Test observation description here",
|
|
hospital=self.hospital,
|
|
assigned_department=self.dept,
|
|
sent_to_department=True,
|
|
status="in_progress",
|
|
)
|
|
|
|
def test_dept_manager_of_assigned_dept_can_access_response_view(self):
|
|
"""GET to observation_department_response succeeds (200) for dept manager of assigned dept."""
|
|
self.client.force_login(self.dept_manager)
|
|
response = self.client.get(
|
|
reverse("observations:observation_department_response", kwargs={"pk": self.observation.pk})
|
|
)
|
|
assert response.status_code == 200, \
|
|
f"dept_manager of assigned dept should be allowed, got {response.status_code}"
|
|
|
|
def test_dept_manager_of_other_dept_cannot_access(self):
|
|
"""Dept manager of a non-assigned department is denied (302 redirect)."""
|
|
self.client.force_login(self.other_manager)
|
|
response = self.client.get(
|
|
reverse("observations:observation_department_response", kwargs={"pk": self.observation.pk})
|
|
)
|
|
assert response.status_code == 302, \
|
|
f"dept_manager of other dept should be redirected (denied), got {response.status_code}"
|
|
|
|
|
|
@pytest.mark.django_db
|
|
class TestObservationDetailRespondButtonGate(TestCase):
|
|
"""The 'Submit Response' button must be visible to dept_manager of the
|
|
assigned department — not just pass the view's permission check.
|
|
|
|
Locks in the fix for the Important issue found in whole-branch review:
|
|
Task 2 added dept_manager to the view predicate but the template context
|
|
var `can_respond_to_department` was missed, so the button stayed hidden.
|
|
"""
|
|
|
|
def setUp(self):
|
|
self.hospital = Hospital.objects.create(name="Test Hospital Gate", code="TH04")
|
|
self.dept = Department.objects.create(name="Dept Gate", hospital=self.hospital, code="GT")
|
|
|
|
_ensure_group("Department Manager")
|
|
self.dept_manager = User.objects.create_user(
|
|
username="gdmgr", email="gdmgr@test", password="x", department=self.dept
|
|
)
|
|
self.dept_manager.groups.add(Group.objects.get(name="Department Manager"))
|
|
|
|
self.observation = Observation.objects.create(
|
|
description="Gate test observation",
|
|
hospital=self.hospital,
|
|
assigned_department=self.dept,
|
|
sent_to_department=True,
|
|
department_responded_at=None,
|
|
status="in_progress",
|
|
)
|
|
|
|
def test_dept_manager_sees_respond_button(self):
|
|
"""The department detail page renders the respond control for dept managers."""
|
|
self.client.force_login(self.dept_manager)
|
|
response = self.client.get(
|
|
reverse("observations:observation_detail", kwargs={"pk": self.observation.pk})
|
|
)
|
|
assert response.status_code == 200
|
|
assert response.context["can_respond_to_department"] is True, \
|
|
"dept_manager of assigned dept must see can_respond_to_department=True"
|