feat(tests): Jest backend (38 tests), Jest RTL frontend (28 tests), Playwright E2E spec
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
import React from 'react';
|
||||
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import AnimalForm from '../src/components/AnimalForm';
|
||||
import * as client from '../src/api/client';
|
||||
|
||||
jest.mock('../src/api/client', () => ({
|
||||
animalsApi: {
|
||||
create: jest.fn(),
|
||||
update: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const EXP_ID = 'exp-001';
|
||||
const onSuccess = jest.fn();
|
||||
const onCancel = jest.fn();
|
||||
|
||||
beforeEach(() => jest.clearAllMocks());
|
||||
|
||||
describe('AnimalForm', () => {
|
||||
it('renders Animal ID and Animal Name fields', () => {
|
||||
render(<AnimalForm experimentId={EXP_ID} onSuccess={onSuccess} onCancel={onCancel} />);
|
||||
expect(screen.getByLabelText(/animal id/i)).toBeInTheDocument();
|
||||
expect(screen.getByLabelText(/animal name/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows required field errors on empty submit', async () => {
|
||||
render(<AnimalForm experimentId={EXP_ID} onSuccess={onSuccess} onCancel={onCancel} />);
|
||||
fireEvent.click(screen.getByRole('button', { name: /add animal/i }));
|
||||
expect(await screen.findAllByRole('alert')).toHaveLength(2);
|
||||
expect(client.animalsApi.create).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls create with correct payload', async () => {
|
||||
const animal = { id: 'a-1', animal_id_string: 'M-001', animal_name: 'Whiskers', experiment_id: EXP_ID };
|
||||
client.animalsApi.create.mockResolvedValue(animal);
|
||||
|
||||
render(<AnimalForm experimentId={EXP_ID} onSuccess={onSuccess} onCancel={onCancel} />);
|
||||
await userEvent.type(screen.getByLabelText(/animal id/i), 'M-001');
|
||||
await userEvent.type(screen.getByLabelText(/animal name/i), 'Whiskers');
|
||||
fireEvent.click(screen.getByRole('button', { name: /add animal/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(client.animalsApi.create).toHaveBeenCalledWith({
|
||||
animal_id_string: 'M-001',
|
||||
animal_name: 'Whiskers',
|
||||
experiment_id: EXP_ID,
|
||||
})
|
||||
);
|
||||
await waitFor(() => expect(onSuccess).toHaveBeenCalledWith(animal));
|
||||
});
|
||||
|
||||
it('pre-fills fields for existing animal and uses update API', async () => {
|
||||
const existing = { id: 'a-1', animal_id_string: 'M-001', animal_name: 'Whiskers' };
|
||||
const updated = { ...existing, animal_name: 'Mr Whiskers' };
|
||||
client.animalsApi.update.mockResolvedValue(updated);
|
||||
|
||||
render(<AnimalForm existing={existing} experimentId={EXP_ID} onSuccess={onSuccess} onCancel={onCancel} />);
|
||||
expect(screen.getByDisplayValue('Whiskers')).toBeInTheDocument();
|
||||
|
||||
const nameInput = screen.getByLabelText(/animal name/i);
|
||||
await userEvent.clear(nameInput);
|
||||
await userEvent.type(nameInput, 'Mr Whiskers');
|
||||
fireEvent.click(screen.getByRole('button', { name: /save changes/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(client.animalsApi.update).toHaveBeenCalledWith('a-1', {
|
||||
animal_id_string: 'M-001',
|
||||
animal_name: 'Mr Whiskers',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user