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

browser-contexts.mddocs/

0

# Browser Contexts

1

2

Isolated browser contexts for managing sessions, cookies, permissions, and parallel test execution.

3

4

## Capabilities

5

6

### BrowserContext Interface

7

8

Provides isolated browser sessions with independent cookies, storage, and permissions.

9

10

```typescript { .api }

11

interface BrowserContext extends EventEmitter {

12

/** Create new page in this context */

13

newPage(): Promise<Page>;

14

/** Get all pages in this context */

15

pages(): Page[];

16

/** Get browser instance */

17

browser(): Browser;

18

/** Close context and all pages */

19

close(): Promise<void>;

20

/** Check if context is closed */

21

isIncognito(): boolean;

22

/** Get/set cookies */

23

cookies(...urls: string[]): Promise<Cookie[]>;

24

setCookie(...cookies: CookieParam[]): Promise<void>;

25

addCookies(cookies: CookieParam[]): Promise<void>;

26

clearCookies(): Promise<void>;

27

/** Permissions management */

28

grantPermissions(permissions: Permission[], options?: { origin?: string }): Promise<void>;

29

clearPermissionOverrides(): Promise<void>;

30

overridePermissions(origin: string, permissions: Permission[]): Promise<void>;

31

/** Geolocation */

32

setGeolocation(geolocation: GeolocationOptions): Promise<void>;

33

/** HTTP credentials */

34

setHTTPCredentials(httpCredentials: HTTPCredentials | null): Promise<void>;

35

/** User agent */

36

setUserAgent(userAgent: string): Promise<void>;

37

/** Viewport */

38

setViewportSize(viewportSize: ViewportSize): Promise<void>;

39

/** Offline mode */

40

setOffline(offline: boolean): Promise<void>;

41

/** Extra HTTP headers */

42

setExtraHTTPHeaders(headers: Record<string, string>): Promise<void>;

43

/** Request interception */

44

setRequestInterception(value: boolean): Promise<void>;

45

/** Default timeout */

46

setDefaultTimeout(timeout: number): void;

47

setDefaultNavigationTimeout(timeout: number): void;

48

/** Wait for events */

49

waitForEvent(event: string, optionsOrPredicate?: Function | { timeout?: number; predicate?: Function }): Promise<any>;

50

/** Tracing */

51

tracing(): Tracing;

52

/** Route handling */

53

route(url: string | RegExp | ((url: URL) => boolean), handler: RouteHandler): Promise<void>;

54

unroute(url: string | RegExp | ((url: URL) => boolean), handler?: RouteHandler): Promise<void>;

55

/** Storage state */

56

storageState(options?: { path?: string }): Promise<StorageState>;

57

addInitScript(script: Function | string | { path?: string; content?: string }): Promise<void>;

58

/** Expose function to all pages */

59

exposeFunction(name: string, callback: Function): Promise<void>;

60

exposeBinding(name: string, callback: Function, options?: { handle?: boolean }): Promise<void>;

61

/** Service workers */

62

serviceWorkers(): Worker[];

63

/** Background pages */

64

backgroundPages(): Page[];

65

/** CDPSession */

66

newCDPSession(page: Page): Promise<CDPSession>;

67

}

68

69

interface Cookie {

70

name: string;

71

value: string;

72

domain?: string;

73

path?: string;

74

expires?: number;

75

httpOnly?: boolean;

76

secure?: boolean;

77

sameSite?: "Strict" | "Lax" | "None";

78

priority?: "Low" | "Medium" | "High";

79

sameParty?: boolean;

80

sourceScheme?: "Unset" | "NonSecure" | "Secure";

81

partitionKey?: string;

82

}

83

84

interface CookieParam {

85

name: string;

86

value: string;

87

url?: string;

88

domain?: string;

89

path?: string;

90

secure?: boolean;

91

httpOnly?: boolean;

92

sameSite?: "Strict" | "Lax" | "None";

93

expires?: number;

94

priority?: "Low" | "Medium" | "High";

95

sameParty?: boolean;

96

sourceScheme?: "Unset" | "NonSecure" | "Secure";

97

partitionKey?: string;

98

}

99

100

type Permission =

101

| "geolocation"

102

| "midi"

103

| "notifications"

104

| "camera"

105

| "microphone"

106

| "background-sync"

107

| "ambient-light-sensor"

108

| "accelerometer"

109

| "gyroscope"

110

| "magnetometer"

111

| "accessibility-events"

112

| "clipboard-read"

113

| "clipboard-write"

114

| "payment-handler"

115

| "persistent-storage"

116

| "idle-detection"

117

| "midi-sysex";

118

119

interface GeolocationOptions {

120

latitude: number;

121

longitude: number;

122

accuracy?: number;

123

}

124

125

interface HTTPCredentials {

126

username: string;

127

password: string;

128

origin?: string;

129

}

130

131

interface ViewportSize {

132

width: number;

133

height: number;

134

}

135

136

interface RouteHandler {

137

(route: Route, request: Request): Promise<void> | void;

138

}

139

140

interface StorageState {

141

cookies: Cookie[];

142

origins: OriginState[];

143

}

144

145

interface OriginState {

146

origin: string;

147

localStorage: NameValuePair[];

148

sessionStorage: NameValuePair[];

149

}

150

151

interface NameValuePair {

152

name: string;

153

value: string;

154

}

155

```

