"""Stack integration verification tests. These tests verify that all configuration files needed for 'docker compose up' are present, consistent, and well-formed. They do NOT start actual containers. """ import os from pathlib import Path import pytest ROOT = Path(__file__).resolve().parents[2] # repo root class TestDockerComposeConfig: """Verify docker-compose.yml references are satisfied.""" def test_docker_compose_exists(self): assert (ROOT / "docker-compose.yml").is_file() def test_dockerfile_exists(self): assert (ROOT / "docker" / "Dockerfile").is_file() def test_nginx_conf_exists(self): assert (ROOT / "docker" / "nginx.conf").is_file() def test_entrypoint_exists(self): assert (ROOT / "docker" / "entrypoint.sh").is_file() def test_requirements_txt_exists(self): assert (ROOT / "backend" / "requirements.txt").is_file() def test_alembic_ini_exists(self): assert (ROOT / "alembic.ini").is_file() def test_alembic_env_exists(self): assert (ROOT / "alembic" / "env.py").is_file() def test_alembic_has_migration(self): versions = list((ROOT / "alembic" / "versions").glob("*.py")) assert len(versions) >= 1, "Expected at least one Alembic migration" class TestDockerfileConsistency: """Verify Dockerfile references match actual files.""" def test_dockerfile_copies_backend(self): content = (ROOT / "docker" / "Dockerfile").read_text() assert "COPY backend/" in content def test_dockerfile_copies_alembic(self): content = (ROOT / "docker" / "Dockerfile").read_text() assert "COPY alembic/" in content assert "COPY alembic.ini" in content def test_dockerfile_copies_entrypoint(self): content = (ROOT / "docker" / "Dockerfile").read_text() assert "entrypoint.sh" in content def test_dockerfile_runs_migrations_via_entrypoint(self): content = (ROOT / "docker" / "entrypoint.sh").read_text() assert "alembic upgrade head" in content class TestNginxConfig: """Verify nginx proxies correctly.""" def test_nginx_proxies_api(self): content = (ROOT / "docker" / "nginx.conf").read_text() assert "proxy_pass http://promptlooper-api:8000" in content def test_nginx_proxies_websocket(self): content = (ROOT / "docker" / "nginx.conf").read_text() assert "upgrade" in content.lower() def test_nginx_serves_spa_fallback(self): content = (ROOT / "docker" / "nginx.conf").read_text() assert "try_files" in content assert "/index.html" in content class TestFrontendBuildability: """Verify frontend has all files needed for a build.""" def test_package_json_exists(self): assert (ROOT / "frontend" / "package.json").is_file() def test_index_html_exists(self): assert (ROOT / "frontend" / "index.html").is_file() def test_main_tsx_exists(self): assert (ROOT / "frontend" / "src" / "main.tsx").is_file() def test_app_tsx_exists(self): assert (ROOT / "frontend" / "src" / "App.tsx").is_file() def test_all_page_components_exist(self): pages = [ "SetupPage", "LoginPage", "DashboardPage", "ProjectsPage", "ExperimentPage", "LivePage", "ComparePage", "AdminPage", ] for page in pages: assert (ROOT / "frontend" / "src" / "pages" / f"{page}.tsx").is_file(), f"Missing {page}.tsx" def test_vite_config_exists(self): assert (ROOT / "frontend" / "vite.config.ts").is_file() def test_tailwind_config_exists(self): assert (ROOT / "frontend" / "tailwind.config.js").is_file() class TestWorkerConfig: """Verify Celery worker module exists and is importable.""" def test_worker_module_exists(self): assert (ROOT / "backend" / "worker.py").is_file() class TestHealthEndpoint: """Verify /health endpoint works in test mode.""" def test_health_returns_ok(self): from fastapi.testclient import TestClient # Ensure backend is importable import sys backend_dir = str(ROOT / "backend") if backend_dir not in sys.path: sys.path.insert(0, backend_dir) from main import app client = TestClient(app) resp = client.get("/health") assert resp.status_code == 200 data = resp.json() assert data["status"] in ("ok", "degraded") assert "database" in data assert "redis" in data