or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-testing.mdconfiguration.mdhooks.mdindex.mdinteractions.mdmatchers.mdqueries.mdrendering.md

interactions.mddocs/

0

# User Interactions

1

2

Realistic user interaction simulation supporting press events, text input, scrolling, and other React Native-specific gestures. Provides both synchronous fireEvent API and more realistic asynchronous userEvent API.

3

4

## Capabilities

5

6

### FireEvent API

7

8

Synchronous event firing utility for immediate event simulation - faster but less realistic than userEvent.

9

10

```typescript { .api }

11

/**

12

* Synchronous event firing utility

13

* Fires events immediately without realistic timing or validation

14

*/

15

declare const fireEvent: {

16

/** Fire press event on pressable elements */

17

press(element: ReactTestInstance): void;

18

19

/** Fire long press event */

20

longPress(element: ReactTestInstance): void;

21

22

/** Fire text change event on TextInput elements */

23

changeText(element: ReactTestInstance, text: string): void;

24

25

/** Fire scroll event on scrollable elements */

26

scroll(element: ReactTestInstance, eventData?: ScrollEventData): void;

27

28

/** Fire focus event on focusable elements */

29

focus(element: ReactTestInstance): void;

30

31

/** Fire blur event on focusable elements */

32

blur(element: ReactTestInstance): void;

33

34

/** Fire layout event */

35

layout(element: ReactTestInstance, layoutData: LayoutEventData): void;

36

37

/** Fire content size change event */

38

contentSizeChange(element: ReactTestInstance, contentSize: ContentSizeData): void;

39

40

/** Fire end editing event on TextInput */

41

endEditing(element: ReactTestInstance, text?: string): void;

42

43

/** Fire selection change event on TextInput */

44

selectionChange(element: ReactTestInstance, selection: SelectionData): void;

45

46

/** Fire refresh event on RefreshControl */

47

refresh(element: ReactTestInstance): void;

48

49

/** Fire momentum scroll begin event */

50

momentumScrollBegin(element: ReactTestInstance): void;

51

52

/** Fire momentum scroll end event */

53

momentumScrollEnd(element: ReactTestInstance): void;

54

55

/** Fire scroll begin drag event */

56

scrollBeginDrag(element: ReactTestInstance): void;

57

58

/** Fire scroll end drag event */

59

scrollEndDrag(element: ReactTestInstance): void;

60

};

61

62

/**

63

* Async version of fireEvent for more realistic timing

64

*/

65

declare const fireEventAsync: typeof fireEvent;

66

67

interface ScrollEventData {

68

nativeEvent: {

69

contentOffset: { x: number; y: number };

70

contentSize: { width: number; height: number };

71

layoutMeasurement: { width: number; height: number };

72

};

73

}

74

75

interface LayoutEventData {

76

nativeEvent: {

77

layout: { x: number; y: number; width: number; height: number };

78

};

79

}

80

81

interface ContentSizeData {

82

nativeEvent: {

83

contentSize: { width: number; height: number };

84

};

85

}

86

87

interface SelectionData {

88

nativeEvent: {

89

selection: { start: number; end: number };

90

};

91

}

92

```

93

94

**Usage Examples:**

95

96

```typescript

97

import { render, screen, fireEvent } from "@testing-library/react-native";

98

99

test("fireEvent interactions", () => {

100

const handlePress = jest.fn();

101

const handleTextChange = jest.fn();

102

const handleScroll = jest.fn();

103

104

render(

105

<View>

106

<Pressable onPress={handlePress} testID="button">

107

<Text>Press Me</Text>

108

</Pressable>

109

<TextInput

110

onChangeText={handleTextChange}

111

testID="input"

112

placeholder="Type here"

113

/>

114

<ScrollView onScroll={handleScroll} testID="scroll">

115

<Text>Scrollable content</Text>

116

</ScrollView>

117

</View>

118

);

119

120

// Press button

121

const button = screen.getByTestId("button");

122

fireEvent.press(button);

123

expect(handlePress).toHaveBeenCalledTimes(1);

124

125

// Change text

126

const input = screen.getByTestId("input");

127

fireEvent.changeText(input, "Hello World");

128

expect(handleTextChange).toHaveBeenCalledWith("Hello World");

129

130

// Scroll

131

const scrollView = screen.getByTestId("scroll");

132

fireEvent.scroll(scrollView, {

133

nativeEvent: {

134

contentOffset: { x: 0, y: 100 },

135

contentSize: { width: 300, height: 1000 },

136

layoutMeasurement: { width: 300, height: 400 }

137

}

138

});

139

expect(handleScroll).toHaveBeenCalled();

140

141

// Long press

142

fireEvent.longPress(button);

143

144

// Focus and blur

145

fireEvent.focus(input);

146

fireEvent.blur(input);

147

148

// End editing

149

fireEvent.endEditing(input, "Final text");

150

});

151

```

