or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

browser-contexts.mdbrowser-management.mdelement-handling.mdindex.mdinput-simulation.mdlocators-selectors.mdnetwork-management.mdpage-interaction.md

input-simulation.mddocs/

0

# Input Simulation

1

2

Realistic keyboard, mouse, and touchscreen input simulation with timing controls and platform-specific key mappings.

3

4

## Capabilities

5

6

### Keyboard Interface

7

8

Provides keyboard input simulation with support for key combinations, text typing, and special keys.

9

10

```typescript { .api }

11

interface Keyboard {

12

/** Press key down (without releasing) */

13

down(key: string, options?: KeyDownOptions): Promise<void>;

14

/** Release key */

15

up(key: string): Promise<void>;

16

/** Press and release key */

17

press(key: string, options?: PressOptions): Promise<void>;

18

/** Type text character by character */

19

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

20

/** Send single character */

21

sendCharacter(char: string): Promise<void>;

22

}

23

24

interface KeyDownOptions {

25

/** Text to insert */

26

text?: string;

27

/** Commands to send (Mac only) */

28

commands?: string[];

29

}

30

31

interface PressOptions {

32

/** Delay between key down and up */

33

delay?: number;

34

/** Text to insert */

35

text?: string;

36

/** Commands to send (Mac only) */

37

commands?: string[];

38

}

39

40

interface TypeOptions {

41

/** Delay between key presses */

42

delay?: number;

43

}

44

```

45

46

**Usage Examples:**

47

48

```typescript

49

import puppeteer from "puppeteer-core";

50

51

const browser = await puppeteer.launch({ executablePath: "/path/to/chrome" });

52

const page = await browser.newPage();

53

await page.goto("https://example.com");

54

55

const keyboard = page.keyboard;

56

57

// Basic typing

58

await page.focus("#text-input");

59

await keyboard.type("Hello World!", { delay: 100 });

60

61

// Key combinations

62

await keyboard.down("Control");

63

await keyboard.press("a"); // Select all

64

await keyboard.up("Control");

65

66

await keyboard.down("Control");

67

await keyboard.press("c"); // Copy

68

await keyboard.up("Control");

69

70

// Special keys

71

await keyboard.press("Tab");

72

await keyboard.press("Enter");

73

await keyboard.press("Escape");

74

await keyboard.press("Backspace");

75

76

// Arrow keys and navigation

77

await keyboard.press("ArrowUp");

78

await keyboard.press("ArrowDown");

79

await keyboard.press("ArrowLeft");

80

await keyboard.press("ArrowRight");

81

82

await keyboard.press("Home");

83

await keyboard.press("End");

84

await keyboard.press("PageUp");

85

await keyboard.press("PageDown");

86

87

// Function keys

88

await keyboard.press("F1");

89

await keyboard.press("F12");

90

91

// Modifier combinations

92

await keyboard.down("Shift");

93

await keyboard.press("ArrowRight"); // Select text

94

await keyboard.up("Shift");

95

96

await keyboard.down("Alt");

97

await keyboard.press("Tab"); // Alt+Tab

98

await keyboard.up("Alt");

99

100

await browser.close();

101

```

102

103

### Mouse Interface

104

105

Provides mouse input simulation including movement, clicking, dragging, and scrolling.

106

107

```typescript { .api }

108

interface Mouse {

109

/** Move mouse to coordinates */

110

move(x: number, y: number, options?: MouseMoveOptions): Promise<void>;

111

/** Click at coordinates */

112

click(x: number, y: number, options?: ClickOptions): Promise<void>;

113

/** Press mouse button down */

114

down(options?: MouseDownOptions): Promise<void>;

115

/** Release mouse button */

116

up(options?: MouseUpOptions): Promise<void>;

117

/** Scroll mouse wheel */

118

wheel(options?: MouseWheelOptions): Promise<void>;

119

/** Drag from current position to target */

120

drag(start: { x: number; y: number }, target: { x: number; y: number }): Promise<void>;

121

/** Drag and drop operation */

122

dragAndDrop(start: { x: number; y: number }, target: { x: number; y: number }, options?: DragAndDropOptions): Promise<void>;

123

}

124

125

interface MouseMoveOptions {

126

/** Number of intermediate steps */

127

steps?: number;

128

}

129

130

interface ClickOptions {

131

/** Mouse button to click */

132

button?: "left" | "right" | "middle";

133

/** Number of clicks */

134

clickCount?: number;

135

/** Delay between mousedown and mouseup */

136

delay?: number;

137

}

138

139

interface MouseDownOptions {

140

/** Mouse button to press */

141

button?: "left" | "right" | "middle";

142

/** Number of clicks */

143

clickCount?: number;

144

}

145

146

interface MouseUpOptions {

147

/** Mouse button to release */

148

button?: "left" | "right" | "middle";

149

/** Number of clicks */

150

clickCount?: number;

151

}

152

153

interface MouseWheelOptions {

154

/** Horizontal scroll delta */

155

deltaX?: number;

156

/** Vertical scroll delta */

157

deltaY?: number;

158

}

159

160

interface DragAndDropOptions {

161

/** Delay during drag operation */

162

delay?: number;

163

}

164

```

