or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-testing.mdasync.mdcomponent-rendering.mdconfiguration.mdelement-queries.mdevent-simulation.mdevents.mdhook-testing.mdhooks.mdindex.mdqueries.mdquick-reference.mdrendering.md

events.mddocs/

0

# Firing Events

1

2

Simulate user interactions with automatic act() wrapping for React state updates.

3

4

## API

5

6

Main utility for firing DOM events. Automatically wrapped in `act()` for proper React state updates.

7

8

```typescript { .api }

9

/**

10

* Fire a DOM event on an element

11

* @param element - Target element

12

* @param event - Event object to fire

13

* @returns true if event was not cancelled

14

*/

15

const fireEvent: {

16

(element: HTMLElement, event: Event): boolean;

17

18

// Mouse Events

19

click(element: HTMLElement, options?: MouseEventInit): void;

20

dblClick(element: HTMLElement, options?: MouseEventInit): void;

21

mouseDown(element: HTMLElement, options?: MouseEventInit): void;

22

mouseUp(element: HTMLElement, options?: MouseEventInit): void;

23

mouseMove(element: HTMLElement, options?: MouseEventInit): void;

24

mouseOver(element: HTMLElement, options?: MouseEventInit): void;

25

mouseOut(element: HTMLElement, options?: MouseEventInit): void;

26

mouseEnter(element: HTMLElement, options?: MouseEventInit): void;

27

mouseLeave(element: HTMLElement, options?: MouseEventInit): void;

28

contextMenu(element: HTMLElement, options?: MouseEventInit): void;

29

wheel(element: HTMLElement, options?: WheelEventInit): void;

30

31

// Pointer Events

32

pointerDown(element: HTMLElement, options?: PointerEventInit): void;

33

pointerUp(element: HTMLElement, options?: PointerEventInit): void;

34

pointerMove(element: HTMLElement, options?: PointerEventInit): void;

35

pointerOver(element: HTMLElement, options?: PointerEventInit): void;

36

pointerOut(element: HTMLElement, options?: PointerEventInit): void;

37

pointerEnter(element: HTMLElement, options?: PointerEventInit): void;

38

pointerLeave(element: HTMLElement, options?: PointerEventInit): void;

39

pointerCancel(element: HTMLElement, options?: PointerEventInit): void;

40

gotPointerCapture(element: HTMLElement, options?: PointerEventInit): void;

41

lostPointerCapture(element: HTMLElement, options?: PointerEventInit): void;

42

43

// Keyboard Events

44

keyDown(element: HTMLElement, options?: KeyboardEventInit): void;

45

keyUp(element: HTMLElement, options?: KeyboardEventInit): void;

46

keyPress(element: HTMLElement, options?: KeyboardEventInit): void;

47

48

// Focus Events

49

focus(element: HTMLElement, options?: FocusEventInit): void;

50

blur(element: HTMLElement, options?: FocusEventInit): void;

51

focusIn(element: HTMLElement, options?: FocusEventInit): void;

52

focusOut(element: HTMLElement, options?: FocusEventInit): void;

53

54

// Form Events

55

change(element: HTMLElement, options?: EventInit): void;

56

input(element: HTMLElement, options?: InputEventInit): void;

57

invalid(element: HTMLElement, options?: EventInit): void;

58

submit(element: HTMLElement, options?: EventInit): void;

59

reset(element: HTMLElement, options?: EventInit): void;

60

select(element: HTMLElement, options?: EventInit): void;

61

62

// Clipboard Events

63

copy(element: HTMLElement, options?: ClipboardEventInit): void;

64

cut(element: HTMLElement, options?: ClipboardEventInit): void;

65

paste(element: HTMLElement, options?: ClipboardEventInit): void;

66

67

// Composition Events

68

compositionStart(element: HTMLElement, options?: CompositionEventInit): void;

69

compositionUpdate(element: HTMLElement, options?: CompositionEventInit): void;

70

compositionEnd(element: HTMLElement, options?: CompositionEventInit): void;

71

72

// Drag Events

73

drag(element: HTMLElement, options?: DragEventInit): void;

74

dragEnd(element: HTMLElement, options?: DragEventInit): void;

75

dragEnter(element: HTMLElement, options?: DragEventInit): void;

76

dragExit(element: HTMLElement, options?: DragEventInit): void;

77

dragLeave(element: HTMLElement, options?: DragEventInit): void;

78

dragOver(element: HTMLElement, options?: DragEventInit): void;

79

dragStart(element: HTMLElement, options?: DragEventInit): void;

80

drop(element: HTMLElement, options?: DragEventInit): void;

81

82

// Touch Events

83

touchStart(element: HTMLElement, options?: TouchEventInit): void;

84

touchMove(element: HTMLElement, options?: TouchEventInit): void;

85

touchEnd(element: HTMLElement, options?: TouchEventInit): void;

86

touchCancel(element: HTMLElement, options?: TouchEventInit): void;

87

88

// Animation Events

89

animationStart(element: HTMLElement, options?: AnimationEventInit): void;

90

animationEnd(element: HTMLElement, options?: AnimationEventInit): void;

91

animationIteration(element: HTMLElement, options?: AnimationEventInit): void;

92

93

// Transition Events

94

transitionEnd(element: HTMLElement, options?: TransitionEventInit): void;

95

96

// Media Events

97

abort(element: HTMLElement, options?: EventInit): void;

98

canPlay(element: HTMLElement, options?: EventInit): void;

99

canPlayThrough(element: HTMLElement, options?: EventInit): void;

100

durationChange(element: HTMLElement, options?: EventInit): void;

101

emptied(element: HTMLElement, options?: EventInit): void;

102

encrypted(element: HTMLElement, options?: EventInit): void;

103

ended(element: HTMLElement, options?: EventInit): void;

104

error(element: HTMLElement, options?: EventInit): void;

105

load(element: HTMLElement, options?: EventInit): void;

106

loadedData(element: HTMLElement, options?: EventInit): void;

107

loadedMetadata(element: HTMLElement, options?: EventInit): void;

108

loadStart(element: HTMLElement, options?: EventInit): void;

109

pause(element: HTMLElement, options?: EventInit): void;

110

play(element: HTMLElement, options?: EventInit): void;

111

playing(element: HTMLElement, options?: EventInit): void;

112

progress(element: HTMLElement, options?: EventInit): void;

113

rateChange(element: HTMLElement, options?: EventInit): void;

114

seeked(element: HTMLElement, options?: EventInit): void;

115

seeking(element: HTMLElement, options?: EventInit): void;

116

stalled(element: HTMLElement, options?: EventInit): void;

117

suspend(element: HTMLElement, options?: EventInit): void;

118

timeUpdate(element: HTMLElement, options?: EventInit): void;

119

volumeChange(element: HTMLElement, options?: EventInit): void;

120

waiting(element: HTMLElement, options?: EventInit): void;

121

122

// Other Events

123

scroll(element: HTMLElement, options?: EventInit): void;

124

};

125

```

