Skip to content

Commit b7347b4

Browse files
committed
test: pin projects-card shape + fix docstring route (review on PR #26)
- Docstring listed GET /api/projects but the leak was on GET /api/projects/<project>/sessions; corrected so the next reader doesn't grep the wrong route. - test_per_session_error_card_omits_error_detail was passing without exercising anything: parse_session is tolerant of malformed lines, so the malformed-jsonl input never triggered the except branch and the conditional `if/for` walked an empty list. Switched to monkeypatching parse_session to raise (mirrors the session-level tests above) and pinned the response shape — assert status == 200 and body is a list, assert at least one error card exists, and verify the leaked field name doesn't appear in the body.
1 parent 0d52875 commit b7347b4

1 file changed

Lines changed: 30 additions & 16 deletions

File tree

tests/test_error_propagation.py

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
88
- GET /api/sessions/<project>/<id> (api/sessions.py)
99
- GET /api/sessions/<project>/<id>/stats (api/sessions.py)
10-
- GET /api/projects (per-session card error_detail)
10+
- GET /api/projects/<project>/sessions (api/projects.py — per-session card error_detail)
1111
1212
This file exercises each via Flask test_client with a payload that triggers
1313
the failure path, asserts a 500 (or 200 for projects, since the per-session
@@ -168,24 +168,38 @@ def _boom(*args, **kwargs):
168168

169169
class TestGetProjectsErrorCard:
170170

171-
def test_per_session_error_card_omits_error_detail(self, tmp_path, client):
172-
# One project with one unparseable session file → the per-session
173-
# card should have error: True but no error_detail string.
174-
_write_session(tmp_path, "myproj", "deadbeef-aaaa-bbbb-cccc-000000000000", "totally not jsonl\n")
171+
def test_per_session_error_card_omits_error_detail(self, tmp_path, client, monkeypatch):
172+
# parse_session is tolerant of malformed lines, so to exercise the
173+
# except branch deterministically (the one that builds the error
174+
# card), monkeypatch it to raise — same pattern as the session-level
175+
# tests above.
176+
_write_session(tmp_path, "myproj", "deadbeef-aaaa-bbbb-cccc-000000000000", "{}")
177+
178+
def _boom(*args, **kwargs):
179+
raise KeyError("internal_secret_field_id")
180+
181+
# api/projects.py imports parse_session inside the handler body,
182+
# so patch the source module rather than the consumer.
183+
monkeypatch.setattr("utils.jsonl_parser.parse_session", _boom)
175184

176185
resp = client.get("/api/projects/myproj/sessions")
177-
# Response shape varies — accept 200 with a list, 200 with a dict,
178-
# or any error code as long as it doesn't leak class names.
186+
# Pin the response shape so a future wrapper change (e.g. {"sessions": [...]})
187+
# doesn't silently turn this test green by skipping the per-row scan.
188+
assert resp.status_code == 200
179189
body = resp.get_json()
180-
body_text = json.dumps(body) if body is not None else ""
181-
_assert_no_class_name_leak(body_text)
182-
# If there's a per-row error, error_detail must NOT be present
183-
if isinstance(body, list):
184-
for row in body:
185-
if isinstance(row, dict) and row.get("error"):
186-
assert "error_detail" not in row, (
187-
"Per-session error card still includes error_detail (issue #25)"
188-
)
190+
assert isinstance(body, list), (
191+
f"Expected JSON array of session cards; got {type(body).__name__}"
192+
)
193+
_assert_no_class_name_leak(json.dumps(body))
194+
error_rows = [r for r in body if isinstance(r, dict) and r.get("error")]
195+
assert error_rows, "Expected at least one per-session error card from the forced parse failure"
196+
for row in error_rows:
197+
assert "error_detail" not in row, (
198+
"Per-session error card still includes error_detail (issue #25)"
199+
)
200+
# The exception's args include "internal_secret_field_id" — must not
201+
# appear anywhere in the response.
202+
assert "internal_secret_field_id" not in json.dumps(body)
189203

190204

191205
# ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)