The audit log showed a failed RSS poll as the server's English sentence under a Hungarian UI. A job can now raise progress.JobFailed(reason, message, **params): the scheduler stores the reason and params as the run's data (dashboard, manual-run notice, audit row) beside the English line, and the client renders scheduler.failure.<reason>. The RSS outage names its first channel and the reason code (HTTP 404 vs unreachable). An upstream's own error text stays as raised (diagnostic).
99 lines
3.8 KiB
TypeScript
99 lines
3.8 KiB
TypeScript
// @vitest-environment jsdom
|
|
//
|
|
// E30: a scheduler job's result in the reader's language, through the REAL catalog. The server's own
|
|
// one-liner was "recent={'channels_processed': 0, …}, deep={…}" — English keys and a Python repr.
|
|
import { afterEach, describe, expect, it } from "vitest";
|
|
import i18n, { setLanguage } from "../i18n";
|
|
import { jobFailureText, jobResultText, jobRunText, parseSummary } from "./jobResult";
|
|
|
|
afterEach(() => setLanguage("en"));
|
|
|
|
describe("a job's result", () => {
|
|
it("names each count, and a phase's own counts inside it", () => {
|
|
setLanguage("hu");
|
|
const t = i18n.getFixedT("hu");
|
|
expect(jobResultText(t, { new: 3, failed: 0 }, "hu")).toBe("új videó: 3 · sikertelen: 0");
|
|
expect(
|
|
jobResultText(
|
|
t,
|
|
{
|
|
recent: { channels_processed: 0, videos_added: 0, reason: "no service user" },
|
|
deep: { channels_processed: 2, videos_added: 5, reconciled_full: 1 },
|
|
},
|
|
"hu",
|
|
),
|
|
).toBe(
|
|
"friss (feldolgozott csatorna: 0 · hozzáadott videó: 0 · indok: nincs szolgáltatásfiók) · " +
|
|
"mély (feldolgozott csatorna: 2 · hozzáadott videó: 5 · teljesen egyeztetve: 1)",
|
|
);
|
|
});
|
|
|
|
it("names a skip reason; an upstream error stays its own text", () => {
|
|
const t = i18n.getFixedT("hu");
|
|
expect(jobResultText(t, { enriched: 0, skipped: "tmdb_api_key not set" }, "hu")).toBe(
|
|
"dúsítva: 0 · kihagyva: nincs TMDB API-kulcs",
|
|
);
|
|
expect(jobResultText(t, { error: "Plex returned 500" }, "hu")).toBe("hiba: Plex returned 500");
|
|
});
|
|
|
|
it("shows a key or word it does not know as it is, readable", () => {
|
|
const t = i18n.getFixedT("hu");
|
|
expect(jobResultText(t, { brand_new_count: 3, skipped: "moon is full" }, "hu")).toBe(
|
|
"brand new count: 3 · kihagyva: moon is full",
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("an older notice's one-liner", () => {
|
|
it("reads back into a result when flat", () => {
|
|
expect(parseSummary("new=403, failed=396, fallback=375")).toEqual({
|
|
new: 403,
|
|
failed: 396,
|
|
fallback: 375,
|
|
});
|
|
expect(parseSummary("enriched=0, skipped=tmdb_api_key not set")).toEqual({
|
|
enriched: 0,
|
|
skipped: "tmdb_api_key not set",
|
|
});
|
|
// enrich's bare count, as the server's `_result_data` names it
|
|
expect(parseSummary("42")).toEqual({ enriched: 42 });
|
|
});
|
|
|
|
it("does not when a phase is nested, or it is no summary at all", () => {
|
|
expect(parseSummary("recent={'channels_processed': 0}, deep={'videos_added': 1}")).toBeNull();
|
|
expect(parseSummary("sync paused")).toBeNull();
|
|
expect(parseSummary(null)).toBeNull();
|
|
});
|
|
});
|
|
|
|
// E31: the audit log showed a failed RSS poll as the server's English sentence ("RSS poll failed for
|
|
// all 399 channels — first: …") under a Hungarian UI. A failure the job names rides along as data.
|
|
describe("a failed run", () => {
|
|
const run = {
|
|
job_id: "rss_poll",
|
|
status: "error",
|
|
summary:
|
|
"RSS poll failed for all 399 channels — first: UCx: RSS fetch for UCx returned HTTP 404",
|
|
result: { failure: "rss_all_failed", total: 1399, channel: "UCx", cause: "http_404", read: 0 },
|
|
};
|
|
|
|
it("says the failure the job named in the reader's language", () => {
|
|
const t = i18n.getFixedT("hu");
|
|
expect(jobRunText(t, run, "hu").body).toBe(
|
|
"Az RSS-hírcsatorna egyik csatornánál sem válaszolt (1399) — az első: UCx, HTTP 404. " +
|
|
"Az API-n át beolvasva helyette: 0",
|
|
);
|
|
expect(jobFailureText(t, { ...run.result, cause: "transport" }, "hu")).toContain(
|
|
"UCx, nem érhető el.",
|
|
);
|
|
});
|
|
|
|
it("keeps any other failure's own text", () => {
|
|
const t = i18n.getFixedT("hu");
|
|
expect(jobRunText(t, { ...run, summary: "Plex returned 500", result: null }, "hu").body).toBe(
|
|
"Plex returned 500",
|
|
);
|
|
expect(jobFailureText(t, { failure: "moon_is_full" }, "hu")).toBeNull();
|
|
});
|
|
});
|