In a real spaceship, the pilot presses buttons, turns knobs, and enters data on the keyboard. In React tests, we must simulate the same interactions to ensure the application responds correctly.
fireEvent is a React Testing Library tool for triggering DOM events:1import { render, screen, fireEvent } from '@testing-library/react';
2
3test('toggles engine status on button click', () => {
4 render(<EnginePanel />);
5
6 const toggleButton = screen.getByRole('button', { name: 'Toggle Engine' });
7 expect(screen.getByText('Engine: OFF')).toBeInTheDocument();
8
9 fireEvent.click(toggleButton);
10 expect(screen.getByText('Engine: ON')).toBeInTheDocument();
11
12 fireEvent.click(toggleButton);
13 expect(screen.getByText('Engine: OFF')).toBeInTheDocument();
14});1test('updates pilot name input', () => {
2 render(<PilotForm />);
3
4 const nameInput = screen.getByLabelText('Pilot Name');
5 fireEvent.change(nameInput, { target: { value: 'Commander Nova' } });
6
7 expect(nameInput).toHaveValue('Commander Nova');
8});
9
10test('submits mission form', () => {
11 const mockSubmit = jest.fn();
12 render(<MissionForm onSubmit={mockSubmit} />);
13
14 fireEvent.change(screen.getByLabelText('Destination'), {
15 target: { value: 'Mars' }
16 });
17 fireEvent.click(screen.getByRole('button', { name: 'Launch' }));
18
19 expect(mockSubmit).toHaveBeenCalledWith({ destination: 'Mars' });
20});userEvent is a more advanced library that simulates events the way a real user does them. Instead of a single change event, it simulates pressing individual keys:1import userEvent from '@testing-library/user-event';
2
3test('types pilot name realistically', async () => {
4 const user = userEvent.setup();
5 render(<PilotForm />);
6
7 const nameInput = screen.getByLabelText('Pilot Name');
8 await user.type(nameInput, 'Commander Nova');
9
10 expect(nameInput).toHaveValue('Commander Nova');
11});1// fireEvent -- fast but less realistic
2fireEvent.change(input, { target: { value: 'text' } });
3// Triggers ONLY the change event
4
5// userEvent -- slower but realistic
6await user.type(input, 'text');
7// Triggers focus, keyDown, keyPress, input, keyUp
8// for EACH character, plus change at the end1test('handles click and double click', async () => {
2 const user = userEvent.setup();
3 render(<NavigationPanel />);
4
5 // Single click
6 await user.click(screen.getByRole('button', { name: 'Select' }));
7
8 // Double click
9 await user.dblClick(screen.getByText('Mission Details'));
10
11 // Right click
12 await user.pointer({
13 keys: '[MouseRight]',
14 target: screen.getByText('Options')
15 });
16});1test('keyboard navigation in mission list', async () => {
2 const user = userEvent.setup();
3 render(<MissionList />);
4
5 // Tab to next element
6 await user.tab();
7 expect(screen.getByText('Mission Alpha')).toHaveFocus();
8
9 // Tab to the next one
10 await user.tab();
11 expect(screen.getByText('Mission Beta')).toHaveFocus();
12
13 // Enter to select
14 await user.keyboard('{Enter}');
15 expect(screen.getByText('Selected: Mission Beta')).toBeInTheDocument();
16});1test('clears and replaces input value', async () => {
2 const user = userEvent.setup();
3 render(<CoordinateInput defaultValue="0,0,0" />);
4
5 const input = screen.getByRole('textbox');
6 // Select all and clear
7 await user.clear(input);
8 expect(input).toHaveValue('');
9
10 // Type new value
11 await user.type(input, '42,15,88');
12 expect(input).toHaveValue('42,15,88');
13});1test('selects planet from dropdown', async () => {
2 const user = userEvent.setup();
3 render(<PlanetSelector />);
4
5 await user.selectOptions(
6 screen.getByRole('combobox'),
7 screen.getByRole('option', { name: 'Mars' })
8 );
9
10 expect(screen.getByRole('option', { name: 'Mars' }).selected).toBe(true);
11});
12
13test('toggles autopilot checkbox', async () => {
14 const user = userEvent.setup();
15 render(<AutopilotSwitch />);
16
17 const checkbox = screen.getByRole('checkbox', { name: 'Autopilot' });
18 expect(checkbox).not.toBeChecked();
19
20 await user.click(checkbox);
21 expect(checkbox).toBeChecked();
22});1test('calls onLaunch when all systems ready', async () => {
2 const user = userEvent.setup();
3 const handleLaunch = jest.fn();
4
5 render(<LaunchButton onLaunch={handleLaunch} systemsReady={true} />);
6
7 await user.click(screen.getByRole('button', { name: 'Launch' }));
8 expect(handleLaunch).toHaveBeenCalledTimes(1);
9});
10
11test('does not call onLaunch when systems not ready', async () => {
12 const user = userEvent.setup();
13 const handleLaunch = jest.fn();
14
15 render(<LaunchButton onLaunch={handleLaunch} systemsReady={false} />);
16
17 await user.click(screen.getByRole('button', { name: 'Launch' }));
18 expect(handleLaunch).not.toHaveBeenCalled();
19});