156

157

**Usage Examples:**

158

159

```typescript

160

import puppeteer from "puppeteer-core";

161

162

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

163

164

// Create isolated contexts

165

const context1 = await browser.createBrowserContext();

166

const context2 = await browser.createBrowserContext();

167

168

// Each context has its own session

169

const page1 = await context1.newPage();

170

const page2 = await context2.newPage();

171

172

// Set different cookies for each context

173

await context1.setCookie({

174

name: "user",

175

value: "alice",

176

domain: "example.com"

177

});

178

179

await context2.setCookie({

180

name: "user",

181

value: "bob",

182

domain: "example.com"

183

});

184

185

// Navigate to same site - each will have different cookies

186

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

187

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

188

189

// Set different permissions

190

await context1.grantPermissions(["geolocation"], { origin: "https://example.com" });

191

await context2.overridePermissions("https://example.com", []); // No permissions

192

193

// Close contexts

194

await context1.close();

195

await context2.close();

196

await browser.close();

197

```

198

199

### Context Creation and Configuration

200

201

Create browser contexts with specific configurations:

202

203

```typescript { .api }

204

interface BrowserContextOptions {

205

/** Accept downloads */

206

acceptDownloads?: boolean;

207

/** Bypass CSP */

208

bypassCSP?: boolean;

209

/** Color scheme */

210

colorScheme?: "light" | "dark" | "no-preference";

211

/** Device scale factor */

212

deviceScaleFactor?: number;

213

/** Extra HTTP headers */

214

extraHTTPHeaders?: Record<string, string>;

215

/** Geolocation */

216

geolocation?: GeolocationOptions;

217

/** Has touch */

218

hasTouch?: boolean;

219

/** HTTP credentials */

220

httpCredentials?: HTTPCredentials;

221

/** Ignore HTTPS errors */

222

ignoreHTTPSErrors?: boolean;

223

/** Is mobile */

224

isMobile?: boolean;

225

/** Java Script enabled */

226

javaScriptEnabled?: boolean;

227

/** Locale */

228

locale?: string;

229

/** Offline */

230

offline?: boolean;

231

/** Permissions */

232

permissions?: Permission[];

233

/** Proxy */

234

proxy?: ProxySettings;

235

/** Record HAR */

236

recordHar?: HarOptions;

237

/** Record video */

238

recordVideo?: VideoOptions;

239

/** Reduced motion */

240

reducedMotion?: "reduce" | "no-preference";

241

/** Screen */

242

screen?: ScreenSize;

243

/** Service workers */

244

serviceWorkers?: "allow" | "block";

245

/** Storage state */

246

storageState?: string | StorageState;

247

/** Timezone */

248

timezoneId?: string;

249

/** User agent */

250

userAgent?: string;

251

/** Viewport */

252

viewport?: ViewportSize | null;

253

}

254

255

interface ProxySettings {

256

server: string;

257

bypass?: string;

258

username?: string;

259

password?: string;

260

}

261

262

interface HarOptions {

263

omitContent?: boolean;

264

path?: string;

265

}

266

267

interface VideoOptions {

268

dir: string;

269

size?: ViewportSize;

270

}

271

272

interface ScreenSize {

273

width: number;

274

height: number;

275

}

276

```

277

278

**Usage Examples:**

279

280

```typescript

281

// Create context with mobile emulation

282

const mobileContext = await browser.createBrowserContext({

283

viewport: { width: 375, height: 667 },

284

userAgent: "Mozilla/5.0 (iPhone; CPU iPhone OS 14_0 like Mac OS X) AppleWebKit/605.1.15",

285

isMobile: true,

286

hasTouch: true,

287

deviceScaleFactor: 2

288

});

289

290

// Create context with specific locale and timezone

291

const localizedContext = await browser.createBrowserContext({

292

locale: "de-DE",

293

timezoneId: "Europe/Berlin",

294

colorScheme: "dark"

295

});

296

297

// Create context with geolocation and permissions

298

const locationContext = await browser.createBrowserContext({

299

geolocation: { latitude: 37.7749, longitude: -122.4194 },

300

permissions: ["geolocation", "notifications"]

301

});

302

303

// Create context with proxy

304

const proxyContext = await browser.createBrowserContext({

305

proxy: {

306

server: "http://proxy.example.com:8080",

307

username: "proxyuser",

308

password: "proxypass"

309

}

310

});

311

312

// Create context with custom storage state

313

const contextWithStorage = await browser.createBrowserContext({

314

storageState: {

315

cookies: [

316

{

317

name: "session_id",

318

value: "abc123",

319

domain: "example.com",

320

path: "/",

321

secure: true,

322

httpOnly: true

323

}

324

],

325

origins: [

326

{

327

origin: "https://example.com",

328

localStorage: [

329

{ name: "theme", value: "dark" },

330

{ name: "language", value: "en" }

331

],

332

sessionStorage: []

333

}

334

]

335

}

336

});

337

```

338

339

### Cookie Management

340

341

Comprehensive cookie management within contexts:

342

343

```typescript { .api }

344

interface CookieManagement {

345

/** Add single cookie */

346

addCookie(cookie: CookieParam): Promise<void>;

347

/** Add multiple cookies */

348

addCookies(cookies: CookieParam[]): Promise<void>;

349

/** Get cookies for URLs */

350

getCookies(urls?: string[]): Promise<Cookie[]>;

351

/** Set cookies (replaces existing) */

352

setCookies(cookies: CookieParam[]): Promise<void>;

353

/** Delete specific cookies */

354

deleteCookies(cookies: DeleteCookieParam[]): Promise<void>;

355

/** Clear all cookies */

356

clearAllCookies(): Promise<void>;

357

/** Get cookie by name */

358

getCookie(name: string, url?: string): Promise<Cookie | null>;

359

}

360

361

interface DeleteCookieParam {

362

name: string;

363

url?: string;

364

domain?: string;

365

path?: string;

366

}

367

```

368

369

**Usage Examples:**

370

371

```typescript

372

const context = await browser.createBrowserContext();

373

374

// Add authentication cookies

375

await context.addCookies([

376

{

377

name: "auth_token",

378

value: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",

379

domain: "api.example.com",

380

path: "/",

381

secure: true,

382

httpOnly: true,

383

sameSite: "Strict"

384

},

385

{

386

name: "session_id",

387

value: "sess_abc123",

388

domain: "example.com",

389

path: "/",

390

expires: Date.now() + 86400000 // 24 hours

391

}

392

]);

393

394

// Get cookies for specific domains

395

const allCookies = await context.cookies();

396

const exampleCookies = await context.cookies("https://example.com");

397

const apiCookies = await context.cookies("https://api.example.com");

398

399

// Update cookie value

400

await context.setCookie({

401

name: "theme",

402

value: "dark",

403

domain: "example.com"

404

});

405

406

// Delete specific cookies

407

await context.clearCookies();

408

409

// Cookie-based session management

410

class SessionManager {

411

constructor(private context: BrowserContext) {}

412

413

async login(username: string, password: string) {

414

const page = await this.context.newPage();

415

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

416

417

await page.type("#username", username);

418

await page.type("#password", password);

419

await page.click("#login-button");

420

421

// Wait for redirect and session cookie

422

await page.waitForNavigation();

423

await page.close();

424

}

425

426

async isLoggedIn(): Promise<boolean> {

427

const cookies = await this.context.cookies("https://example.com");

428

return cookies.some(cookie => cookie.name === "session_id");

429

}

430

431

async logout() {

432

await this.context.clearCookies();

433

}

434

}

435

436

const sessionManager = new SessionManager(context);

437

await sessionManager.login("user@example.com", "password123");

438

```

439

440

### Permission Management

441

442

Control browser permissions within contexts:

443

444

```typescript { .api }

445

interface PermissionManagement {

446

/** Grant permissions for origin */

447

grantPermissions(permissions: Permission[], origin?: string): Promise<void>;

448

/** Override permissions for origin */

449

overridePermissions(origin: string, permissions: Permission[]): Promise<void>;

450

/** Clear permission overrides */

451

clearPermissionOverrides(): Promise<void>;

452

/** Check permission state */

453

getPermissionState(permission: Permission, origin?: string): Promise<PermissionState>;

454

}

455

456

type PermissionState = "granted" | "denied" | "prompt";

457

```

458

459

**Usage Examples:**

460

461

```typescript

462

const context = await browser.createBrowserContext();

463

464

// Grant geolocation permission

465

await context.grantPermissions(["geolocation"], {

466

origin: "https://maps.example.com"

467

});

468

469

// Block notifications globally

470

await context.overridePermissions("https://example.com", []);

471

472

// Grant multiple permissions

473

await context.grantPermissions([

474

"camera",

475

"microphone",

476

"notifications"

477

], { origin: "https://video-chat.example.com" });

478

479

// Permission-based testing

480

async function testLocationFeature(context: BrowserContext) {

481

// Test with permission granted

482

await context.grantPermissions(["geolocation"]);

483

const page = await context.newPage();

484

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

485

486

const locationButton = await page.$("#get-location");

487

await locationButton.click();

488

489

// Verify location was obtained

490

const locationText = await page.$("#current-location").textContent();

491

console.log("Location with permission:", locationText);

492

493

await page.close();

494

495

// Test with permission denied

496

await context.overridePermissions("https://example.com", []);

497

const page2 = await context.newPage();

498

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

499

500

await page2.click("#get-location");

501

502

// Verify error message

503

const errorText = await page2.$("#location-error").textContent();

504

console.log("Location without permission:", errorText);

505

506

await page2.close();

507

}

508

509

await testLocationFeature(context);

510

```

511

512

### Context Events

513

514

Browser context events for monitoring and automation:

515

516

```typescript { .api }

517

interface BrowserContextEvents {

518

/** Emitted when page is created */

519

"page": (page: Page) => void;

520

/** Emitted when page is closed */

521

"close": () => void;

522

/** Emitted when background page is created */

523

"backgroundpage": (page: Page) => void;

524

/** Emitted when service worker is created */

525

"serviceworker": (worker: Worker) => void;

526

/** Emitted when request starts */

527

"request": (request: HTTPRequest) => void;

528

/** Emitted when response is received */

529

"response": (response: HTTPResponse) => void;

530

/** Emitted when request fails */

531

"requestfailed": (request: HTTPRequest) => void;

532

/** Emitted when request finishes */

533

"requestfinished": (request: HTTPRequest) => void;

534

}

535

```

