@prosopo/locale 3.2.9 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +10 -9
  2. package/.turbo/turbo-build$colon$tsc.log +5 -5
  3. package/.turbo/turbo-build.log +17 -16
  4. package/CHANGELOG.md +24 -0
  5. package/dist/cjs/i18SharedOptions.cjs +1 -1
  6. package/dist/cjs/i18nBackend.cjs +4 -1
  7. package/dist/cjs/i18nFrontend.cjs +4 -1
  8. package/dist/cjs/loadI18next.cjs +41 -14
  9. package/dist/cjs/process.cjs +17 -0
  10. package/dist/cjs/translationKey.cjs +2 -0
  11. package/dist/i18SharedOptions.js +2 -1
  12. package/dist/i18SharedOptions.js.map +1 -1
  13. package/dist/i18nBackend.d.ts.map +1 -1
  14. package/dist/i18nBackend.js +4 -1
  15. package/dist/i18nBackend.js.map +1 -1
  16. package/dist/i18nFrontend.d.ts.map +1 -1
  17. package/dist/i18nFrontend.js +4 -1
  18. package/dist/i18nFrontend.js.map +1 -1
  19. package/dist/loadI18next.d.ts +1 -0
  20. package/dist/loadI18next.d.ts.map +1 -1
  21. package/dist/loadI18next.js +41 -15
  22. package/dist/loadI18next.js.map +1 -1
  23. package/dist/process.d.ts +2 -0
  24. package/dist/process.d.ts.map +1 -0
  25. package/dist/process.js +17 -0
  26. package/dist/process.js.map +1 -0
  27. package/dist/tests/i18SharedOptions.unit.test.d.ts +2 -0
  28. package/dist/tests/i18SharedOptions.unit.test.d.ts.map +1 -0
  29. package/dist/tests/i18SharedOptions.unit.test.js +91 -0
  30. package/dist/tests/i18SharedOptions.unit.test.js.map +1 -0
  31. package/dist/tests/i18nBackend.unit.test.d.ts +2 -0
  32. package/dist/tests/i18nBackend.unit.test.d.ts.map +1 -0
  33. package/dist/tests/i18nBackend.unit.test.js +153 -0
  34. package/dist/tests/i18nBackend.unit.test.js.map +1 -0
  35. package/dist/tests/i18nFrontend.unit.test.d.ts +2 -0
  36. package/dist/tests/i18nFrontend.unit.test.d.ts.map +1 -0
  37. package/dist/tests/i18nFrontend.unit.test.js +199 -0
  38. package/dist/tests/i18nFrontend.unit.test.js.map +1 -0
  39. package/dist/tests/i18nMiddleware.unit.test.d.ts +2 -0
  40. package/dist/tests/i18nMiddleware.unit.test.d.ts.map +1 -0
  41. package/dist/tests/i18nMiddleware.unit.test.js +80 -0
  42. package/dist/tests/i18nMiddleware.unit.test.js.map +1 -0
  43. package/dist/tests/loadI18next.unit.test.d.ts +2 -0
  44. package/dist/tests/loadI18next.unit.test.d.ts.map +1 -0
  45. package/dist/tests/loadI18next.unit.test.js +270 -0
  46. package/dist/tests/loadI18next.unit.test.js.map +1 -0
  47. package/dist/tests/locale.test-d.d.ts +2 -0
  48. package/dist/tests/locale.test-d.d.ts.map +1 -0
  49. package/dist/tests/locale.test-d.js +88 -0
  50. package/dist/tests/locale.test-d.js.map +1 -0
  51. package/dist/tests/process.unit.test.d.ts +2 -0
  52. package/dist/tests/process.unit.test.d.ts.map +1 -0
  53. package/dist/tests/process.unit.test.js +14 -0
  54. package/dist/tests/process.unit.test.js.map +1 -0
  55. package/dist/tests/translationKey.unit.test.d.ts +2 -0
  56. package/dist/tests/translationKey.unit.test.d.ts.map +1 -0
  57. package/dist/tests/translationKey.unit.test.js +108 -0
  58. package/dist/tests/translationKey.unit.test.js.map +1 -0
  59. package/dist/tests/translations.unit.test.d.ts +2 -0
  60. package/dist/tests/translations.unit.test.d.ts.map +1 -0
  61. package/dist/tests/translations.unit.test.js +74 -0
  62. package/dist/tests/translations.unit.test.js.map +1 -0
  63. package/dist/tests/useTranslation.unit.test.d.ts +2 -0
  64. package/dist/tests/useTranslation.unit.test.d.ts.map +1 -0
  65. package/dist/tests/useTranslation.unit.test.js +81 -0
  66. package/dist/tests/useTranslation.unit.test.js.map +1 -0
  67. package/dist/tests/util.unit.test.d.ts +2 -0
  68. package/dist/tests/util.unit.test.d.ts.map +1 -0
  69. package/dist/tests/util.unit.test.js +66 -0
  70. package/dist/tests/util.unit.test.js.map +1 -0
  71. package/dist/translationKey.d.ts +4 -0
  72. package/dist/translationKey.d.ts.map +1 -1
  73. package/dist/translationKey.js +2 -1
  74. package/dist/translationKey.js.map +1 -1
  75. package/package.json +1 -1
  76. package/src/i18SharedOptions.ts +4 -4
  77. package/src/i18nBackend.ts +16 -0
  78. package/src/i18nFrontend.ts +16 -0
  79. package/src/loadI18next.ts +83 -15
  80. package/src/process.ts +29 -0
  81. package/src/tests/i18SharedOptions.unit.test.ts +139 -0
  82. package/src/tests/i18nBackend.unit.test.ts +241 -0
  83. package/src/tests/i18nFrontend.unit.test.ts +302 -0
  84. package/src/tests/i18nMiddleware.unit.test.ts +140 -0
  85. package/src/tests/loadI18next.unit.test.ts +443 -0
  86. package/src/tests/locale.test-d.ts +156 -0
  87. package/src/tests/process.unit.test.ts +33 -0
  88. package/src/tests/translationKey.unit.test.ts +166 -0
  89. package/src/tests/translations.unit.test.ts +110 -0
  90. package/src/tests/useTranslation.unit.test.ts +134 -0
  91. package/src/tests/util.unit.test.ts +102 -0
  92. package/src/translationKey.ts +18 -3
  93. package/tsconfig.tsbuildinfo +1 -1
