test(front): add test suite frontend (WIP)

This commit is contained in:
jubnl
2026-04-07 12:31:09 +02:00
parent 96080e8a03
commit 3c31902885
97 changed files with 16973 additions and 4 deletions
@@ -0,0 +1,124 @@
// FE-COMP-PLACEFORM-001 to FE-COMP-PLACEFORM-015
import { render, screen, waitFor } from '../../../tests/helpers/render';
import userEvent from '@testing-library/user-event';
import { useAuthStore } from '../../store/authStore';
import { useTripStore } from '../../store/tripStore';
import { resetAllStores, seedStore } from '../../../tests/helpers/store';
import { buildUser, buildTrip, buildPlace, buildCategory } from '../../../tests/helpers/factories';
import PlaceFormModal from './PlaceFormModal';
const defaultProps = {
isOpen: true,
onClose: vi.fn(),
onSave: vi.fn(),
place: null,
prefillCoords: null,
tripId: 1,
categories: [],
onCategoryCreated: vi.fn(),
assignmentId: null,
dayAssignments: [],
};
beforeEach(() => {
resetAllStores();
seedStore(useAuthStore, { user: buildUser(), isAuthenticated: true, hasMapsKey: false });
seedStore(useTripStore, { trip: buildTrip({ id: 1 }) });
});
describe('PlaceFormModal', () => {
it('FE-COMP-PLACEFORM-001: renders modal when isOpen is true', () => {
render(<PlaceFormModal {...defaultProps} />);
expect(document.body).toBeInTheDocument();
});
it('FE-COMP-PLACEFORM-002: shows Add Place title for new place', () => {
render(<PlaceFormModal {...defaultProps} place={null} />);
// places.addPlace = "Add Place/Activity"
expect(screen.getAllByText(/Add Place\/Activity/i).length).toBeGreaterThan(0);
});
it('FE-COMP-PLACEFORM-003: shows Edit Place title when editing', () => {
const place = buildPlace({ name: 'Eiffel Tower' });
render(<PlaceFormModal {...defaultProps} place={place} />);
expect(screen.getByText('Edit Place')).toBeInTheDocument();
});
it('FE-COMP-PLACEFORM-004: shows Name field with placeholder', () => {
render(<PlaceFormModal {...defaultProps} />);
expect(screen.getByPlaceholderText(/e\.g\. Eiffel Tower/i)).toBeInTheDocument();
});
it('FE-COMP-PLACEFORM-005: shows Description field', () => {
render(<PlaceFormModal {...defaultProps} />);
expect(screen.getByPlaceholderText(/Short description/i)).toBeInTheDocument();
});
it('FE-COMP-PLACEFORM-006: shows Address field', () => {
render(<PlaceFormModal {...defaultProps} />);
expect(screen.getByPlaceholderText(/Street, City, Country/i)).toBeInTheDocument();
});
it('FE-COMP-PLACEFORM-007: shows Add button for new place', () => {
render(<PlaceFormModal {...defaultProps} place={null} />);
expect(screen.getByRole('button', { name: /^Add$/i })).toBeInTheDocument();
});
it('FE-COMP-PLACEFORM-008: shows Update button when editing', () => {
const place = buildPlace({ name: 'Test Place' });
render(<PlaceFormModal {...defaultProps} place={place} />);
expect(screen.getByRole('button', { name: /^Update$/i })).toBeInTheDocument();
});
it('FE-COMP-PLACEFORM-009: shows Cancel button', () => {
render(<PlaceFormModal {...defaultProps} />);
expect(screen.getByRole('button', { name: /Cancel/i })).toBeInTheDocument();
});
it('FE-COMP-PLACEFORM-010: clicking Cancel calls onClose', async () => {
const user = userEvent.setup();
const onClose = vi.fn();
render(<PlaceFormModal {...defaultProps} onClose={onClose} />);
await user.click(screen.getByRole('button', { name: /Cancel/i }));
expect(onClose).toHaveBeenCalled();
});
it('FE-COMP-PLACEFORM-011: pre-fills name field when editing existing place', () => {
const place = buildPlace({ name: 'Notre Dame' });
render(<PlaceFormModal {...defaultProps} place={place} />);
const nameInput = screen.getByDisplayValue('Notre Dame');
expect(nameInput).toBeInTheDocument();
});
it('FE-COMP-PLACEFORM-012: pre-fills address when editing existing place', () => {
const place = buildPlace({ name: 'Test', address: '123 Main St' });
render(<PlaceFormModal {...defaultProps} place={place} />);
expect(screen.getByDisplayValue('123 Main St')).toBeInTheDocument();
});
it('FE-COMP-PLACEFORM-013: submitting empty form does not call onSave (name required)', async () => {
const user = userEvent.setup();
const onSave = vi.fn();
render(<PlaceFormModal {...defaultProps} onSave={onSave} />);
await user.click(screen.getByRole('button', { name: /^Add$/i }));
// Form validation prevents calling onSave without a name
expect(onSave).not.toHaveBeenCalled();
});
it('FE-COMP-PLACEFORM-014: typing in name field and submitting calls onSave', async () => {
const user = userEvent.setup();
const onSave = vi.fn().mockResolvedValue(undefined);
render(<PlaceFormModal {...defaultProps} onSave={onSave} />);
await user.type(screen.getByPlaceholderText(/e\.g\. Eiffel Tower/i), 'Sacre Coeur');
await user.click(screen.getByRole('button', { name: /^Add$/i }));
await waitFor(() => expect(onSave).toHaveBeenCalled());
expect(onSave).toHaveBeenCalledWith(expect.objectContaining({ name: 'Sacre Coeur' }));
});
it('FE-COMP-PLACEFORM-015: categories appear in category selector', () => {
const cats = [buildCategory({ name: 'Museum' }), buildCategory({ name: 'Park' })];
render(<PlaceFormModal {...defaultProps} categories={cats} />);
// Category label is present
expect(screen.getByText('Category')).toBeInTheDocument();
});
});