536

537

**Usage Examples:**

538

539

```typescript

540

const context = await browser.createBrowserContext();

541

542

// Monitor page creation

543

context.on("page", (page) => {

544

console.log("New page created:", page.url());

545

546

// Set up page-level monitoring

547

page.on("console", (msg) => {

548

console.log(`Page console: ${msg.text()}`);

549

});

550

551

page.on("pageerror", (error) => {

552

console.error("Page error:", error.message);

553

});

554

});

555

556

// Monitor network activity across all pages

557

context.on("request", (request) => {

558

console.log(`Request: ${request.method()} ${request.url()}`);

559

});

560

561

context.on("response", (response) => {

562

if (!response.ok()) {

563

console.log(`Failed response: ${response.status()} ${response.url()}`);

564

}

565

});

566

567

// Handle context closure

568

context.on("close", () => {

569

console.log("Browser context closed");

570

});

571

572

// Create pages and trigger events

573

const page1 = await context.newPage();

574

const page2 = await context.newPage();

575

576

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

577

await page2.goto("https://another-example.com");

578

579

await context.close();

580

```

581

582

### Storage State Management

583

584

Save and restore browser state across sessions:

585

586

```typescript { .api }

587

interface StorageStateManagement {

588

/** Get current storage state */

589

getStorageState(): Promise<StorageState>;

590

/** Save storage state to file */

591

saveStorageState(path: string): Promise<void>;

592

/** Load storage state from file */

593

loadStorageState(path: string): Promise<StorageState>;

594

/** Create context with saved state */

595

createContextWithState(statePath: string): Promise<BrowserContext>;

596

}

597

```

598

599

**Usage Examples:**

600

601

```typescript

602

// Save authenticated session

603

const context = await browser.createBrowserContext();

604

const page = await context.newPage();

605

606

// Perform login

607

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

608

await page.type("#username", "user@example.com");

609

await page.type("#password", "password123");

610

await page.click("#login-button");

611

await page.waitForNavigation();

612

613

// Save storage state

614

const storageState = await context.storageState();

615

await context.storageState({ path: "auth-state.json" });

616

617

await context.close();

618

619

// Restore session later

620

const restoredContext = await browser.createBrowserContext({

621

storageState: "auth-state.json"

622

});

623

624

const restoredPage = await restoredContext.newPage();

625

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

626

627

// User should already be logged in

628

const welcomeText = await restoredPage.$("#welcome-message").textContent();

629

console.log(welcomeText); // Should show logged-in state

630

631

// Session state management utility

632

class SessionStateManager {

633

private stateFile: string;

634

635

constructor(stateFile: string) {

636

this.stateFile = stateFile;

637

}

638

639

async createAuthenticatedContext(browser: Browser): Promise<BrowserContext> {

640

try {

641

return await browser.createBrowserContext({

642

storageState: this.stateFile

643

});

644

} catch (error) {

645

console.log("No saved state found, creating fresh context");

646

return await browser.createBrowserContext();

647

}

648

}

649

650

async saveState(context: BrowserContext): Promise<void> {

651

await context.storageState({ path: this.stateFile });

652

}

653

654

async clearState(): Promise<void> {

655

try {

656

await import("fs").then(fs => fs.unlinkSync(this.stateFile));

657

} catch (error) {

658

// File doesn't exist, nothing to do

659

}

660

}

661

}

662

663

const stateManager = new SessionStateManager("user-session.json");

664

const authContext = await stateManager.createAuthenticatedContext(browser);

665

666

// Use context...

667

await stateManager.saveState(authContext);

668

```

