generated from coulomb/repo-seed
Add activity-core scope context API
This commit is contained in:
162
tests/test_scope_context_api.py
Normal file
162
tests/test_scope_context_api.py
Normal file
@@ -0,0 +1,162 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from repo_registry.web_api.app import Settings, app, get_settings
|
||||
|
||||
|
||||
def override_settings(tmp_path):
|
||||
def _override():
|
||||
return Settings(
|
||||
database_path=str(tmp_path / "scope-context.sqlite3"),
|
||||
checkout_root=str(tmp_path / "checkouts"),
|
||||
state_hub_base_url="",
|
||||
)
|
||||
|
||||
return _override
|
||||
|
||||
|
||||
def test_scope_context_endpoint_returns_activity_core_contract(tmp_path):
|
||||
scoped_source = tmp_path / "scoped-repo"
|
||||
scoped_source.mkdir()
|
||||
(scoped_source / "SCOPE.md").write_text(
|
||||
"# SCOPE\n\n"
|
||||
"> Generated context note.\n\n"
|
||||
"---\n\n"
|
||||
"## One-liner\n\n"
|
||||
"Maps repositories into concise operating context.\n\n"
|
||||
"## Notes\n\n"
|
||||
"Further details stay out of the summary.\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
plain_source = tmp_path / "plain-repo"
|
||||
plain_source.mkdir()
|
||||
|
||||
app.dependency_overrides[get_settings] = override_settings(tmp_path)
|
||||
client = TestClient(app)
|
||||
try:
|
||||
scoped = client.post(
|
||||
"/repos",
|
||||
json={
|
||||
"name": "Scoped Repo",
|
||||
"url": str(scoped_source),
|
||||
"description": "Registry fallback for scoped repo.",
|
||||
},
|
||||
).json()
|
||||
ability_id = client.post(
|
||||
f"/repos/{scoped['id']}/abilities",
|
||||
json={
|
||||
"name": "Context Publishing",
|
||||
"description": "Expose repository context to callers.",
|
||||
},
|
||||
).json()["id"]
|
||||
client.post(
|
||||
f"/repos/{scoped['id']}/capabilities",
|
||||
json={
|
||||
"ability_id": ability_id,
|
||||
"name": "Generate SCOPE.md",
|
||||
"description": "Render repository scope from approved entries.",
|
||||
},
|
||||
)
|
||||
|
||||
client.post(
|
||||
"/repos",
|
||||
json={
|
||||
"name": "Plain Repo",
|
||||
"url": str(plain_source),
|
||||
"description": "Plain repository metadata summary.",
|
||||
},
|
||||
)
|
||||
client.post(
|
||||
"/repos",
|
||||
json={
|
||||
"name": "Remote Repo",
|
||||
"url": "https://example.test/remote-repo.git",
|
||||
"description": "Remote repository metadata summary.",
|
||||
},
|
||||
)
|
||||
|
||||
scoped_context = client.get("/repos/scoped-repo/scope/context")
|
||||
assert scoped_context.status_code == 200
|
||||
assert scoped_context.json() == {
|
||||
"repo_slug": "scoped-repo",
|
||||
"capabilities": ["Generate SCOPE.md"],
|
||||
"tags": ["ability", "capability"],
|
||||
"scope_md_exists": True,
|
||||
"scope_summary": "Maps repositories into concise operating context.",
|
||||
}
|
||||
|
||||
plain_context = client.get("/repos/plain-repo/scope/context")
|
||||
assert plain_context.status_code == 200
|
||||
assert plain_context.json() == {
|
||||
"repo_slug": "plain-repo",
|
||||
"capabilities": [],
|
||||
"tags": [],
|
||||
"scope_md_exists": False,
|
||||
"scope_summary": "Plain repository metadata summary.",
|
||||
}
|
||||
|
||||
remote_context = client.get("/repos/remote-repo/scope/context")
|
||||
assert remote_context.status_code == 200
|
||||
assert remote_context.json() == {
|
||||
"repo_slug": "remote-repo",
|
||||
"capabilities": [],
|
||||
"tags": [],
|
||||
"scope_md_exists": False,
|
||||
"scope_summary": "Remote repository metadata summary.",
|
||||
}
|
||||
|
||||
missing_context = client.get("/repos/missing-repo/scope/context")
|
||||
assert missing_context.status_code == 404
|
||||
assert missing_context.json()["detail"]
|
||||
|
||||
markdown_scope = client.get("/repos/scoped-repo/scope")
|
||||
assert markdown_scope.status_code == 200
|
||||
assert markdown_scope.headers["content-type"].startswith("text/markdown")
|
||||
assert "# SCOPE" in markdown_scope.text
|
||||
finally:
|
||||
app.dependency_overrides.clear()
|
||||
|
||||
|
||||
def test_scope_context_schema_artifact_matches_contract_shape():
|
||||
schema = json.loads(
|
||||
(
|
||||
Path(__file__).parents[1]
|
||||
/ "docs"
|
||||
/ "schemas"
|
||||
/ "repo-scope-context-response.json"
|
||||
).read_text(encoding="utf-8")
|
||||
)
|
||||
|
||||
assert schema["additionalProperties"] is False
|
||||
assert schema["required"] == [
|
||||
"repo_slug",
|
||||
"capabilities",
|
||||
"tags",
|
||||
"scope_md_exists",
|
||||
"scope_summary",
|
||||
]
|
||||
assert schema["properties"]["scope_md_exists"]["type"] == "boolean"
|
||||
assert schema["properties"]["scope_summary"]["type"] == ["string", "null"]
|
||||
|
||||
|
||||
def test_scope_context_openapi_contract_is_exposed(tmp_path):
|
||||
app.dependency_overrides[get_settings] = override_settings(tmp_path)
|
||||
client = TestClient(app)
|
||||
try:
|
||||
schema = client.get("/openapi.json").json()
|
||||
finally:
|
||||
app.dependency_overrides.clear()
|
||||
|
||||
operation = schema["paths"]["/repos/{repo_slug}/scope/context"]["get"]
|
||||
assert operation["tags"] == ["scope"]
|
||||
response_schema = operation["responses"]["200"]["content"]["application/json"][
|
||||
"schema"
|
||||
]
|
||||
assert response_schema["$ref"].endswith("/RepositoryScopeContextResponse")
|
||||
assert (
|
||||
"RepositoryScopeContextResponse"
|
||||
in schema["components"]["schemas"]
|
||||
)
|
||||
Reference in New Issue
Block a user