"""Integration tests for WallSection API endpoints.""" from __future__ import annotations import pytest from django.urls import reverse from rest_framework import status from rest_framework.test import APIClient @pytest.mark.django_db @pytest.mark.integration class TestWallSectionAPI: """Test WallSection CRUD operations via REST API.""" def test_create_wall_section_success(self, api_client: APIClient) -> None: """Test creating a wall section for a profile returns 201.""" profile_url = reverse("profile-list") profile = api_client.post( profile_url, {"name": "Northern Watch", "team_lead": "Jon Snow"}, format="json", ).data url = reverse("wallsection-list") payload = { "profile": profile["id"], "section_name": "Tower 1-2", } response = api_client.post(url, payload, format="json") assert response.status_code == status.HTTP_201_CREATED assert response.data["section_name"] == "Tower 1-2" assert response.data["profile"] == profile["id"] assert "id" in response.data assert "created_at" in response.data def test_create_wall_section_duplicate_name_for_profile_fails(self, api_client: APIClient) -> None: """Test duplicate section name for same profile returns 400.""" profile_url = reverse("profile-list") profile = api_client.post( profile_url, {"name": "Northern Watch", "team_lead": "Jon Snow"}, format="json", ).data url = reverse("wallsection-list") payload = { "profile": profile["id"], "section_name": "Tower 1-2", } api_client.post(url, payload, format="json") response = api_client.post(url, payload, format="json") assert response.status_code == status.HTTP_400_BAD_REQUEST def test_create_wall_section_same_name_different_profiles_succeeds(self, api_client: APIClient) -> None: """Test same section name for different profiles is allowed.""" profile_url = reverse("profile-list") profile1 = api_client.post( profile_url, {"name": "Northern Watch", "team_lead": "Jon Snow"}, format="json", ).data profile2 = api_client.post( profile_url, {"name": "Eastern Defense", "team_lead": "Tormund"}, format="json", ).data url = reverse("wallsection-list") payload1 = { "profile": profile1["id"], "section_name": "Tower 1-2", } payload2 = { "profile": profile2["id"], "section_name": "Tower 1-2", } response1 = api_client.post(url, payload1, format="json") response2 = api_client.post(url, payload2, format="json") assert response1.status_code == status.HTTP_201_CREATED assert response2.status_code == status.HTTP_201_CREATED def test_list_wall_sections(self, api_client: APIClient) -> None: """Test listing wall sections returns all sections.""" profile_url = reverse("profile-list") profile = api_client.post( profile_url, {"name": "Northern Watch", "team_lead": "Jon Snow"}, format="json", ).data section_url = reverse("wallsection-list") api_client.post( section_url, { "profile": profile["id"], "section_name": "Tower 1-2", }, format="json", ) api_client.post( section_url, { "profile": profile["id"], "section_name": "Tower 2-3", }, format="json", ) response = api_client.get(section_url) assert response.status_code == status.HTTP_200_OK assert response.data["count"] == 2 assert len(response.data["results"]) == 2 def test_filter_wall_sections_by_profile(self, api_client: APIClient) -> None: """Test filtering sections by profile ID.""" profile_url = reverse("profile-list") profile1 = api_client.post( profile_url, {"name": "Northern Watch", "team_lead": "Jon Snow"}, format="json", ).data profile2 = api_client.post( profile_url, {"name": "Eastern Defense", "team_lead": "Tormund"}, format="json", ).data section_url = reverse("wallsection-list") api_client.post( section_url, { "profile": profile1["id"], "section_name": "Tower 1-2", }, format="json", ) api_client.post( section_url, { "profile": profile2["id"], "section_name": "Tower 3-4", }, format="json", ) response = api_client.get(section_url, {"profile": profile1["id"]}) assert response.status_code == status.HTTP_200_OK assert response.data["count"] == 1 assert response.data["results"][0]["section_name"] == "Tower 1-2" def test_retrieve_wall_section(self, api_client: APIClient) -> None: """Test retrieving a specific wall section.""" profile_url = reverse("profile-list") profile = api_client.post( profile_url, {"name": "Northern Watch", "team_lead": "Jon Snow"}, format="json", ).data section_url = reverse("wallsection-list") section = api_client.post( section_url, { "profile": profile["id"], "section_name": "Tower 1-2", }, format="json", ).data detail_url = reverse("wallsection-detail", kwargs={"pk": section["id"]}) response = api_client.get(detail_url) assert response.status_code == status.HTTP_200_OK assert response.data["id"] == section["id"] assert response.data["section_name"] == "Tower 1-2" def test_update_wall_section(self, api_client: APIClient) -> None: """Test updating a wall section.""" profile_url = reverse("profile-list") profile = api_client.post( profile_url, {"name": "Northern Watch", "team_lead": "Jon Snow"}, format="json", ).data section_url = reverse("wallsection-list") section = api_client.post( section_url, { "profile": profile["id"], "section_name": "Tower 1-2", }, format="json", ).data detail_url = reverse("wallsection-detail", kwargs={"pk": section["id"]}) updated_payload = { "profile": profile["id"], "section_name": "Tower 1-2 Extended", } response = api_client.put(detail_url, updated_payload, format="json") assert response.status_code == status.HTTP_200_OK assert response.data["section_name"] == "Tower 1-2 Extended" def test_delete_wall_section(self, api_client: APIClient) -> None: """Test deleting a wall section.""" profile_url = reverse("profile-list") profile = api_client.post( profile_url, {"name": "Northern Watch", "team_lead": "Jon Snow"}, format="json", ).data section_url = reverse("wallsection-list") section = api_client.post( section_url, { "profile": profile["id"], "section_name": "Tower 1-2", }, format="json", ).data detail_url = reverse("wallsection-detail", kwargs={"pk": section["id"]}) response = api_client.delete(detail_url) assert response.status_code == status.HTTP_204_NO_CONTENT retrieve_response = api_client.get(detail_url) assert retrieve_response.status_code == status.HTTP_404_NOT_FOUND def test_delete_profile_cascades_to_sections(self, api_client: APIClient) -> None: """Test deleting a profile also deletes associated wall sections.""" profile_url = reverse("profile-list") profile = api_client.post( profile_url, {"name": "Northern Watch", "team_lead": "Jon Snow"}, format="json", ).data section_url = reverse("wallsection-list") section = api_client.post( section_url, { "profile": profile["id"], "section_name": "Tower 1-2", }, format="json", ).data profile_detail_url = reverse("profile-detail", kwargs={"pk": profile["id"]}) api_client.delete(profile_detail_url) section_detail_url = reverse("wallsection-detail", kwargs={"pk": section["id"]}) response = api_client.get(section_detail_url) assert response.status_code == status.HTTP_404_NOT_FOUND def test_wall_section_requires_profile(self, api_client: APIClient) -> None: """Test creating section without profile returns 400.""" url = reverse("wallsection-list") payload = { "section_name": "Tower 1-2", } response = api_client.post(url, payload, format="json") assert response.status_code == status.HTTP_400_BAD_REQUEST assert "profile" in response.data def test_wall_section_requires_section_name(self, api_client: APIClient) -> None: """Test creating section without section_name returns 400.""" profile_url = reverse("profile-list") profile = api_client.post( profile_url, {"name": "Northern Watch", "team_lead": "Jon Snow"}, format="json", ).data url = reverse("wallsection-list") payload = { "profile": profile["id"], } response = api_client.post(url, payload, format="json") assert response.status_code == status.HTTP_400_BAD_REQUEST assert "section_name" in response.data