152

153

### UserEvent API

154

155

More realistic user interaction simulation with proper timing, validation, and event sequences.

156

157

```typescript { .api }

158

/**

159

* Realistic user event simulation

160

* Provides more authentic user interactions with proper timing and validation

161

*/

162

declare const userEvent: {

163

/** Create configured user event instance */

164

setup(config?: UserEventConfig): UserEventInstance;

165

166

// Direct access methods for v13 compatibility

167

/** Press an element */

168

press(element: ReactTestInstance): Promise<void>;

169

170

/** Long press an element with optional configuration */

171

longPress(element: ReactTestInstance, options?: PressOptions): Promise<void>;

172

173

/** Type text into an input element */

174

type(element: ReactTestInstance, text: string, options?: TypeOptions): Promise<void>;

175

176

/** Clear text from an input element */

177

clear(element: ReactTestInstance): Promise<void>;

178

179

/** Paste text into an input element */

180

paste(element: ReactTestInstance, text: string): Promise<void>;

181

182

/** Scroll an element to specific position */

183

scrollTo(element: ReactTestInstance, options: ScrollToOptions): Promise<void>;

184

};

185

186

interface UserEventConfig {

187

/** Delay between keystrokes when typing (ms) */

188

delay?: number;

189

190

/** Whether to skip validation of element state */

191

skipValidation?: boolean;

192

193

/** Custom press duration for long press (ms) */

194

longPressDelay?: number;

195

}

196

197

interface UserEventInstance {

198

/** Press an element */

199

press(element: ReactTestInstance): Promise<void>;

200

201

/** Long press with options */

202

longPress(element: ReactTestInstance, options?: PressOptions): Promise<void>;

203

204

/** Type text with realistic timing */

205

type(element: ReactTestInstance, text: string, options?: TypeOptions): Promise<void>;

206

207

/** Clear text input */

208

clear(element: ReactTestInstance): Promise<void>;

209

210

/** Paste text */

211

paste(element: ReactTestInstance, text: string): Promise<void>;

212

213

/** Scroll to position */

214

scrollTo(element: ReactTestInstance, options: ScrollToOptions): Promise<void>;

215

}

216

```

217

218

**Usage Examples:**

219

220

```typescript

221

import { render, screen, userEvent } from "@testing-library/react-native";

222

223

test("userEvent interactions", async () => {

224

const user = userEvent.setup({ delay: 10 });

225

226

const handlePress = jest.fn();

227

const handleTextChange = jest.fn();

228

229

render(

230

<View>

231

<Pressable onPress={handlePress} testID="button">

232

<Text>Press Me</Text>

233

</Pressable>

234

<TextInput

235

onChangeText={handleTextChange}

236

testID="input"

237

placeholder="Type here"

238

/>

239

</View>

240

);

241

242

// Realistic button press

243

const button = screen.getByTestId("button");

244

await user.press(button);

245

expect(handlePress).toHaveBeenCalledTimes(1);

246

247

// Realistic text typing with delays

248

const input = screen.getByTestId("input");

249

await user.type(input, "Hello World");

250

expect(input.props.value).toBe("Hello World");

251

252

// Clear input

253

await user.clear(input);

254

expect(input.props.value).toBe("");

255

256

// Paste text

257

await user.paste(input, "Pasted content");

258

expect(input.props.value).toBe("Pasted content");

259

260

// Long press with custom duration

261

await user.longPress(button, { duration: 1000 });

262

});

263

264

test("direct userEvent methods", async () => {

265

render(<Pressable testID="button"><Text>Press</Text></Pressable>);

266

267

// Direct method usage (v13 compatibility)

268

const button = screen.getByTestId("button");

269

await userEvent.press(button);

270

await userEvent.longPress(button);

271

});

272

```

273

274

### Press Interactions

275

276

Detailed press interaction options and configurations.

277

278

```typescript { .api }

279

/**

280

* Press an element with realistic touch behavior

281

* @param element - Element to press

282

* @returns Promise that resolves when press is complete

283

*/

284

function press(element: ReactTestInstance): Promise<void>;

285

286

/**

287

* Long press an element with configurable duration

288

* @param element - Element to long press

289

* @param options - Long press configuration options

290

* @returns Promise that resolves when long press is complete

291

*/

292

function longPress(element: ReactTestInstance, options?: PressOptions): Promise<void>;

293

294

interface PressOptions {

295

/** Duration of long press in milliseconds (default: 500) */

296

duration?: number;

297

}

298

```

299

300

**Usage Examples:**

301

302

