All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog.

[Unreleased]

[0.13.0] 2026-10-01

Added

  • Connection.unsubscribe_sync/3 removes channel delivery and managed event ownership before returning. Both synchronous and asynchronous removal leave other recipients and explicit subscriptions intact.
  • Page :frame_navigated events cover main and child frames, including frames created after registration, through existing subscriptions and EventWaiter.

[0.12.1] 2026-09-21

Fixed

  • Restore js_logger: false as an alias for nil to disable JavaScript logging. Console messages and page errors no longer crash the connection with false.

[0.12.0] 2026-09-16

Added

  • Add Locator.evaluate/2, with strict lazy resolution under the locator timeout, unlimited JavaScript evaluation and disposal, and Playwright JS cleanup error precedence.
  • Add ElementHandle.evaluate/2 and dispose/2.
  • Add Frame.expect_result/2 to retain assertion diagnostics; expect/2 keeps its boolean behavior.

[0.11.0] 2026-09-15

Added

  • Frame.snapshot/2 for an atomic read of the cached URL, document request, and client-generated document identity.
  • Optional EventWaiter transforms that run on capture inside the waiting task.
  • Managed opt-in event subscriptions: the first waiter enables an event and the last releases it. Explicit channel subscriptions remain active independently.
  • Frame.document_request/2 to read the committed document's request without event subscriptions, preserving it across same-document navigation.
  • Request.response/2 to retrieve a request's response without subscribing to response events, returning nil when the request fails without a response.

Changed

  • Frame URL/load-state waits use a separate task for each caller. The connection caches current frame state; per-frame recorder processes are removed. Public results stay synchronous, and URL predicate errors affect only that caller.

Fixed

  • Download waiters validate their own options, excluding raw event transforms and subscription overrides to preserve the Download result.
  • Clean up abandoned frame waits when callers exit and discard recorded frame state when the connection closes.

[0.10.0] 2026-09-15

Added

  • Download handles with browser-provided filename and URL, reusable through Download.from_event/2, Download.save_as/3, and explicit Download.delete/2.
  • Page.expect_download/2 and Page.await_download/1 for explicit arm/action/await download capture, with an optional predicate on download metadata.
  • EventWaiter.arm/3, await/1, and cancel/1 for one-shot protocol events, using linked tasks and ref-tagged replies, with synchronous registration, one deadline from arming, optional event predicates, and owner/connection lifecycle handling. :infinity disables the event timeout.

Changed

  • Breaking: timeout: 0 now means no waiting throughout the client. Protocol commands time out without being sent; frame URL/load-state waits check cached state once. Replace timeout: 0 with timeout: :infinity where unlimited waiting was intended.
  • Missing connections, normal stops, supervisor shutdowns, and response timeouts return error results at the connection boundary. Other process exits and URL predicate bugs propagate instead of being converted to ordinary error results.

Fixed

  • Discard unrelated protocol events from event waiters without extending their deadline, preventing mailbox growth while waiting on busy channels.
  • Support :infinity in frame URL/load-state waits and keyboard actions without timeout arithmetic errors. Keyboard delays cannot extend a zero timeout.
  • Artifact saves share one timeout across stream reads, clean up failed transfers, create parent directories, and preserve existing destinations on failure. Stream cleanup runs in an after block and preserves the transfer result. Saving leaves the source artifact available to other readers.
  • Support :infinity command timeouts using Playwright's zero-timeout wire value.

[0.9.0] 2026-09-08

Added

  • Typed local and PlaywrightEx.FilePayload in-memory uploads through Frame.set_input_files/2 and the new ElementHandle.set_input_files/2, including file-chooser handles and empty selections. #80
  • Playwright 1.63 APIs for structured ARIA snapshots, OPFS and WebAuthn storage state, browser-context event subscriptions (including dialog_closed), visible and cross-frame selectors, and expanded browser launch options.

Changed

  • Require Playwright 1.63 or newer and use it as the sole protocol baseline. Older local drivers are rejected, and remote connections advertise 1.63 and reset their protocol state after disconnects.
  • Adopt Playwright 1.63's HTTP-credential and tracing wire formats while retaining the existing map-or-list public credential API.

Fixed

  • Align channel options, events, and results with Playwright 1.63, including headers, enums, cookies, frame polling and selection, subscriptions, tracing modes, void results, and protocol logs.
  • Correct channel lifecycle tracking across initialization, creation, adoption, disposal, and page/frame ownership; console and page errors now reach subscribers.
  • Support every Playwright 1.63 serialized-value variant without altering opaque JSON keys or creating atoms from untrusted data.
  • Harden port framing, stderr isolation, and remote artifact cleanup.

[0.8.0] 2026-08-27

Changed

  • Require Playwright 1.62 or newer. Command timeouts are now sent as protocol metadata, matching the Playwright 1.62 driver contract. The bundled development dependency is updated to 1.62, and the local port transport warns when an older driver is detected.
  • Preserve both the protocol error and error_details in Page.expect_screenshot/2 errors as {:error, {error, error_details}}. #58

Removed

  • Support for the Playwright 1.60 expectation response format. #58

[0.7.1] 2026-06-19

Added

  • Warn about playwright version < 1.61.0 (port transport only). Commit cd9e98e

[0.7.0] 2026-06-16

Fixed

  • Support the Playwright 1.61 Frame.expect wire contract. 1.61 stopped returning %{matches: boolean} and now signals the assertion outcome by success-vs-error: a non-match returns a protocol error carrying error_details. Frame.expect/2 now yields a plain {:ok, boolean} under both 1.60 and 1.61, so phoenix_test_playwright's assert_has/refute_has keep working. Serialization.deserialize_arg/1 also raises a descriptive error on unknown serialized shapes instead of a bare CaseClauseError. Commit d6d9ddc, #57, @oliver-kriska

[0.6.1] 2026-06-16

Added

Fixed

  • Handle viewport: nil to disable default viewport. Commit 8139523, #46

[0.6.0] 2026-05-05

Added

Removed

  • Frame url/2 helper, which is not a supported Playwright server operation. Commit 9490384

Fixed

  • :ignore_https_errors now serializes to Playwright's required ignoreHTTPSErrors casing. Commit 80f28be, #45

[0.5.0] 2026-03-06

Added

Fixed

[0.4.0] 2026-02-09

Added

[0.3.2] 2026-01-30

Fixed

[0.3.1] 2026-01-30

Added

[0.3.0] 2025-12-24

Added

Fixed

[0.2.1] 2025-11-28

Changed

  • Suppress node.js errors on termination

[0.2.0] 2025-11-19

Changed

  • Add typespecs and docs
  • Make channel function input and output consistent

[0.1.2] 2025-11-14

Changed

[0.1.1] 2025-11-14

Fixed

  • Memory leak: Free memory when playwright resource is destroyed (handle __dispose__ messages)

[0.1.0] 2025-11-13

Added

  • First draft