We use cookies to enhance your experience on the site
CodeWorlds

Testing Interactions -- Flight Simulator

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 -- Basic Simulation

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});

Form Events

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 -- Realistic Simulation

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});

Key Differences: fireEvent vs userEvent

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 end

Click and Double Click

1test('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});

Keyboard Interactions

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});

Clearing and Selecting Text

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});

Selectbox and Checkbox

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});

Testing Callbacks and Props

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});
Go to CodeWorlds