fix: resolve DailyStatusForm test stall and add label accessibility
- Use module-level EMPTY_TEMPLATE constant as default prop to prevent useEffect infinite loop (new [] each render changed identity every cycle) - Add htmlFor to date and dynamic field labels for proper a11y association - Add role=alert to date error paragraph so tests can find it - Update tests to pass a template with builtin fields (required by template- driven component design) and mock experimentsApi - Add --max-old-space-size=8192 to test scripts to prevent OOM on full suite All 72 frontend tests now pass across 7 suites. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,17 +9,27 @@ jest.mock('../src/api/client', () => ({
|
||||
create: jest.fn(),
|
||||
update: jest.fn(),
|
||||
},
|
||||
experimentsApi: {
|
||||
updateTemplate: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const ANIMAL_ID = 'animal-001';
|
||||
const onSuccess = jest.fn();
|
||||
const onCancel = jest.fn();
|
||||
|
||||
const BUILTIN_TEMPLATE = [
|
||||
{ fieldId: 'f1', key: 'vitals', label: 'Vitals', type: 'textarea', builtin: true, active: true, width: 100 },
|
||||
{ fieldId: 'f2', key: 'treatment', label: 'Treatment', type: 'textarea', builtin: true, active: true, width: 100 },
|
||||
{ fieldId: 'f3', key: 'notes', label: 'Notes', type: 'textarea', builtin: true, active: true, width: 100 },
|
||||
{ fieldId: 'f4', key: 'experiment_description', label: 'Experiment Description', type: 'textarea', builtin: true, active: true, width: 100 },
|
||||
];
|
||||
|
||||
beforeEach(() => jest.clearAllMocks());
|
||||
|
||||
describe('DailyStatusForm', () => {
|
||||
it('renders date field (required) and optional fields', () => {
|
||||
render(<DailyStatusForm animalId={ANIMAL_ID} onSuccess={onSuccess} onCancel={onCancel} />);
|
||||
render(<DailyStatusForm animalId={ANIMAL_ID} template={BUILTIN_TEMPLATE} onSuccess={onSuccess} onCancel={onCancel} />);
|
||||
expect(screen.getByLabelText(/date/i)).toBeInTheDocument();
|
||||
expect(screen.getByLabelText(/vitals/i)).toBeInTheDocument();
|
||||
expect(screen.getByLabelText(/treatment/i)).toBeInTheDocument();
|
||||
@@ -28,13 +38,13 @@ describe('DailyStatusForm', () => {
|
||||
});
|
||||
|
||||
it('pre-fills date with today by default', () => {
|
||||
render(<DailyStatusForm animalId={ANIMAL_ID} onSuccess={onSuccess} onCancel={onCancel} />);
|
||||
render(<DailyStatusForm animalId={ANIMAL_ID} template={BUILTIN_TEMPLATE} onSuccess={onSuccess} onCancel={onCancel} />);
|
||||
const today = new Date().toISOString().slice(0, 10);
|
||||
expect(screen.getByLabelText(/date/i)).toHaveValue(today);
|
||||
});
|
||||
|
||||
it('shows error when date is cleared', async () => {
|
||||
render(<DailyStatusForm animalId={ANIMAL_ID} onSuccess={onSuccess} onCancel={onCancel} />);
|
||||
render(<DailyStatusForm animalId={ANIMAL_ID} template={BUILTIN_TEMPLATE} onSuccess={onSuccess} onCancel={onCancel} />);
|
||||
const dateInput = screen.getByLabelText(/date/i);
|
||||
await userEvent.clear(dateInput);
|
||||
fireEvent.click(screen.getByRole('button', { name: /log status/i }));
|
||||
@@ -46,11 +56,10 @@ describe('DailyStatusForm', () => {
|
||||
const status = { id: 's-1', animal_id: ANIMAL_ID, date: '2024-06-01', vitals: 'HR 72' };
|
||||
client.dailyStatusesApi.create.mockResolvedValue(status);
|
||||
|
||||
render(<DailyStatusForm animalId={ANIMAL_ID} onSuccess={onSuccess} onCancel={onCancel} />);
|
||||
render(<DailyStatusForm animalId={ANIMAL_ID} template={BUILTIN_TEMPLATE} onSuccess={onSuccess} onCancel={onCancel} />);
|
||||
|
||||
const dateInput = screen.getByLabelText(/date/i);
|
||||
await userEvent.clear(dateInput);
|
||||
await userEvent.type(dateInput, '2024-06-01');
|
||||
fireEvent.change(dateInput, { target: { value: '2024-06-01' } });
|
||||
|
||||
await userEvent.type(screen.getByLabelText(/vitals/i), 'HR 72');
|
||||
|
||||
@@ -76,6 +85,7 @@ describe('DailyStatusForm', () => {
|
||||
render(
|
||||
<DailyStatusForm
|
||||
existing={existing}
|
||||
template={BUILTIN_TEMPLATE}
|
||||
animalId={ANIMAL_ID}
|
||||
onSuccess={onSuccess}
|
||||
onCancel={onCancel}
|
||||
@@ -86,7 +96,7 @@ describe('DailyStatusForm', () => {
|
||||
});
|
||||
|
||||
it('calls onCancel when Cancel is clicked', () => {
|
||||
render(<DailyStatusForm animalId={ANIMAL_ID} onSuccess={onSuccess} onCancel={onCancel} />);
|
||||
render(<DailyStatusForm animalId={ANIMAL_ID} template={BUILTIN_TEMPLATE} onSuccess={onSuccess} onCancel={onCancel} />);
|
||||
fireEvent.click(screen.getByRole('button', { name: /cancel/i }));
|
||||
expect(onCancel).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user