669

670

### Parallel Execution with Contexts

671

672

Use contexts for parallel test execution and isolation:

673

674

```typescript { .api }

675

interface ParallelExecution {

676

/** Run tests in parallel contexts */

677

runParallel<T>(tests: (() => Promise<T>)[], maxConcurrency?: number): Promise<T[]>;

678

/** Create context pool */

679

createContextPool(browser: Browser, poolSize: number): ContextPool;

680

/** Execute with context isolation */

681

withIsolatedContext<T>(browser: Browser, operation: (context: BrowserContext) => Promise<T>): Promise<T>;

682

}

683

684

interface ContextPool {

685

acquire(): Promise<BrowserContext>;

686

release(context: BrowserContext): void;

687

close(): Promise<void>;

688

}

689

```

690

691

**Usage Examples:**

692

693

```typescript

694

// Parallel test execution

695

async function runParallelTests(browser: Browser) {

696

const tests = [

697

async () => {

698

const context = await browser.createBrowserContext();

699

const page = await context.newPage();

700

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

701

const result = await page.$("#result").textContent();

702

await context.close();

703

return { test: "test1", result };

704

},

705

async () => {

706

const context = await browser.createBrowserContext();

707

const page = await context.newPage();

708

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

709

const result = await page.$("#result").textContent();

710

await context.close();

711

return { test: "test2", result };

712

},

713

async () => {

714

const context = await browser.createBrowserContext();

715

const page = await context.newPage();

716

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

717

const result = await page.$("#result").textContent();

718

await context.close();

719

return { test: "test3", result };

720

}

721

];

722

723

const results = await Promise.all(tests.map(test => test()));

724

return results;

725

}

726

727

const testResults = await runParallelTests(browser);

728

console.log("Test results:", testResults);

729

730

// Context pool for resource management

731

class BrowserContextPool {

732

private contexts: BrowserContext[] = [];

733

private inUse: Set<BrowserContext> = new Set();

734

735

constructor(private browser: Browser, private maxSize: number) {}

736

737

async acquire(): Promise<BrowserContext> {

738

// Try to find available context

739

const available = this.contexts.find(ctx => !this.inUse.has(ctx));

740

if (available) {

741

this.inUse.add(available);

742

return available;

743

}

744

745

// Create new context if under limit

746

if (this.contexts.length < this.maxSize) {

747

const context = await this.browser.createBrowserContext();

748

this.contexts.push(context);

749

this.inUse.add(context);

750

return context;

751

}

752

753

// Wait for context to become available

754

return new Promise((resolve) => {

755

const checkAvailable = () => {

756

const available = this.contexts.find(ctx => !this.inUse.has(ctx));

757

if (available) {

758

this.inUse.add(available);

759

resolve(available);

760

} else {

761

setTimeout(checkAvailable, 100);

762

}

763

};

764

checkAvailable();

765

});

766

}

767

768

release(context: BrowserContext): void {

769

this.inUse.delete(context);

770

}

771

772

async close(): Promise<void> {

773

await Promise.all(this.contexts.map(ctx => ctx.close()));

774

this.contexts = [];

775

this.inUse.clear();

776

}

777

}

778

779

// Usage

780

const contextPool = new BrowserContextPool(browser, 5);

781

782

async function runWithPool(operation: (page: Page) => Promise<any>) {

783

const context = await contextPool.acquire();

784

try {

785

const page = await context.newPage();

786

const result = await operation(page);

787

await page.close();

788

return result;

789

} finally {

790

contextPool.release(context);

791

}

792

}

793

794

// Run multiple operations

795

const operations = Array(10).fill(0).map((_, i) =>

796

runWithPool(async (page) => {

797

await page.goto(`https://example.com/item/${i}`);

798

return await page.$("#title").textContent();

799

})

800

);

801

802

const results = await Promise.all(operations);

803

await contextPool.close();

804

```