Skip to content

Commit 947d964

Browse files
committed
add test
1 parent 370200e commit 947d964

File tree

2 files changed

+218
-13
lines changed

2 files changed

+218
-13
lines changed

packages/tests-unit/tests/core/routing/i18n.test.ts

Lines changed: 217 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { NextConfig } from "@opennextjs/aws/adapters/config/index.js";
2-
import { localizePath } from "@opennextjs/aws/core/routing/i18n/index.js";
2+
import {
3+
handleLocaleRedirect,
4+
localizePath,
5+
} from "@opennextjs/aws/core/routing/i18n/index.js";
36
import { convertFromQueryString } from "@opennextjs/aws/core/routing/util.js";
47
import type { InternalEvent } from "@opennextjs/aws/types/open-next.js";
58
import { vi } from "vitest";
@@ -15,16 +18,14 @@ vi.mock("@opennextjs/aws/adapters/config/index.js", () => {
1518
};
1619
});
1720

18-
vi.mock("@opennextjs/aws/core/routing/i18n/accept-header.js", () => ({
19-
acceptLanguage: (header: string, _?: string[]) => (header ? "fr" : undefined),
20-
}));
21-
2221
type PartialEvent = Partial<
2322
Omit<InternalEvent, "body" | "rawPath" | "query">
2423
> & { body?: string };
2524

