"""Test role switching lifecycle — owner→engineer→reset, etc. These tests verify that the session remains consistent after role switches. The critical check: after a reset, the original role's access is fully restored. """ import httpx from tests.conftest import SERVER_URL, PASSWORD class TestRoleSwitch: def _login(self, role: str) -> httpx.Client: """Create a fresh authenticated client.""" c = httpx.Client(base_url=SERVER_URL, follow_redirects=False, timeout=10) resp = c.post("/service/login", data={"login": role, "password": PASSWORD}) assert resp.status_code == 302 return c def _switch_role(self, client: httpx.Client, target: str): resp = client.post("/service/api/role/switch", json={"role": target}) assert resp.status_code == 200 data = resp.json() assert data["ok"] is True return data def _reset_role(self, client: httpx.Client): resp = client.post("/service/api/role/reset") assert resp.status_code == 200 data = resp.json() assert data["ok"] is True return data def test_owner_to_engineer_and_back(self): """Owner switches to engineer, then resets — full access restored.""" client = self._login("owner") # Owner can access owner pages r = client.get("/service/users") assert r.status_code == 200 # Switch to engineer data = self._switch_role(client, "engineer") assert data["role"] == "engineer" assert data["original_role"] == "owner" # Engineer cannot access owner pages r = client.get("/service/users") assert r.status_code == 403, "Engineer should be denied owner pages" # Engineer CAN access shared pages r = client.get("/service/customers") assert r.status_code == 200 # Reset to owner data = self._reset_role(client) assert data["role"] == "owner" # CRITICAL: Owner access restored r = client.get("/service/users") assert r.status_code == 200, "Owner access not restored after reset!" # Dashboard still works r = client.get("/service/dashboard") assert r.status_code == 200 def test_owner_to_technician_and_back(self): """Owner switches directly to technician.""" client = self._login("owner") r = client.get("/service/users") assert r.status_code == 200 self._switch_role(client, "technician") r = client.get("/service/users") assert r.status_code == 403 r = client.get("/service/tasks") assert r.status_code == 200 self._reset_role(client) r = client.get("/service/users") assert r.status_code == 200 def test_engineer_to_technician_and_back(self): """Engineer switches to technician, then resets.""" client = self._login("engineer") # Engineer can access engineer pages r = client.get("/service/customers") assert r.status_code == 200 self._switch_role(client, "technician") # Technician cannot access engineer pages r = client.get("/service/customers") assert r.status_code == 403 r = client.get("/service/checklist") assert r.status_code == 200 self._reset_role(client) # Engineer access restored r = client.get("/service/customers") assert r.status_code == 200 def test_double_switch_owner_engineer_technician_then_reset(self): """Multi-step: owner→engineer→technician→reset→owner.""" client = self._login("owner") self._switch_role(client, "engineer") r = client.get("/service/users") assert r.status_code == 403 # Switch deeper while already impersonating self._switch_role(client, "technician") r = client.get("/service/users") assert r.status_code == 403 r = client.get("/service/tasks") assert r.status_code == 200 # Single reset should restore owner self._reset_role(client) r = client.get("/service/users") assert r.status_code == 200 def test_forbidden_switch_technician_cannot_switch(self): """Technician cannot use role switch (not in allowed_roles).""" client = self._login("technician") resp = client.post("/service/api/role/switch", json={"role": "owner"}) assert resp.status_code == 403 def test_reset_without_switch_does_not_error(self): """Reset without an active override should still work.""" client = self._login("owner") resp = client.post("/service/api/role/reset") assert resp.status_code == 200 data = resp.json() assert data["role"] == "owner"