Files
cc-ci/tests/ghost/custom/test_content_api.py
notplantsandClaude Fable 5.1 9a80002b37
continuous-integration/drone/push Build is failing
lint: ruff format + one auto-fix so the push self-test is green again
`scripts/lint.sh --fix` from the pinned lint devshell: 90 Python files
reformatted (ruff format, mechanical) and one C420 (dict comprehension →
dict.fromkeys) in tests/unit/test_f211_sso_skip.py. The push self-test had
been failing at the lint stage since build 1313 (2026-08-31) on exactly
these files; nothing else changed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FqkQq3CDmFWcQ7u1LzoyRz
2026-09-07 21:15:05 +00:00

45 lines
1.9 KiB
Python

"""ghost — recipe-specific functional test (Phase 2 P3).
Ghost exposes a public JSON Content API at `/ghost/api/content/settings/` which returns the
site's public configuration (title, description, etc.) WITHOUT requiring an API key for the
basic settings endpoint. Some Ghost versions DO require a key here — accept either:
- 200 with JSON envelope: API alive + accessible.
- 401/403 with JSON error: API alive + correctly gating.
Distinguishes "ghost-server JS process is up + serving its API" from "a static page is served
at /" (which the parity test catches by 200).
A wedged Ghost backend returns 502/504 or 503. A misrouted nginx returns 404.
"""
from __future__ import annotations
import os
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..", "..", "runner"))
from harness import http as harness_http # noqa: E402
def test_content_api_settings_endpoint(live_app):
"""GET /ghost/api/content/settings/ → 200 or 401/403; JSON shape."""
url = f"https://{live_app}/ghost/api/content/settings/"
status, body = harness_http.retry_http_get(
url, expect_status=(200, 400, 401, 403), max_wait=60, interval=3
)
assert status in (200, 400, 401, 403), (
f"GET {url} HTTP {status} (expected 200/401/403, NOT 404/5xx — 404=route missing, "
f"5xx=backend broken)"
)
# The API ALWAYS returns JSON (success or error envelope).
assert body is not None, f"GET {url} returned non-JSON body"
# On success: {"settings": {...}}. On error: {"errors": [...]}. Either shape is valid.
if status == 200:
assert isinstance(body, dict) and "settings" in body, (
f"200 response missing 'settings' envelope: {body!r}"
)
else:
assert isinstance(body, dict) and ("errors" in body or "message" in body or body), (
f"error response not a proper Ghost error envelope: {body!r}"
)