126

127

## Common Patterns

128

129

### Click Events

130

```typescript

131

const button = screen.getByRole('button', { name: /submit/i });

132

fireEvent.click(button);

133

134

// With modifier keys

135

fireEvent.click(button, { ctrlKey: true, shiftKey: true });

136

```

137

138

### Form Input

139

```typescript

140

const input = screen.getByLabelText(/email/i);

141

142

// Text input

143

fireEvent.change(input, { target: { value: 'user@example.com' } });

144

145

// Checkbox

146

const checkbox = screen.getByRole('checkbox');

147

fireEvent.click(checkbox);

148

149

// Select dropdown

150

const select = screen.getByLabelText(/country/i);

151

fireEvent.change(select, { target: { value: 'USA' } });

152

```

153

154

### Keyboard Events

155

```typescript

156

const input = screen.getByRole('textbox');

157

158

// Single key

159

fireEvent.keyDown(input, { key: 'Enter', code: 'Enter' });

160

fireEvent.keyDown(input, { key: 'Escape', code: 'Escape' });

161

162

// With modifiers

163

fireEvent.keyDown(input, {

164

key: 's',

165

code: 'KeyS',

166

ctrlKey: true,

167

});

168

```

169

170

### Focus/Blur

171

```typescript

172

const input = screen.getByRole('textbox');

173

174

fireEvent.focus(input);

175

expect(document.activeElement).toBe(input);

176

177

fireEvent.blur(input);

178

```

179

180

### Mouse Hover

181

```typescript

182

const button = screen.getByRole('button');

183

184

fireEvent.mouseEnter(button); // Shows hover state

185

fireEvent.mouseLeave(button); // Hides hover state

186

```

187

188

## Testing Patterns

189

190

### Button Click

191

```typescript

192

test('increments counter', () => {

193

render(<Counter />);

194

195

const button = screen.getByRole('button', { name: /increment/i });

196

fireEvent.click(button);

197

198

expect(screen.getByText('Count: 1')).toBeInTheDocument();

199

});

200

```

201

202

### Form Submission

203

