| """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 |
|
|