MeshChatX/tests/frontend/localeLoader.test.js

95 lines
4 KiB
JavaScript

// SPDX-License-Identifier: 0BSD
import { describe, expect, it, afterEach } from "vitest";
import { createI18n } from "vue-i18n";
import {
ensureLocaleMessages,
listLocaleCodes,
normalizeUiLocaleCode,
registerUiI18n,
setLocale,
} from "../../meshchatx/src/frontend/js/localeLoader.js";
describe("localeLoader", () => {
afterEach(() => {
registerUiI18n(null);
});
it("lists locale codes with english first", () => {
const codes = listLocaleCodes();
expect(codes[0]).toBe("en");
expect(codes).toEqual(expect.arrayContaining(["de", "es", "fr", "ru", "zh"]));
expect(new Set(codes).size).toBe(codes.length);
});
it("ensureLocaleMessages rejects bad codes without throwing", async () => {
const i18n = createI18n({ legacy: false, locale: "en", messages: { en: { hi: "hi" } } });
for (const bad of [null, undefined, "", 12, {}, [], "nope-xx"]) {
await expect(ensureLocaleMessages(i18n, bad)).resolves.toBe(false);
}
});
it("ensureLocaleMessages is idempotent for already-loaded locales", async () => {
const i18n = createI18n({ legacy: false, locale: "en", messages: { en: { hi: "hi" } } });
expect(await ensureLocaleMessages(i18n, "en")).toBe(true);
expect(await ensureLocaleMessages(i18n, "en")).toBe(true);
});
it("loads a non-english locale into the composer", async () => {
const i18n = createI18n({ legacy: false, locale: "en", messages: { en: { hi: "hi" } } });
expect(i18n.global.availableLocales).not.toContain("de");
expect(await ensureLocaleMessages(i18n, "de")).toBe(true);
expect(i18n.global.availableLocales).toContain("de");
expect(i18n.global.getLocaleMessage("de")._languageName).toBeTruthy();
});
it("setLocale updates locale.value for composition i18n", async () => {
const i18n = createI18n({ legacy: false, locale: "en", messages: { en: { hi: "hi" } } });
expect(await setLocale(i18n, "fr")).toBe(true);
expect(i18n.global.locale.value).toBe("fr");
});
it("setLocale works when given the composer directly", async () => {
const i18n = createI18n({ legacy: false, locale: "en", messages: { en: { hi: "hi" } } });
expect(await setLocale(i18n.global, "es")).toBe(true);
expect(i18n.global.locale.value).toBe("es");
});
it("ensureLocaleMessages returns false when setLocaleMessage is missing", async () => {
const fake = { availableLocales: [], setLocaleMessage: undefined };
expect(await ensureLocaleMessages(fake, "de")).toBe(false);
});
it("adversarial: ensureLocaleMessages(null) is false", async () => {
expect(await ensureLocaleMessages(null, "en")).toBe(false);
expect(await setLocale(undefined, "en")).toBe(false);
});
it("normalizeUiLocaleCode maps aliases and rejects unknown packs", () => {
expect(normalizeUiLocaleCode("zh-cn")).toBe("zh");
expect(normalizeUiLocaleCode("ru")).toBe("ru");
expect(normalizeUiLocaleCode("jp")).toBe("en");
expect(normalizeUiLocaleCode("")).toBe("en");
});
it("fuzz: random codes never throw", async () => {
const i18n = createI18n({ legacy: false, locale: "en", messages: { en: {} } });
const junk = ["", "en", "de", "../en", "EN", "en.json", "🚀", "a".repeat(200), "zh-CN", "pt"];
for (const code of junk) {
await expect(ensureLocaleMessages(i18n, code)).resolves.toBeTypeOf("boolean");
}
});
it("registerUiI18n lets setLocale recover from a locale-only proxy", async () => {
const i18n = createI18n({ legacy: false, locale: "en", messages: { en: { hi: "hi" } } });
const proxy = {
locale: "en",
availableLocales: ["en"],
fallbackLocale: "en",
};
expect(await setLocale(proxy, "de")).toBe(false);
registerUiI18n(i18n);
expect(await setLocale(proxy, "de")).toBe(true);
expect(i18n.global.locale.value).toBe("de");
});
});