Summary
BrowserContext has six public members — pages, browser, close, waitUntilComplete, abort, newPage — and no state of its own. In Playwright a context is the isolation boundary: it owns cookies, storage, permissions and geolocation, and storageState() is how authenticated sessions get reused across tests.
Here a context is only a grouping of pages. Each page's document carries its own CookieContainer, so cookies set in one page are invisible to a sibling page in the same context.
Reproduction
import { Browser } from 'very-happy-dom'
const context = new Browser().newIncognitoContext()
console.log(typeof context.cookies) // undefined
console.log(typeof context.addCookies) // undefined
console.log(typeof context.clearCookies) // undefined
console.log(typeof context.storageState) // undefined
console.log(typeof context.grantPermissions) // undefined
console.log(typeof context.setGeolocation) // undefined
console.log(typeof context.setOffline) // undefined
console.log(typeof context.setExtraHTTPHeaders) // undefined
console.log(typeof context.addInitScript) // undefined
console.log(typeof context.route) // undefined
// Cookies do not cross pages inside one context:
const p1 = context.newPage()
const p2 = context.newPage()
p1.mainFrame.document.cookie = 'session=abc'
console.log(p1.mainFrame.document.cookie) // session=abc
console.log(p2.mainFrame.document.cookie) // "" — Playwright shares these per contextConfirmed against main at 5fae54d4 with Bun 1.4.3.
Current implementation
BrowserContext stores a Browser reference and a page array. CookieContainer already exists and is a good fit for context-level ownership, but it is currently instantiated per document (VirtualDocument._cookieContainer = new CookieContainer()) and also wrapped by the jsdom CookieJar. Nothing connects it to a context.
Expected behavior
The context owns the jar, and documents read and write through it, so cookies are shared between pages in a context and isolated between contexts.
Cookies:
await context.addCookies([{ name: 'session', value: 'abc', domain: 'example.com', path: '/' }])
const cookies = await context.cookies() // optionally filtered by URL
await context.clearCookies()Storage state — the highest-value piece, since it is how auth is reused:
const state = await context.storageState() // { cookies: [...], origins: [{ origin, localStorage: [...] }] }with the matching storageState accepted when creating a context, so a saved session can be restored. That depends on localStorage also being context-scoped per origin rather than per Window.
Emulation, which mostly needs wiring to things that already exist:
| Method | Notes |
|---|---|
grantPermissions(names, options) / clearPermissions() | navigator.permissions.query() already exists and could read this |
setGeolocation(coords) | the Geolocation API already exists and could read this |
setOffline(offline) | should flip navigator.onLine and fail requests |
setExtraHTTPHeaders(headers) | applied to requests from the context |
addInitScript(script) | run in every new page before its document loads |
setDefaultTimeout(ms) | default for the waitFor* family |
route/unroute on the context is tracked separately in #1594.
Related: #1590 — per-origin localStorage needs frames to have real Window objects first.