@@ -0,0 +1,91 @@
1
+ import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
2
+ import { Languages } from "../translations.js";
3
+ const loadOptions = async () => {
4
+ vi.resetModules();
5
+ const { i18nSharedOptions } = await import("../i18SharedOptions.js");
6
+ return i18nSharedOptions;
7
+ };
8
+ const originalLogLevel = process.env.PROSOPO_LOG_LEVEL;
9
+ beforeEach(() => {
10
+ Reflect.deleteProperty(process.env, "PROSOPO_LOG_LEVEL");
11
+ });
12
+ afterEach(() => {
13
+ vi.doUnmock("../process.js");
14
+ vi.resetModules();
15
+ if (originalLogLevel === undefined) {
16
+ Reflect.deleteProperty(process.env, "PROSOPO_LOG_LEVEL");
17
+ }
18
+ else {
19
+ process.env.PROSOPO_LOG_LEVEL = originalLogLevel;
20
+ }
21
+ });
22
+ describe("i18nSharedOptions", () => {
23
+ test("falls back to English", async () => {
24
+ const options = await loadOptions();
25
+ expect(options.fallbackLng).toBe("en");
26
+ });
27
+ test("uses the single translation namespace", async () => {
28
+ const options = await loadOptions();
29
+ expect(options.namespace).toBe("translation");
30
+ });
31
+ test("supports exactly the declared language codes", async () => {
32
+ const options = await loadOptions();
33
+ expect(new Set(options.supportedLngs)).toEqual(new Set(Object.values(Languages)));
34
+ });
35
+ test("does not accept non-explicit regional variants", async () => {
36
+ const options = await loadOptions();
37
+ expect(options.nonExplicitSupportedLngs).toBe(false);
38
+ });
39
+ describe("debug flag", () => {
40
+ test("is off when PROSOPO_LOG_LEVEL is unset", async () => {
41
+ const options = await loadOptions();
42
+ expect(options.debug).toBe(false);
43
+ });
44
+ test("is on only for the exact value 'debug'", async () => {
45
+ process.env.PROSOPO_LOG_LEVEL = "debug";
46
+ expect((await loadOptions()).debug).toBe(true);
47
+ });
48
+ test("is off for any other log level", async () => {
49
+ for (const level of ["info", "warn", "error", "trace", ""]) {
50
+ process.env.PROSOPO_LOG_LEVEL = level;
51
+ expect((await loadOptions()).debug, level).toBe(false);
52
+ }
53
+ });
54
+ test("is case sensitive — 'DEBUG' does not enable it", async () => {
55
+ process.env.PROSOPO_LOG_LEVEL = "DEBUG";
56
+ expect((await loadOptions()).debug).toBe(false);
57
+ });
58
+ });
59
+ describe("browser runtime, where process may be absent or partial", () => {
60
+ const mockProcess = (value) => {
61
+ vi.resetModules();
62
+ vi.doMock("../process.js", () => ({
63
+ getProcess: () => value,
64
+ }));
65
+ };
66
+ test("loads when there is no process at all", async () => {
67
+ mockProcess(undefined);
68
+ const { i18nSharedOptions } = await import("../i18SharedOptions.js");
69
+ expect(i18nSharedOptions.debug).toBe(false);
70
+ expect(i18nSharedOptions.fallbackLng).toBe("en");
71
+ });
72
+ test("loads when process exists but exposes no env", async () => {
73
+ const partial = Object.create(process);
74
+ Reflect.defineProperty(partial, "env", {
75
+ value: undefined,
76
+ configurable: true,
77
+ });
78
+ mockProcess(partial);
79
+ const { i18nSharedOptions } = await import("../i18SharedOptions.js");
80
+ expect(i18nSharedOptions.debug).toBe(false);
81
+ expect(i18nSharedOptions.fallbackLng).toBe("en");
82
+ });
83
+ test("still reads the log level when process is present", async () => {
84
+ process.env.PROSOPO_LOG_LEVEL = "debug";
85
+ mockProcess(process);
86
+ const { i18nSharedOptions } = await import("../i18SharedOptions.js");
87
+ expect(i18nSharedOptions.debug).toBe(true);
88
+ });
89
+ });
90
+ });
91
+ //# sourceMappingURL=i18SharedOptions.unit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18SharedOptions.unit.test.js","sourceRoot":"","sources":["../../src/tests/i18SharedOptions.unit.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=i18nBackend.unit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18nBackend.unit.test.d.ts","sourceRoot":"","sources":["../../src/tests/i18nBackend.unit.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,153 @@
1
+ import { afterEach, describe, expect, test, vi } from "vitest";
2
+ const makeHarness = (isInitialized) => {
3
+ const plugins = [];
4
+ const initOptions = [];
5
+ const listeners = new Map();
6
+ const fake = {
7
+ isInitialized,
8
+ use: (plugin) => {
9
+ plugins.push(plugin);
10
+ return fake;
11
+ },
12
+ init: (options) => {
13
+ initOptions.push(options);
14
+ return fake;
15
+ },
16
+ on: (event, listener) => {
17
+ listeners.set(event, [...(listeners.get(event) ?? []), listener]);
18
+ },
19
+ };
20
+ return {
21
+ fake,
22
+ plugins,
23
+ initOptions,
24
+ listeners,
25
+ emit: (event) => {
26
+ for (const listener of listeners.get(event) ?? []) {
27
+ listener();
28
+ }
29
+ },
30
+ };
31
+ };
32
+ const load = async (options) => {
33
+ vi.resetModules();
34
+ const harness = makeHarness(options.isInitialized ?? false);
35
+ vi.doMock("i18next", () => ({ default: harness.fake }));
36
+ vi.doMock("i18next-fs-backend/cjs", () => ({ default: "FSBackend" }));
37
+ vi.doMock("i18next-http-middleware", () => ({
38
+ LanguageDetector: class {
39
+ constructor(_services, opts) {
40
+ this.options = opts;
41
+ }
42
+ },
43
+ }));
44
+ vi.doMock("../util.js", () => ({
45
+ isServerSide: () => options.serverSide ?? true,
46
+ isClientSide: () => !(options.serverSide ?? true),
47
+ }));
48
+ const imported = await import("../i18nBackend.js");
49
+ return { initializeI18n: imported.default, harness };
50
+ };
51
+ afterEach(() => {
52
+ vi.resetModules();
53
+ vi.doUnmock("i18next");
54
+ vi.doUnmock("i18next-fs-backend/cjs");
55
+ vi.doUnmock("i18next-http-middleware");
56
+ vi.doUnmock("../util.js");
57
+ });
58
+ describe("i18nBackend on a server, not yet initialised", () => {
59
+ test("initialises i18next exactly once", async () => {
60
+ const { initializeI18n, harness } = await load({});
61
+ initializeI18n();
62
+ expect(harness.initOptions).toHaveLength(1);
63
+ });
64
+ test("registers the filesystem backend and the header language detector", async () => {
65
+ const { initializeI18n, harness } = await load({});
66
+ initializeI18n();
67
+ expect(harness.plugins).toHaveLength(2);
68
+ expect(harness.plugins[0]).toBe("FSBackend");
69
+ });
70
+ test("carries the shared options through to init", async () => {
71
+ const { initializeI18n, harness } = await load({});
72
+ initializeI18n();
73
+ const options = harness.initOptions[0];
74
+ expect(options?.fallbackLng).toBe("en");
75
+ expect(options?.supportedLngs).toContain("en");
76
+ expect(options?.nonExplicitSupportedLngs).toBe(false);
77
+ });
78
+ test("declares the translation namespace", async () => {
79
+ const { initializeI18n, harness } = await load({});
80
+ initializeI18n();
81
+ expect(harness.initOptions[0]?.ns).toEqual(["translation"]);
82
+ });
83
+ test("points the backend at a filesystem path, not a file:// URL", async () => {
84
+ const { initializeI18n, harness } = await load({});
85
+ initializeI18n();
86
+ const backend = harness.initOptions[0]?.backend;
87
+ expect(backend?.loadPath).toBeDefined();
88
+ expect(backend?.loadPath).not.toContain("file://");
89
+ expect(backend?.loadPath).toContain("/locales/{{lng}}/{{ns}}.json");
90
+ });
91
+ test("defers the callback until resources have loaded", async () => {
92
+ const callback = vi.fn();
93
+ const { initializeI18n, harness } = await load({});
94
+ initializeI18n(callback);
95
+ expect(callback).not.toHaveBeenCalled();
96
+ harness.emit("loaded");
97
+ expect(callback).toHaveBeenCalledTimes(1);
98
+ });
99
+ test("fires the callback once, however often `loaded` is emitted", async () => {
100
+ const callback = vi.fn();
101
+ const { initializeI18n, harness } = await load({});
102
+ initializeI18n(callback);
103
+ harness.emit("loaded");
104
+ harness.emit("loaded");
105
+ harness.emit("loaded");
106
+ expect(callback).toHaveBeenCalledTimes(1);
107
+ });
108
+ test("hands the i18next instance to the callback", async () => {
109
+ const callback = vi.fn();
110
+ const { initializeI18n, harness } = await load({});
111
+ initializeI18n(callback);
112
+ harness.emit("loaded");
113
+ expect(callback).toHaveBeenCalledWith(harness.fake);
114
+ });
115
+ test("returns the i18next instance", async () => {
116
+ const { initializeI18n, harness } = await load({});
117
+ expect(initializeI18n()).toBe(harness.fake);
118
+ });
119
+ test("tolerates being called with no callback at all", async () => {
120
+ const { initializeI18n, harness } = await load({});
121
+ initializeI18n();
122
+ expect(() => harness.emit("loaded")).not.toThrow();
123
+ });
124
+ });
125
+ describe("i18nBackend when there is nothing to initialise", () => {
126
+ test("fires the callback immediately when i18next is already up", async () => {
127
+ const callback = vi.fn();
128
+ const { initializeI18n, harness } = await load({ isInitialized: true });
129
+ const returned = initializeI18n(callback);
130
+ expect(harness.initOptions).toHaveLength(0);
131
+ expect(callback).toHaveBeenCalledTimes(1);
132
+ expect(callback).toHaveBeenCalledWith(harness.fake);
133
+ expect(returned).toBe(harness.fake);
134
+ });
135
+ test("fires the callback immediately when running client side", async () => {
136
+ const callback = vi.fn();
137
+ const { initializeI18n, harness } = await load({ serverSide: false });
138
+ const returned = initializeI18n(callback);
139
+ expect(harness.initOptions).toHaveLength(0);
140
+ expect(callback).toHaveBeenCalledTimes(1);
141
+ expect(returned).toBe(harness.fake);
142
+ });
143
+ test("registers no plugins when initialisation is skipped", async () => {
144
+ const { initializeI18n, harness } = await load({ isInitialized: true });
145
+ initializeI18n();
146
+ expect(harness.plugins).toHaveLength(0);
147
+ });
148
+ test("tolerates no callback when initialisation is skipped", async () => {
149
+ const { initializeI18n } = await load({ isInitialized: true });
150
+ expect(() => initializeI18n()).not.toThrow();
151
+ });
152
+ });
153
+ //# sourceMappingURL=i18nBackend.unit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18nBackend.unit.test.js","sourceRoot":"","sources":["../../src/tests/i18nBackend.unit.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=i18nFrontend.unit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18nFrontend.unit.test.d.ts","sourceRoot":"","sources":["../../src/tests/i18nFrontend.unit.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,199 @@
1
+ import { afterEach, describe, expect, test, vi } from "vitest";
2
+ const load = async (isInitialized = false) => {
3
+ vi.resetModules();
4
+ const plugins = [];
5
+ const initOptions = [];
6
+ const resourceLoaders = [];
7
+ const detectorOptions = [];
8
+ const listeners = new Map();
9
+ const fake = {
10
+ isInitialized,
11
+ use: (plugin) => {
12
+ plugins.push(plugin);
13
+ return fake;
14
+ },
15
+ init: (options) => {
16
+ initOptions.push(options);
17
+ return fake;
18
+ },
19
+ on: (event, listener) => {
20
+ listeners.set(event, [...(listeners.get(event) ?? []), listener]);
21
+ },
22
+ };
23
+ const harness = {
24
+ fake,
25
+ plugins,
26
+ initOptions,
27
+ resourceLoaders,
28
+ detectorOptions,
29
+ emit: (event) => {
30
+ for (const listener of listeners.get(event) ?? []) {
31
+ listener();
32
+ }
33
+ },
34
+ };
35
+ vi.doMock("i18next", () => ({ default: fake }));
36
+ vi.doMock("i18next-chained-backend", () => ({ default: "ChainedBackend" }));
37
+ vi.doMock("i18next-http-backend", () => ({ default: "HttpBackend" }));
38
+ vi.doMock("i18next-browser-languagedetector", () => ({
39
+ default: class {
40
+ constructor(_services, opts) {
41
+ detectorOptions.push(opts);
42
+ }
43
+ },
44
+ }));
45
+ vi.doMock("i18next-resources-to-backend", () => ({
46
+ default: (loader) => {
47
+ resourceLoaders.push(loader);
48
+ return "InMemoryBackend";
49
+ },
50
+ }));
51
+ vi.doMock("react-i18next", () => ({ initReactI18next: "initReactI18next" }));
52
+ const imported = await import("../i18nFrontend.js");
53
+ return { initializeI18n: imported.default, harness };
54
+ };
55
+ const backendOf = (options) => (options?.backend ?? {});
56
+ afterEach(() => {
57
+ vi.resetModules();
58
+ for (const module of [
59
+ "i18next",
60
+ "i18next-chained-backend",
61
+ "i18next-http-backend",
62
+ "i18next-browser-languagedetector",
63
+ "i18next-resources-to-backend",
64
+ "react-i18next",
65
+ ]) {
66
+ vi.doUnmock(module);
67
+ }
68
+ });
69
+ describe("i18nFrontend, first initialisation", () => {
70
+ test("initialises i18next exactly once", async () => {
71
+ const { initializeI18n, harness } = await load();
72
+ initializeI18n();
73
+ expect(harness.initOptions).toHaveLength(1);
74
+ });
75
+ test("registers the chained backend, the detector and the react binding", async () => {
76
+ const { initializeI18n, harness } = await load();
77
+ initializeI18n();
78
+ expect(harness.plugins).toHaveLength(3);
79
+ expect(harness.plugins[0]).toBe("ChainedBackend");
80
+ expect(harness.plugins[2]).toBe("initReactI18next");
81
+ });
82
+ test("carries the shared options through to init", async () => {
83
+ const { initializeI18n, harness } = await load();
84
+ initializeI18n();
85
+ const options = harness.initOptions[0];
86
+ expect(options?.fallbackLng).toBe("en");
87
+ expect(options?.nonExplicitSupportedLngs).toBe(false);
88
+ expect(options?.supportedLngs).toContain("en");
89
+ });
90
+ test("returns the i18next instance", async () => {
91
+ const { initializeI18n, harness } = await load();
92
+ expect(initializeI18n()).toBe(harness.fake);
93
+ });
94
+ });
95
+ describe("i18nFrontend language selection", () => {
96
+ test("pins lng when the site owner supplied one", async () => {
97
+ const { initializeI18n, harness } = await load();
98
+ initializeI18n(undefined, "fr");
99
+ expect(harness.initOptions[0]?.lng).toBe("fr");
100
+ });
101
+ test("omits lng entirely when none was supplied, leaving detection on", async () => {
102
+ const { initializeI18n, harness } = await load();
103
+ initializeI18n();
104
+ expect(harness.initOptions[0]).not.toHaveProperty("lng");
105
+ });
106
+ test("treats the empty string as no language rather than pinning it", async () => {
107
+ const { initializeI18n, harness } = await load();
108
+ initializeI18n(undefined, "");
109
+ expect(harness.initOptions[0]).not.toHaveProperty("lng");
110
+ });
111
+ test("configures the detector to prefer a stored choice over the browser", async () => {
112
+ const { initializeI18n, harness } = await load();
113
+ initializeI18n();
114
+ expect(harness.detectorOptions[0]).toMatchObject({
115
+ order: ["cookie", "localStorage", "navigator"],
116
+ lookupQuerystring: "lng",
117
+ });
118
+ });
119
+ test("persists the detected language to localStorage and a cookie", async () => {
120
+ const { initializeI18n, harness } = await load();
121
+ initializeI18n();
122
+ expect(harness.detectorOptions[0]).toMatchObject({
123
+ caches: ["localStorage", "cookie"],
124
+ });
125
+ });
126
+ });
127
+ describe("i18nFrontend resource loading", () => {
128
+ test("chains an in-memory fallback behind the http backend", async () => {
129
+ const { initializeI18n, harness } = await load();
130
+ initializeI18n();
131
+ const backend = backendOf(harness.initOptions[0]);
132
+ expect(backend.backends).toEqual(["HttpBackend", "InMemoryBackend"]);
133
+ });
134
+ test("gives the http backend a templated load path", async () => {
135
+ const { initializeI18n, harness } = await load();
136
+ initializeI18n();
137
+ const backend = backendOf(harness.initOptions[0]);
138
+ const loadPath = backend.backendOptions?.[0]?.loadPath;
139
+ expect(loadPath).toContain("/locales/{{lng}}/{{ns}}.json");
140
+ });
141
+ test("derives the load path from the module URL, not the page URL", async () => {
142
+ const { initializeI18n, harness } = await load();
143
+ initializeI18n();
144
+ const loadPath = backendOf(harness.initOptions[0]).backendOptions?.[0]
145
+ ?.loadPath;
146
+ expect(loadPath).toMatch(/^[a-z]+:\/\//);
147
+ expect(loadPath).not.toContain("i18nFrontend");
148
+ });
149
+ test("hands resourcesToBackend a loader that resolves a language and namespace", async () => {
150
+ const { initializeI18n, harness } = await load();
151
+ initializeI18n();
152
+ const loader = harness.resourceLoaders[0];
153
+ expect(loader).toBeTypeOf("function");
154
+ await expect(Promise.resolve(loader?.("en", "translation")).catch(() => undefined)).resolves.not.toThrow();
155
+ });
156
+ });
157
+ describe("i18nFrontend callback", () => {
158
+ test("defers the callback until resources have loaded", async () => {
159
+ const callback = vi.fn();
160
+ const { initializeI18n, harness } = await load();
161
+ initializeI18n(callback);
162
+ expect(callback).not.toHaveBeenCalled();
163
+ harness.emit("loaded");
164
+ expect(callback).toHaveBeenCalledWith(harness.fake);
165
+ });
166
+ test("fires the callback once, however often `loaded` is emitted", async () => {
167
+ const callback = vi.fn();
168
+ const { initializeI18n, harness } = await load();
169
+ initializeI18n(callback);
170
+ harness.emit("loaded");
171
+ harness.emit("loaded");
172
+ expect(callback).toHaveBeenCalledTimes(1);
173
+ });
174
+ test("tolerates being called with no callback", async () => {
175
+ const { initializeI18n, harness } = await load();
176
+ initializeI18n();
177
+ expect(() => harness.emit("loaded")).not.toThrow();
178
+ });
179
+ test("fires the callback immediately when i18next is already initialised", async () => {
180
+ const callback = vi.fn();
181
+ const { initializeI18n, harness } = await load(true);
182
+ const returned = initializeI18n(callback);
183
+ expect(harness.initOptions).toHaveLength(0);
184
+ expect(callback).toHaveBeenCalledTimes(1);
185
+ expect(callback).toHaveBeenCalledWith(harness.fake);
186
+ expect(returned).toBe(harness.fake);
187
+ });
188
+ test("registers no plugins when already initialised", async () => {
189
+ const { initializeI18n, harness } = await load(true);
190
+ initializeI18n();
191
+ expect(harness.plugins).toHaveLength(0);
192
+ });
193
+ test("ignores lng when already initialised — the caller reconciles instead", async () => {
194
+ const { initializeI18n, harness } = await load(true);
195
+ initializeI18n(undefined, "fr");
196
+ expect(harness.initOptions).toHaveLength(0);
197
+ });
198
+ });
199
+ //# sourceMappingURL=i18nFrontend.unit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18nFrontend.unit.test.js","sourceRoot":"","sources":["../../src/tests/i18nFrontend.unit.test.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAyB/D,MAAM,IAAI,GAAG,KAAK,EACjB,aAAa,GAAG,KAAK,EAInB,EAAE;IACJ,EAAE,CAAC,YAAY,EAAE,CAAC;IAElB,MAAM,OAAO,GAAc,EAAE,CAAC;IAC9B,MAAM,WAAW,GAAkB,EAAE,CAAC;IACtC,MAAM,eAAe,GAAqB,EAAE,CAAC;IAC7C,MAAM,eAAe,GAAc,EAAE,CAAC;IACtC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAsB,CAAC;IAEhD,MAAM,IAAI,GAAa;QACtB,aAAa;QACb,GAAG,EAAE,CAAC,MAAe,EAAY,EAAE;YAClC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,OAAO,IAAI,CAAC;QACb,CAAC;QACD,IAAI,EAAE,CAAC,OAAoB,EAAY,EAAE;YACxC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC1B,OAAO,IAAI,CAAC;QACb,CAAC;QACD,EAAE,EAAE,CAAC,KAAa,EAAE,QAAkB,EAAQ,EAAE;YAC/C,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;QACnE,CAAC;KACD,CAAC;IAEF,MAAM,OAAO,GAAY;QACxB,IAAI;QACJ,OAAO;QACP,WAAW;QACX,eAAe;QACf,eAAe;QACf,IAAI,EAAE,CAAC,KAAa,EAAQ,EAAE;YAC7B,KAAK,MAAM,QAAQ,IAAI,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;gBACnD,QAAQ,EAAE,CAAC;YACZ,CAAC;QACF,CAAC;KACD,CAAC;IAEF,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAChD,EAAE,CAAC,MAAM,CAAC,yBAAyB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC;IAC5E,EAAE,CAAC,MAAM,CAAC,sBAAsB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;IACtE,EAAE,CAAC,MAAM,CAAC,kCAAkC,EAAE,GAAG,EAAE,CAAC,CAAC;QACpD,OAAO,EAAE;YACR,YAAY,SAAkB,EAAE,IAAa;gBAC5C,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC;SACD;KACD,CAAC,CAAC,CAAC;IACJ,EAAE,CAAC,MAAM,CAAC,8BAA8B,EAAE,GAAG,EAAE,CAAC,CAAC;QAChD,OAAO,EAAE,CAAC,MAAsB,EAAU,EAAE;YAC3C,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC7B,OAAO,iBAAiB,CAAC;QAC1B,CAAC;KACD,CAAC,CAAC,CAAC;IACJ,EAAE,CAAC,MAAM,CAAC,eAAe,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC;IAE7E,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACpD,OAAO,EAAE,cAAc,EAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC;AACtD,CAAC,CAAC;AAEF,MAAM,SAAS,GAAG,CACjB,OAAgC,EACqC,EAAE,CACvE,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,CAGtB,CAAC;AAEH,SAAS,CAAC,GAAG,EAAE;IACd,EAAE,CAAC,YAAY,EAAE,CAAC;IAClB,KAAK,MAAM,MAAM,IAAI;QACpB,SAAS;QACT,yBAAyB;QACzB,sBAAsB;QACtB,kCAAkC;QAClC,8BAA8B;QAC9B,eAAe;KACf,EAAE,CAAC;QACH,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACrB,CAAC;AACF,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IACnD,IAAI,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QACjD,cAAc,EAAE,CAAC;QACjB,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,mEAAmE,EAAE,KAAK,IAAI,EAAE;QACpF,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QACjD,cAAc,EAAE,CAAC;QACjB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAClD,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC7D,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QACjD,cAAc,EAAE,CAAC;QACjB,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,MAAM,CAAC,OAAO,EAAE,wBAAwB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtD,MAAM,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QACjD,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,iCAAiC,EAAE,GAAG,EAAE;IAIhD,IAAI,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QAC5D,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QACjD,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;QAClF,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QACjD,cAAc,EAAE,CAAC;QACjB,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAGhF,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QACjD,cAAc,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAC9B,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QACrF,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QACjD,cAAc,EAAE,CAAC;QACjB,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;YAChD,KAAK,EAAE,CAAC,QAAQ,EAAE,cAAc,EAAE,WAAW,CAAC;YAC9C,iBAAiB,EAAE,KAAK;SACxB,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAC9E,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QACjD,cAAc,EAAE,CAAC;QACjB,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;YAChD,MAAM,EAAE,CAAC,cAAc,EAAE,QAAQ,CAAC;SAClC,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC9C,IAAI,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QAGvE,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QACjD,cAAc,EAAE,CAAC;QACjB,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,iBAAiB,CAAC,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QACjD,cAAc,EAAE,CAAC;QACjB,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;QACvD,MAAM,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,8BAA8B,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;QAG9E,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QACjD,cAAc,EAAE,CAAC;QACjB,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;YACrE,EAAE,QAAQ,CAAC;QAGZ,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAGzC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QAC3F,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QACjD,cAAc,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAGtC,MAAM,MAAM,CACX,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CACrE,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IAC1B,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACtC,IAAI,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAClE,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACzB,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QAEjD,cAAc,CAAC,QAAQ,CAAC,CAAC;QACzB,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAExC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvB,MAAM,CAAC,QAAQ,CAAC,CAAC,oBAAoB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;QAI7E,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACzB,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QAEjD,cAAc,CAAC,QAAQ,CAAC,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvB,MAAM,CAAC,QAAQ,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,EAAE,CAAC;QACjD,cAAc,EAAE,CAAC;QACjB,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;IACpD,CAAC,CAAC,CAAC;IAKH,IAAI,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;QACrF,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QACzB,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QAErD,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;QAE1C,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAC5C,MAAM,CAAC,QAAQ,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAC1C,MAAM,CAAC,QAAQ,CAAC,CAAC,oBAAoB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACpD,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QACrD,cAAc,EAAE,CAAC;QACjB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,sEAAsE,EAAE,KAAK,IAAI,EAAE;QACvF,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QACrD,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QAChC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=i18nMiddleware.unit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18nMiddleware.unit.test.d.ts","sourceRoot":"","sources":["../../src/tests/i18nMiddleware.unit.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,80 @@
1
+ import { afterEach, describe, expect, test, vi } from "vitest";
2
+ const asI18n = (value) => value;
3
+ const load = async (options) => {
4
+ vi.resetModules();
5
+ const instance = asI18n({ name: "the singleton" });
6
+ const handleCalls = [];
7
+ const handler = (() => { });
8
+ vi.doMock("i18next-http-middleware", () => ({
9
+ handle: (i18next, opts) => {
10
+ handleCalls.push([i18next, opts]);
11
+ return handler;
12
+ },
13
+ }));
14
+ vi.doMock("../loadI18next.js", () => ({
15
+ default: async () => {
16
+ if (options.loadRejects) {
17
+ throw new Error("i18n failed to load");
18
+ }
19
+ return instance;
20
+ },
21
+ }));
22
+ const imported = await import("../i18nMiddleware.js");
23
+ return {
24
+ i18nMiddleware: imported.default,
25
+ harness: { instance, handleCalls, handler },
26
+ };
27
+ };
28
+ afterEach(() => {
29
+ vi.resetModules();
30
+ vi.doUnmock("i18next-http-middleware");
31
+ vi.doUnmock("../loadI18next.js");
32
+ });
33
+ describe("i18nMiddleware", () => {
34
+ test("builds the handler from the loaded i18next instance", async () => {
35
+ const { i18nMiddleware, harness } = await load({});
36
+ const handler = await i18nMiddleware({});
37
+ expect(harness.handleCalls).toHaveLength(1);
38
+ expect(harness.handleCalls[0]?.[0]).toBe(harness.instance);
39
+ expect(handler).toBe(harness.handler);
40
+ });
41
+ test("forwards the caller's options", async () => {
42
+ const { i18nMiddleware, harness } = await load({});
43
+ const options = { ignoreRoutes: ["/healthz"] };
44
+ await i18nMiddleware(options);
45
+ expect(harness.handleCalls[0]?.[1]).toEqual({ ignoreRoutes: ["/healthz"] });
46
+ });
47
+ test("copies the options rather than passing the caller's object through", async () => {
48
+ const { i18nMiddleware, harness } = await load({});
49
+ const options = { ignoreRoutes: ["/healthz"] };
50
+ await i18nMiddleware(options);
51
+ expect(harness.handleCalls[0]?.[1]).not.toBe(options);
52
+ });
53
+ test("accepts an empty options object", async () => {
54
+ const { i18nMiddleware, harness } = await load({});
55
+ await i18nMiddleware({});
56
+ expect(harness.handleCalls[0]?.[1]).toEqual({});
57
+ });
58
+ test("always requests the backend instance", async () => {
59
+ const loadSpy = vi.fn(async () => asI18n({}));
60
+ vi.resetModules();
61
+ vi.doMock("i18next-http-middleware", () => ({
62
+ handle: () => (() => { }),
63
+ }));
64
+ vi.doMock("../loadI18next.js", () => ({ default: loadSpy }));
65
+ const imported = await import("../i18nMiddleware.js");
66
+ await imported.default({});
67
+ expect(loadSpy).toHaveBeenCalledWith(true);
68
+ });
69
+ test("propagates a failure to load i18next instead of returning a broken handler", async () => {
70
+ const { i18nMiddleware } = await load({ loadRejects: true });
71
+ await expect(i18nMiddleware({})).rejects.toThrow("i18n failed to load");
72
+ });
73
+ test("returns a fresh handler per call", async () => {
74
+ const { i18nMiddleware, harness } = await load({});
75
+ await i18nMiddleware({});
76
+ await i18nMiddleware({ ignoreRoutes: ["/x"] });
77
+ expect(harness.handleCalls).toHaveLength(2);
78
+ });
79
+ });
80
+ //# sourceMappingURL=i18nMiddleware.unit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18nMiddleware.unit.test.js","sourceRoot":"","sources":["../../src/tests/i18nMiddleware.unit.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=loadI18next.unit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadI18next.unit.test.d.ts","sourceRoot":"","sources":["../../src/tests/loadI18next.unit.test.ts"],"names":[],"mappings":""}