wall-demo / tests /api /test_deployment.py
AIVLAD's picture
fix: add database migrations at container startup and deployment tests
5422df1
Raw History Blame Contribute Delete
9.27 kB
"""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