From b6843175543aa43eb9933ae7f06bf6d7ae1d31dd Mon Sep 17 00:00:00 2001 From: Frank Song Date: Fri, 8 May 2026 11:34:12 +0800 Subject: [PATCH] test: parametrize kanban double-404 guard across HTTP methods --- tests/test_issue1823_kanban_not_found.py | 31 +++++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/tests/test_issue1823_kanban_not_found.py b/tests/test_issue1823_kanban_not_found.py index d9fdd3e2..211953a8 100644 --- a/tests/test_issue1823_kanban_not_found.py +++ b/tests/test_issue1823_kanban_not_found.py @@ -4,6 +4,7 @@ from __future__ import annotations import io import json +import pytest from types import SimpleNamespace from urllib.parse import urlparse @@ -20,6 +21,7 @@ class _FakeHandler: self.headers = {} self.response_headers = [] self.wfile = io.BytesIO() + self.rfile = io.BytesIO() def send_response(self, status): self.status = status @@ -67,7 +69,18 @@ def test_kanban_stale_client_error_renders_hard_refresh_escape_hatch(): assert "window.location.reload()" in PANELS -def test_inner_handler_bad_response_does_not_emit_double_404(monkeypatch): +@pytest.mark.parametrize( + ("method", "path", "payload_attr", "payload_error"), + [ + ("GET", "/api/kanban/tasks/abc/log", "_task_log_payload", "task not found"), + ("POST", "/api/kanban/boards", "_create_board_payload", "invalid board payload"), + ("PATCH", "/api/kanban/boards/abc", "_update_board_payload", "invalid patch payload"), + ("DELETE", "/api/kanban/links", "_link_tasks_payload", "invalid delete payload"), + ], +) +def test_inner_handler_bad_response_does_not_emit_double_404( + method, path, payload_attr, payload_error, monkeypatch +): """Regression: when the kanban bridge already sent a response via bad() (returns None), the unknown-endpoint wrapper must not concatenate a second 404 body on the wire. Only an explicit `False` from the bridge means the @@ -75,12 +88,18 @@ def test_inner_handler_bad_response_does_not_emit_double_404(monkeypatch): """ from api import kanban_bridge - # Force the task-log payload helper to report "not found" so the bridge - # calls bad() and returns None. - monkeypatch.setattr(kanban_bridge, "_task_log_payload", lambda *a, **kw: None) + # Force one kanban payload helper to hit bad() and return None, so the + # wrapper path should not append _kanban_unknown_endpoint. + monkeypatch.setattr( + kanban_bridge, payload_attr, lambda *a, **kw: (_ for _ in ()).throw(LookupError(payload_error)) + ) handler = _FakeHandler() - handled = routes.handle_get(handler, urlparse("/api/kanban/tasks/abc/log")) + handler_fn = getattr(routes, f"handle_{method.lower()}") + if method == "GET": + handled = handler_fn(handler, urlparse(path)) + else: + handled = handler_fn(handler, urlparse(path)) assert handled is True assert handler.status == 404 @@ -89,7 +108,7 @@ def test_inner_handler_bad_response_does_not_emit_double_404(monkeypatch): # objects would produce something like `}{` between them. assert body.count("}{") == 0, f"double response detected: {body!r}" payload = json.loads(body) - assert payload["error"] == "task not found" + assert payload["error"] == payload_error def test_kanban_load_resolves_board_before_board_scoped_requests():