```typescript

204

test('submits form', () => {

205

const handleSubmit = jest.fn();

206

render(<Form onSubmit={handleSubmit} />);

207

208

fireEvent.change(screen.getByLabelText(/email/i), {

209

target: { value: 'user@example.com' }

210

});

211

212

fireEvent.click(screen.getByRole('button', { name: /submit/i }));

213

214

expect(handleSubmit).toHaveBeenCalledWith({

215

email: 'user@example.com'

216

});

217

});

218

```

219

220

### Keyboard Navigation

221

```typescript

222

test('navigates with keyboard', () => {

223

render(<Menu />);

224

225

const menu = screen.getByRole('menu');

226

227

fireEvent.keyDown(menu, { key: 'ArrowDown', code: 'ArrowDown' });

228

expect(screen.getByRole('menuitem', { name: 'Item 1' })).toHaveFocus();

229

230

fireEvent.keyDown(menu, { key: 'Enter', code: 'Enter' });

231

// Menu item activated

232

});

233

```

234

235

### Input Validation

236

```typescript

237

test('validates email on blur', () => {

238

render(<EmailInput />);

239

240

const input = screen.getByLabelText(/email/i);

241

242

fireEvent.change(input, { target: { value: 'invalid' } });

243

fireEvent.blur(input);

244

245

expect(screen.getByText(/invalid email/i)).toBeInTheDocument();

246

});

247

```

248

249

### Hover Interactions

250

```typescript

251

test('shows tooltip on hover', () => {

252

render(<Button tooltip="Click me" />);

253

254

const button = screen.getByRole('button');

255

256

fireEvent.mouseEnter(button);

257

expect(screen.getByRole('tooltip')).toHaveTextContent('Click me');

258

259

fireEvent.mouseLeave(button);

260

expect(screen.queryByRole('tooltip')).not.toBeInTheDocument();

261

});

262

```

263

264

## React-Specific Event Behaviors

265

266

React Testing Library enhances certain events with React-specific behavior:

267

268

### mouseEnter / mouseLeave

269

270

In React, `mouseEnter` and `mouseLeave` are tracked by native `mouseOver` and `mouseOut` events. fireEvent automatically fires both:

271

272

```typescript { .api }

273

// Fires both mouseEnter and mouseOver

274

fireEvent.mouseEnter(element);

275

276

// Fires both mouseLeave and mouseOut

277

fireEvent.mouseLeave(element);

278

```

279

280

### pointerEnter / pointerLeave

281

282

Similar to mouse events, pointer enter/leave events fire both the synthetic and native events:

283

284

```typescript { .api }

285

// Fires both pointerEnter and pointerOver

286

fireEvent.pointerEnter(element);

287

288

// Fires both pointerLeave and pointerOut

289

fireEvent.pointerLeave(element);

290

```

291

292

### select Event

293

294

React's select event requires the element to be focused and fires a keyUp event:

295

296

```typescript { .api }

297

// Fires select, focuses element, then fires keyUp

298

fireEvent.select(element);

299

```

300

301

### focus / blur Events

302

303

React tracks native focusin/focusout events for focus/blur handlers:

304

305

```typescript { .api }

306

// Fires focusIn then focus

307

fireEvent.focus(element);

308

309

// Fires focusOut then blur

310

fireEvent.blur(element);

311

```

312

313

## Event Options

314

315

All event methods accept an optional options object with event-specific properties:

316

317

### MouseEventInit

318

```typescript { .api }

319

interface MouseEventInit {

320

altKey?: boolean;

321

button?: number; // 0=left, 1=middle, 2=right

322

buttons?: number;

323

clientX?: number;

324

clientY?: number;

325

ctrlKey?: boolean;

326

metaKey?: boolean;

327

relatedTarget?: EventTarget | null;

328

screenX?: number;

329

screenY?: number;

330

shiftKey?: boolean;

331

}

332

```

333

334

**Example:**

335

```typescript

336

fireEvent.click(element, {

337

ctrlKey: true,

338

shiftKey: true,

339

button: 0,

340

});

341

```

342

343

### KeyboardEventInit

344

```typescript { .api }

345

interface KeyboardEventInit {

346

key?: string; // 'Enter', 'Escape', 'a', etc.

347

code?: string; // 'Enter', 'Escape', 'KeyA', etc.

348

altKey?: boolean;

349

ctrlKey?: boolean;

350

metaKey?: boolean;

351

shiftKey?: boolean;

352

repeat?: boolean;

353

}

354

```

355

356

**Example:**

357

```typescript

358

fireEvent.keyDown(element, {

359

key: 'Enter',

360

code: 'Enter',

361

ctrlKey: false,

362

});

363

```

