// Catalog completeness + a byte snapshot of all three catalogs — the CLJS
// replacement for the TS-era MsgKey type check. Passing on the first run is the
// signal that the mechanical transliteration changed no strings.
import test from "node:test";
import assert from "node:assert/strict";
import { boot, vectors } from "./harness.mjs";
const { lib } = await boot();
const snap = vectors("i18n");
const calls = vectors("i18n-calls");
const en = [...lib.catalogKeys("en")];
test("EN is non-empty and carries the social.* block the kits look up", () => {
assert.ok(en.length >= 150, `only ${en.length} keys`);
assert.ok(en.some((k) => k.startsWith("social.")));
});
for (const lang of ["ro", "hu"]) {
test(`${lang} covers every EN key, and nothing else`, () => {
assert.deepEqual([...lib.catalogKeys(lang)], en);
});
}
for (const lang of ["en", "ro", "hu"]) {
test(`${lang} is byte-identical to the TS catalog`, () => {
const got = JSON.parse(JSON.stringify(lib.catalogJson(lang)));
// key ORDER is not part of the contract (a CLJS map literal loses it and
// lookups don't care) — the key SET and every value are.
assert.deepEqual(Object.keys(got).sort(), Object.keys(snap[lang]).sort());
for (const k of Object.keys(snap[lang])) {
assert.deepEqual(got[k], snap[lang][k], `${lang} ${k}`);
}
});
}
test("plural sites: ro one/few/other, hu other-only, en one/other", () => {
assert.deepEqual([...lib.catalogMsg("en", "lb.matches")], ["one", "other"]);
assert.deepEqual([...lib.catalogMsg("ro", "lb.matches")], ["few", "one", "other"]);
assert.deepEqual([...lib.catalogMsg("hu", "lb.matches")], ["other"]);
});
test("t()/tn() through the shared runtime, per language", () => {
for (const lang of ["en", "ro", "hu"]) {
lib.setLang(lang);
const got = calls.script.map((s) =>
s[0] === "t" ? lib.t(s[1], s[2] ?? undefined) : lib.tn(s[1], s[2], s[3] ?? undefined));
assert.deepEqual(got, calls.out[lang], `calls in ${lang}`);
}
lib.setLang("en");
});