Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
// React-specific polyfill layer. The base webcrypto polyfill is loaded via
// `@suaveplan/testing/polyfills` (see vitest.config.ts setupFiles). This
// file adds the React 18+ `IS_REACT_ACT_ENVIRONMENT` global expected by
// React DOM when assertions are made outside an `act(...)` wrapper, plus
// a `ResizeObserver` shim used by react-hook-form's controller in some
// happy-dom branches.
interface ReactActEnvWindow {
IS_REACT_ACT_ENVIRONMENT?: boolean;
}
const win = globalThis as unknown as ReactActEnvWindow;
if (win.IS_REACT_ACT_ENVIRONMENT === undefined) {
win.IS_REACT_ACT_ENVIRONMENT = true;
}
interface MaybeResizeObserverGlobal {
ResizeObserver?: unknown;
}
class ResizeObserverPolyfill {
public observe(): void {
// no-op: happy-dom does not lay out elements, so observed entries
// would always carry size 0 — the polyfill is structural only.
}
public unobserve(): void {
// no-op
}
public disconnect(): void {
// no-op
}
}
const maybeRO = globalThis as unknown as MaybeResizeObserverGlobal;
if (maybeRO.ResizeObserver === undefined) {
maybeRO.ResizeObserver = ResizeObserverPolyfill;
}

View File

@@ -0,0 +1,58 @@
/**
* Helper for spinning up a real `@suaveplan/i18n` `I18nInstance` plus
* the `react-forms` recipe-default bundles for use inside tests. No
* mocks — every test that needs a `<TranslationProvider>` builds a
* real instance via this helper so wiring matches production.
*/
import { createI18n, type I18nInstance } from "@suaveplan/i18n/plugin";
import {
reactFormsBundles,
type SupportedFormsLocale,
} from "../../src/locales/locales.js";
export interface CreateTestI18nOptions {
readonly locale?: SupportedFormsLocale;
}
type NestedTranslationRecord = {
[key: string]: string | NestedTranslationRecord;
};
function nestFlatKeys(bag: Record<string, string>): NestedTranslationRecord {
const out: NestedTranslationRecord = {};
for (const [flatKey, value] of Object.entries(bag)) {
const parts = flatKey.split(".");
let cursor: NestedTranslationRecord = out;
for (let i = 0; i < parts.length - 1; i += 1) {
const seg = parts[i] as string;
const existing = cursor[seg];
if (
typeof existing !== "object" ||
existing === null ||
Array.isArray(existing)
) {
cursor[seg] = {};
}
cursor = cursor[seg] as NestedTranslationRecord;
}
cursor[parts[parts.length - 1] as string] = value;
}
return out;
}
export async function createTestI18n(
options: CreateTestI18nOptions = {}
): Promise<I18nInstance> {
const locale = options.locale ?? "en-GB";
const i18n = createI18n({
defaultLocale: locale,
fallbackLocale: "en-GB",
});
for (const code of ["en-GB", "zh-CN", "ar-AE", "cy-GB", "ru-RU"] as const) {
const bundle = await reactFormsBundles[code]();
const nested = nestFlatKeys(bundle as Record<string, string>);
i18n.catalog.mergeMessages(code, nested as Record<string, unknown>);
}
return i18n;
}