"""A row that is gone answers with a reason the bilingual UI can translate (deep-review round 3). The 404 a user actually meets is the one for something deleted in another tab or on another device. `owned_or_404` / `get_or_404` sent it as a bare English string ("Unknown view", "Not found"), and the Hungarian UI toasted it verbatim. The structured-404 fix had gone into one ad-hoc helper instead of the shared one, so every other owner check kept the English. Needs the DB. """ def test_a_gone_view_tag_or_pin_says_what_is_gone(db, make_user, as_user): client = as_user(make_user()) for method, url, what in [ ("patch", "/api/saved-views/999999", "view"), ("delete", "/api/saved-views/999999", "view"), ("delete", "/api/tags/999999", "tag"), ("delete", "/api/discover/pins/999999", "pin"), ]: r = getattr(client, method)(url, **({"json": {"name": "x"}} if method == "patch" else {})) assert r.status_code == 404, (url, r.text) assert r.json()["detail"] == {"code": "not_found", "reason": what}, url def test_a_gone_channel_video_or_user_says_what_is_gone(db, make_user, as_user): """The siblings that still hand-wrote `db.get(...) is None → 404 "Unknown …"` (deep-review round 4): the same gone row, but the Hungarian UI showed the English.""" admin = make_user(role="admin") client = as_user(admin) for method, url, body, what in [ ("post", "/api/channels/UCgone000000000000000000/block", None, "channel"), ("post", "/api/videos/gone0000000/state", {"status": "watched"}, "video"), ( "post", "/api/videos/gone0000000/progress", {"position_seconds": 60, "duration_seconds": 600}, "video", ), ("put", "/api/admin/downloads/quota/999999", {"max_bytes": 1}, "user"), ]: r = getattr(client, method)(url, **({"json": body} if body is not None else {})) assert r.status_code == 404, (url, r.text) assert r.json()["detail"] == {"code": "not_found", "reason": what}, url def test_a_nul_in_a_request_string_is_a_422_not_a_500(db, make_user, as_user): """Postgres cannot hold NUL in text, so the driver refuses the query outright: a DataError, i.e. a 500 with a traceback, wherever a `%00` or an escaped NUL reached a comparison (deep-review round 4 — round 3 had guarded only the by-rating_key lookup). One app-wide handler now answers all of them.""" client = as_user(make_user()) r = client.get("/api/plex/playlists?contains=%00") assert r.status_code == 422, r.text assert r.json()["detail"] == {"code": "invalid_input", "reason": "nul"} assert client.get("/api/plex/playlists?contains_group=1,%00").status_code == 422