PlaywrightEx.Page (PlaywrightEx v0.15.0)

Copy Markdown View Source

Interact with a Playwright Page.

There is no official documentation, since this is considered Playwright internal.

Reference: https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/client/page.ts

Summary

Functions

Adds a script which would be evaluated in one of the following scenarios

Brings page to front (activates tab).

Closes the page.

Asserts that a screenshot of the page matches the provided baseline.

Dispatches a mousedown event at the current mouse position.

Moves the mouse to the specified coordinates.

Dispatches a mouseup event at the current mouse position.

Reloads the page.

Returns the screenshot as a base64-encoded binary string.

Updates the subscription for page events.

Client-Composed Functions

Consumes the download event captured by expect_download/2.

Arms a download listener before the action that triggers it.

Expects page URL to match the provided expectation.

Registers one handler for a driver-matched URL glob. A second registration returns {:error, %{reason: :route_already_registered}}; remove it first. Globs support *, **, {a,b}, and backslash escapes; ? is literal. Matching and base-URL resolution are delegated to Playwright.

Removes the handler if its glob and optional callback match. Active callbacks are canceled and unresolved requests aborted. Requires :timeout; accepts :connection. This cancellation policy differs from Playwright.js unroute.

Removes the handler and cancels active callbacks. Options: required :timeout, optional :connection. No handler is a successful no-op.

Types

add_init_script_opt()

@type add_init_script_opt() ::
  {:connection, GenServer.name()} | {:timeout, timeout()} | {:source, binary()}

bring_to_front_opt()

@type bring_to_front_opt() :: {:connection, GenServer.name()} | {:timeout, timeout()}

close_opt()

@type close_opt() ::
  {:connection, GenServer.name()} | {:timeout, timeout()} | {:reason, binary()}

expect_download_opt()

@type expect_download_opt() ::
  {:connection, GenServer.name()}
  | {:timeout, timeout()}
  | {:predicate, (term() -> term())}

expect_screenshot_opt()

@type expect_screenshot_opt() ::
  {:connection, GenServer.name()}
  | {:timeout, timeout()}
  | {:is_not, boolean()}
  | {:expected, term()}
  | {:comparator, term()}
  | {:max_diff_pixels, integer()}
  | {:max_diff_pixel_ratio, float()}
  | {:threshold, float()}
  | {:full_page, boolean()}
  | {:locator, map()}
  | {:clip, map()}
  | {:omit_background, boolean()}
  | {:caret, term()}
  | {:animations, term()}
  | {:scale, term()}
  | {:mask, term()}
  | {:mask_color, binary()}
  | {:style, binary()}

expect_url_opt()

@type expect_url_opt() ::
  {:connection, GenServer.name()}
  | {:timeout, timeout()}
  | {:url, binary() | struct() | (term() -> term())}
  | {:is_not, boolean()}
  | {:ignore_case, boolean()}

mouse_down_opt()

@type mouse_down_opt() ::
  {:connection, GenServer.name()} | {:timeout, timeout()} | {:button, term()}

mouse_move_opt()

@type mouse_move_opt() ::
  {:connection, GenServer.name()}
  | {:timeout, timeout()}
  | {:x, integer() | float()}
  | {:y, integer() | float()}

mouse_up_opt()

@type mouse_up_opt() ::
  {:connection, GenServer.name()} | {:timeout, timeout()} | {:button, term()}

reload_opt()

@type reload_opt() ::
  {:connection, GenServer.name()}
  | {:timeout, timeout()}
  | {:wait_until, term()}

screenshot_opt()

@type screenshot_opt() ::
  {:connection, GenServer.name()}
  | {:timeout, timeout()}
  | {:full_page, boolean()}
  | {:omit_background, boolean()}

update_subscription_opt()

@type update_subscription_opt() ::
  {:connection, GenServer.name()}
  | {:timeout, timeout()}
  | {:event, term()}
  | {:enabled, boolean()}

Functions

add_init_script(context_id, opts \\ [])

@spec add_init_script(PlaywrightEx.guid(), [
  add_init_script_opt() | PlaywrightEx.unknown_opt()
]) ::
  {:ok, any()} | {:error, any()}

