"""API foundation flow — Experience Phase 11.0.""" from __future__ import annotations import pytest from app.events.publisher import get_event_publisher from app.events.types import ExperienceEventType from app.tests.conftest import TENANT_A, TENANT_B, tenant_headers @pytest.mark.asyncio async def test_health(client): resp = await client.get("/health") assert resp.status_code == 200 body = resp.json() assert body["service"] == "experience-service" assert body["status"] == "ok" assert body["version"] == "0.11.10.0" @pytest.mark.asyncio async def test_capabilities_and_metrics(client): caps = await client.get("/capabilities") assert caps.status_code == 200 body = caps.json() assert body["phase"] == "11.10" assert body["features"]["widgets"] is True assert body["features"]["consumer_connectors"] is True assert body["features"]["analytics"] is True assert body["features"]["ai_content"] is True assert body["commercial_product"] == "Torbat Pages" assert body["features"]["foundation"] is True assert body["features"]["sites"] is True assert body["features"]["components"] is True assert body["features"]["themes"] is True assert body["features"]["layouts"] is True assert body["features"]["page_builder"] is False assert body["features"]["templates"] is True assert body["features"]["template_versions"] is True assert body["features"]["template_instantiation"] is True assert body["features"]["site_locale_bindings"] is True assert body["features"]["localizations"] is True assert body["features"]["media_refs"] is True assert body["features"]["forms"] is True assert body["features"]["surveys"] is True assert body["features"]["appointment_pages"] is True assert body["features"]["seo_engine"] is True assert body["independence"]["integration_mode"] == "api_and_events_only" metrics = await client.get("/metrics") assert metrics.status_code == 200 assert metrics.json()["metrics"]["sites"] == "tenant_scoped" assert metrics.json()["metrics"]["components"] == "tenant_scoped" assert metrics.json()["metrics"]["themes"] == "tenant_scoped" assert metrics.json()["metrics"]["layouts"] == "tenant_scoped" assert metrics.json()["metrics"]["media_refs"] == "tenant_scoped" assert metrics.json()["metrics"]["forms"] == "tenant_scoped" assert metrics.json()["phase"] == "11.10" @pytest.mark.asyncio async def test_foundation_flow_and_events(client): ws = await client.post( "/api/v1/workspaces", json={"code": "main", "name": "Main Workspace", "status": "active"}, headers=tenant_headers(TENANT_A), ) assert ws.status_code == 201, ws.text workspace_id = ws.json()["id"] assert ws.json()["code"] == "main" locale = await client.post( "/api/v1/locale-profiles", json={ "workspace_id": workspace_id, "code": "fa", "name": "Persian", "language": "fa", "text_direction": "rtl", }, headers=tenant_headers(TENANT_A), ) assert locale.status_code == 201, locale.text assert locale.json()["text_direction"] == "rtl" provider = await client.post( "/api/v1/external-providers", json={ "workspace_id": workspace_id, "code": "cdn1", "name": "CDN", "provider_kind": "cdn", "adapter_key": "cdn.generic", }, headers=tenant_headers(TENANT_A), ) assert provider.status_code == 201, provider.text engine = await client.post( "/api/v1/render-engines", json={ "workspace_id": workspace_id, "code": "ssg", "name": "SSG Ready", "adapter_key": "render.ssg", }, headers=tenant_headers(TENANT_A), ) assert engine.status_code == 201, engine.text cfg = await client.post( "/api/v1/configurations", json={ "workspace_id": workspace_id, "code": "default", "timezone": "Asia/Tehran", "language": "fa", }, headers=tenant_headers(TENANT_A), ) assert cfg.status_code == 201, cfg.text setting = await client.put( "/api/v1/settings", json={"workspace_id": workspace_id, "key": "default_locale", "value": {"code": "fa"}}, headers=tenant_headers(TENANT_A), ) assert setting.status_code == 200, setting.text events = get_event_publisher().published types = {e.event_type for e in events} assert ExperienceEventType.WORKSPACE_CREATED.value in types assert ExperienceEventType.LOCALE_PROFILE_CREATED.value in types assert ExperienceEventType.RENDER_ENGINE_REGISTERED.value in types @pytest.mark.asyncio async def test_tenant_isolation(client): created = await client.post( "/api/v1/workspaces", json={"code": "iso", "name": "Iso"}, headers=tenant_headers(TENANT_A), ) assert created.status_code == 201 workspace_id = created.json()["id"] other = await client.get( f"/api/v1/workspaces/{workspace_id}", headers=tenant_headers(TENANT_B), ) assert other.status_code == 404 missing = await client.get("/api/v1/workspaces") assert missing.status_code in (400, 422)