```typescript

303

test("press interactions", async () => {

304

const user = userEvent.setup();

305

const handlePress = jest.fn();

306

const handleLongPress = jest.fn();

307

308

render(

309

<Pressable

310

onPress={handlePress}

311

onLongPress={handleLongPress}

312

testID="interactive-button"

313

>

314

<Text>Interactive Button</Text>

315

</Pressable>

316

);

317

318

const button = screen.getByTestId("interactive-button");

319

320

// Standard press

321

await user.press(button);

322

expect(handlePress).toHaveBeenCalledTimes(1);

323

324

// Long press with default duration (500ms)

325

await user.longPress(button);

326

expect(handleLongPress).toHaveBeenCalledTimes(1);

327

328

// Long press with custom duration

329

await user.longPress(button, { duration: 1000 });

330

expect(handleLongPress).toHaveBeenCalledTimes(2);

331

});

332

```

333

334

### Text Input Interactions

335

336

Comprehensive text input simulation with realistic typing, clearing, and pasting.

337

338

```typescript { .api }

339

/**

340

* Type text into an input element with realistic timing

341

* @param element - TextInput element to type into

342

* @param text - Text to type

343

* @param options - Typing configuration options

344

* @returns Promise that resolves when typing is complete

345

*/

346

function type(element: ReactTestInstance, text: string, options?: TypeOptions): Promise<void>;

347

348

/**

349

* Clear all text from an input element

350

* @param element - TextInput element to clear

351

* @returns Promise that resolves when clearing is complete

352

*/

353

function clear(element: ReactTestInstance): Promise<void>;

354

355

/**

356

* Paste text into an input element

357

* @param element - TextInput element to paste into

358

* @param text - Text to paste

359

* @returns Promise that resolves when pasting is complete

360

*/

361

function paste(element: ReactTestInstance, text: string): Promise<void>;

362

363

interface TypeOptions {

364

/** Delay between keystrokes in milliseconds */

365

delay?: number;

366

367

/** Whether to skip element validation */

368

skipValidation?: boolean;

369

370

/** Whether to clear existing text before typing */

371

clearFirst?: boolean;

372

}

373

```

374

375

**Usage Examples:**

376

377

```typescript

378

test("text input interactions", async () => {

379

const user = userEvent.setup();

380

const handleTextChange = jest.fn();

381

const handleSelectionChange = jest.fn();

382

383

render(

384

<TextInput

385

testID="text-input"

386

placeholder="Enter text"

387

onChangeText={handleTextChange}

388

onSelectionChange={handleSelectionChange}

389

multiline

390

/>

391

);

392

393

const input = screen.getByTestId("text-input");

394

395

// Type with default timing

396

await user.type(input, "Hello");

397

expect(handleTextChange).toHaveBeenLastCalledWith("Hello");

398

399

// Type with custom delay

400

await user.type(input, " World", { delay: 50 });

401

expect(handleTextChange).toHaveBeenLastCalledWith("Hello World");

402

403

// Clear input

404

await user.clear(input);

405

expect(handleTextChange).toHaveBeenLastCalledWith("");

406

407

// Type after clearing

408

await user.type(input, "New text", { clearFirst: true });

409

expect(handleTextChange).toHaveBeenLastCalledWith("New text");

410

411

// Paste text

412

await user.paste(input, "\nPasted line");

413

expect(handleTextChange).toHaveBeenLastCalledWith("New text\nPasted line");

414

});

415

416

test("text input with validation", async () => {

417

const user = userEvent.setup();

418

419

render(

420

<TextInput

421

testID="disabled-input"

422

editable={false}

423

placeholder="Disabled input"

424

/>

425

);

426

427

const disabledInput = screen.getByTestId("disabled-input");

428

429

// This will throw an error because input is not editable

430

await expect(user.type(disabledInput, "text")).rejects.toThrow();

431

432

// Skip validation to force typing

433

await user.type(disabledInput, "forced text", { skipValidation: true });

434

});

435

```

436

437

### Scroll Interactions

438

439

Realistic scrolling simulation for ScrollView and other scrollable components.

440

441

```typescript { .api }

442

/**

443

* Scroll an element to a specific position

444

* @param element - ScrollView or scrollable element

445

* @param options - Scroll target options

446

* @returns Promise that resolves when scrolling is complete

447

*/

448

function scrollTo(element: ReactTestInstance, options: ScrollToOptions): Promise<void>;

449

450

interface ScrollToOptions {

451

/** Horizontal scroll position */

452

x?: number;

453

454

/** Vertical scroll position */

455

y?: number;

456

457

/** Whether to animate the scroll */

458

animated?: boolean;

459

}

460

```

461

462

**Usage Examples:**

463

464

