import React from 'react'; import '@testing-library/jest-dom'; import { render, screen } from '@testing-library/react'; import { MemoryRouter } from 'react-router-dom'; import VerifyEmailPage from './views/VerifyEmailPage'; import { I18nProvider } from './i18n/I18nProvider'; import { api, getApiErrorMessage } from './api'; const mockedApi = api as jest.Mocked; // CRA's jest config sets resetMocks: true, which wipes the initial implementation given to // jest.fn() in setupTests.ts before every test -- re-arm it here so error-derived text is testable. const mockedGetApiErrorMessage = getApiErrorMessage as jest.Mock; function renderVerifyEmailPage(search: string, emailChange = false) { const path = emailChange ? '/confirm-email-change' : '/verify-email'; window.history.pushState({}, '', `${path}${search}`); return render( , ); } describe('VerifyEmailPage', () => { beforeEach(() => { mockedApi.post.mockReset(); mockedGetApiErrorMessage.mockImplementation((e: any, fallback?: string) => { const data = e?.response?.data; return typeof data === 'string' && data.trim() ? data.trim() : fallback; }); }); it('confirms the account and shows success when the link is valid', async () => { mockedApi.post.mockResolvedValueOnce({ data: {} } as any); renderVerifyEmailPage('?userId=user-1&token=good-token'); expect(await screen.findByText('Your email has been verified. You can now sign in.')).toBeInTheDocument(); expect(mockedApi.post).toHaveBeenCalledWith('/auth/verify-email', { userId: 'user-1', token: 'good-token' }); }); it('shows an error when the link is invalid or expired', async () => { mockedApi.post.mockRejectedValueOnce({ response: { status: 400, data: 'Invalid or expired link.' } }); renderVerifyEmailPage('?userId=user-1&token=bad-token'); expect(await screen.findByText('Invalid or expired link.')).toBeInTheDocument(); }); it('shows an error without calling the API when the link is missing userId/token', async () => { renderVerifyEmailPage(''); expect(await screen.findByText('Missing user/token in link.')).toBeInTheDocument(); expect(mockedApi.post).not.toHaveBeenCalled(); }); it('confirms a pending email change and requires a fresh sign-in', async () => { mockedApi.post.mockResolvedValueOnce({ data: {} } as any); renderVerifyEmailPage('?userId=user-1&email=new%40example.com&token=change-token', true); expect(await screen.findByText('Your email has changed. Sign in again with the new address.')).toBeInTheDocument(); expect(mockedApi.post).toHaveBeenCalledWith('/auth/email-change/confirm', { userId: 'user-1', email: 'new@example.com', token: 'change-token' }); }); });