# User Interactions with user-event — Jest, Vitest & Testing Library

Source: https://www.skillbyai.com/en/javascript-testing/c-events

> Simulate real typing and clicking.

## user-event over fireEvent

`fireEvent` dispatches one DOM event. Real interactions are sequences: a click involves pointer down/up, focus changes and the click itself; typing fires keydown, keypress, input and keyup per character and respects `maxLength` and disabled fields. **`@testing-library/user-event`** simulates those sequences. In version 14, create a session with **`const user = userEvent.setup()`** before rendering, and **`await`** every call: `await user.click(el)`, `await user.type(input, 'hello')`, `await user.clear(input)`, `await user.selectOptions(select, 'UK')`, `await user.keyboard('{Enter}')`, `await user.tab()`. If you use fake timers, pass `advanceTimers` to `setup` so user-event's internal delays advance too.

## Filling in and submitting a form

The submit handler is a mock prop.

```tsx
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { expect, it, vi } from 'vitest';
import { LoginForm } from './LoginForm';

it('submits the email and password', async () => {
  const user = userEvent.setup();
  const onSubmit = vi.fn();
  render(<LoginForm onSubmit={onSubmit} />);

  await user.type(screen.getByRole('textbox', { name: 'Email' }), 'asha@example.com');
  await user.type(screen.getByLabelText('Password'), 'correct horse');
  await user.click(screen.getByRole('button', { name: 'Log in' }));

  expect(onSubmit).toHaveBeenCalledWith({ email: 'asha@example.com', password: 'correct horse' });
});

it('keeps the button disabled until both fields are filled', async () => {
  const user = userEvent.setup();
  render(<LoginForm onSubmit={vi.fn()} />);

  await user.type(screen.getByRole('textbox', { name: 'Email' }), 'asha@example.com');
  expect(screen.getByRole('button', { name: 'Log in' })).toBeDisabled();
});
```

## A real hand versus a poke

fireEvent is poking a button with a stick from across the room; user-event is a hand that moves the mouse, presses, releases and lets the page react to every step, exactly as a person would.

**Quiz:** How should user-event v14 interactions be called?

- [ ] Wrap every call in setTimeout
- [ ] Call userEvent.click synchronously and never await
- [x] Create user = userEvent.setup() and await each call such as await user.click(button)
- [ ] Only through fireEvent

*Answer:* Create user = userEvent.setup() and await each call such as await user.click(button). The v14 API is asynchronous.
