134 lines
4.1 KiB
Python
134 lines
4.1 KiB
Python
|
|
"""Tests for T01 — REST service foundation (FR-900 core)."""
|
||
|
|
|
||
|
|
from __future__ import annotations
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
from fastapi.testclient import TestClient
|
||
|
|
|
||
|
|
from markidocx import __version__
|
||
|
|
from markidocx.manifest import SUPPORTED_FAMILIES, FeatureLevel
|
||
|
|
from markidocx.rest import create_app
|
||
|
|
|
||
|
|
|
||
|
|
@pytest.fixture()
|
||
|
|
def client() -> TestClient:
|
||
|
|
return TestClient(create_app())
|
||
|
|
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# GET /health (FR-910)
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
|
||
|
|
def test_health_returns_200(client: TestClient) -> None:
|
||
|
|
resp = client.get("/health")
|
||
|
|
assert resp.status_code == 200
|
||
|
|
|
||
|
|
|
||
|
|
def test_health_body(client: TestClient) -> None:
|
||
|
|
body = client.get("/health").json()
|
||
|
|
assert body["status"] == "ok"
|
||
|
|
assert body["version"] == __version__
|
||
|
|
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# GET /version (FR-911)
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
|
||
|
|
def test_version_returns_200(client: TestClient) -> None:
|
||
|
|
assert client.get("/version").status_code == 200
|
||
|
|
|
||
|
|
|
||
|
|
def test_version_envelope(client: TestClient) -> None:
|
||
|
|
body = client.get("/version").json()
|
||
|
|
assert body["status"] == "ok"
|
||
|
|
assert body["outputs"]["version"] == __version__
|
||
|
|
assert "warnings" in body
|
||
|
|
assert "errors" in body
|
||
|
|
assert "context" in body
|
||
|
|
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# GET /capabilities (FR-909)
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
|
||
|
|
def test_capabilities_returns_200(client: TestClient) -> None:
|
||
|
|
assert client.get("/capabilities").status_code == 200
|
||
|
|
|
||
|
|
|
||
|
|
def test_capabilities_feature_levels(client: TestClient) -> None:
|
||
|
|
body = client.get("/capabilities").json()
|
||
|
|
assert body["status"] == "ok"
|
||
|
|
levels = body["outputs"]["feature_levels"]
|
||
|
|
for level in FeatureLevel:
|
||
|
|
assert level.value in levels
|
||
|
|
|
||
|
|
|
||
|
|
def test_capabilities_families(client: TestClient) -> None:
|
||
|
|
body = client.get("/capabilities").json()
|
||
|
|
families = body["outputs"]["families"]
|
||
|
|
for family in SUPPORTED_FAMILIES:
|
||
|
|
assert family in families
|
||
|
|
|
||
|
|
|
||
|
|
def test_capabilities_has_context(client: TestClient) -> None:
|
||
|
|
body = client.get("/capabilities").json()
|
||
|
|
assert "version" in body["context"]
|
||
|
|
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# GET /templates (FR-906)
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
|
||
|
|
def test_templates_returns_200(client: TestClient) -> None:
|
||
|
|
assert client.get("/templates").status_code == 200
|
||
|
|
|
||
|
|
|
||
|
|
def test_templates_lists_built_ins(client: TestClient) -> None:
|
||
|
|
body = client.get("/templates").json()
|
||
|
|
assert body["status"] == "ok"
|
||
|
|
names = {f["name"] for f in body["outputs"]}
|
||
|
|
assert "article" in names
|
||
|
|
assert "book" in names
|
||
|
|
assert "website" in names
|
||
|
|
|
||
|
|
|
||
|
|
def test_templates_envelope_shape(client: TestClient) -> None:
|
||
|
|
body = client.get("/templates").json()
|
||
|
|
assert "warnings" in body
|
||
|
|
assert "errors" in body
|
||
|
|
assert "context" in body
|
||
|
|
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# GET /styles (FR-907)
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
|
||
|
|
def test_styles_returns_200(client: TestClient) -> None:
|
||
|
|
assert client.get("/styles").status_code == 200
|
||
|
|
|
||
|
|
|
||
|
|
def test_styles_is_list(client: TestClient) -> None:
|
||
|
|
body = client.get("/styles").json()
|
||
|
|
assert body["status"] == "ok"
|
||
|
|
assert isinstance(body["outputs"], list)
|
||
|
|
|
||
|
|
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
# Response envelope shape (FR-912)
|
||
|
|
# ---------------------------------------------------------------------------
|
||
|
|
|
||
|
|
|
||
|
|
@pytest.mark.parametrize("endpoint", ["/version", "/capabilities", "/templates", "/styles"])
|
||
|
|
def test_envelope_fields_present(client: TestClient, endpoint: str) -> None:
|
||
|
|
body = client.get(endpoint).json()
|
||
|
|
assert "status" in body
|
||
|
|
assert "outputs" in body
|
||
|
|
assert "warnings" in body
|
||
|
|
assert "errors" in body
|
||
|
|
assert "context" in body
|