File size: 9,274 Bytes
5422df1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 | """Deployment tests for Wall Construction API.
Tests that verify the full stack is properly deployed and functional:
- Database migrations have run successfully
- API endpoints are accessible and return correct status codes
- CRUD operations work end-to-end
- Data persistence works correctly
"""
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.deployment
class TestDeploymentHealth:
"""Test deployment health and basic API functionality."""
def test_api_root_accessible(self, api_client: APIClient) -> None:
"""Test API root endpoint is accessible."""
url = "/"
response = api_client.get(url)
assert response.status_code in (
status.HTTP_200_OK,
status.HTTP_301_MOVED_PERMANENTLY,
status.HTTP_302_FOUND,
)
def test_profiles_endpoint_accessible(self, api_client: APIClient) -> None:
"""Test profiles list endpoint returns 200 with empty database."""
url = reverse("profile-list")
response = api_client.get(url)
assert response.status_code == status.HTTP_200_OK
assert "results" in response.data
assert "count" in response.data
assert isinstance(response.data["results"], list)
def test_wallsections_endpoint_accessible(self, api_client: APIClient) -> None:
"""Test wallsections list endpoint returns 200 with empty database."""
url = reverse("wallsection-list")
response = api_client.get(url)
assert response.status_code == status.HTTP_200_OK
assert "results" in response.data
assert "count" in response.data
assert isinstance(response.data["results"], list)
@pytest.mark.django_db
@pytest.mark.deployment
class TestDeploymentEndToEnd:
"""Test end-to-end workflows to verify deployment integrity."""
def test_create_profile_and_retrieve(self, api_client: APIClient) -> None:
"""Test creating a profile and retrieving it verifies database works."""
list_url = reverse("profile-list")
# Create profile
create_payload = {
"name": "Deployment Test Profile",
"team_lead": "Test Lead",
"is_active": True,
}
create_response = api_client.post(list_url, create_payload, format="json")
assert create_response.status_code == status.HTTP_201_CREATED
assert create_response.data["name"] == "Deployment Test Profile"
assert "id" in create_response.data
profile_id = create_response.data["id"]
# Retrieve profile
detail_url = reverse("profile-detail", kwargs={"pk": profile_id})
retrieve_response = api_client.get(detail_url)
assert retrieve_response.status_code == status.HTTP_200_OK
assert retrieve_response.data["id"] == profile_id
assert retrieve_response.data["name"] == "Deployment Test Profile"
assert retrieve_response.data["team_lead"] == "Test Lead"
def test_create_wallsection_with_profile(self, api_client: APIClient) -> None:
"""Test creating wallsection with profile verifies foreign keys work."""
# Create profile first
profile_url = reverse("profile-list")
profile_payload = {"name": "Wall Builder", "team_lead": "Builder Lead"}
profile_response = api_client.post(
profile_url,
profile_payload,
format="json",
)
assert profile_response.status_code == status.HTTP_201_CREATED
profile_id = profile_response.data["id"]
# Create wallsection
wallsection_url = reverse("wallsection-list")
wallsection_payload = {
"profile": profile_id,
"section_name": "Section 1",
}
wallsection_response = api_client.post(
wallsection_url,
wallsection_payload,
format="json",
)
assert wallsection_response.status_code == status.HTTP_201_CREATED
assert wallsection_response.data["profile"] == profile_id
assert wallsection_response.data["section_name"] == "Section 1"
assert "id" in wallsection_response.data
def test_list_profiles_after_creation(self, api_client: APIClient) -> None:
"""Test listing profiles returns created profiles."""
url = reverse("profile-list")
# Create multiple profiles
for i in range(3):
payload = {
"name": f"Profile {i}",
"team_lead": f"Lead {i}",
}
create_response = api_client.post(url, payload, format="json")
assert create_response.status_code == status.HTTP_201_CREATED
# List all profiles
list_response = api_client.get(url)
assert list_response.status_code == status.HTTP_200_OK
assert list_response.data["count"] == 3
assert len(list_response.data["results"]) == 3
def test_update_profile(self, api_client: APIClient) -> None:
"""Test updating a profile verifies write operations work."""
# Create profile
list_url = reverse("profile-list")
create_payload = {"name": "Original Name", "team_lead": "Original Lead"}
create_response = api_client.post(list_url, create_payload, format="json")
assert create_response.status_code == status.HTTP_201_CREATED
profile_id = create_response.data["id"]
# Update profile
detail_url = reverse("profile-detail", kwargs={"pk": profile_id})
update_payload = {
"name": "Updated Name",
"team_lead": "Updated Lead",
"is_active": False,
}
update_response = api_client.put(detail_url, update_payload, format="json")
assert update_response.status_code == status.HTTP_200_OK
assert update_response.data["name"] == "Updated Name"
assert update_response.data["team_lead"] == "Updated Lead"
assert update_response.data["is_active"] is False
def test_delete_profile(self, api_client: APIClient) -> None:
"""Test deleting a profile verifies delete operations work."""
# Create profile
list_url = reverse("profile-list")
create_payload = {"name": "To Delete", "team_lead": "Delete Lead"}
create_response = api_client.post(list_url, create_payload, format="json")
assert create_response.status_code == status.HTTP_201_CREATED
profile_id = create_response.data["id"]
# Delete profile
detail_url = reverse("profile-detail", kwargs={"pk": profile_id})
delete_response = api_client.delete(detail_url)
assert delete_response.status_code == status.HTTP_204_NO_CONTENT
# Verify deletion
retrieve_response = api_client.get(detail_url)
assert retrieve_response.status_code == status.HTTP_404_NOT_FOUND
@pytest.mark.django_db
@pytest.mark.deployment
class TestDatabaseMigrations:
"""Test that database migrations have been applied correctly."""
def test_profile_model_exists(self, api_client: APIClient) -> None:
"""Test Profile model table exists and is accessible."""
url = reverse("profile-list")
response = api_client.get(url)
assert response.status_code == status.HTTP_200_OK
def test_wallsection_model_exists(self, api_client: APIClient) -> None:
"""Test WallSection model table exists and is accessible."""
url = reverse("wallsection-list")
response = api_client.get(url)
assert response.status_code == status.HTTP_200_OK
def test_profile_fields_exist(self, api_client: APIClient) -> None:
"""Test Profile model has all required fields."""
url = reverse("profile-list")
payload = {
"name": "Field Test",
"team_lead": "Test Lead",
"is_active": True,
}
response = api_client.post(url, payload, format="json")
assert response.status_code == status.HTTP_201_CREATED
assert "id" in response.data
assert "name" in response.data
assert "team_lead" in response.data
assert "is_active" in response.data
assert "created_at" in response.data
assert "updated_at" in response.data
def test_wallsection_fields_exist(self, api_client: APIClient) -> None:
"""Test WallSection model has all required fields."""
# Create profile first
profile_url = reverse("profile-list")
profile_response = api_client.post(
profile_url,
{"name": "Test", "team_lead": "Lead"},
format="json",
)
profile_id = profile_response.data["id"]
# Create wallsection
url = reverse("wallsection-list")
payload = {
"profile": profile_id,
"section_name": "Test Section",
}
response = api_client.post(url, payload, format="json")
assert response.status_code == status.HTTP_201_CREATED
assert "id" in response.data
assert "profile" in response.data
assert "section_name" in response.data
assert "created_at" in response.data
|