Re-verified staged increment from a clean requirements.lock.txt venv: - 330 backend tests pass (17/17 in new error_handlers + json_import tests) - compileall + frontend npm build clean - git diff --check clean; no secrets in diff - importer CLI dry-run bootstrap works Includes JSON HTTPException handler under /api/* and parse-safe static 404 via abort. JSON stores remain runtime-authoritative; production operation still gated behind operator approval.
39 lines
1.3 KiB
Python
39 lines
1.3 KiB
Python
"""HTTP error handlers preserve Werkzeug status semantics."""
|
|
from __future__ import annotations
|
|
|
|
from werkzeug.exceptions import MethodNotAllowed, NotFound
|
|
from werkzeug.wrappers import Response
|
|
|
|
from app.api.helpers import unhandled_error_handler
|
|
|
|
|
|
def test_http_exceptions_keep_status_codes(client):
|
|
missing = client.get("/api/route-that-does-not-exist")
|
|
api_root = client.get("/api")
|
|
|
|
assert missing.status_code == 404
|
|
assert missing.is_json
|
|
assert isinstance(missing.get_json()["error"], str)
|
|
assert api_root.status_code == 404
|
|
assert api_root.is_json
|
|
assert isinstance(api_root.get_json()["error"], str)
|
|
|
|
|
|
def test_api_http_exception_keeps_json_body_and_headers(app):
|
|
with app.test_request_context("/api/example", method="POST"):
|
|
response = unhandled_error_handler(MethodNotAllowed(valid_methods=["GET"]))
|
|
|
|
assert isinstance(response, Response)
|
|
assert response.status_code == 405
|
|
assert response.is_json
|
|
assert response.get_json()["error"]
|
|
assert response.headers["Allow"] == "GET"
|
|
|
|
|
|
def test_unhandled_handler_preserves_werkzeug_http_exception(app):
|
|
with app.app_context():
|
|
response = unhandled_error_handler(NotFound())
|
|
|
|
assert isinstance(response, Response)
|
|
assert response.status_code == 404
|