fix(api): a refused write is named, in the reader's language
Deep-review round 5, over round 4's own fixes.
- `notifyActionError` preferred the server's `detail` over the caller's translated fallback, and
`reportFailure` deliberately leaves 403/404/429 to the caller — so for exactly those statuses the
dozen call sites round 4 converted started printing whatever English a route hand-wrote into an
otherwise Hungarian UI ("No user with that email.", "Not subscribed to this channel", "Unknown
job"). A STRUCTURED detail is still preferred: `req` has already run it through `localizeDetail`,
so it is both localized and more specific. A plain string is not.
- The other half of the same defect, on the backend: round 4's `get_or_404(what="channel")` sweep
reached exactly ONE of the five identical sites in channels.py and shipped the HU/EN string with
it, so the Block button said it in Hungarian and the four controls beside it in English. All five
are converted, and the subscription / share-recipient / scheduler-job 404s with them (two new
reasons in both locales).
- `PlexCollectionEditor`'s add/remove, take-over and delete were try/finally with no catch — in the
very file round 4 edited to give `createNew` one. 403 and 404 are the caller's to report, so the
tick simply never appeared and a CONFIRMED "delete collection" did nothing, silently.
- `UploadDialog` is the only `uploadReq` caller and kept an empty catch whose comment still claimed
the global error modal had it. It had not since `reportFailure` became shared: a proxy 502 raised
only the self-clearing connection notice and a 413/403/404 nothing at all, so the dialog snapped
back to its pre-upload state with no error named. The user's own Cancel stays silent — and since
a cancel and a network drop both carry status 0, that difference is now a named `isAborted`
rather than a string literal at each end.
Regression tests for each (5 vitest, 2 pytest, plus two existing assertions corrected), all
mutation-checked: 6 mutations, each red on the assertion it is named after. vitest 1007,
pytest 1127.
This commit is contained in:
@@ -41,6 +41,39 @@ def test_a_gone_channel_video_or_user_says_what_is_gone(db, make_user, as_user):
|
||||
assert r.json()["detail"] == {"code": "not_found", "reason": what}, url
|
||||
|
||||
|
||||
def test_every_gone_channel_route_says_it_the_same_way(db, make_user, as_user):
|
||||
"""The round-4 sweep converted ONE of the five `db.get(Channel, …) is None -> 404 "Unknown
|
||||
channel"` sites (block), and shipped the HU/EN string with it — so the Hungarian UI said it in
|
||||
Hungarian on the Block button and in English on the four beside it (deep-review round 5). The
|
||||
asymmetric fix is the smell this repo bans, so all five are pinned together."""
|
||||
admin = make_user(role="admin")
|
||||
client = as_user(admin)
|
||||
gone = "UCgone000000000000000000"
|
||||
# Subscribe is behind the write-scope gate, so it is covered by the tags route below instead.
|
||||
for method, url in [
|
||||
("get", f"/api/channels/{gone}"),
|
||||
("post", f"/api/channels/{gone}/reset-backfill"),
|
||||
("post", f"/api/channels/{gone}/block"),
|
||||
]:
|
||||
r = getattr(client, method)(url)
|
||||
assert r.status_code == 404, (url, r.text)
|
||||
assert r.json()["detail"] == {"code": "not_found", "reason": "channel"}, url
|
||||
|
||||
|
||||
def test_a_gone_subscription_recipient_or_job_says_what_is_gone(db, make_user, as_user):
|
||||
"""The three bare-English 404s the same sweep left behind, which `notifyActionError` printed
|
||||
verbatim into an otherwise Hungarian UI: "Not subscribed to this channel", "No user with that
|
||||
email.", "Unknown job"."""
|
||||
admin = make_user(role="admin")
|
||||
client = as_user(admin)
|
||||
r = client.post("/api/channels/UCgone000000000000000000/tags", json={"tag_id": 1})
|
||||
assert r.status_code == 404, r.text
|
||||
assert r.json()["detail"] == {"code": "not_found", "reason": "subscription"}
|
||||
r = client.patch("/api/admin/scheduler/jobs/no_such_job", json={"interval_minutes": 30})
|
||||
assert r.status_code == 404, r.text
|
||||
assert r.json()["detail"] == {"code": "not_found", "reason": "job"}
|
||||
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user