```typescript

465

test("scroll interactions", async () => {

466

const user = userEvent.setup();

467

const handleScroll = jest.fn();

468

const handleMomentumScrollEnd = jest.fn();

469

470

render(

471

<ScrollView

472

testID="scroll-view"

473

onScroll={handleScroll}

474

onMomentumScrollEnd={handleMomentumScrollEnd}

475

scrollEventThrottle={16}

476

>

477

<View style={{ height: 2000 }}>

478

<Text>Long scrollable content</Text>

479

</View>

480

</ScrollView>

481

);

482

483

const scrollView = screen.getByTestId("scroll-view");

484

485

// Scroll vertically

486

await user.scrollTo(scrollView, { y: 500 });

487

expect(handleScroll).toHaveBeenCalled();

488

489

// Scroll horizontally

490

await user.scrollTo(scrollView, { x: 200 });

491

492

// Scroll to specific position with animation

493

await user.scrollTo(scrollView, {

494

x: 100,

495

y: 300,

496

animated: true

497

});

498

499

// Scroll back to top

500

await user.scrollTo(scrollView, { x: 0, y: 0 });

501

});

502

```

503

504

### Event Validation and Utilities

505

506

Utilities for validating element states and event capabilities.

507

508

```typescript { .api }

509

/**

510

* Check if element is a touch responder

511

* @param element - Element to check

512

* @returns True if element can respond to touch events

513

*/

514

function isTouchResponder(element: ReactTestInstance): boolean;

515

516

/**

517

* Check if event is enabled for element

518

* @param element - Element to check

519

* @param eventName - Event name to validate

520

* @returns True if event can be fired on element

521

*/

522

function isEventEnabled(

523

element: ReactTestInstance,

524

eventName: string

525

): boolean;

526

```

527

528

**Usage Examples:**

529

530

```typescript

531

import { render, screen, isTouchResponder, isEventEnabled } from "@testing-library/react-native";

532

533

test("event validation utilities", () => {

534

render(

535

<View>

536

<Pressable testID="pressable">

537

<Text>Pressable</Text>

538

</Pressable>

539

<View testID="plain-view">

540

<Text>Plain View</Text>

541

</View>

542

<TextInput testID="input" editable={false} />

543

<View pointerEvents="none" testID="no-pointer-events">

544

<Text>No Pointer Events</Text>

545

</View>

546

</View>

547

);

548

549

const pressable = screen.getByTestId("pressable");

550

const plainView = screen.getByTestId("plain-view");

551

const input = screen.getByTestId("input");

552

const noPointerView = screen.getByTestId("no-pointer-events");

553

554

// Check touch responder capability

555

expect(isTouchResponder(pressable)).toBe(true);

556

expect(isTouchResponder(plainView)).toBe(false);

557

expect(isTouchResponder(input)).toBe(true); // TextInput is always touch responder

558

559

// Check specific event capabilities

560

expect(isEventEnabled(pressable, "press")).toBe(true);

561

expect(isEventEnabled(noPointerView, "press")).toBe(false);

562

expect(isEventEnabled(input, "changeText")).toBe(false); // Not editable

563

});

564

```

565

566

## Configuration and Setup

567

568

Global configuration for user event behavior and timing.

569

570

```typescript { .api }

571

/**

572

* Create configured user event instance

573

* @param config - User event configuration options

574

* @returns Configured user event instance

575

*/

576

function setup(config?: UserEventConfig): UserEventInstance;

577

578

interface UserEventConfig {

579

/** Default delay between keystrokes when typing (ms) */

580

delay?: number;

581

582

/** Whether to skip element state validation by default */

583

skipValidation?: boolean;

584

585

/** Default duration for long press interactions (ms) */

586

longPressDelay?: number;

587

588

/** Whether to advance timers automatically in fake timer environments */

589

advanceTimers?: boolean;

590

}

591

```

592

593

**Usage Examples:**

594

595

```typescript

596

test("user event configuration", async () => {

597

// Create instance with custom configuration

598

const fastUser = userEvent.setup({

599

delay: 5, // Fast typing

600

longPressDelay: 200 // Short long press

601

});

602

603

const slowUser = userEvent.setup({

604

delay: 100, // Slow typing

605

longPressDelay: 1000 // Long press

606

});

607

608

const permissiveUser = userEvent.setup({

609

skipValidation: true // Skip all validation

610

});

611

612

render(<TextInput testID="input" placeholder="Type here" />);

613

const input = screen.getByTestId("input");

614

615

// Fast typing

616

await fastUser.type(input, "Fast text");

617

618

// Slow typing

619

await slowUser.type(input, "Slow text", { clearFirst: true });

620

621

// Type in disabled input (normally would throw)

622

render(<TextInput testID="disabled" editable={false} />);

623

const disabled = screen.getByTestId("disabled");

624

await permissiveUser.type(disabled, "Force type");

625

});

626

```