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

element-handling.mddocs/

0

# Element Handling

1

2

Advanced element selection, interaction, and manipulation with comprehensive locator strategies and event handling.

3

4

## Capabilities

5

6

### ElementHandle Interface

7

8

Represents a reference to a DOM element in the page, providing methods for interaction and property access.

9

10

```typescript { .api }

11

interface ElementHandle extends JSHandle {

12

/** Click the element */

13

click(options?: ClickOptions): Promise<void>;

14

/** Double-click the element */

15

dblclick(options?: ClickOptions): Promise<void>;

16

/** Right-click the element */

17

rightclick(options?: ClickOptions): Promise<void>;

18

/** Focus the element */

19

focus(): Promise<void>;

20

/** Hover over the element */

21

hover(): Promise<void>;

22

/** Tap the element (mobile) */

23

tap(): Promise<void>;

24

/** Type text into the element */

25

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

26

/** Press a key */

27

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

28

/** Select options in a select element */

29

select(...values: string[]): Promise<string[]>;

30

/** Upload file(s) to input element */

31

uploadFile(...filePaths: string[]): Promise<void>;

32

/** Get bounding box */

33

boundingBox(): Promise<BoundingBox | null>;

34

/** Get bounding box relative to main frame */

35

boxModel(): Promise<BoxModel | null>;

36

/** Take screenshot of element */

37

screenshot(options?: ScreenshotOptions): Promise<Buffer>;

38

/** Get content frame (for iframe elements) */

39

contentFrame(): Promise<Frame | null>;

40

/** Scroll element into view if needed */

41

scrollIntoView(): Promise<void>;

42

/** Scroll within element */

43

scroll(options: ScrollOptions): Promise<void>;

44

/** Drag element to another element or coordinate */

45

drag(target: { x: number; y: number } | ElementHandle): Promise<void>;

46

/** Drag and drop element */

47

dragAndDrop(target: ElementHandle, options?: DragAndDropOptions): Promise<void>;

48

/** Check if element is intersecting viewport */

49

isIntersectingViewport(options?: { threshold?: number }): Promise<boolean>;

50

/** Get inner text */

51

innerText(): Promise<string>;

52

/** Get inner HTML */

53

innerHTML(): Promise<string>;

54

/** Get outer HTML */

55

outerHTML(): Promise<string>;

56

/** Get text content */

57

textContent(): Promise<string>;

58

/** Get attribute value */

59

getAttribute(name: string): Promise<string | null>;

60

/** Get property value */

61

getProperty(propertyName: string): Promise<JSHandle>;

62

/** Get all properties */

63

getProperties(): Promise<Map<string, JSHandle>>;

64

/** Get JSON value */

65

jsonValue(): Promise<any>;

66

/** Convert to ElementHandle if this is an element */

67

asElement(): ElementHandle | null;

68

/** Dispose the handle */

69

dispose(): Promise<void>;

70

/** Get execution context */

71

executionContext(): ExecutionContext;

72

/** Evaluate function with element as this */

73

evaluate<T>(pageFunction: Function, ...args: any[]): Promise<T>;

74

/** Evaluate function and return handle */

75

evaluateHandle(pageFunction: Function, ...args: any[]): Promise<JSHandle>;

76

/** Query selector within element */

77

$(selector: string): Promise<ElementHandle | null>;

78

/** Query selector all within element */

79

$$(selector: string): Promise<ElementHandle[]>;

80

/** Evaluate with selector within element */

81

$eval<T>(selector: string, pageFunction: Function, ...args: any[]): Promise<T>;

82

/** Evaluate with selector all within element */

83

$$eval<T>(selector: string, pageFunction: Function, ...args: any[]): Promise<T>;

84

/** XPath query within element */

85

$x(expression: string): Promise<ElementHandle[]>;

86

/** Wait for selector within element */

87

waitForSelector(selector: string, options?: WaitForSelectorOptions): Promise<ElementHandle | null>;

88

/** Wait for XPath within element */

89

waitForXPath(xpath: string, options?: WaitForSelectorOptions): Promise<ElementHandle | null>;

90

/** Wait for function */

91

waitForFunction(pageFunction: Function, options?: WaitForFunctionOptions, ...args: any[]): Promise<JSHandle>;

92

/** Check if element is visible */

93

isVisible(): Promise<boolean>;

94

/** Check if element is hidden */

95

isHidden(): Promise<boolean>;

96

/** Get owning frame */

97

ownerFrame(): Promise<Frame | null>;

98

/** Get remote object */

99

remoteObject(): Protocol.Runtime.RemoteObject;

100

}

101

102

interface ClickOptions {

103

/** Mouse button to use */

104

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

105

/** Number of clicks */

106

clickCount?: number;

107

/** Delay between mousedown and mouseup */

108

delay?: number;

109

/** Offset from element center */

110

offset?: { x: number; y: number };

111

/** Wait for element to be actionable */

112

force?: boolean;

113

/** Timeout for actionability checks */

114

timeout?: number;

115

/** Trial run without actually clicking */

116

trial?: boolean;

117

}

118

119

interface TypeOptions {

120

/** Delay between key presses */

121

delay?: number;

122

/** Timeout for actionability checks */

123

timeout?: number;

124

/** Whether to clear existing text first */

125

clear?: boolean;

126

}

127

128

interface PressOptions {

129

/** Delay between key down and up */

130

delay?: number;

131

/** Timeout for actionability checks */

132

timeout?: number;

133

}

134

135

interface BoundingBox {

136

x: number;

137

y: number;

138

width: number;

139

height: number;

140

}

141

142

interface BoxModel {

143

content: Quad;

144

padding: Quad;

145

border: Quad;

146

margin: Quad;

147

width: number;

148

height: number;

149

}

150

151

interface Quad {

152

p1: { x: number; y: number };

153

p2: { x: number; y: number };

154

p3: { x: number; y: number };

155

p4: { x: number; y: number };

156

}

157

158

interface ScrollOptions {

159

top?: number;

160

left?: number;

161

behavior?: "auto" | "instant" | "smooth";

162

}

163

164

interface DragAndDropOptions {

165

delay?: number;

166

force?: boolean;

167

timeout?: number;

168

}

169

170

interface WaitForSelectorOptions {

171

/** Wait for element to be visible */

172

visible?: boolean;

173

/** Wait for element to be hidden */

174

hidden?: boolean;

175

/** Maximum wait time */

176

timeout?: number;

177

/** Wait for element to be attached to DOM */

178

attached?: boolean;

179

/** Wait for element to be detached from DOM */

180

detached?: boolean;

181

}

182

183

interface WaitForFunctionOptions {

184

/** Maximum wait time */

185

timeout?: number;

186

/** Polling strategy */

187

polling?: "raf" | "mutation" | number;

188

}

189

```

