// Every string a page of the module shows is a message in English and in Lithuanian, and no component of // the module carries a string of its own. import { readdirSync, readFileSync } from "node:fs" import { join } from "node:path" import { buildRegistry } from "@conusai-kit/core" import { filesModule } from "@conusai-kit/files" import { createI18n, lintUiStrings } from "@conusai-kit/i18n" import { tenancyModule } from "@conusai-kit/tenancy" import { describe, expect, it } from "vitest" import { archiveModule } from "../module.js" import { documentActionsLabels, documentListLabels, registerFormLabels, retentionFormLabels, retentionLabels, versionFormLabels, versionsLabels, } from "../ui/labels.js" // The messages as an app that turned the module on has them: from the manifest, flattened by the kit. const catalogues = buildRegistry([tenancyModule, filesModule, archiveModule]).catalogues const en = catalogues.en?.archive ?? {} const lt = catalogues.lt?.archive ?? {} function keysUsed(): string[] { const asked: string[] = [] const t = (key: string) => { asked.push(key) return key } documentListLabels(t, "failed", {}) registerFormLabels(t, "failed", {}) versionFormLabels(t, "failed", {}) versionsLabels(t, 2) documentActionsLabels(t, "failed", {}) retentionLabels(t) retentionFormLabels(t, "failed", {}) return asked } describe("the archive catalogues", () => { it("hold the same keys in English and in Lithuanian, none empty", () => { expect(Object.keys(lt).sort()).toEqual(Object.keys(en).sort()) for (const [key, text] of [...Object.entries(en), ...Object.entries(lt)]) expect(text.trim(), key).not.toBe("") }) it("hold every message the labels ask for, and none that nothing asks for", () => { const asked = keysUsed() for (const key of asked) { expect(en[key as keyof typeof en], `en is missing archive.${key}`).toBeTruthy() expect(lt[key as keyof typeof lt], `lt is missing archive.${key}`).toBeTruthy() } // The pages and the navigation ask for these directly. const direct = new Set([ "title", "intro", "nav.documents", "nav.retention", "document.back", "document.retentionClass", "document.status", "document.revision", "document.created", "document.hold", "document.disposedAt", "document.yes", "document.no", "statuses.active", "statuses.disposed", "retention.title", "retention.intro", "retention.bases.created", "retention.bases.last_version", "retention.bases.event", ]) expect(Object.keys(en).filter((key) => !asked.includes(key) && !direct.has(key))).toEqual([]) }) it("answer the navigation label the manifest names", () => { expect(archiveModule.ui?.nav?.map((item) => item.label)).toEqual(["archive.title"]) }) it("count versions with the Lithuanian one, few and other forms", () => { const count = (locale: "en" | "lt", n: number) => createI18n(locale, { en: { archive: en }, lt: { archive: lt } }).message("archive.versions.count", { count: n }) expect(count("lt", 1)).toBe("1 versija") expect(count("lt", 2)).toBe("2 versijos") expect(count("lt", 10)).toBe("10 versijų") expect(count("lt", 21)).toBe("21 versija") expect(count("en", 2)).toBe("2 versions") }) }) describe("the components", () => { const dir = new URL("../ui/", import.meta.url).pathname const sources = readdirSync(dir) .filter((name) => name.endsWith(".tsx")) .map((name) => ({ name, text: readFileSync(join(dir, name), "utf8") })) it("carry no hard-coded user-facing string and no colour literal", () => { expect(sources.length).toBeGreaterThanOrEqual(5) for (const { name, text } of sources) { expect(lintUiStrings(text, name), name).toEqual([]) expect(text, name).not.toMatch(/#[0-9a-fA-F]{3,8}\b|\brgb\(|\bhsl\(|\boklch\(/) } }) })