mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-31 06:51:29 +00:00
test(kanban-dashboard): pin enriched 409 detail and inline error wiring (#26744)
- Existing ``test_patch_drag_drop_move_todo_to_ready`` now asserts the enriched 409 detail names the blocking parent (id, quoted title, and current status), so the dashboard always has something actionable to render. - New bundle-assertion test ``test_dashboard_surfaces_ready_blocked_error_inline`` pins the frontend wiring: the ``parseApiErrorMessage`` helper exists, the drag/drop banner runs through it, and the drawer maintains a visible ``patchErr`` state that's cleared between PATCHes and tasks.
This commit is contained in:
parent
9d9f3161ae
commit
e215558ba7
1 changed files with 40 additions and 0 deletions
|
|
@ -341,6 +341,18 @@ def test_patch_drag_drop_move_todo_to_ready(client):
|
||||||
)
|
)
|
||||||
assert r.status_code == 409
|
assert r.status_code == 409
|
||||||
|
|
||||||
|
# The 409 detail must name the blocking parent so the dashboard can
|
||||||
|
# render an actionable toast instead of a silent no-op (#26744).
|
||||||
|
detail = r.json()["detail"]
|
||||||
|
assert "Cannot move to 'ready'" in detail
|
||||||
|
assert parent["id"] in detail
|
||||||
|
assert "'p'" in detail
|
||||||
|
assert "status=" in detail
|
||||||
|
# Whatever non-``done`` status the parent currently has must show up
|
||||||
|
# so the operator knows what to fix.
|
||||||
|
assert f"status={parent['status']}" in detail
|
||||||
|
assert parent["status"] != "done"
|
||||||
|
|
||||||
# Complete the parent.
|
# Complete the parent.
|
||||||
r = client.patch(
|
r = client.patch(
|
||||||
f"/api/plugins/kanban/tasks/{parent['id']}",
|
f"/api/plugins/kanban/tasks/{parent['id']}",
|
||||||
|
|
@ -918,6 +930,34 @@ def test_dashboard_done_actions_prompt_for_completion_summary():
|
||||||
assert "body: JSON.stringify(finalPatch)" in bundle
|
assert "body: JSON.stringify(finalPatch)" in bundle
|
||||||
|
|
||||||
|
|
||||||
|
def test_dashboard_surfaces_ready_blocked_error_inline():
|
||||||
|
"""Regression for #26744: failed status transitions must be surfaced
|
||||||
|
inline, not swallowed. The drag/drop banner and the drawer's action
|
||||||
|
row each render the parsed API ``detail`` so operators see *why*
|
||||||
|
their click did nothing.
|
||||||
|
"""
|
||||||
|
repo_root = Path(__file__).resolve().parents[2]
|
||||||
|
bundle = (
|
||||||
|
repo_root / "plugins" / "kanban" / "dashboard" / "dist" / "index.js"
|
||||||
|
).read_text()
|
||||||
|
|
||||||
|
# Helper that strips ``"409: {\"detail\":\"…\"}"`` down to the
|
||||||
|
# human-readable message before it lands in any banner.
|
||||||
|
assert "function parseApiErrorMessage(err)" in bundle
|
||||||
|
assert "parsed.detail" in bundle
|
||||||
|
|
||||||
|
# Drag/drop banner now uses the parsed message instead of raw
|
||||||
|
# ``err.message`` so it no longer leaks HTTP plumbing.
|
||||||
|
assert "setError(tx(t, \"moveFailed\", \"Move failed: \") + parseApiErrorMessage(err))" in bundle
|
||||||
|
|
||||||
|
# Drawer action row has its own visible error surface and clears it
|
||||||
|
# on success/refresh so stale failures don't follow the operator
|
||||||
|
# around.
|
||||||
|
assert "const [patchErr, setPatchErr] = useState(null);" in bundle
|
||||||
|
assert "setPatchErr(parseApiErrorMessage(e))" in bundle
|
||||||
|
assert "setPatchErr(null)" in bundle
|
||||||
|
|
||||||
|
|
||||||
def test_dashboard_dependency_selects_use_value_change_handler():
|
def test_dashboard_dependency_selects_use_value_change_handler():
|
||||||
"""Regression for the dependency selects in the task drawer: the
|
"""Regression for the dependency selects in the task drawer: the
|
||||||
add-parent / add-child dropdowns must wire through the shared
|
add-parent / add-child dropdowns must wire through the shared
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue