Playwriter.Browser.Session (Playwriter v0.3.0)

Copy Markdown View Source

Manages a browser session lifecycle.

A session owns:

  • A transport connection
  • A browser instance
  • Multiple browser contexts
  • Pages within those contexts

Example

{:ok, session} = Session.start_link(mode: :local, headless: true)
{:ok, page} = Session.new_page(session)
:ok = Session.goto(session, page, "https://example.com")
{:ok, html} = Session.content(session, page)
:ok = Session.close(session)

Summary

Functions

Add cookies to a context (guid from new_context/2). Each cookie is a map using Playwright's field names (name, value, and either url or domain+path; optionally httpOnly, secure, sameSite, expires).

Add an init script to a context (identified by the guid returned from new_context/2). The script runs before any page scripts on every page and navigation in that context, so it must be added before the page is created.

Send a CDP command over a session opened with new_cdp_session/2.

Returns a specification to start this module under a supervisor.

Close the entire session.

Get page HTML content.

Evaluate a JavaScript expression in a page's main frame and return the result.

Expose an Elixir callback to the page as a binding (experimental, :windows-only). The page can call window.<name>(...args) and the callback is invoked with the argument list; its return value is passed back to the page.

Open a Chrome DevTools Protocol session for a page. Returns an opaque CDP session id to use with cdp_send/4.

Create a new browser context.

Create a new page in the default context.

Start a new browser session.

Return a context's storage state (cookies + localStorage). Capture it after a UI login and re-seed it with add_cookies/3 in later runs.

Wait until a JavaScript predicate becomes truthy in a page's main frame.

Types

page_info()

@type page_info() :: %{
  page_guid: String.t(),
  frame_guid: String.t(),
  context_guid: String.t()
}

Functions

add_cookies(session, context_guid, cookies)

@spec add_cookies(GenServer.server(), String.t(), [map()]) :: :ok | {:error, term()}

Add cookies to a context (guid from new_context/2). Each cookie is a map using Playwright's field names (name, value, and either url or domain+path; optionally httpOnly, secure, sameSite, expires).

This is the fast way past an auth gate: seed a pre-signed session cookie instead of driving the login UI.

Examples

{:ok, ctx} = Session.new_context(session, [])
:ok = Session.add_cookies(session, ctx, [
  %{name: "_listener_web_key", value: signed, domain: "localhost", path: "/", sameSite: "Lax"}
])
{:ok, page} = Session.new_page(session, context_guid: ctx)   # starts past the gate

add_init_script(session, context_guid, script, opts \\ [])

@spec add_init_script(GenServer.server(), String.t(), String.t(), keyword()) ::
  :ok | {:error, term()}

Add an init script to a context (identified by the guid returned from new_context/2). The script runs before any page scripts on every page and navigation in that context, so it must be added before the page is created.

Examples

{:ok, ctx} = Session.new_context(session, [])
:ok = Session.add_init_script(session, ctx, "window.__debug = 1")
{:ok, page} = Session.new_page(session, context_guid: ctx)

cdp_send(session, cdp_session_id, method, params \\ %{})

@spec cdp_send(GenServer.server(), String.t(), String.t(), map()) ::
  {:ok, term()} | {:error, term()}

Send a CDP command over a session opened with new_cdp_session/2.

Examples

{:ok, cdp} = Session.new_cdp_session(session, page)
{:ok, _} = Session.cdp_send(session, cdp, "Network.emulateNetworkConditions", %{
  offline: false, latency: 200, downloadThroughput: 100_000, uploadThroughput: 100_000
})

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

click(session, page_id, selector, opts \\ [])

@spec click(GenServer.server(), String.t(), String.t(), keyword()) ::
  :ok | {:error, term()}

Click an element.

Options

  • :timeout - Click timeout in ms (default: 30000)

close(session)

@spec close(GenServer.server()) :: :ok

Close the entire session.

close_page(session, page_id)

@spec close_page(GenServer.server(), String.t()) :: :ok | {:error, term()}

Close a page.

content(session, page_id)

@spec content(GenServer.server(), String.t()) :: {:ok, String.t()} | {:error, term()}

Get page HTML content.

evaluate(session, page_id, expression, opts \\ [])

