// @vitest-environment jsdom // // A failed download's explanation: the failure-catalog entry first, its category as the fallback. // The second case runs the REAL i18next with the real locales, because the fallback is // i18next's list-key lookup, not code of ours — an older client meeting a detail it has no copy for // must still say the category, not print a key. import { describe, expect, it } from "vitest"; import i18n from "../i18n"; import { failCopyKeys, failTitleKey } from "./downloadFailure"; describe("failCopyKeys", () => { it("puts a catalog entry before its category, and is the category alone without one", () => { expect( failCopyKeys({ error_code: "login_required", error_detail: "facebook.login_wall" }, "body"), ).toEqual([ "downloads.errors.fail.catalog.facebook.login_wall.body", "downloads.errors.fail.cat.login_required.body", "downloads.errors.fail.cat.unknown.body", ]); expect(failCopyKeys({ error_code: "network", error_detail: null }, "short")).toEqual([ "downloads.errors.fail.cat.network.short", "downloads.errors.fail.cat.unknown.short", ]); expect(failCopyKeys({ error_code: null, error_detail: null }, "short")).toEqual([ "downloads.errors.fail.cat.unknown.short", ]); }); it("reads the entry's copy, and the category's for an entry this client does not know", async () => { await i18n.changeLanguage("en"); expect( i18n.t( failCopyKeys( { error_code: "login_required", error_detail: "facebook.login_wall" }, "short", ), ), ).toBe("Facebook sign-in required"); expect( i18n.t( failCopyKeys({ error_code: "login_required", error_detail: "facebook.newer" }, "short"), ), ).toBe("Sign-in required"); // A category this client has no copy for (a newer backend): the generic sentence, never a key. expect(i18n.t(failCopyKeys({ error_code: "rate_limited", error_detail: null }, "short"))).toBe( "Couldn't download", ); }); }); describe("failTitleKey", () => { it("titles an upload's failure as a conversion, anything else as a download", async () => { await i18n.changeLanguage("en"); // the locale has the copy (a missing key would come back as the key itself) expect(i18n.t(failTitleKey({ job_kind: "upload" }))).not.toMatch(/^downloads\./); expect(failTitleKey({ job_kind: "upload" })).toBe("downloads.errors.fail.titleUpload"); expect(failTitleKey({ job_kind: "edit" })).toBe("downloads.errors.fail.title"); expect(failTitleKey({})).toBe("downloads.errors.fail.title"); }); it("an upload's own failures read as an upload's", async () => { await i18n.changeLanguage("en"); for (const code of ["convert_failed", "upload_missing"]) { const short = i18n.t(failCopyKeys({ error_code: code, error_detail: null }, "short")); expect(short).not.toBe(i18n.t("downloads.errors.fail.cat.unknown.short")); } }); });