generated from coulomb/repo-seed
163 lines
5.2 KiB
Python
163 lines
5.2 KiB
Python
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"]
|
|
)
|