Adds a script which would be evaluated in one of the following scenarios:

  • Whenever the page is navigated.
  • Whenever the child frame is attached or navigated. In this case, the script is evaluated in the context of the newly attached frame.

The script is evaluated after the document was created but before any of its scripts were run. This is useful to amend the JavaScript environment, e.g. to seed Math.random.

Reference: https://playwright.dev/docs/api/class-page#page-add-init-script

Script Execution Order Is Not Defined

The order of evaluation of multiple scripts installed via PlaywrightEx.BrowserContext.add_init_script/2 and PlaywrightEx.Page.add_init_script/2 is not defined.

Options

  • :connection (term/0) - The Connection process name. Defaults to PlaywrightEx.Supervisor.Connection. The default value is PlaywrightEx.Supervisor.Connection.

  • :timeout (timeout/0) - Required. Operation timeout in milliseconds. 0 means no waiting; :infinity disables the timeout.

  • :source (String.t/0) - Required. Raw JavaScript code to be evaluated in all pages before any scripts run.

bring_to_front(page_id, opts \\ [])

@spec bring_to_front(PlaywrightEx.guid(), [
  bring_to_front_opt() | PlaywrightEx.unknown_opt()
]) ::
  {:ok, any()} | {:error, any()}

Brings page to front (activates tab).

Reference: https://playwright.dev/docs/api/class-page#page-bring-to-front

Options

  • :connection (term/0) - The Connection process name. Defaults to PlaywrightEx.Supervisor.Connection. The default value is PlaywrightEx.Supervisor.Connection.

  • :timeout (timeout/0) - Required. Operation timeout in milliseconds. 0 means no waiting; :infinity disables the timeout.

close(page_id, opts \\ [])

@spec close(PlaywrightEx.guid(), [close_opt() | PlaywrightEx.unknown_opt()]) ::
  {:ok, any()} | {:error, any()}

Closes the page.

Reference: https://playwright.dev/docs/api/class-page#page-close

Options

  • :connection (term/0) - The Connection process name. Defaults to PlaywrightEx.Supervisor.Connection. The default value is PlaywrightEx.Supervisor.Connection.

  • :timeout (timeout/0) - Required. Operation timeout in milliseconds. 0 means no waiting; :infinity disables the timeout.

  • :reason (String.t/0) - The reason to be reported to the operations interrupted by the page closure.

expect_screenshot(page_id, opts \\ [])

@spec expect_screenshot(PlaywrightEx.guid(), [
  expect_screenshot_opt() | PlaywrightEx.unknown_opt()
]) ::
  {:ok, binary() | nil} | {:error, {map(), map()}} | {:error, any()}

Asserts that a screenshot of the page matches the provided baseline.

Pass expected: nil (or omit it) for capture-only mode — the server takes a screenshot and returns the PNG bytes without performing any comparison.

Reference: https://playwright.dev/docs/api/class-pageassertions#page-assertions-to-have-screenshot-1

Options

  • :connection (term/0) - The Connection process name. Defaults to PlaywrightEx.Supervisor.Connection. The default value is PlaywrightEx.Supervisor.Connection.

  • :timeout (timeout/0) - Required. Operation timeout in milliseconds. 0 means no waiting; :infinity disables the timeout.

  • :is_not (boolean/0) - The default value is false.

  • :expected (term/0) - Base64-encoded baseline image. nil = capture-only mode.

  • :comparator - The default value is "pixelmatch".

  • :max_diff_pixels (integer/0) - Max absolute pixel count allowed to differ.

  • :max_diff_pixel_ratio (float/0) - Max ratio (0-1) of differing pixels.

  • :threshold (float/0) - Per-pixel color distance tolerance (0-1).

  • :full_page (boolean/0) - Capture the full scrollable page.

  • :locator (map/0) - Scope the assertion to a sub-element: %{frame: %{guid: frame_guid}, selector: string}.

  • :clip (map/0) - %{x: float, y: float, width: float, height: float}

  • :omit_background (boolean/0) - Transparent background (PNG only).

  • :caret

  • :animations

  • :scale

  • :mask (term/0) - List of %{frame: %{guid: frame_guid}, selector: string}.

  • :mask_color (String.t/0) - Colour for masked areas.

  • :style (String.t/0) - CSS to apply before screenshotting.

mouse_down(page_id, opts \\ [])

@spec mouse_down(PlaywrightEx.guid(), [mouse_down_opt() | PlaywrightEx.unknown_opt()]) ::
  {:ok, any()} | {:error, any()}

Dispatches a mousedown event at the current mouse position.

Reference: https://playwright.dev/docs/api/class-mouse#mouse-down

Example

# Perform a manual drag operation
{:ok, _} = Page.mouse_move(page_id, x: 100, y: 100, timeout: 5000)
{:ok, _} = Page.mouse_down(page_id, timeout: 5000)
{:ok, _} = Page.mouse_move(page_id, x: 200, y: 100, timeout: 5000)
{:ok, _} = Page.mouse_up(page_id, timeout: 5000)

Options

  • :connection (term/0) - The Connection process name. Defaults to PlaywrightEx.Supervisor.Connection. The default value is PlaywrightEx.Supervisor.Connection.

  • :timeout (timeout/0) - Required. Operation timeout in milliseconds. 0 means no waiting; :infinity disables the timeout.

  • :button - Defaults to :left. The default value is :left.

mouse_move(page_id, opts \\ [])

@spec mouse_move(PlaywrightEx.guid(), [mouse_move_opt() | PlaywrightEx.unknown_opt()]) ::
  {:ok, any()} | {:error, any()}

Moves the mouse to the specified coordinates.

This method dispatches a mousemove event. Supports fractional coordinates for precise positioning.

Reference: https://playwright.dev/docs/api/class-mouse#mouse-move

Example

# Get element position
{:ok, result} = Frame.evaluate(frame_id,
  expression: "() => {
    const el = document.querySelector('.slider-handle');
    const box = el.getBoundingClientRect();
    return { x: box.x + box.width / 2, y: box.y + box.height / 2 };
  }",
  is_function: true,
  timeout: 5000
)

# Move to element
{:ok, _} = Page.mouse_move(page_id, x: result["x"], y: result["y"], timeout: 5000)

Options

  • :connection (term/0) - The Connection process name. Defaults to PlaywrightEx.Supervisor.Connection. The default value is PlaywrightEx.Supervisor.Connection.

  • :timeout (timeout/0) - Required. Operation timeout in milliseconds. 0 means no waiting; :infinity disables the timeout.

  • :x - Required. x coordinate relative to the main frame's viewport in CSS pixels.

  • :y - Required. y coordinate relative to the main frame's viewport in CSS pixels.

mouse_up(page_id, opts \\ [])

@spec mouse_up(PlaywrightEx.guid(), [mouse_up_opt() | PlaywrightEx.unknown_opt()]) ::
  {:ok, any()} | {:error, any()}

Dispatches a mouseup event at the current mouse position.

Reference: https://playwright.dev/docs/api/class-mouse#mouse-up

Example

# Right-click at current position
{:ok, _} = Page.mouse_down(page_id, button: :right, timeout: 5000)
{:ok, _} = Page.mouse_up(page_id, button: :right, timeout: 5000)

Options

  • :connection (term/0) - The Connection process name. Defaults to PlaywrightEx.Supervisor.Connection. The default value is PlaywrightEx.Supervisor.Connection.

  • :timeout (timeout/0) - Required. Operation timeout in milliseconds. 0 means no waiting; :infinity disables the timeout.

  • :button - Defaults to :left. The default value is :left.

reload(page_id, opts \\ [])

@spec reload(PlaywrightEx.guid(), [reload_opt() | PlaywrightEx.unknown_opt()]) ::
  {:ok, any()} | {:error, any()}

Reloads the page.

Reference: https://playwright.dev/docs/api/class-page#page-reload

Options

  • :connection (term/0) - The Connection process name. Defaults to PlaywrightEx.Supervisor.Connection. The default value is PlaywrightEx.Supervisor.Connection.

  • :timeout (timeout/0) - Required. Operation timeout in milliseconds. 0 means no waiting; :infinity disables the timeout.

  • :wait_until - When to consider operation succeeded, defaults to load.

screenshot(page_id, opts \\ [])

@spec screenshot(PlaywrightEx.guid(), [screenshot_opt() | PlaywrightEx.unknown_opt()]) ::
  {:ok, binary()} | {:error, any()}

Returns the screenshot as a base64-encoded binary string.

Reference: https://playwright.dev/docs/api/class-page#page-screenshot

Options

  • :connection (term/0) - The Connection process name. Defaults to PlaywrightEx.Supervisor.Connection. The default value is PlaywrightEx.Supervisor.Connection.

  • :timeout (timeout/0) - Required. Operation timeout in milliseconds. 0 means no waiting; :infinity disables the timeout.

  • :full_page (boolean/0) - When true, takes a screenshot of the full scrollable page, instead of the currently visible viewport. Defaults to false.

  • :omit_background (boolean/0) - Hides default white background and allows capturing screenshots with transparency. Defaults to false. Not applicable to jpeg images.

update_subscription(page_id, opts \\ [])

@spec update_subscription(PlaywrightEx.guid(), [
  update_subscription_opt() | PlaywrightEx.unknown_opt()
]) ::
  {:ok, any()} | {:error, any()}

Updates the subscription for page events.

Explicit enabling keeps the subscription active until explicitly disabled. Disabling releases that explicit subscription; active PlaywrightEx.EventWaiter listeners keep their subscription until they finish or are canceled.

Reference: https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/client/page.ts

Options

  • :connection (term/0) - The Connection process name. Defaults to PlaywrightEx.Supervisor.Connection. The default value is PlaywrightEx.Supervisor.Connection.

  • :timeout (timeout/0) - Required. Operation timeout in milliseconds. 0 means no waiting; :infinity disables the timeout.

  • :event - Required.

  • :enabled (boolean/0) - The default value is true.

Client-Composed Functions

Helpers composed in this client from multiple channel operations/events, primarily to keep API parity with other Playwright clients where no single server method maps directly.

await_download(pending)

@spec await_download(PlaywrightEx.EventWaiter.t()) ::
  {:ok, PlaywrightEx.Download.t()} | {:error, PlaywrightEx.EventWaiter.error()}

Consumes the download event captured by expect_download/2.

Returns metadata as soon as downloading starts. Use Download.save_as/3 to wait for completion and copy the contents. The original event deadline is retained even if awaiting begins after the action finishes. Like Task.await/2, call this once, from the process that called expect_download/2.

expect_download(page_id, opts \\ [])

Arms a download listener before the action that triggers it.

Accepts only :timeout, :connection, and :predicate.

Returns a handle for await_download/1. Pass a required :timeout in milliseconds (0 means no waiting; :infinity disables the timeout) and an optional :connection. The deadline bounds event capture, not file transfer. Await once, from the process that armed the listener. Cancel with PlaywrightEx.EventWaiter.cancel/1 if you abandon the action.

An optional :predicate receives a PlaywrightEx.Download and accepts the first download for which it returns a truthy value, for example predicate: &(&1.suggested_filename == "report.csv"). It runs in the task; keep it quick and nonblocking. Rejected downloads do not restart the timeout.

{:ok, pending} = Page.expect_download(page_id, timeout: 1_000)
try do
  {:ok, _} = Frame.click(frame_id, selector: "a#export", timeout: 1_000)
  {:ok, download} = Page.await_download(pending)
  :ok = Download.save_as(download, "report.csv", timeout: 5_000)
after
  PlaywrightEx.EventWaiter.cancel(pending)
end

expect_url(page_id, opts \\ [])

@spec expect_url(PlaywrightEx.guid(), [expect_url_opt() | PlaywrightEx.unknown_opt()]) ::
  {:ok, boolean()} | {:error, any()}

Expects page URL to match the provided expectation.

This library exposes URL assertions as Page.expect_url/2.

In the official Playwright JavaScript API, URL assertions are written as await expect(page).toHaveURL(...). That matcher API is not exposed here.

Matching strategy:

  • String/Regex: delegates to PlaywrightEx.Frame.expect/2 with expression "to.have.url", which uses server-side assertion polling (is_not is passed through for retry semantics).
  • Predicate function: delegates to PlaywrightEx.Frame.wait_for_url/2, which is navigation-event based (waits on :navigated + lifecycle events rather than polling page JavaScript).

