import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { vi, test, expect, beforeEach } from 'vitest'; vi.mock('../syncService.js', () => ({ requestPasswordReset: vi.fn(), resetPassword: vi.fn() })); import ResetPasswordForm from './ResetPasswordForm.jsx'; import { requestPasswordReset, resetPassword } from '../syncService.js'; beforeEach(() => { vi.clearAllMocks(); requestPasswordReset.mockResolvedValue({ ok: true, data: { message: 'A code was sent if you have a topic.' } }); resetPassword.mockResolvedValue({ ok: true, data: { ok: true } }); }); test('asks for a code, then sets the new password with it', async () => { const user = userEvent.setup(); const onDone = vi.fn(); render( {}} />); await user.click(screen.getByRole('button', { name: /send me a code/i })); expect(requestPasswordReset).toHaveBeenCalledWith('me@x.co'); expect(await screen.findByText(/A code was sent/)).toBeInTheDocument(); await user.type(screen.getByLabelText(/^Code/), 'ABCD2345'); await user.type(screen.getByLabelText(/^New password/), 'brand-new-pass'); await user.click(screen.getByRole('button', { name: /change password/i })); expect(resetPassword).toHaveBeenCalledWith({ email: 'me@x.co', code: 'ABCD2345', newPassword: 'brand-new-pass', token: undefined }); await user.click(await screen.findByRole('button', { name: /back to sign in/i })); expect(onDone).toHaveBeenCalled(); }); test('a wrong code shows the server\'s message and stays on the form', async () => { resetPassword.mockResolvedValue({ ok: false, error: 'That code is wrong or has expired. Ask for a new one.' }); const user = userEvent.setup(); render( {}} onBack={() => {}} />); await user.click(screen.getByRole('button', { name: /i already have a code/i })); await user.type(screen.getByLabelText(/^Code/), 'WRONG123'); await user.type(screen.getByLabelText(/^New password/), 'brand-new-pass'); await user.click(screen.getByRole('button', { name: /change password/i })); expect(await screen.findByRole('alert')).toHaveTextContent(/wrong or has expired/); }); test('an authenticator code is passed along when one is typed', async () => { const user = userEvent.setup(); render( {}} onBack={() => {}} />); await user.click(screen.getByRole('button', { name: /i already have a code/i })); await user.type(screen.getByLabelText(/^Code/), 'ABCD2345'); await user.type(screen.getByLabelText(/^New password/), 'brand-new-pass'); await user.type(screen.getByLabelText(/Authenticator code/), '123456'); await user.click(screen.getByRole('button', { name: /change password/i })); expect(resetPassword).toHaveBeenCalledWith(expect.objectContaining({ token: '123456' })); });