190

191

**Usage Examples:**

192

193

```typescript

194

import puppeteer from "puppeteer-core";

195

196

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

197

const page = await browser.newPage();

198

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

199

200

// Basic element selection and interaction

201

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

202

if (button) {

203

await button.click();

204

}

205

206

const input = await page.$("input[type='text']");

207

if (input) {

208

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

209

await input.press("Enter");

210

}

211

212

// Element properties and content

213

const heading = await page.$("h1");

214

if (heading) {

215

const text = await heading.innerText();

216

const html = await heading.innerHTML();

217

const id = await heading.getAttribute("id");

218

219

console.log("Heading text:", text);

220

console.log("Heading HTML:", html);

221

console.log("Heading ID:", id);

222

}

223

224

// Element positioning and visibility

225

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

226

if (element) {

227

const box = await element.boundingBox();

228

const isVisible = await element.isVisible();

229

const isInViewport = await element.isIntersectingViewport();

230

231

console.log("Element bounds:", box);

232

console.log("Element visible:", isVisible);

233

console.log("Element in viewport:", isInViewport);

234

}

235

236

// File upload

237

const fileInput = await page.$("input[type='file']");

238

if (fileInput) {

239

await fileInput.uploadFile("/path/to/file.txt", "/path/to/another-file.pdf");

240

}

241

242

// Select options

243

const selectElement = await page.$("select");

244

if (selectElement) {

245

const selectedValues = await selectElement.select("option1", "option2");

246

console.log("Selected values:", selectedValues);

247

}

248

249

await browser.close();

250

```

251

252

### JSHandle Interface

253

254

Base interface for JavaScript object references in the page context.

255

256

```typescript { .api }

257

interface JSHandle {

258

/** Evaluate function with handle as this */

259

evaluate<T>(pageFunction: Function, ...args: any[]): Promise<T>;

260

/** Evaluate function and return handle */

261

evaluateHandle(pageFunction: Function, ...args: any[]): Promise<JSHandle>;

262

/** Get property value */

263

getProperty(propertyName: string): Promise<JSHandle>;

264

/** Get all properties */

265

getProperties(): Promise<Map<string, JSHandle>>;

266

/** Get JSON value */

267

jsonValue(): Promise<any>;

268

/** Convert to ElementHandle if this is an element */

269

asElement(): ElementHandle | null;

270

/** Dispose the handle */

271

dispose(): Promise<void>;

272

/** Convert to string representation */

273

toString(): string;

274

/** Get execution context */

275

executionContext(): ExecutionContext;

276

/** Get remote object */

277

remoteObject(): Protocol.Runtime.RemoteObject;

278

}

279

```

280

281

**Usage Examples:**

282

283

```typescript

284

// Get JavaScript objects

285

const windowHandle = await page.evaluateHandle(() => window);

286

const documentHandle = await page.evaluateHandle(() => document);

287

288

// Get object properties

289

const locationHandle = await windowHandle.getProperty("location");

290

const href = await locationHandle.jsonValue();

291

292

// Evaluate with handle

293

const title = await documentHandle.evaluate((doc) => doc.title);

294

295

// Dispose handles to prevent memory leaks

296

await windowHandle.dispose();

297

await documentHandle.dispose();

298

await locationHandle.dispose();

299

```

300

301

### Element Selection Methods

302

303

Various methods for selecting elements in the page:

304

305

```typescript { .api }

306

interface ElementSelectionMethods {

307

/** Query single element by CSS selector */

308

$(selector: string): Promise<ElementHandle | null>;

309

/** Query multiple elements by CSS selector */

310

$$(selector: string): Promise<ElementHandle[]>;

311

/** Evaluate function with selected element */

312

$eval<T>(selector: string, pageFunction: Function, ...args: any[]): Promise<T>;

313

/** Evaluate function with all selected elements */

314

$$eval<T>(selector: string, pageFunction: Function, ...args: any[]): Promise<T>;

315

/** Query elements by XPath */

316

$x(expression: string): Promise<ElementHandle[]>;

317

}

318

```

319

320

**Usage Examples:**

321

322

```typescript

323

// CSS selectors

324

const header = await page.$("header");

325

const allButtons = await page.$$("button");

326

const navLinks = await page.$$("nav a");

327

328

// Evaluate with selected elements

329

const buttonTexts = await page.$$eval("button", (buttons) =>

330

buttons.map(btn => btn.textContent)

331

);

332

333

const firstLinkHref = await page.$eval("a", (link) => link.href);

334

335

// XPath selectors

336

const elementsWithText = await page.$x("//div[contains(text(), 'Hello')]");

337

const tableRows = await page.$x("//table//tr");

338

339

// Complex selectors

340

const specificElement = await page.$(

341

"div.container > section:nth-child(2) button[data-action='submit']"

342

);

343

```

344

345

### Advanced Element Operations

346

347

Complex element interactions and advanced features:

348

349

```typescript { .api }

350

interface AdvancedElementOperations {

351

/** Drag and drop operations */

352

dragAndDrop(source: ElementHandle, target: ElementHandle, options?: DragAndDropOptions): Promise<void>;

353

/** Scroll operations */

354

scroll(element: ElementHandle, options: ScrollOptions): Promise<void>;

355

/** Visibility checks */

356

isVisible(element: ElementHandle): Promise<boolean>;

357

isHidden(element: ElementHandle): Promise<boolean>;

358

/** Wait for element state changes */

359

waitForElementState(element: ElementHandle, state: "visible" | "hidden" | "stable"): Promise<void>;

360

}

361

```

362

363

**Usage Examples:**

364

365

```typescript

366

// Drag and drop

367

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

368

const dropZone = await page.$("#drop-zone");

369

370

if (draggable && dropZone) {

371

await draggable.dragAndDrop(dropZone, { delay: 100 });

372

}

373

374

// Scroll operations

375

const scrollableDiv = await page.$("#scrollable-content");

376

if (scrollableDiv) {

377

await scrollableDiv.scroll({ top: 100, behavior: "smooth" });

378

}

379

380

// Advanced waiting

381

const dynamicElement = await page.$("#dynamic-content");

382

if (dynamicElement) {

383

// Wait for element to become visible

384

await page.waitForFunction(

385

(el) => el.offsetHeight > 0,

386

{},

387

dynamicElement

388

);

389

}

390

391

// Element screenshots

392

const chart = await page.$("#sales-chart");

393

if (chart) {

394

await chart.screenshot({ path: "chart.png" });

395

}

396

```

397

398

### Frame Context

399

400

Working with elements in different frames:

401

402

```typescript { .api }

403

interface Frame {

404

/** Query selector in frame */

405

$(selector: string): Promise<ElementHandle | null>;

406

/** Query selector all in frame */

407

$$(selector: string): Promise<ElementHandle[]>;

408

/** Evaluate with selector in frame */

409

$eval<T>(selector: string, pageFunction: Function, ...args: any[]): Promise<T>;

410

/** Evaluate with selector all in frame */

411

$$eval<T>(selector: string, pageFunction: Function, ...args: any[]): Promise<T>;

412

/** XPath query in frame */

413

$x(expression: string): Promise<ElementHandle[]>;

414

/** Wait for selector in frame */

415

waitForSelector(selector: string, options?: WaitForSelectorOptions): Promise<ElementHandle | null>;

416

/** Get frame name */

417

name(): string;

418

/** Get frame URL */

419

url(): string;

420

/** Get parent frame */

421

parentFrame(): Frame | null;

422

/** Get child frames */

423

childFrames(): Frame[];

424

/** Check if frame detached */

425

isDetached(): boolean;

426

/** Get execution context */

427

executionContext(): Promise<ExecutionContext>;

428

/** Evaluate in frame */

429

evaluate<T>(pageFunction: Function, ...args: any[]): Promise<T>;

430

/** Evaluate and return handle in frame */

431

evaluateHandle<T>(pageFunction: Function, ...args: any[]): Promise<JSHandle<T>>;

432

/** Click in frame */

433

click(selector: string, options?: ClickOptions): Promise<void>;

434

/** Focus in frame */

435

focus(selector: string): Promise<void>;

436

/** Hover in frame */

437

hover(selector: string): Promise<void>;

438

/** Select in frame */

439

select(selector: string, ...values: string[]): Promise<string[]>;

440

/** Tap in frame */

441

tap(selector: string): Promise<void>;

442

/** Type in frame */

443

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

444

}

445

```

446

447

**Usage Examples:**

448

449

```typescript

450

// Working with iframes

451

const frames = page.frames();

452

const iframe = frames.find(frame => frame.name() === "content-frame");

453

454

if (iframe) {

455

// Select elements within iframe

456

const iframeButton = await iframe.$("#iframe-button");

457

if (iframeButton) {

458

await iframeButton.click();

459

}

460

461

// Evaluate within iframe

462

const iframeTitle = await iframe.evaluate(() => document.title);

463

console.log("Iframe title:", iframeTitle);

464

}

465

466

// Handle nested frames

467

const childFrames = iframe?.childFrames() || [];

468

for (const childFrame of childFrames) {

469

const childContent = await childFrame.$eval("body", (body) => body.textContent);

470

console.log("Child frame content:", childContent);

471

}

472

```

473

474

### Error Handling

475

476

Common errors when working with elements:

477

478

```typescript { .api }

479

class TimeoutError extends Error {

480

constructor(message: string);

481

}

482

483

class ElementHandleError extends Error {

484

constructor(message: string);

485

}

486

```

487

488

**Usage Examples:**

489

490

```typescript

491

try {

492

// Element might not exist

493

const element = await page.waitForSelector("#dynamic-element", {

494

timeout: 5000

495

});

496

497

if (element) {

498

await element.click();

499

}

500

} catch (error) {

501

if (error instanceof TimeoutError) {

502

console.log("Element did not appear within timeout");

503

} else {

504

console.log("Unexpected error:", error.message);

505

}

506

}

507

508

// Safe element operations

509

async function safeClick(page: Page, selector: string) {

510

try {

511

const element = await page.$(selector);

512

if (element) {

513

const isVisible = await element.isVisible();

514

if (isVisible) {

515

await element.click();

516

return true;

517

}

518

}

519

} catch (error) {

520

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

521

}

522

return false;

523

}

524

525

// Usage

526

const success = await safeClick(page, "#submit-button");

527

if (!success) {

528

console.log("Could not click submit button");

529

}

530

```