165

166

**Usage Examples:**

167

168

```typescript

169

const mouse = page.mouse;

170

171

// Basic mouse operations

172

await mouse.move(100, 200);

173

await mouse.click(100, 200);

174

175

// Different click types

176

await mouse.click(300, 400, { button: "right" }); // Right-click

177

await mouse.click(500, 600, { button: "middle" }); // Middle-click

178

await mouse.click(700, 800, { clickCount: 2 }); // Double-click

179

180

// Mouse down/up for custom timing

181

await mouse.move(150, 250);

182

await mouse.down();

183

await page.waitForTimeout(1000); // Hold for 1 second

184

await mouse.up();

185

186

// Drag operations

187

await mouse.move(100, 100);

188

await mouse.down();

189

await mouse.move(200, 200, { steps: 10 }); // Smooth movement

190

await mouse.up();

191

192

// Drag and drop

193

await mouse.dragAndDrop(

194

{ x: 100, y: 100 },

195

{ x: 300, y: 300 },

196

{ delay: 100 }

197

);

198

199

// Scrolling

200

await mouse.move(500, 500);

201

await mouse.wheel({ deltaY: -100 }); // Scroll up

202

await mouse.wheel({ deltaY: 100 }); // Scroll down

203

await mouse.wheel({ deltaX: -50 }); // Scroll left

204

await mouse.wheel({ deltaX: 50 }); // Scroll right

205

206

// Complex mouse interactions

207

const element = await page.$("#draggable");

208

if (element) {

209

const box = await element.boundingBox();

210

if (box) {

211

// Click and drag element

212

await mouse.move(box.x + box.width / 2, box.y + box.height / 2);

213

await mouse.down();

214

await mouse.move(box.x + 100, box.y + 100, { steps: 5 });

215

await mouse.up();

216

}

217

}

218

```

219

220

### Touchscreen Interface

221

222

Provides touch input simulation for mobile and touch-enabled devices.

223

224

```typescript { .api }

225

interface Touchscreen {

226

/** Tap at coordinates */

227

tap(x: number, y: number): Promise<void>;

228

/** Start touch at coordinates */

229

touchStart(touches: TouchPoint[]): Promise<void>;

230

/** Move touch points */

231

touchMove(touches: TouchPoint[]): Promise<void>;

232

/** End touch */

233

touchEnd(): Promise<void>;

234

}

235

236

interface TouchPoint {

237

x: number;

238

y: number;

239

/** Touch identifier for multi-touch */

240

id?: number;

241

/** Touch radius */

242

radiusX?: number;

243

radiusY?: number;

244

/** Touch rotation angle */

245

rotationAngle?: number;

246

/** Touch pressure */

247

force?: number;

248

}

249

```

250

251

**Usage Examples:**

252

253

```typescript

254

const touchscreen = page.touchscreen;

255

256

// Basic tap

257

await touchscreen.tap(200, 300);

258

259

// Multi-touch gestures

260

await touchscreen.touchStart([

261

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

262

{ x: 200, y: 200, id: 1 }

263

]);

264

265

// Pinch gesture (zoom out)

266

await touchscreen.touchMove([

267

{ x: 110, y: 110, id: 0 },

268

{ x: 190, y: 190, id: 1 }

269

]);

270

271

await touchscreen.touchEnd();

272

273

// Swipe gesture

274

await touchscreen.touchStart([{ x: 300, y: 400 }]);

275

await touchscreen.touchMove([{ x: 100, y: 400 }]); // Swipe left

276

await touchscreen.touchEnd();

277

278

// Complex touch interaction

279

const button = await page.$("#touch-button");

280

if (button) {

281

const box = await button.boundingBox();

282

if (box) {

283

await touchscreen.tap(

284

box.x + box.width / 2,

285

box.y + box.height / 2

286

);

287

}

288

}

289

```

290

291

### Key Constants and Mappings

292

293

Common key constants and platform-specific mappings:

294

295

