"""Department and principal integration tests. Covers department CRUD, principal CRUD, membership management, and principal-department linking. """ import pytest import uuid from tests.integration.client.base import ApiError from gatehouse_app.utils.constants import OrganizationRole def assert_success(response: dict, message_contains: str = "") -> dict: data = response.get("data", {}) assert response.get("success") is not False, ( f"Expected success but got error: {response.get('message')}" ) if message_contains: assert message_contains.lower() in response.get("message", "").lower() return data def assert_error(exc: ApiError, expected_status: int, expected_error_type: str | None = None): assert exc.status_code == expected_status, ( f"Expected status {expected_status} but got {exc.status_code}" ) if expected_error_type: assert exc.error_type == expected_error_type, ( f"Expected error_type '{expected_error_type}' but got '{exc.error_type}'" ) class TestDepartmentCRUD: """Test department lifecycle.""" def test_create_department_positive(self, integration_client, create_test_user, create_test_org, create_test_membership): """TEST: DEPT-01 — Create department as admin. WHAT: Admin POST /organizations//departments. WHY: Departments group users for access control. EXPECTED: 201 Created with department data. """ admin = create_test_user(password="AdminPass123!") org = create_test_org() create_test_membership(admin["id"], org["id"], OrganizationRole.ADMIN) integration_client.auth.login(email=admin["email"], password="AdminPass123!") result = integration_client.orgs.create_department(org["id"], "Engineering", "Software dev team") data = assert_success(result) assert "id" in data.get("department", data) def test_create_department_non_admin_negative(self, integration_client, create_test_user, create_test_org, create_test_membership): """TEST: DEPT-02 — Reject department creation as member. WHAT: Member attempts POST /organizations//departments. WHY: Department management is admin-only. EXPECTED: 403 Forbidden. """ member = create_test_user(password="MemberPass123!") org = create_test_org() create_test_membership(member["id"], org["id"], OrganizationRole.MEMBER) integration_client.auth.login(email=member["email"], password="MemberPass123!") with pytest.raises(ApiError) as exc_info: integration_client.orgs.create_department(org["id"], "Engineering") assert exc_info.value.status_code == 403 def test_list_departments_positive(self, integration_client, create_test_user, create_test_org, create_test_membership): """TEST: DEPT-03 — List departments. WHAT: GET /organizations//departments. WHY: Users need to see available departments. EXPECTED: 200 OK with departments array. """ user = create_test_user(password="MyPassword123!") org = create_test_org() create_test_membership(user["id"], org["id"], OrganizationRole.MEMBER) integration_client.auth.login(email=user["email"], password="MyPassword123!") result = integration_client.orgs.list_departments(org["id"]) data = assert_success(result) assert "departments" in data def test_add_department_member_positive(self, integration_client, create_test_user, create_test_org, create_test_membership): """TEST: DEPT-04 — Add member to department. WHAT: Admin adds a member to a department by email. WHY: Department membership controls access. EXPECTED: 200 OK. """ admin = create_test_user(password="AdminPass123!") member = create_test_user(password="MemberPass123!") org = create_test_org() create_test_membership(admin["id"], org["id"], OrganizationRole.ADMIN) create_test_membership(member["id"], org["id"], OrganizationRole.MEMBER) integration_client.auth.login(email=admin["email"], password="AdminPass123!") dept_result = integration_client.orgs.create_department(org["id"], "Engineering") dept_id = dept_result["data"]["department"]["id"] result = integration_client.orgs.add_department_member(org["id"], dept_id, member["email"]) assert_success(result) class TestPrincipalCRUD: """Test principal lifecycle.""" def test_create_principal_positive(self, integration_client, create_test_user, create_test_org, create_test_membership): """TEST: PRINC-01 — Create principal as admin. WHAT: Admin POST /organizations//principals. WHY: Principals represent SSH access roles. EXPECTED: 201 Created. """ admin = create_test_user(password="AdminPass123!") org = create_test_org() create_test_membership(admin["id"], org["id"], OrganizationRole.ADMIN) integration_client.auth.login(email=admin["email"], password="AdminPass123!") result = integration_client.orgs.create_principal(org["id"], "deploy", "Deployment access") data = assert_success(result) assert "id" in data.get("principal", data) def test_list_principals_positive(self, integration_client, create_test_user, create_test_org, create_test_membership): """TEST: PRINC-02 — List principals. WHAT: GET /organizations//principals. WHY: Users need visibility into available principals. EXPECTED: 200 OK with principals array. """ user = create_test_user(password="MyPassword123!") org = create_test_org() create_test_membership(user["id"], org["id"], OrganizationRole.MEMBER) integration_client.auth.login(email=user["email"], password="MyPassword123!") result = integration_client.orgs.list_principals(org["id"]) data = assert_success(result) assert "principals" in data def test_add_principal_member_positive(self, integration_client, create_test_user, create_test_org, create_test_membership): """TEST: PRINC-03 — Add member to principal. WHAT: Admin adds a user to a principal. WHY: Principal membership grants SSH principals. EXPECTED: 200 OK. """ admin = create_test_user(password="AdminPass123!") member = create_test_user(password="MemberPass123!") org = create_test_org() create_test_membership(admin["id"], org["id"], OrganizationRole.ADMIN) create_test_membership(member["id"], org["id"], OrganizationRole.MEMBER) integration_client.auth.login(email=admin["email"], password="AdminPass123!") princ_result = integration_client.orgs.create_principal(org["id"], "deploy") princ_id = princ_result["data"]["principal"]["id"] result = integration_client.orgs.add_principal_member(org["id"], princ_id, member["email"]) assert_success(result) def test_link_principal_department_positive(self, integration_client, create_test_user, create_test_org, create_test_membership): """TEST: PRINC-04 — Link principal to department. WHAT: Admin links a principal to a department. WHY: Department-principal links automate access assignment. EXPECTED: 200 OK. """ admin = create_test_user(password="AdminPass123!") org = create_test_org() create_test_membership(admin["id"], org["id"], OrganizationRole.ADMIN) integration_client.auth.login(email=admin["email"], password="AdminPass123!") dept_result = integration_client.orgs.create_department(org["id"], "Engineering") dept_id = dept_result["data"]["department"]["id"] princ_result = integration_client.orgs.create_principal(org["id"], "deploy") princ_id = princ_result["data"]["principal"]["id"] result = integration_client.orgs.link_principal_department(org["id"], princ_id, dept_id) assert_success(result)