Returns true when the expectation is satisfied and false otherwise.

Reference: https://playwright.dev/docs/api/class-pageassertions#page-assertions-to-have-url

Options

  • :connection (term/0) - The Connection process name. Defaults to PlaywrightEx.Supervisor.Connection. The default value is PlaywrightEx.Supervisor.Connection.

  • :timeout (timeout/0) - Required. Operation timeout in milliseconds. 0 means no waiting; :infinity disables the timeout.

  • :url - Required. Expected URL as a string, Regex, or predicate function fn URI.t() -> boolean end.

  • :is_not (boolean/0) - Whether to negate the expectation. The default value is false.

  • :ignore_case (boolean/0) - Whether URL comparison should ignore case. The default value is false.

route(guid, glob, callback, opts \\ [])

Registers one handler for a driver-matched URL glob. A second registration returns {:error, %{reason: :route_already_registered}}; remove it first. Globs support *, **, {a,b}, and backslash escapes; ? is literal. Matching and base-URL resolution are delegated to Playwright.

Requires :timeout; accepts :connection and on_error: :raise | :message. Registration is ready before returning. Callbacks run independently and receive (route, request), where request is a metadata map with :guid, :url, :method, and :headers. Resolve the route inside the callback with PlaywrightEx.Route.fulfill/2, PlaywrightEx.Route.abort/2, or PlaywrightEx.Route.continue/2, before returning.

By default callback failures propagate through an OTP link to the registering process (failing an ExUnit test). With on_error: :message, failures instead send {:playwright_route_error, %{guid: guid, matcher: glob, reason: reason}}. Unresolved failed requests are aborted. Registration ends when its owner, target, or connection exits; active callbacks are canceled on teardown.

Matching page routes precede context routes; continue goes straight to the network. Context routes cover popup initial requests. Service Workers may bypass routing; use service_workers: "block" when creating the context. Routing disables HTTP caching. Handler chains, fallback, regexes, times, and wait/ignore-errors removal modes are not supported.

:timeout bounds driver operations, not the lifetime of the callback. Methods return {:ok, result} or {:error, reason}; pattern match on success inside callbacks so operation errors also fail the registering process.

Example

Replace a third-party script while loading the real application page. Assume page is returned by PlaywrightEx.BrowserContext.new_page/2 and connection is the connection name or pid used to create it:

alias PlaywrightEx.{Frame, Page, Route}

opts = [connection: connection, timeout: 5_000]
{:ok, _} = Page.route(page.guid, "**/forms/js.php/**", fn route, _request ->
  {:ok, _} = Route.fulfill(route, path: "test/fixtures/formstack_stub.js")
end, opts)

try do
  {:ok, _} = Frame.goto(page.main_frame.guid,
    Keyword.put(opts, :url, "http://localhost:4000/form"))
  # Exercise and assert the application's submission flow here.
after
  {:ok, _} = Page.unroute_all(page.guid, opts)
end

The route inherits connection and timeout. Its callback can fulfill the script while the registering process is blocked in navigation.

unroute(guid, matcher, callback \\ nil, opts \\ [])

Removes the handler if its glob and optional callback match. Active callbacks are canceled and unresolved requests aborted. Requires :timeout; accepts :connection. This cancellation policy differs from Playwright.js unroute.

Remove by glob, or retain the callback function to require an identity match:

{:ok, _} = Page.unroute(page.guid, "**/api/profile", timeout: 5_000)

callback = fn route, _request ->
  {:ok, _} = PlaywrightEx.Route.fulfill(route, json: %{name: "Ada"})
end
{:ok, _} = Page.route(page.guid, "**/api/profile", callback, timeout: 5_000)
{:ok, _} = Page.unroute(page.guid, "**/api/profile", callback, timeout: 5_000)

unroute_all(guid, opts \\ [])

Removes the handler and cancels active callbacks. Options: required :timeout, optional :connection. No handler is a successful no-op.

{:ok, _} = Page.unroute_all(page.guid, connection: connection, timeout: 5_000)