Skip to content

Commit 382c262

Browse files
etoyamaclaude
andcommitted
fix: add handler priority comment and corrupt list REST test from team-review
- Add NOTE comment on ValidationError/ValueError handler priority in web.py - Add test_list_designs_with_corrupt_returns_valid_only to test_web.py (707 tests) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 8f156f6 commit 382c262

2 files changed

Lines changed: 45 additions & 1 deletion

File tree

src/insight_blueprint/web.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,13 @@ async def value_error_handler(request: Request, exc: ValueError) -> JSONResponse
6262
async def validation_error_handler(
6363
request: Request, exc: ValidationError
6464
) -> JSONResponse:
65-
"""Convert Pydantic ValidationError to 422 for corrupt design files."""
65+
"""Convert Pydantic ValidationError to 422 for corrupt design files.
66+
67+
NOTE: ValidationError is a subclass of ValueError. FastAPI matches the
68+
most specific handler first, so this 422 handler takes priority over the
69+
ValueError 400 handler above. If FastAPI's resolution order ever changes,
70+
the test ``test_get_design_corrupt_returns_422`` will catch the regression.
71+
"""
6672
return JSONResponse(
6773
status_code=422,
6874
content={

tests/test_web.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,3 +1145,41 @@ def test_get_design_corrupt_returns_422(client: TestClient, tmp_path: Path) -> N
11451145
data = resp.json()
11461146
assert "error" in data
11471147
assert "validation error" in data["error"].lower()
1148+
1149+
1150+
def test_list_designs_with_corrupt_returns_valid_only(
1151+
client: TestClient, tmp_path: Path
1152+
) -> None:
1153+
"""GET /api/designs with a corrupt file returns only valid designs."""
1154+
from insight_blueprint.storage.yaml_store import write_yaml
1155+
1156+
# Create 2 valid designs via API
1157+
_create_design(client)
1158+
_create_design(client, title="Second Design")
1159+
1160+
# Write 1 corrupt YAML directly
1161+
corrupt_path = tmp_path / ".insight" / "designs" / "CORRUPT-H01_hypothesis.yaml"
1162+
write_yaml(
1163+
corrupt_path,
1164+
{
1165+
"id": "CORRUPT-H01",
1166+
"theme_id": "CORRUPT",
1167+
"title": "Corrupt",
1168+
"hypothesis_statement": "stmt",
1169+
"hypothesis_background": "bg",
1170+
"status": "BOGUS",
1171+
"metrics": [],
1172+
"explanatory": [],
1173+
"chart": [],
1174+
"source_ids": [],
1175+
"created_at": "2025-01-01T00:00:00+09:00",
1176+
"updated_at": "2025-01-01T00:00:00+09:00",
1177+
},
1178+
)
1179+
1180+
resp = client.get("/api/designs")
1181+
assert resp.status_code == 200
1182+
designs = resp.json()["designs"]
1183+
assert len(designs) == 2
1184+
design_ids = [d["id"] for d in designs]
1185+
assert "CORRUPT-H01" not in design_ids

0 commit comments

Comments
 (0)