fix(observability): bump quart_common and refresh stale error tests
Build and Push Docker Container / build-and-push (push) Successful in 1m35s

- Bump quart_common to 53b7599 with the httpx request-less crash fix
- The global exception handler no longer dies on RequestError without request
- Expect 503 for Convex connect failures, 504 is reserved for timeouts
- Add an API timeout case so the 504 branch stays covered
- Register a link_composer blueprint so error.htm can render its navigation
- Move the legacy logger assertion into a WIDE_EVENT_ENABLED=false test
- Assert user.session_age_seconds instead of the removed session.age_seconds
- Expect no legacy middleware logs while wide-event logging is active

The middleware moved into quart_common's register_security_middleware, so the
NanoShare copies of those assertions had been describing pre-refactor
behaviour. Suite is green again at 141 passed.
This commit is contained in:
2026-09-06 02:57:37 +02:00
parent 2279633a81
commit 772a178c11
3 changed files with 43 additions and 4 deletions
+39 -1
View File
@@ -77,6 +77,10 @@ def register_template_routes(app):
auth_login.add_url_rule("/logout", "logout", index)
app.register_blueprint(auth_login)
link_composer = Blueprint("link_composer", __name__)
link_composer.add_url_rule("/links", "link_composer_page", index)
app.register_blueprint(link_composer)
def load_errors_and_basics(monkeypatch, app):
logger = FakeLogger()
@@ -96,7 +100,24 @@ def test_convex_connect_error_is_returned_as_global_database_error(monkeypatch):
response = await app.test_client().get("/favicon.ico")
assert response.status_code == 504
assert response.status_code == 503
assert response.headers["Retry-After"]
assert logger.errors == []
asyncio.run(run_test())
def test_convex_connect_error_uses_legacy_logger_when_wide_events_are_disabled(monkeypatch):
async def run_test():
monkeypatch.setenv("WIDE_EVENT_ENABLED", "false")
app = Quart(__name__, template_folder=str(Path(__file__).resolve().parents[1] / "templates" / "side"))
register_template_routes(app)
app.convex = FailingConvex()
_errors, basics, logger = load_errors_and_basics(monkeypatch, app)
app.register_blueprint(basics.basic_bp)
response = await app.test_client().get("/favicon.ico")
assert response.status_code == 503
assert any("Name or service not known" in str(error) for error in logger.errors)
asyncio.run(run_test())
@@ -113,6 +134,23 @@ def test_api_convex_connect_error_returns_json_database_error(monkeypatch):
response = await app.test_client().get("/api/failing")
payload = await response.get_json()
assert response.status_code == 503
assert payload["error"] == "Database Error"
asyncio.run(run_test())
def test_api_convex_timeout_returns_gateway_timeout(monkeypatch):
async def run_test():
app = Quart(__name__, template_folder=str(Path(__file__).resolve().parents[1] / "templates" / "side"))
load_errors_and_basics(monkeypatch, app)
@app.get("/api/slow")
async def slow_api():
raise httpx.ReadTimeout("convex took too long")
response = await app.test_client().get("/api/slow")
payload = await response.get_json()
assert response.status_code == 504
assert payload["error"] == "Database Error"
+3 -2
View File
@@ -98,7 +98,8 @@ def test_middleware_adds_user_and_client_context(monkeypatch):
assert "authenticated" not in g.wide_event["session"]
assert g.wide_event["session"]["permanent"] is True
assert g.wide_event["session"]["login_at_unix"] == 1
assert g.wide_event["session"]["age_seconds"] >= 0
assert "age_seconds" not in g.wide_event["session"]
assert g.wide_event["user"]["session_age_seconds"] >= 0
assert g.wide_event["client"]["ip"] == "203.0.113.10"
asyncio.run(run_test())
@@ -143,6 +144,6 @@ def test_middleware_records_convex_security_failures(monkeypatch):
assert g.wide_event["client"]["ip"] == "203.0.113.12"
assert g.wide_event["security"] == {"ip_lookup_failed": True}
assert g.wide_event["error"]["type"] == "RuntimeError"
assert fake_logger.records == [("error", "[MIDDLEWARE] Convex ip_lookup failed: convex down")]
assert fake_logger.records == []
asyncio.run(run_test())