2625
function createEvent(event: PartialEvent): InternalEvent {
27-
const [rawPath, qs] = (event.url ?? "/").split("?", 2);
26+
const url = new URL(event.url ?? "/");
27+
const rawPath = url.pathname;
28+
const qs = url.search;
2829
return {
2930
type: "core",
3031
method: event.method ?? "GET",
@@ -49,7 +50,7 @@ describe("localizePath", () => {
4950
.mockReturnValue(undefined);
5051

5152
const event = createEvent({
52-
url: "/foo",
53+
url: "http://localhost/foo",
5354
});
5455

5556
const result = localizePath(event);
@@ -67,7 +68,7 @@ describe("localizePath", () => {
6768
});
6869

6970
const event = createEvent({
70-
url: "/foo",
71+
url: "http://localhost/foo",
7172
headers: {
7273
"accept-language": "fr",
7374
},
@@ -85,7 +86,7 @@ describe("localizePath", () => {
8586

8687
it("should return the same path if the path is already localized", () => {
8788
const event = createEvent({
88-
url: "/fr/foo",
89+
url: "http://localhost/fr/foo",
8990
});
9091

9192
const result = localizePath(event);
@@ -95,7 +96,7 @@ describe("localizePath", () => {
9596

9697
it("should get locale from cookies if NEXT_LOCALE cookie is set to a valid locale", () => {
9798
const event = createEvent({
98-
url: "/foo",
99+
url: "http://localhost/foo",
99100
cookies: {
100101
NEXT_LOCALE: "fr",
101102
},
@@ -108,7 +109,7 @@ describe("localizePath", () => {
108109

109110
it("should fallback on default locale if NEXT_LOCALE cookie is set to an invalid locale", () => {
110111
const event = createEvent({
111-
url: "/foo",
112+
url: "http://localhost/foo",
112113
cookies: {
113114
NEXT_LOCALE: "pt",
114115
},
@@ -121,7 +122,7 @@ describe("localizePath", () => {
121122

122123
it("should use accept-language header if no cookie are present", () => {
123124
const event = createEvent({
124-
url: "/foo",
125+
url: "http://localhost/foo",
125126
headers: {
126127
"accept-language": "fr",
127128
},
@@ -134,11 +135,214 @@ describe("localizePath", () => {
134135

135136
it("should fallback to default locale if no cookie or header are set", () => {
136137
const event = createEvent({
137-
url: "/foo",
138+
url: "http://localhost/foo",
138139
});
139140

140141
const result = localizePath(event);
141142

142143
expect(result).toEqual("/en/foo");
143144
});
144145
});
146+
147+
describe("handleLocaleRedirect", () => {
148+
it("should redirect to the localized path if the path is not localized", () => {
149+
const event = createEvent({
150+
url: "http://localhost",
151+
152+
headers: {
153+
"accept-language": "fr",
154+
},
155+
});
156+
157+
const result = handleLocaleRedirect(event);
158+
159+
expect(result).toBeTruthy();
160+
expect(result!.statusCode).toEqual(307);
161+
expect(result!.headers).toEqual({
162+
Location: "http://localhost/fr",
163+
});
164+
});
165+
166+
it("should not redirect if the path is already localized", () => {
167+
const event = createEvent({
168+
url: "http://localhost/fr",
169+
});
170+
171+
const result = handleLocaleRedirect(event);
172+
173+
expect(result).toBeFalsy();
174+
});
175+
176+
it("should not redirect if not the root path", () => {
177+
const event = createEvent({
178+
url: "http://localhost/foo",
179+
});
180+
181+
const result = handleLocaleRedirect(event);
182+
183+
expect(result).toBeFalsy();
184+
});
185+
186+
describe("using domain", () => {
187+
it("should redirect to the preferred domain if the domain is different", () => {
188+
vi.spyOn(NextConfig, "i18n", "get").mockReturnValue({
189+
defaultLocale: "en",
190+
locales: ["en", "en-US", "en-CA", "fr"],
191+
domains: [
192+
{
193+
domain: "mydomain.com",
194+
defaultLocale: "en",
195+
},
196+
{
197+
domain: "localhost",
198+
defaultLocale: "fr",
199+
http: true,
200+
},
201+
],
202+
});
203+
const event = createEvent({
204+
url: "http://mydomain.com",
205+
headers: {
206+
host: "mydomain.com",
207+
"accept-language": "fr",
208+
},
209+
});
210+
211+
const result = handleLocaleRedirect(event);
212+
213+
expect(result).toBeTruthy();
214+
expect(result!.statusCode).toEqual(307);
215+
expect(result!.headers).toEqual({
216+
Location: "http://localhost/",
217+
});
218+
});
219+
220+
it("should redirect to the same domain with not default locale", () => {
221+
vi.spyOn(NextConfig, "i18n", "get").mockReturnValue({
222+
defaultLocale: "en",
223+
locales: ["en", "fr", "fr-FR"],
224+
domains: [
225+
{
226+
domain: "mydomain.com",
227+
defaultLocale: "en",
228+
},
229+
{
230+
domain: "localhost",
231+
defaultLocale: "fr",
232+
locales: ["fr-FR"],
233+
http: true,
234+
},
235+
],
236+
});
237+
const event = createEvent({
238+
url: "http://localhost",
239+
headers: {
240+
host: "localhost",
241+
"accept-language": "fr-FR,fr;q=0.9,en;q=0.8",
242+
},
243+
});
244+
245+
const result = handleLocaleRedirect(event);
246+
247+
expect(result).toBeTruthy();
248+
expect(result!.statusCode).toEqual(307);
249+
expect(result!.headers).toEqual({
250+
Location: "http://localhost/fr-FR",
251+
});
252+
});
253+
254+
it("should redirect to different domain with not default locale", () => {
255+
vi.spyOn(NextConfig, "i18n", "get").mockReturnValue({
256+
defaultLocale: "en",
257+
locales: ["en", "fr", "fr-FR"],
258+
domains: [
259+
{
260+
domain: "mydomain.com",
261+
defaultLocale: "en",
262+
},
263+
{
264+
domain: "localhost",
265+
defaultLocale: "fr",
266+
locales: ["fr-FR"],
267+
http: true,
268+
},
269+
],
270+
});
271+
const event = createEvent({
272+
url: "http://mydomain.com",
273+
headers: {
274+
host: "mydomain.com",
275+
"accept-language": "fr-FR,fr;q=0.9,en;q=0.8",
276+
},
277+
});
278+
279+
const result = handleLocaleRedirect(event);
280+
281+
expect(result).toBeTruthy();
282+
expect(result!.statusCode).toEqual(307);
283+
expect(result!.headers).toEqual({
284+
Location: "http://localhost/fr-FR",
285+
});
286+
});
287+
288+
it("should not redirect if the domain and locale are the same", () => {
289+
vi.spyOn(NextConfig, "i18n", "get").mockReturnValue({
290+
defaultLocale: "en",
291+
locales: ["en", "fr", "fr-FR"],
292+
domains: [
293+
{
294+
domain: "mydomain.com",
295+
defaultLocale: "en",
296+
},
297+
{
298+
domain: "localhost",
299+
defaultLocale: "fr",
300+
locales: ["fr-FR"],
301+
http: true,
302+
},
303+
],
304+
});
305+
const event = createEvent({
306+
url: "http://localhost/fr-FR",
307+
headers: {
308+
host: "localhost",
309+
"accept-language": "fr-FR,fr;q=0.9,en;q=0.8",
310+
},
311+
});
312+
313+
const result = handleLocaleRedirect(event);
314+
315+
expect(result).toBeFalsy();
316+
});
317+
318+
it("should not redirect if locale is not found", () => {
319+
vi.spyOn(NextConfig, "i18n", "get").mockReturnValue({
320+
defaultLocale: "en",
321+
locales: ["en", "fr", "fr-FR"],
322+
domains: [
323+
{
324+
domain: "mydomain.com",
325+
defaultLocale: "en",
326+
},
327+
{
328+
domain: "localhost",
329+
defaultLocale: "fr",
330+
locales: ["fr-FR"],
331+
http: true,
332+
},
333+
],
334+
});
335+
const event = createEvent({
336+
url: "http://localhost",
337+
headers: {
338+
host: "localhost",
339+
"accept-language": "es",
340+
},
341+
});
342+
343+
const result = handleLocaleRedirect(event);
344+
345+
expect(result).toBeFalsy();
346+
});
347+
});
348+
});

packages/tests-unit/tests/core/routing/matcher.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ vi.mock("@opennextjs/aws/adapters/config/index.js", () => ({
1414
}));
1515
vi.mock("@opennextjs/aws/core/routing/i18n/index.js", () => ({
1616
localizePath: (event: InternalEvent) => event.rawPath,
17+
handleLocaleRedirect: (_event: InternalEvent) => false,
1718
}));
1819

1920
type PartialEvent = Partial<

0 commit comments

Comments
 (0)