UNPKG

alepha

Version:

Easy-to-use modern TypeScript framework for building many kind of applications.

177 lines (157 loc) 5.47 kB
import { Alepha } from "alepha"; import { FileSystemProvider, MemoryFileSystemProvider } from "alepha/system"; import { beforeEach, describe, expect, it } from "vitest"; import { I18nCheckService } from "../services/I18nCheckService.ts"; describe("I18nCheckService", () => { const ROOT = "/proj"; const createEnv = () => { const alepha = Alepha.create().with({ provide: FileSystemProvider, use: MemoryFileSystemProvider, }); const service = alepha.inject(I18nCheckService); const fs = alepha.inject(MemoryFileSystemProvider); return { service, fs }; }; const dictionary = (keys: Record<string, string>) => { const body = Object.entries(keys) .map(([k, v]) => ` "${k}": "${v}",`) .join("\n"); return `import { $dictionary } from "alepha/react/i18n"; export class I18n { en = $dictionary({ lazy: async () => ({ default: { ${body} }, }), }); } `; }; let env: ReturnType<typeof createEnv>; beforeEach(() => { env = createEnv(); }); it("reports keys with no quoted reference as unused", async () => { await env.fs.mkdir(`${ROOT}/src/web`, { recursive: true }); await env.fs.writeFile( `${ROOT}/src/web/I18n.ts`, dictionary({ "home.title": "Home", "home.unused": "Nothing" }), ); await env.fs.writeFile( `${ROOT}/src/web/Home.tsx`, `export const Home = () => tr("home.title");`, ); const result = await env.service.check({ root: ROOT, scan: ["src"], dynamicPrefixes: [], exclude: [], }); expect(result.totalKeys).toBe(2); expect(result.unused).toEqual(["home.unused"]); expect(result.dictionaryFiles).toHaveLength(1); }); it("exempts keys matching a dynamic prefix", async () => { await env.fs.mkdir(`${ROOT}/src`, { recursive: true }); await env.fs.writeFile( `${ROOT}/src/I18n.ts`, dictionary({ "archive.type.directory": "Folder", "archive.type.folio": "Folio", "home.title": "Home", }), ); await env.fs.writeFile( `${ROOT}/src/App.tsx`, "tr(`archive.type.${k}`); tr('home.title');", ); const result = await env.service.check({ root: ROOT, scan: ["src"], dynamicPrefixes: ["archive.type."], exclude: [], }); expect(result.unused).toEqual([]); expect(result.exemptKeys).toBe(2); }); it("skips excluded paths and built-in excludes", async () => { await env.fs.mkdir(`${ROOT}/src/__tests__`, { recursive: true }); await env.fs.writeFile( `${ROOT}/src/I18n.ts`, dictionary({ "home.title": "Home" }), ); // Reference lives only in an excluded test file — should not count. await env.fs.writeFile( `${ROOT}/src/__tests__/Home.spec.ts`, `tr("home.title");`, ); const result = await env.service.check({ root: ROOT, scan: ["src"], dynamicPrefixes: [], exclude: [], }); expect(result.unused).toEqual(["home.title"]); }); it("extracts keys from lazily-imported per-language files", async () => { await env.fs.mkdir(`${ROOT}/src/web/i18n`, { recursive: true }); // Marker file declares `$dictionary` but the keys live in split, // markerless per-language files referenced via `lazy: () => import(...)`. // A sibling `$page` lazy import must NOT be mistaken for a key file. await env.fs.writeFile( `${ROOT}/src/web/Router.ts`, `import { $dictionary } from "alepha/react/i18n"; export class Router { fr = $dictionary({ lazy: () => import("./i18n/fr.ts"), lang: "fr" }); en = $dictionary({ lazy: () => import("./i18n/en.ts"), lang: "en" }); page = $page({ lazy: () => import("./Home.tsx") }); } `, ); await env.fs.writeFile( `${ROOT}/src/web/i18n/fr.ts`, `export default { "home.title": "Accueil", "home.unused": "Rien" };`, ); await env.fs.writeFile( `${ROOT}/src/web/i18n/en.ts`, `export default { "home.title": "Home", "home.unused": "Nothing" };`, ); // The only reference — `home.unused` is dead in both languages. The // `"home.title": "…"` lines in the sibling language file must not count // as references (key files are excluded from the usage corpus). await env.fs.writeFile( `${ROOT}/src/web/Home.tsx`, `export const Home = () => tr("home.title");`, ); const result = await env.service.check({ root: ROOT, scan: ["src"], dynamicPrefixes: [], exclude: [], }); expect(result.totalKeys).toBe(2); expect(result.unused).toEqual(["home.unused"]); // The resolved language file is treated as a dictionary; the sibling // `$page` lazy import is not (it contributed no keys and stays in the // usage corpus). `en.ts` is also a dictionary file but adds no *new* // keys, so only the first contributor is listed. expect(result.dictionaryFiles).toContain(`${ROOT}/src/web/i18n/fr.ts`); expect(result.dictionaryFiles).not.toContain(`${ROOT}/src/web/Home.tsx`); }); it("returns totalKeys=0 when no dictionary is found", async () => { await env.fs.mkdir(`${ROOT}/src`, { recursive: true }); await env.fs.writeFile( `${ROOT}/src/App.tsx`, `export const App = () => "hi";`, ); const result = await env.service.check({ root: ROOT, scan: ["src"], dynamicPrefixes: [], exclude: [], }); expect(result.totalKeys).toBe(0); }); });