158 lines
6.0 KiB
TypeScript
158 lines
6.0 KiB
TypeScript
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
import { vi } from 'vitest';
|
|
import ResetPassword from './ResetPassword';
|
|
import { axiosInstance } from '../../axiosApi.js';
|
|
import { MemoryRouter } from 'react-router-dom';
|
|
|
|
// Mock axiosInstance
|
|
vi.mock('../../axiosApi.js', () => ({
|
|
axiosInstance: {
|
|
post: vi.fn(),
|
|
},
|
|
}));
|
|
|
|
// Mock useSearchParams
|
|
const mockGet = vi.fn();
|
|
vi.mock('react-router-dom', async () => {
|
|
const actual = await vi.importActual('react-router-dom');
|
|
return {
|
|
...actual,
|
|
useSearchParams: () => [{ get: mockGet }],
|
|
};
|
|
});
|
|
|
|
describe('ResetPassword', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
mockGet.mockImplementation((key) => {
|
|
if (key === 'email') return 'test@example.com';
|
|
if (key === 'code') return '123456';
|
|
return null;
|
|
});
|
|
});
|
|
|
|
const renderComponent = () => {
|
|
render(
|
|
<MemoryRouter>
|
|
<ResetPassword />
|
|
</MemoryRouter>
|
|
);
|
|
};
|
|
|
|
it('renders correctly', () => {
|
|
renderComponent();
|
|
expect(screen.getByRole('heading', { name: /Reset Password/i })).toBeInTheDocument();
|
|
expect(screen.getByLabelText('Email')).toBeInTheDocument();
|
|
expect(screen.getByLabelText('Reset Code')).toBeInTheDocument();
|
|
expect(screen.getByLabelText('Password')).toBeInTheDocument();
|
|
expect(screen.getByLabelText('Confirm Password')).toBeInTheDocument();
|
|
expect(screen.getByRole('button', { name: /Reset Password/i })).toBeInTheDocument();
|
|
});
|
|
|
|
it('updates inputs', () => {
|
|
renderComponent();
|
|
const emailInput = screen.getByLabelText('Email');
|
|
const codeInput = screen.getByLabelText('Reset Code');
|
|
const passwordInput = screen.getByLabelText('Password');
|
|
const confirmInput = screen.getByLabelText('Confirm Password');
|
|
|
|
fireEvent.change(emailInput, { target: { value: 'new@example.com' } });
|
|
fireEvent.change(codeInput, { target: { value: '654321' } });
|
|
fireEvent.change(passwordInput, { target: { value: 'password123' } });
|
|
fireEvent.change(confirmInput, { target: { value: 'password123' } });
|
|
|
|
expect(emailInput).toHaveValue('new@example.com');
|
|
expect(codeInput).toHaveValue('654321');
|
|
expect(passwordInput).toHaveValue('password123');
|
|
expect(confirmInput).toHaveValue('password123');
|
|
});
|
|
|
|
it('shows error if passwords do not match', async () => {
|
|
renderComponent();
|
|
const passwordInput = screen.getByLabelText('Password');
|
|
const confirmInput = screen.getByLabelText('Confirm Password');
|
|
const submitButton = screen.getByRole('button', { name: /Reset Password/i });
|
|
|
|
fireEvent.change(passwordInput, { target: { value: 'password123' } });
|
|
fireEvent.change(confirmInput, { target: { value: 'password456' } });
|
|
fireEvent.click(submitButton);
|
|
|
|
expect(screen.getByText("Passwords don't match")).toBeInTheDocument();
|
|
expect(axiosInstance.post).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('calls API and shows success message on valid submission', async () => {
|
|
(axiosInstance.post as any).mockResolvedValue({ status: 200 });
|
|
renderComponent();
|
|
|
|
// Email and Code are pre-filled from mock
|
|
const passwordInput = screen.getByLabelText('Password');
|
|
const confirmInput = screen.getByLabelText('Confirm Password');
|
|
const submitButton = screen.getByRole('button', { name: /Reset Password/i });
|
|
|
|
fireEvent.change(passwordInput, { target: { value: 'password123' } });
|
|
fireEvent.change(confirmInput, { target: { value: 'password123' } });
|
|
fireEvent.click(submitButton);
|
|
|
|
expect(submitButton).toBeDisabled();
|
|
expect(screen.getByText('Resetting...')).toBeInTheDocument();
|
|
|
|
await waitFor(() => {
|
|
expect(axiosInstance.post).toHaveBeenCalledWith('password-reset/confirm/', {
|
|
email: 'test@example.com',
|
|
code: '123456',
|
|
new_password: 'password123',
|
|
new_password2: 'password123',
|
|
});
|
|
expect(screen.getByText('Reset Successfully')).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
it('shows error message on API failure', async () => {
|
|
const errorMessage = 'Invalid token';
|
|
(axiosInstance.post as any).mockRejectedValue({
|
|
response: {
|
|
data: {
|
|
detail: errorMessage,
|
|
},
|
|
},
|
|
});
|
|
|
|
renderComponent();
|
|
|
|
const passwordInput = screen.getByLabelText('Password');
|
|
const confirmInput = screen.getByLabelText('Confirm Password');
|
|
const submitButton = screen.getByRole('button', { name: /Reset Password/i });
|
|
|
|
fireEvent.change(passwordInput, { target: { value: 'password123' } });
|
|
fireEvent.change(confirmInput, { target: { value: 'password123' } });
|
|
fireEvent.click(submitButton);
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByText(errorMessage)).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
it('shows error if email or code is missing', async () => {
|
|
mockGet.mockReturnValue(null); // No URL params
|
|
renderComponent();
|
|
|
|
// Inputs should be empty
|
|
const emailInput = screen.getByLabelText('Email');
|
|
const codeInput = screen.getByLabelText('Reset Code');
|
|
expect(emailInput).toHaveValue('');
|
|
expect(codeInput).toHaveValue('');
|
|
|
|
const passwordInput = screen.getByLabelText('Password');
|
|
const confirmInput = screen.getByLabelText('Confirm Password');
|
|
const submitButton = screen.getByRole('button', { name: /Reset Password/i });
|
|
|
|
fireEvent.change(passwordInput, { target: { value: 'password123' } });
|
|
fireEvent.change(confirmInput, { target: { value: 'password123' } });
|
|
fireEvent.click(submitButton);
|
|
|
|
expect(screen.getByText('Please provide both email and reset code.')).toBeInTheDocument();
|
|
expect(axiosInstance.post).not.toHaveBeenCalled();
|
|
});
|
|
});
|