Skip to content

Commit b4cd909

Browse files
committed
Add tests
1 parent 6ee2266 commit b4cd909

File tree

10 files changed

+108
-16
lines changed

10 files changed

+108
-16
lines changed

.github/workflows/CI.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ jobs:
5555
# CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
5656

5757
# - name: Install Playwright (used for Storybook and E2E tests)
58-
# run: pnpx playwright install --with-deps
58+
# run: npx playwright install --with-deps
5959

6060
# - name: Run storybook tests
6161
# run: pnpm test-storybook:ci

.husky/pre-commit

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ if [ "$branch" = "main" ]; then
55
exit 1
66
fi
77

8-
pnpx lint-staged
8+
npx lint-staged

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"check-types": "tsc --noEmit --pretty",
77
"test": "vitest run",
88
"test:e2e": "playwright test",
9-
"dev:spotlight": "pnpx @spotlightjs/spotlight",
9+
"dev:spotlight": "npx @spotlightjs/spotlight",
1010
"dev:next": "next dev --turbopack",
1111
"dev": "run-p dev:*",
1212
"build": "next build",
@@ -117,7 +117,7 @@
117117
"prettier --write"
118118
],
119119
"src/**/*.{ts,tsx}": [
120-
"pnpx eslint --max-warnings=0 --fix"
120+
"npx eslint --max-warnings=0 --fix"
121121
]
122122
}
123123
}

src/actions/locale.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use server';
22

3-
import type { Locale } from '@/types/locale';
3+
import type { Locale } from '@/lib/locale';
44
import { cookies } from 'next/headers';
55

66
export const setLocale = async (locale: Locale) => {

src/app/layout.tsx

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ import '@/styles/globals.css';
33
import type { Metadata } from 'next';
44
import { NextIntlClientProvider } from 'next-intl';
55
import { getLocale } from 'next-intl/server';
6-
import { enUS, frFR } from '@clerk/localizations';
76
import { ClerkProvider } from '@clerk/nextjs';
87

9-
import { ThemeProvider } from '@/components/layout/ThemeProvider';
8+
import { getClerkLocale } from '@/lib/locale';
9+
import { ThemeProvider } from '@/components/layout';
1010

1111
export const metadata: Metadata = {
1212
icons: [
@@ -41,13 +41,8 @@ export default async function RootLayout({
4141
suppressHydrationWarning
4242
>
4343
<NextIntlClientProvider>
44-
<ThemeProvider
45-
attribute="class"
46-
defaultTheme="system"
47-
enableSystem
48-
disableTransitionOnChange
49-
>
50-
<ClerkProvider localization={locale === 'fr' ? frFR : enUS}>
44+
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
45+
<ClerkProvider localization={getClerkLocale(locale)}>
5146
{children}
5247
</ClerkProvider>
5348
</ThemeProvider>

src/components/layout/LocaleSwitcher.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { useCallback } from 'react';
44
import { useRouter } from 'next/navigation';
55
import { useLocale } from 'next-intl';
66

7-
import { Locales, isLocale } from '@/types/locale';
7+
import { Locales, isLocale } from '@/lib/locale';
88
import { setLocale } from '@/actions/locale';
99
import {
1010
Button,

src/components/layout/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ export { Navbar } from './Navbar';
22
export { Footer } from './Footer';
33
export { Section } from './Section';
44
export { LocaleSwitcher } from './LocaleSwitcher';
5+
export { ThemeProvider } from './ThemeProvider';
56
export { ThemeSwitcher } from './ThemeSwitcher';
67
export { Logo } from './Logo';

src/i18n/request.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { cookies } from 'next/headers';
2-
import { isLocale } from '@/types/locale';
2+
import { isLocale } from '@/lib/locale';
33
import { getRequestConfig } from 'next-intl/server';
44

55
export default getRequestConfig(async (params) => {

src/lib/locale.test.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// npx vitest run src/lib/locale.test.ts
2+
3+
import { enUS, frFR } from '@clerk/localizations';
4+
5+
import { locales, isLocale, Locales, getClerkLocale, Locale } from './locale';
6+
7+
describe('locale module', () => {
8+
describe('locales', () => {
9+
it('should contain supported locales', () => {
10+
expect(locales).toEqual(['en', 'fr']);
11+
});
12+
});
13+
14+
describe('isLocale', () => {
15+
it('should return true for valid locales', () => {
16+
expect(isLocale('en')).toBe(true);
17+
expect(isLocale('fr')).toBe(true);
18+
});
19+
20+
it('should return false for invalid locales', () => {
21+
expect(isLocale('es')).toBe(false);
22+
expect(isLocale('de')).toBe(false);
23+
expect(isLocale('')).toBe(false);
24+
expect(isLocale(undefined)).toBe(false);
25+
});
26+
27+
it('should properly type-narrow the input', () => {
28+
const testLocale = (locale: string | undefined): Locale | null => {
29+
if (isLocale(locale)) {
30+
const validLocale: Locale = locale;
31+
return validLocale;
32+
}
33+
34+
return null;
35+
};
36+
37+
expect(testLocale('en')).toBe('en');
38+
expect(testLocale('invalid')).toBe(null);
39+
});
40+
});
41+
42+
describe('Locales', () => {
43+
it('should map locale codes to display names', () => {
44+
expect(Locales).toEqual({
45+
en: 'English',
46+
fr: 'Français',
47+
});
48+
});
49+
50+
it('should have an entry for each supported locale', () => {
51+
locales.forEach((locale) => {
52+
expect(Locales[locale]).toBeDefined();
53+
});
54+
});
55+
});
56+
57+
describe('getClerkLocale', () => {
58+
it('should return enUS for "en" locale', () => {
59+
expect(getClerkLocale('en')).toBe(enUS);
60+
});
61+
62+
it('should return frFR for "fr" locale', () => {
63+
expect(getClerkLocale('fr')).toBe(frFR);
64+
});
65+
66+
it('should return enUS for invalid locales', () => {
67+
expect(getClerkLocale('es')).toBe(enUS);
68+
expect(getClerkLocale('de')).toBe(enUS);
69+
expect(getClerkLocale('')).toBe(enUS);
70+
// @ts-expect-error Testing with invalid type
71+
expect(getClerkLocale(undefined)).toBe(enUS);
72+
// @ts-expect-error Testing with invalid type
73+
expect(getClerkLocale(null)).toBe(enUS);
74+
});
75+
76+
it('should handle case sensitivity correctly', () => {
77+
expect(getClerkLocale('EN')).toBe(enUS);
78+
expect(getClerkLocale('Fr')).toBe(enUS);
79+
});
80+
});
81+
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { enUS, frFR } from '@clerk/localizations';
2+
13
export const locales = ['en', 'fr'] as const;
24

35
export type Locale = (typeof locales)[number];
@@ -9,3 +11,16 @@ export const Locales: Record<Locale, string> = {
911
en: 'English',
1012
fr: 'Français',
1113
};
14+
15+
export const getClerkLocale = (locale: string) => {
16+
if (!isLocale(locale)) {
17+
return enUS;
18+
}
19+
20+
switch (locale) {
21+
case 'fr':
22+
return frFR;
23+
default:
24+
return enUS;
25+
}
26+
};

0 commit comments

Comments
 (0)