364

365

### InputEventInit

366

```typescript { .api }

367

interface InputEventInit {

368

data?: string | null;

369

inputType?: string;

370

}

371

```

372

373

### FocusEventInit

374

```typescript { .api }

375

interface FocusEventInit {

376

relatedTarget?: EventTarget | null;

377

}

378

```

379

380

### Common Keys

381

```typescript

382

// Special keys

383

{ key: 'Enter', code: 'Enter' }

384

{ key: 'Escape', code: 'Escape' }

385

{ key: 'Tab', code: 'Tab' }

386

{ key: 'ArrowDown', code: 'ArrowDown' }

387

{ key: 'ArrowUp', code: 'ArrowUp' }

388

{ key: 'ArrowLeft', code: 'ArrowLeft' }

389

{ key: 'ArrowRight', code: 'ArrowRight' }

390

{ key: 'Backspace', code: 'Backspace' }

391

{ key: 'Delete', code: 'Delete' }

392

393

// Letter keys

394

{ key: 'a', code: 'KeyA' }

395

{ key: 'A', code: 'KeyA', shiftKey: true }

396

```

397

398

## Important Notes

399

400

### Automatic act() Wrapping

401

402

All fireEvent calls are automatically wrapped in React's `act()` function, ensuring state updates are flushed before assertions:

403

404

```typescript

405

// No need to manually wrap in act()

406

fireEvent.click(button);

407

expect(screen.getByText('Updated')).toBeInTheDocument();

408

```

409

410

### Synthetic Events vs Native Events

411

412

React uses a synthetic event system. fireEvent fires native DOM events which are then processed by React's event system, matching how real browser events work.

413

414

### Event Bubbling

415

416

Events fired with fireEvent bubble through the DOM tree like real browser events:

417

418

```typescript

419

render(

420

<div onClick={() => console.log('Div clicked')}>

421

<button onClick={() => console.log('Button clicked')}>Click</button>

422

</div>

423

);

424

425

const button = screen.getByRole('button');

426

fireEvent.click(button);

427

// Logs: "Button clicked"

428

// Then logs: "Div clicked"

429

```

430

431

### User Event Alternative

432

433

For more realistic user interactions, consider using `@testing-library/user-event` which simulates complete user interactions (e.g., typing includes keydown, keypress, input, keyup events). However, `fireEvent` is simpler and sufficient for most cases.

434

435

```typescript

436

// fireEvent - simple, fast

437

fireEvent.change(input, { target: { value: 'hello' } });

438

439

// userEvent - more realistic (requires separate package)

440

import userEvent from '@testing-library/user-event';

441

await userEvent.type(input, 'hello');

442

```

443

444

## Testing Complex Interactions

445

446

### Multi-Step Form

447

```typescript

448

test('completes multi-step form', () => {

449

render(<WizardForm />);

450

451

// Step 1

452

fireEvent.change(screen.getByLabelText(/name/i), {

453

target: { value: 'John' }

454

});

455

fireEvent.click(screen.getByRole('button', { name: /next/i }));

456

457

// Step 2

458

fireEvent.change(screen.getByLabelText(/email/i), {

459

target: { value: 'john@example.com' }

460

});

461

fireEvent.click(screen.getByRole('button', { name: /submit/i }));

462

463

expect(screen.getByText(/success/i)).toBeInTheDocument();

464

});

465

```

466

467

### Drag and Drop

468

```typescript

469

test('reorders items with drag and drop', () => {

470

render(<DragList />);

471

472

const item = screen.getByText('Item 1');

473

474

fireEvent.dragStart(item);

475

fireEvent.dragEnter(screen.getByText('Item 3'));

476

fireEvent.drop(screen.getByText('Item 3'));

477

fireEvent.dragEnd(item);

478

479

const items = screen.getAllByRole('listitem');

480

expect(items[2]).toHaveTextContent('Item 1');

481

});

482

```

483

484

## Alternative: user-event

485

486

For more realistic interactions, consider `@testing-library/user-event` (separate package):

487

488

```typescript

489

import userEvent from '@testing-library/user-event';

490

491

// More realistic typing (includes keyDown, keyPress, input, keyUp)

492

await userEvent.type(input, 'Hello');

493

494

// Realistic clicking (includes mouseDown, mouseUp, click)

495

await userEvent.click(button);

496

```

497

498

**When to use fireEvent:**

499

- Simpler, faster tests

500

- Testing specific event handlers

501

- Legacy codebase

502

503

**When to use user-event:**

504

- More realistic user behavior

505

- Testing complex interactions

506

- Accessibility testing

507