From 0b192ce030b52e723fc3bac9aca5bf210ca0badc Mon Sep 17 00:00:00 2001 From: Felipe Cardoso Date: Wed, 19 Nov 2025 01:31:35 +0100 Subject: [PATCH] Update e2e tests and mocks for locale-based routing - Adjusted assertions and navigation tests to include `/en` locale prefix for consistency. - Updated next-intl and components-i18n mocks to support locale handling in tests. - Renamed "Components" link and related references to "Design System" in homepage tests. - Disabled typing delay in debounce test for improved test reliability. --- frontend/e2e/admin-access.spec.ts | 2 +- frontend/e2e/auth-guard.spec.ts | 4 +-- frontend/e2e/homepage.spec.ts | 30 +++++++++---------- frontend/e2e/settings-navigation.spec.ts | 4 +-- frontend/tests/__mocks__/components-i18n.tsx | 5 ++++ frontend/tests/__mocks__/next-intl.tsx | 11 +++++++ .../admin/users/UserListTable.test.tsx | 4 +-- 7 files changed, 38 insertions(+), 22 deletions(-) create mode 100644 frontend/tests/__mocks__/components-i18n.tsx create mode 100644 frontend/tests/__mocks__/next-intl.tsx diff --git a/frontend/e2e/admin-access.spec.ts b/frontend/e2e/admin-access.spec.ts index c99b409..523f49d 100644 --- a/frontend/e2e/admin-access.spec.ts +++ b/frontend/e2e/admin-access.spec.ts @@ -31,7 +31,7 @@ test.describe('Admin Access Control', () => { await page.goto('/en/admin'); // Should be redirected away from admin (to login or home) - await page.waitForURL(/\/en\/(auth\/login|$)/); + await page.waitForURL(/\/en(\/login)?$/); expect(page.url()).not.toContain('/admin'); }); diff --git a/frontend/e2e/auth-guard.spec.ts b/frontend/e2e/auth-guard.spec.ts index 543f6c8..05ceb3b 100644 --- a/frontend/e2e/auth-guard.spec.ts +++ b/frontend/e2e/auth-guard.spec.ts @@ -21,9 +21,9 @@ test.describe('AuthGuard - Route Protection', () => { // Wait for page to stabilize await page.waitForTimeout(1000); - // Should either be on login or homepage (not crashing) + // Should either be on login or homepage (not crashing) - with locale prefix const url = page.url(); - expect(url).toMatch(/\/(login)?$/); + expect(url).toMatch(/\/en(\/login)?$/); }); test('should allow access to public routes without auth', async ({ page }) => { diff --git a/frontend/e2e/homepage.spec.ts b/frontend/e2e/homepage.spec.ts index 76125d4..fd6dc24 100644 --- a/frontend/e2e/homepage.spec.ts +++ b/frontend/e2e/homepage.spec.ts @@ -18,7 +18,7 @@ test.describe('Homepage - Desktop Navigation', () => { // Desktop navigation links should be visible (use locator to find within header) const header = page.locator('header').first(); - await expect(header.getByRole('link', { name: 'Components', exact: true })).toBeVisible(); + await expect(header.getByRole('link', { name: 'Design System', exact: true })).toBeVisible(); await expect(header.getByRole('link', { name: 'Admin Demo', exact: true })).toBeVisible(); }); @@ -29,22 +29,22 @@ test.describe('Homepage - Desktop Navigation', () => { await expect(githubLink).toHaveAttribute('target', '_blank'); }); - test('should navigate to components page via header link', async ({ page }) => { - // Click the exact Components link in header navigation + test('should navigate to design system page via header link', async ({ page }) => { + // Click the exact Design System link in header navigation const header = page.locator('header').first(); - const componentsLink = header.getByRole('link', { name: 'Components', exact: true }); + const designSystemLink = header.getByRole('link', { name: 'Design System', exact: true }); // Verify link exists and has correct href - await expect(componentsLink).toBeVisible(); - await expect(componentsLink).toHaveAttribute('href', '/en/dev'); + await expect(designSystemLink).toBeVisible(); + await expect(designSystemLink).toHaveAttribute('href', '/en/dev'); // Click and wait for navigation - await componentsLink.click(); + await designSystemLink.click(); await page.waitForURL('/en/dev', { timeout: 10000 }).catch(() => {}); // Verify URL (might not navigate if /dev page has issues, that's ok for this test) const currentUrl = page.url(); - expect(currentUrl).toMatch(/\/(dev)?$/); + expect(currentUrl).toMatch(/\/en(\/dev)?$/); }); test('should navigate to admin demo via header link', async ({ page }) => { @@ -62,7 +62,7 @@ test.describe('Homepage - Desktop Navigation', () => { // Verify URL (might not navigate if /admin requires auth, that's ok for this test) const currentUrl = page.url(); - expect(currentUrl).toMatch(/\/(admin)?$/); + expect(currentUrl).toMatch(/\/en(\/admin)?$/); }); test('should navigate to login page via header button', async ({ page }) => { @@ -154,7 +154,7 @@ test.describe('Homepage - Mobile Menu Interactions', () => { // Verify URL (might not navigate if /dev page has issues, that's ok) const currentUrl = page.url(); - expect(currentUrl).toMatch(/\/(dev)?$/); + expect(currentUrl).toMatch(/\/en(\/dev)?$/); }); test.skip('should navigate to admin demo from mobile menu', async ({ page }) => { @@ -172,7 +172,7 @@ test.describe('Homepage - Mobile Menu Interactions', () => { // Verify URL (might not navigate if /admin requires auth, that's ok) const currentUrl = page.url(); - expect(currentUrl).toMatch(/\/(admin)?$/); + expect(currentUrl).toMatch(/\/en(\/admin)?$/); }); test.skip('should display Try Demo button in mobile menu', async ({ page }) => { @@ -263,7 +263,7 @@ test.describe('Homepage - Hero Section', () => { // Verify URL (flexible to handle auth redirects) const currentUrl = page.url(); - expect(currentUrl).toMatch(/\/(dev)?$/); + expect(currentUrl).toMatch(/\/en(\/dev)?$/); }); }); @@ -395,7 +395,7 @@ test.describe('Homepage - Animated Terminal', () => { // Verify URL (flexible to handle redirects) const currentUrl = page.url(); - expect(currentUrl).toMatch(/\/(login)?$/); + expect(currentUrl).toMatch(/\/en(\/login)?$/); }); }); @@ -425,7 +425,7 @@ test.describe('Homepage - Feature Sections', () => { // Verify URL (flexible to handle redirects) const currentUrl = page.url(); - expect(currentUrl).toMatch(/\/(login)?$/); + expect(currentUrl).toMatch(/\/en(\/login)?$/); }); test('should navigate to admin from admin panel CTA', async ({ page }) => { @@ -440,7 +440,7 @@ test.describe('Homepage - Feature Sections', () => { // Verify URL (flexible to handle auth redirects) const currentUrl = page.url(); - expect(currentUrl).toMatch(/\/(admin)?$/); + expect(currentUrl).toMatch(/\/en(\/admin)?$/); }); test('should display tech stack section', async ({ page }) => { diff --git a/frontend/e2e/settings-navigation.spec.ts b/frontend/e2e/settings-navigation.spec.ts index d1bd00a..d0db880 100644 --- a/frontend/e2e/settings-navigation.spec.ts +++ b/frontend/e2e/settings-navigation.spec.ts @@ -18,7 +18,7 @@ test.describe('Settings Navigation', () => { test('should navigate from home to settings profile', async ({ page }) => { // Start at home page (auth already cached in storage state) await page.goto('/en'); - await expect(page).toHaveURL('/'); + await expect(page).toHaveURL('/en'); // Navigate to settings/profile await page.goto('/en/settings/profile'); @@ -33,7 +33,7 @@ test.describe('Settings Navigation', () => { test('should navigate from home to settings password', async ({ page }) => { // Start at home page (auth already cached in storage state) await page.goto('/en'); - await expect(page).toHaveURL('/'); + await expect(page).toHaveURL('/en'); // Navigate to settings/password await page.goto('/en/settings/password'); diff --git a/frontend/tests/__mocks__/components-i18n.tsx b/frontend/tests/__mocks__/components-i18n.tsx new file mode 100644 index 0000000..c88c3ef --- /dev/null +++ b/frontend/tests/__mocks__/components-i18n.tsx @@ -0,0 +1,5 @@ +/** + * Mock for @/components/i18n + */ + +export const LocaleSwitcher = () =>
EN
; diff --git a/frontend/tests/__mocks__/next-intl.tsx b/frontend/tests/__mocks__/next-intl.tsx new file mode 100644 index 0000000..10c3f17 --- /dev/null +++ b/frontend/tests/__mocks__/next-intl.tsx @@ -0,0 +1,11 @@ +/** + * Mock for next-intl + */ + +export const useLocale = jest.fn(() => 'en'); +export const useTranslations = jest.fn(() => (key: string) => key); +export const NextIntlClientProvider = ({ children }: { children: React.ReactNode }) => <>{children}; +export const useFormatter = jest.fn(() => ({})); +export const useMessages = jest.fn(() => ({})); +export const useNow = jest.fn(() => new Date()); +export const useTimeZone = jest.fn(() => 'UTC'); diff --git a/frontend/tests/components/admin/users/UserListTable.test.tsx b/frontend/tests/components/admin/users/UserListTable.test.tsx index 567ce98..8172dc8 100644 --- a/frontend/tests/components/admin/users/UserListTable.test.tsx +++ b/frontend/tests/components/admin/users/UserListTable.test.tsx @@ -161,14 +161,14 @@ describe('UserListTable', () => { }); it('calls onSearch after debounce delay', async () => { - const user = userEvent.setup(); + const user = userEvent.setup({ delay: null }); // Disable typing delay for debounce test render(); const searchInput = screen.getByPlaceholderText('Search by name or email...'); await user.type(searchInput, 'alice'); - // Should not call immediately + // Should not call immediately (debounce is 300ms) expect(defaultProps.onSearch).not.toHaveBeenCalled(); // Should call after debounce (300ms)