Skip to content

Commit

Permalink
Handle invalid cases default locales and add more middleware tests
Browse files Browse the repository at this point in the history
  • Loading branch information
fkapsahili committed Feb 19, 2024
1 parent 20ae0bf commit 4680973
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 6 deletions.
4 changes: 3 additions & 1 deletion packages/next-intl/src/middleware/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ export function getKnownLocaleFromPathname<Locales extends AllLocales>(
locales: Locales
): Locales[number] | undefined {
const pathLocaleCandidate = getLocaleFromPathname(pathname);
const pathLocale = locales.includes(pathLocaleCandidate)
const pathLocale = locales.find(
(locale) => locale.toLowerCase() === pathLocaleCandidate.toLowerCase()
)
? pathLocaleCandidate
: undefined;
return pathLocale;
Expand Down
80 changes: 75 additions & 5 deletions packages/next-intl/test/middleware/middleware.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -537,23 +537,63 @@ describe('prefix-based routing', () => {
);
});

it('redirects an invalid, upper-cased request for a localized route to the case-sensitive format', () => {
it('redirects uppercase locale requests to case-sensitive defaults at the root', () => {
middlewareWithPathnames(createMockRequest('/EN', 'en'));
expect(MockedNextResponse.rewrite).not.toHaveBeenCalled();
expect(MockedNextResponse.next).not.toHaveBeenCalled();
expect(MockedNextResponse.redirect).toHaveBeenCalled();
expect(MockedNextResponse.redirect.mock.calls[0][0].toString()).toBe(
'http://localhost:3000/en/'
);
});

it('redirects uppercase locale requests to case-sensitive defaults for nested paths', () => {
middlewareWithPathnames(createMockRequest('/EN/about', 'en'));
expect(MockedNextResponse.rewrite).not.toHaveBeenCalled();
expect(MockedNextResponse.next).not.toHaveBeenCalled();
expect(MockedNextResponse.redirect).toHaveBeenCalled();
expect(MockedNextResponse.redirect.mock.calls[0][0].toString()).toBe(
'http://localhost:3000/en/about'
);
});

it('redirects uppercase locale requests for non-default locales at the root', () => {
middlewareWithPathnames(createMockRequest('/DE-AT', 'de-AT'));
expect(MockedNextResponse.rewrite).not.toHaveBeenCalled();
expect(MockedNextResponse.next).not.toHaveBeenCalled();
expect(MockedNextResponse.redirect).toHaveBeenCalled();
expect(MockedNextResponse.redirect.mock.calls[0][0].toString()).toBe(
'http://localhost:3000/de-AT'
'http://localhost:3000/de-AT/'
);
});

it('redirects an invalid, lower-cased request for a localized route to the case-sensitive format', () => {
it('redirects uppercase locale requests for non-default locales and nested paths', () => {
middlewareWithPathnames(createMockRequest('/DE-AT/ueber', 'de-AT'));
expect(MockedNextResponse.rewrite).not.toHaveBeenCalled();
expect(MockedNextResponse.next).not.toHaveBeenCalled();
expect(MockedNextResponse.redirect).toHaveBeenCalled();
expect(MockedNextResponse.redirect.mock.calls[0][0].toString()).toBe(
'http://localhost:3000/de-AT/ueber'
);
});

it('redirects lowercase locale requests for non-default locales to case-sensitive format at the root', () => {
middlewareWithPathnames(createMockRequest('/de-at', 'de-AT'));
expect(MockedNextResponse.rewrite).not.toHaveBeenCalled();
expect(MockedNextResponse.next).not.toHaveBeenCalled();
expect(MockedNextResponse.redirect).toHaveBeenCalled();
expect(MockedNextResponse.redirect.mock.calls[0][0].toString()).toBe(
'http://localhost:3000/de-AT'
'http://localhost:3000/de-AT/'
);
});

it('redirects lowercase locale requests for non-default locales to case-sensitive format for nested paths', () => {
middlewareWithPathnames(createMockRequest('/de-at/ueber', 'de-AT'));
expect(MockedNextResponse.rewrite).not.toHaveBeenCalled();
expect(MockedNextResponse.next).not.toHaveBeenCalled();
expect(MockedNextResponse.redirect).toHaveBeenCalled();
expect(MockedNextResponse.redirect.mock.calls[0][0].toString()).toBe(
'http://localhost:3000/de-AT/ueber'
);
});

Expand Down Expand Up @@ -976,7 +1016,7 @@ describe('prefix-based routing', () => {
describe('localePrefix: never', () => {
const middleware = createIntlMiddleware({
defaultLocale: 'en',
locales: ['en', 'de'],
locales: ['en', 'de', 'de-AT'],
localePrefix: 'never'
});

Expand Down Expand Up @@ -1074,6 +1114,36 @@ describe('prefix-based routing', () => {
);
});

it('redirects requests with uppercase default locale in a nested path', () => {
middleware(createMockRequest('/EN/list'));
expect(MockedNextResponse.rewrite).not.toHaveBeenCalled();
expect(MockedNextResponse.next).not.toHaveBeenCalled();
expect(MockedNextResponse.redirect).toHaveBeenCalled();
expect(MockedNextResponse.redirect.mock.calls[0][0].toString()).toBe(
'http://localhost:3000/list'
);
});

it('redirects requests with uppercase non-default locale in a nested path', () => {
middleware(createMockRequest('/DE-AT/list'));
expect(MockedNextResponse.rewrite).not.toHaveBeenCalled();
expect(MockedNextResponse.next).not.toHaveBeenCalled();
expect(MockedNextResponse.redirect).toHaveBeenCalled();
expect(MockedNextResponse.redirect.mock.calls[0][0].toString()).toBe(
'http://localhost:3000/list'
);
});

it('redirects requests with lowercase non-default locale in a nested path', () => {
middleware(createMockRequest('/de-at/list'));
expect(MockedNextResponse.rewrite).not.toHaveBeenCalled();
expect(MockedNextResponse.next).not.toHaveBeenCalled();
expect(MockedNextResponse.redirect).toHaveBeenCalled();
expect(MockedNextResponse.redirect.mock.calls[0][0].toString()).toBe(
'http://localhost:3000/list'
);
});

it('rewrites requests for the root if a cookie exists with a non-default locale', () => {
middleware(createMockRequest('/', 'en', 'http://localhost:3000', 'de'));
expect(MockedNextResponse.next).not.toHaveBeenCalled();
Expand Down

0 comments on commit 4680973

Please sign in to comment.