```typescript { .api }

296

type Key =

297

| "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"

298

| "Power" | "Eject" | "Abort" | "Help" | "Backspace" | "Tab"

299

| "Numlock" | "Scrolllock" | "Delete" | "Escape" | "F1" | "F2"

300

| "F3" | "F4" | "F5" | "F6" | "F7" | "F8" | "F9" | "F10"

301

| "F11" | "F12" | "F13" | "F14" | "F15" | "F16" | "F17" | "F18"

302

| "F19" | "F20" | "F21" | "F22" | "F23" | "F24" | "Digit0"

303

| "Digit1" | "Digit2" | "Digit3" | "Digit4" | "Digit5" | "Digit6"

304

| "Digit7" | "Digit8" | "Digit9" | "KeyA" | "KeyB" | "KeyC"

305

| "KeyD" | "KeyE" | "KeyF" | "KeyG" | "KeyH" | "KeyI" | "KeyJ"

306

| "KeyK" | "KeyL" | "KeyM" | "KeyN" | "KeyO" | "KeyP" | "KeyQ"

307

| "KeyR" | "KeyS" | "KeyT" | "KeyU" | "KeyV" | "KeyW" | "KeyX"

308

| "KeyY" | "KeyZ" | "Semicolon" | "Equal" | "Comma" | "Minus"

309

| "Period" | "Slash" | "Backquote" | "BracketLeft" | "Backslash"

310

| "BracketRight" | "Quote" | "Altleft" | "Altright" | "CapsLock"

311

| "ControlLeft" | "MetaLeft" | "ShiftLeft" | "ControlRight"

312

| "MetaRight" | "ShiftRight" | "ContextMenu" | "Enter" | "Space"

313

| "ArrowDown" | "ArrowLeft" | "ArrowRight" | "ArrowUp" | "End"

314

| "Home" | "Insert" | "PageDown" | "PageUp" | "PrintScreen"

315

| "NumpadDivide" | "NumpadMultiply" | "NumpadSubtract"

316

| "NumpadAdd" | "NumpadEnter" | "NumpadDecimal" | "Numpad0"

317

| "Numpad1" | "Numpad2" | "Numpad3" | "Numpad4" | "Numpad5"

318

| "Numpad6" | "Numpad7" | "Numpad8" | "Numpad9" | "Copy"

319

| "Cut" | "Paste" | "AudioVolumeMute" | "AudioVolumeDown"

320

| "AudioVolumeUp" | "MediaTrackNext" | "MediaTrackPrevious"

321

| "MediaStop" | "MediaPlayPause" | "BrowserSearch" | "BrowserHome"

322

| "BrowserBack" | "BrowserForward" | "BrowserRefresh"

323

| "BrowserStop" | "BrowserFavorites" | "LaunchApplication1"

324

| "LaunchApplication2" | "LaunchMail" | "LaunchMediaPlayer";

325

326

interface USKeyboardLayout {

327

[key: string]: {

328

keyCode: number;

329

shiftKeyCode?: number;

330

key: string;

331

shiftKey?: string;

332

code: string;

333

text?: string;

334

shiftText?: string;

335

location?: number;

336

};

337

}

338

```

339

340

**Usage Examples:**

341

342

```typescript

343

// Using key constants

344

await keyboard.press("Enter");

345

await keyboard.press("ArrowDown");

346

await keyboard.press("F1");

347

await keyboard.press("ControlLeft");

348

349

// Key combinations with proper timing

350

await keyboard.down("ShiftLeft");

351

await keyboard.press("KeyA"); // Capital A

352

await keyboard.up("ShiftLeft");

353

354

// Platform-specific shortcuts

355

const isMac = process.platform === "darwin";

356

const cmdOrCtrl = isMac ? "MetaLeft" : "ControlLeft";

357

358

await keyboard.down(cmdOrCtrl);

359

await keyboard.press("KeyC"); // Copy

360

await keyboard.up(cmdOrCtrl);

361

362

await keyboard.down(cmdOrCtrl);

363

await keyboard.press("KeyV"); // Paste

364

await keyboard.up(cmdOrCtrl);

365

```

366

367

### Advanced Input Scenarios

368

369

Complex input scenarios and best practices:

370

371

```typescript { .api }

372

interface AdvancedInputScenarios {

373

/** Simulate realistic typing with human-like delays */

374

humanType(text: string, options?: HumanTypeOptions): Promise<void>;

375

/** Simulate form filling with tab navigation */

376

fillForm(fields: FormField[]): Promise<void>;

377

/** Simulate file drag and drop */

378

dragDropFile(filePath: string, target: ElementHandle): Promise<void>;

379

/** Simulate drawing/signature input */

380

drawPath(points: Point[], options?: DrawOptions): Promise<void>;

381

}

382

383

interface HumanTypeOptions {

384

/** Base delay between keystrokes */

385

baseDelay?: number;

386

/** Random delay variation */

387

variation?: number;

388

/** Typing mistakes probability */

389

mistakeRate?: number;

390

}

391

392

interface FormField {

393

selector: string;

394

value: string;

395

type?: "text" | "email" | "password" | "number";

396

}

397

398

interface Point {

399

x: number;

400

y: number;

401

}

402

403

interface DrawOptions {

404

pressure?: number;

405

smooth?: boolean;

406

delay?: number;

407

}

408

```

