~150 HTTPExceptions carried a hand-written English sentence as their detail,
shown verbatim under the Hungarian UI — in the blocking error dialog and on
every inline surface that printed HttpError.detail (sign-in, setup wizard,
change password, the passphrase gate, live search). Four also quoted an
upstream exception's text back to the user.
- app/refusal.py: `refused(status, reason, **params)` → {code: "refused",
reason, …params}; localizeDetail translates errors.refused.<reason> with the
params interpolated. "Unknown X" 404s use the existing not_found(what).
- sysconfig.set_value raises InvalidSetting (reason + bounds) instead of an
English ValueError; the three writers answer it through setting_refused.
- The Plex connection/write/image failures log what the upstream said and
answer a reason; the search scraper's failure is logged and answered as
youtube/unavailable (it crashed refusal_reason before).
- HttpError.detail now only ever holds a translated reason: a string detail
(only the framework's own can remain) is left out, so reading .detail is
safe everywhere — including destructured, the hole the raw-detail source
scan could not see. That scan and its five-file exception list are gone.
- Enforced: test_http_details.py fails on any HTTPException with a sentence
for a detail; the contract test requires every refused reason and every
not_found "what" in both languages, and no key for one that is gone.
- local/jsx-comment-text: a // inside JSX children renders as text; the rule
is ten lines in eslint.config.js rather than eslint-plugin-react's ~1800
lockfile lines.
31 lines
1.4 KiB
TypeScript
31 lines
1.4 KiB
TypeScript
import { fileURLToPath } from "node:url";
|
|
|
|
import { ESLint } from "eslint";
|
|
import { describe, expect, it } from "vitest";
|
|
|
|
// `local/jsx-comment-text` (eslint.config.js): a `//` inside JSX children is rendered as text. One
|
|
// reached the Playlists page past tsc, eslint and every test — only a visual check caught it. A rule
|
|
// that matches nothing looks exactly like a clean codebase, so this asserts it fires.
|
|
const RULE = "local/jsx-comment-text";
|
|
const FRONTEND = fileURLToPath(new URL("../../", import.meta.url));
|
|
|
|
async function hits(source: string): Promise<number> {
|
|
const eslint = new ESLint({ cwd: FRONTEND });
|
|
const [result] = await eslint.lintText(source, { filePath: "src/components/__probe.tsx" });
|
|
return (result?.messages ?? []).filter((m) => m.ruleId === RULE).length;
|
|
}
|
|
|
|
describe("a comment inside JSX children", () => {
|
|
it("is refused — it would render as text", async () => {
|
|
expect(
|
|
await hits(`export const A = () => (\n <>\n // the list\n <ul />\n </>\n);\n`),
|
|
).toBe(1);
|
|
expect(await hits(`export const B = () => <div>/* note */</div>;\n`)).toBe(1);
|
|
});
|
|
|
|
it("is fine as a real comment, and text that merely contains a slash pair is text", async () => {
|
|
expect(await hits(`export const C = () => <div>{/* the list */}</div>;\n`)).toBe(0);
|
|
expect(await hits(`export const D = () => <p>See https://example.com</p>;\n`)).toBe(0);
|
|
});
|
|
});
|