Files
jobtrackingapp/job-tracker-ui/src/login-page.test.tsx
T

85 lines
3.1 KiB
TypeScript

import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MemoryRouter } from 'react-router-dom';
import LoginPage from './pages/LoginPage';
import { ToastProvider } from './toast';
import { I18nProvider } from './i18n/I18nProvider';
import { api } from './api';
const mockNavigate = jest.fn();
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useNavigate: () => mockNavigate,
}));
const mockedApi = api as jest.Mocked<typeof api>;
let consoleErrorSpy: jest.SpyInstance;
function renderLoginPage() {
return render(
<MemoryRouter future={{ v7_startTransition: true, v7_relativeSplatPath: true }}>
<I18nProvider>
<ToastProvider>
<LoginPage />
</ToastProvider>
</I18nProvider>
</MemoryRouter>,
);
}
describe('LoginPage', () => {
beforeEach(() => {
const originalConsoleError = console.error.bind(console);
consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation((...args: unknown[]) => {
const [first] = args;
const message = typeof first === 'string' ? first : '';
if (message.includes('ForwardRef(TouchRipple) inside a test was not wrapped in act')) {
return;
}
originalConsoleError(...args);
});
window.localStorage.clear();
window.sessionStorage.clear();
mockedApi.post.mockReset();
mockNavigate.mockReset();
});
afterEach(() => {
consoleErrorSpy.mockRestore();
});
it('posts remember-me preference without storing an auth token in browser storage', async () => {
mockedApi.post.mockResolvedValueOnce({ data: { authenticated: true, provider: 'local' } } as any);
mockedApi.get.mockResolvedValueOnce({ data: { roles: [], email: 'person@example.com', userName: 'person' } } as any);
renderLoginPage();
await screen.findByLabelText('Email');
await userEvent.type(screen.getByLabelText('Email'), 'person@example.com');
await userEvent.type(screen.getByLabelText('Current password'), 'hunter2');
await userEvent.click(screen.getByLabelText('Remember me'));
await userEvent.click(screen.getByRole('button', { name: 'Sign in' }));
await waitFor(() => expect(mockedApi.post).toHaveBeenCalledWith('/auth/login', { email: 'person@example.com', password: 'hunter2', rememberMe: false }));
await waitFor(() => expect(mockedApi.get).toHaveBeenCalledWith('/auth/me'));
expect(window.sessionStorage.getItem('authToken')).toBeNull();
expect(window.localStorage.getItem('authToken')).toBeNull();
expect(window.localStorage.getItem('authTokenPersistence')).toBe('session');
});
it('opens the separate forgot-password page with the typed email prefilled', async () => {
renderLoginPage();
await screen.findByLabelText('Email');
await userEvent.type(screen.getByLabelText('Email'), 'person@example.com');
await userEvent.click(screen.getByRole('button', { name: 'Forgot password?' }));
expect(mockNavigate).toHaveBeenCalledWith('/forgot-password?email=person%40example.com');
});
});