@spec evaluate(GenServer.server(), String.t(), String.t(), keyword()) ::
  {:ok, term()} | {:error, term()}

Evaluate a JavaScript expression in a page's main frame and return the result.

Options

  • :is_function - treat the expression as a function body (default: false)
  • :arg - argument passed to the function
  • :timeout - evaluation timeout in ms (default: 30000)

Examples

{:ok, true} = Session.evaluate(session, page, "crossOriginIsolated")
{:ok, 3} = Session.evaluate(session, page, "(a) => a + 1", arg: 2, is_function: true)

expose_binding(session, context_guid, name, callback)

@spec expose_binding(GenServer.server(), String.t(), String.t(), (list() -> term())) ::
  :ok | {:error, term()}

Expose an Elixir callback to the page as a binding (experimental, :windows-only). The page can call window.<name>(...args) and the callback is invoked with the argument list; its return value is passed back to the page.

Register the binding on a context (guid from new_context/2) before creating the page. :local/:remote return {:error, :not_supported}.

fill(session, page_id, selector, value, opts \\ [])

@spec fill(GenServer.server(), String.t(), String.t(), String.t(), keyword()) ::
  :ok | {:error, term()}

Fill an input field.

Options

  • :timeout - Fill timeout in ms (default: 30000)

goto(session, page_id, url, opts \\ [])

@spec goto(GenServer.server(), String.t(), String.t(), keyword()) ::
  :ok | {:error, term()}

Navigate to a URL.

Options

  • :timeout - Navigation timeout in ms (default: 30000)
  • :wait_until - When to consider navigation complete (:load, :domcontentloaded, :networkidle)

new_cdp_session(session, page_id)

@spec new_cdp_session(GenServer.server(), String.t()) ::
  {:ok, String.t()} | {:error, term()}

Open a Chrome DevTools Protocol session for a page. Returns an opaque CDP session id to use with cdp_send/4.

Only supported by the :windows transport; :local returns {:error, :not_supported}.

new_context(session, opts \\ [])

@spec new_context(
  GenServer.server(),
  keyword()
) :: {:ok, String.t()} | {:error, term()}

Create a new browser context.

Options

  • :viewport - Viewport dimensions %{width: 1920, height: 1080}
  • :user_agent - Custom user agent string
  • :locale - User locale (e.g., "en-US")
  • :color_scheme - Color scheme preference (:light, :dark)

new_page(session, opts \\ [])

@spec new_page(
  GenServer.server(),
  keyword()
) :: {:ok, String.t()} | {:error, term()}

Create a new page in the default context.

Returns a page_id that can be used with other Session functions.

screenshot(session, page_id, opts \\ [])

@spec screenshot(GenServer.server(), String.t(), keyword()) ::
  {:ok, binary()} | {:error, term()}

Take a screenshot.

Options

  • :full_page - Capture full scrollable page (default: false)
  • :omit_background - Omit background for transparent screenshots (default: false)

start_link(opts \\ [])

@spec start_link(keyword()) :: {:ok, pid()} | {:error, term()}

Start a new browser session.

Options

  • :mode - :local, :remote, or :auto (default: :auto)
  • :ws_endpoint - WebSocket URL for remote mode
  • :headless - Run browser in headless mode (default: true)
  • :browser_type - :chromium, :firefox, or :webkit (default: :chromium)
  • :name - Optional name for the GenServer

storage_state(session, context_guid)

@spec storage_state(GenServer.server(), String.t()) :: {:ok, map()} | {:error, term()}

Return a context's storage state (cookies + localStorage). Capture it after a UI login and re-seed it with add_cookies/3 in later runs.

wait_for_function(session, page_id, expression, opts \\ [])

@spec wait_for_function(GenServer.server(), String.t(), String.t(), keyword()) ::
  :ok | {:error, term()}

Wait until a JavaScript predicate becomes truthy in a page's main frame.

Options

  • :is_function - treat the expression as a function body (default: false)
  • :arg - argument passed to the function
  • :polling - a number of ms, or "raf" (default: "raf")
  • :timeout - timeout in ms (default: 30000)

Examples

:ok = Session.wait_for_function(session, page, "window.__ready === true", timeout: 60_000)