409

410

**Usage Examples:**

411

412

```typescript

413

// Realistic human typing

414

async function humanType(page: Page, selector: string, text: string) {

415

await page.focus(selector);

416

417

for (let i = 0; i < text.length; i++) {

418

const char = text[i];

419

const delay = Math.random() * 100 + 50; // 50-150ms random delay

420

421

await page.keyboard.type(char);

422

await page.waitForTimeout(delay);

423

424

// Occasionally make a mistake and correct it

425

if (Math.random() < 0.05) { // 5% mistake rate

426

await page.keyboard.press("Backspace");

427

await page.waitForTimeout(200);

428

await page.keyboard.type(char);

429

}

430

}

431

}

432

433

// Form automation with tab navigation

434

async function fillFormWithTabs(page: Page) {

435

const fields = [

436

{ selector: "#firstName", value: "John" },

437

{ selector: "#lastName", value: "Doe" },

438

{ selector: "#email", value: "john.doe@example.com" },

439

{ selector: "#phone", value: "555-0123" }

440

];

441

442

await page.focus(fields[0].selector);

443

444

for (const field of fields) {

445

await page.keyboard.type(field.value);

446

await page.keyboard.press("Tab");

447

await page.waitForTimeout(200);

448

}

449

}

450

451

// Signature/drawing simulation

452

async function drawSignature(page: Page, canvasSelector: string) {

453

const canvas = await page.$(canvasSelector);

454

if (!canvas) return;

455

456

const box = await canvas.boundingBox();

457

if (!box) return;

458

459

const startX = box.x + 50;

460

const startY = box.y + box.height / 2;

461

462

// Draw a simple signature curve

463

await page.mouse.move(startX, startY);

464

await page.mouse.down();

465

466

for (let i = 0; i <= 100; i++) {

467

const x = startX + i * 2;

468

const y = startY + Math.sin(i * 0.1) * 20;

469

await page.mouse.move(x, y);

470

await page.waitForTimeout(10);

471

}

472

473

await page.mouse.up();

474

}

475

476

// File drag and drop simulation

477

async function simulateFileDrop(page: Page, filePath: string, dropSelector: string) {

478

const dropZone = await page.$(dropSelector);

479

if (!dropZone) return;

480

481

const box = await dropZone.boundingBox();

482

if (!box) return;

483

484

// Simulate drag and drop events

485

const fileInput = await page.evaluateHandle(() => {

486

const input = document.createElement('input');

487

input.type = 'file';

488

input.style.display = 'none';

489

document.body.appendChild(input);

490

return input;

491

});

492

493

await fileInput.uploadFile(filePath);

494

495

await page.evaluate((input, dropZone) => {

496

const file = input.files[0];

497

const dt = new DataTransfer();

498

dt.items.add(file);

499

500

const dragEvent = new DragEvent('drop', {

501

dataTransfer: dt,

502

bubbles: true,

503

cancelable: true

504

});

505

506

dropZone.dispatchEvent(dragEvent);

507

}, await fileInput.asElement(), await dropZone.asElement());

508

}

509

```

510

511

### Error Handling

512

513

Common input-related errors and handling strategies:

514

515

```typescript { .api }

516

class InputError extends Error {

517

constructor(message: string);

518

}

519

520

class KeyboardError extends InputError {

521

constructor(message: string);

522

}

523

524

class MouseError extends InputError {

525

constructor(message: string);

526

}

527

```

528

529

**Usage Examples:**

530

531

```typescript

532

// Safe input operations

533

async function safeType(page: Page, selector: string, text: string) {

534

try {

535

await page.waitForSelector(selector, { timeout: 5000 });

536

await page.focus(selector);

537

await page.keyboard.type(text);

538

return true;

539

} catch (error) {

540

console.log(`Failed to type in ${selector}:`, error.message);

541

return false;

542

}

543

}

544

545

// Retry mechanism for flaky inputs

546

async function retryClick(page: Page, x: number, y: number, maxRetries = 3) {

547

for (let i = 0; i < maxRetries; i++) {

548

try {

549

await page.mouse.click(x, y);

550

return true;

551

} catch (error) {

552

console.log(`Click attempt ${i + 1} failed:`, error.message);

553

if (i === maxRetries - 1) throw error;

554

await page.waitForTimeout(1000);

555

}

556

}

557

return false;

558

}

559

```