Skip to content

Releases: padamson/playwright-rust

v0.12.1

25 Apr 12:26

Choose a tag to compare

Security

  • RUSTSEC-2026-0104 — bump rustls-webpki from 0.103.12 to 0.103.13. Reachable panic in CRL parsing via BorrowedCertRevocationList::from_der when handling a syntactically valid empty BIT STRING in the onlySomeReasons element of an IssuingDistributionPoint extension. Reachable prior to signature verification. Applications that don't use CRLs are not affected. Advisory: https://rustsec.org/advisories/RUSTSEC-2026-0104

v0.12.0

19 Apr 19:29

Choose a tag to compare

Added

  • context.set_storage_state(state) — replaces cookies and localStorage on an existing context without recreation (implemented client-side: clear cookies, add new cookies, restore per-origin localStorage via JS evaluation)

  • context.is_closed() — returns true after close() or a server-initiated "close" event

  • context.clock() / page.clock() — Clock API for fake timer control in deterministic tests

    • Clock::install(options) — install fake timers, optionally setting an initial epoch timestamp (clockInstall RPC on BrowserContext channel)
    • Clock::fast_forward(ticks) — advance the clock by milliseconds, firing due timers (clockFastForward RPC with ticksNumber)
    • Clock::pause_at(time) — jump to an epoch timestamp and pause; no timers fire until resumed (clockPauseAt RPC with timeNumber)
    • Clock::resume() — resume the clock after pause_at (clockResume RPC)
    • Clock::set_fixed_time(time) — freeze Date.now() at a fixed epoch without affecting timer scheduling (clockSetFixedTime RPC with timeNumber)
    • Clock::set_system_time(time) — update system time without freezing the clock (clockSetSystemTime RPC with timeNumber)
    • ClockInstallOptionstime: Option<u64> for setting the install epoch
    • page.clock() delegates to the parent BrowserContext::clock() — all RPCs go on the context channel
    • Clock and ClockInstallOptions exported from crate root
    • See: https://playwright.dev/docs/api/class-clock
  • page.route_from_har(har_path, options) / context.route_from_har(har_path, options) — replays network requests from a HAR archive; uses client-side HarRouter pattern (calls local_utils.har_open() then local_utils.har_lookup() per request); accepts RouteFromHarOptions with url (glob filter), not_found ("abort" or "fallback"), update, update_content, and update_mode fields; maps to harOpen/harLookup RPCs on the LocalUtils channel

  • Touchscreen classpage.touchscreen() returns a Touchscreen handle; touchscreen.tap(x, y) simulates a single touch event at viewport coordinates (touchscreenTap RPC on Page channel); requires has_touch: true in BrowserContextOptions

  • page.drag_and_drop(source, target, options) — performs drag and drop between two CSS selectors on the main frame; delegates to Frame::locator_drag_to (dragAndDrop RPC); accepts the same DragToOptions as Locator::drag_to

  • page.console_messages() — returns all console messages accumulated since page creation (Vec<ConsoleMessage>); console subscription enabled by default on every BrowserContext so no handler registration required

  • page.page_errors() — returns all uncaught JS error messages accumulated since page creation (Vec<String>); populated automatically via pageError events

  • page.opener() — returns the page that opened this popup (Option<Page>), or None for non-popup pages; reads the opener GUID from the page initializer

  • Video classpage.video() returns Some(Video) when the context was created with record_video; Video::path() returns the recording path, Video::save_as(path) copies the file, Video::delete() removes it; all methods wait internally for the artifact (fired via "video" event on page close), so no manual sleep is required

  • page.request_gc() — forces garbage collection (Chromium only)

  • page.workers() — returns all active web workers in the page (Vec<Worker>); accumulated from worker events as workers are created

  • context.service_workers() — returns all active service workers in the browser context (Vec<Worker>); accumulated from serviceWorker events

  • expect_event() — generic event waiting on Page and BrowserContext, returning typed EventValue enum

  • playwright.request() — headless API testing without a browser (get, post, put, delete, patch, head, fetch, APIResponse)

  • to_match_aria_snapshot(expected) — ARIA accessibility tree assertion with auto-retry

  • Locator::aria_snapshot() — returns the ARIA accessibility tree as a YAML string (ariaSnapshot RPC on Frame)

  • Locator::describe(description) — returns a new Locator with a human-readable label appended to the selector (internal:describe=...) for cleaner trace/error output; client-side only

  • Locator::highlight() — highlights the matched element in the browser for visual debugging (highlight RPC on Frame)

  • Locator::content_frame() — returns a FrameLocator for the content of an <iframe> element; client-side only

  • ElementHandle::content_frame() — returns the Frame for an <iframe> element, or None if not an iframe (contentFrame RPC on ElementHandle channel)

  • ElementHandle::owner_frame() — returns the Frame that owns this element (ownerFrame RPC on ElementHandle channel)

  • ElementHandle::wait_for_element_state(state, timeout) — waits until the element reaches the given state ("visible", "hidden", "stable", "enabled", "disabled", "editable") (waitForElementState RPC on ElementHandle channel)

  • Accessibility classpage.accessibility() returns an Accessibility handle; accessibility.snapshot(options) returns the page's ARIA accessibility tree as a YAML string wrapped in serde_json::Value; implemented via FrameAriaSnapshot RPC (the modern Playwright equivalent — the legacy accessibilitySnapshot RPC was removed in current Playwright versions)

  • Coverage classpage.coverage() returns a Coverage handle (Chromium only); start_js_coverage(options) / stop_js_coverage() collect V8 JS coverage (JSCoverageEntry with url, script_id, source, functions: Vec<JSFunctionCoverage>); start_css_coverage(options) / stop_css_coverage() collect CSS coverage (CSSCoverageEntry with url, text, ranges: Vec<CoverageRange>); maps to startJSCoverage / stopJSCoverage / startCSSCoverage / stopCSSCoverage RPCs on the Page channel

  • page.add_locator_handler() / page.remove_locator_handler() — registers an async handler that Playwright calls whenever a matching element appears and blocks an actionability check (e.g. cookie banners, permission dialogs); accepts AddLocatorHandlerOptions with no_wait_after and times; maps to registerLocatorHandler / resolveLocatorHandler / unregisterLocatorHandler RPCs; handler receives the matching Locator as argument

  • page.route_web_socket(url, handler) / context.route_web_socket(url, handler) — intercepts WebSocket connections matching a URL glob pattern; handler receives a WebSocketRoute object with connect_to_server(), close(options), send(message), on_message(handler), and on_close(handler); maps to setWebSocketInterceptionPatterns RPC with webSocketRoute events; WebSocketRoute and WebSocketRouteCloseOptions exported from crate root

  • ConsoleMessage::timestamp() — epoch milliseconds (f64) when the message was emitted

  • Response::http_version() — HTTP version string (e.g. "HTTP/1.1", "HTTP/2.0") via the httpVersion RPC added in Playwright 1.59

  • Request::existing_response() — synchronous Option<Response> for the already-received response, complementing the async response() getter

  • browser.bind(title, options) / browser.unbind() — expose a playwright-rs-launched browser over WebSocket so external clients (@playwright/mcp, Playwright CLI, agent tooling) can attach via BrowserType::connect(); BindOptions has host/port/workspace_dir/metadata; maps to startServer / stopServer RPCs (Playwright 1.59+)

  • Playwright driver upgraded to 1.59.1 (from 1.58.2) — required for Response::http_version() and picks up current Chromium/Firefox/WebKit binaries

Breaking Changes

  • BrowserContextOptions::accept_downloads type changed (closes #49) — field type is now Option<AcceptDownloads> instead of Option<bool>, matching the protocol's three-state "accept"/"deny"/"internal" string. The builder method accepts impl Into<AcceptDownloads>, so bool callers still work (trueAccept, falseDeny). Direct struct-literal construction or field pattern-matching must migrate.
  • macOS 14 WebKit no longer supported — Playwright 1.59 dropped macOS 14 ("Sonoma") support for WebKit. Users on macOS 14 must upgrade to macOS 15+ or pin to playwright-rs = "0.11" (which ships driver 1.58.2). Chromium and Firefox are unaffected on macOS 14.

v0.11.0

16 Apr 10:11

Choose a tag to compare

Added

  • New classes: JSHandle, Worker, WebError, WebSocket (completed), ConsoleMessage, FileChooser, Selectors
  • playwright.devices() — device descriptor map for browser emulation (DeviceDescriptor, DeviceViewport)
  • ConsoleMessage::args() — returns &[Arc<JSHandle>] for console method arguments
  • Browser methodscontexts(), browser_type(), on_disconnected(), start_tracing()/stop_tracing(), new_browser_cdp_session()
  • Page event handlerson_close, on_load, on_crash, on_pageerror, on_popup, on_frameattached, on_framedetached, on_framenavigated, on_worker, on_console, on_filechooser
  • Page expect methodsexpect_popup, expect_download, expect_response, expect_request, expect_console_message, expect_file_chooser
  • BrowserContext eventson_console, on_weberror, on_serviceworker, on_dialog, expect_console_message

Breaking Changes

  • ConnectionLike trait gains selectors() method — internal server infrastructure, not user-facing API. Any code implementing ConnectionLike directly must add the new method.

Fixed

  • unwrap() audit (closes #48) — replaced bare unwrap() calls in library code with expect() (for infallible operations) or proper error handling (for protocol data). Remaining unwrap() calls are only mutex locks (lock().unwrap()) and test code.
  • 15 broken rustdoc links — all intra-doc links now resolve correctly (qualified paths for cross-module references)

v0.10.0

11 Apr 21:51

Choose a tag to compare

Added

  • BrowserContext::new_cdp_session(page) — creates a Chrome DevTools Protocol session (Chromium only)

    • CDPSession::send(method, params) — send any CDP command and receive the result as JSON
    • CDPSession::detach() — detach from the CDP session
    • CDPSession registered in the object factory for server-created sessions
    • See: https://playwright.dev/docs/api/class-cdpsession
  • BrowserContext::tracing() — access the per-context Tracing object

    • Tracing::start(options) — begin trace recording (tracingStart + tracingStartChunk)
    • Tracing::stop(options) — stop trace recording (tracingStopChunk + tracingStop)
    • TracingStartOptionsname, screenshots, snapshots fields
    • TracingStopOptionspath field to export trace as a .zip archive
    • Artifact export wired through Artifact::save_as for path-based stop
    • See: https://playwright.dev/docs/api/class-tracing
  • install_browsers() / install_browsers_with_deps() — programmatic browser installation (closes #46)

    • install_browsers(None) — install all browsers
    • install_browsers(Some(&["chromium", "firefox"])) — install specific browsers
    • install_browsers_with_deps(browsers) — also installs system dependencies (useful for CI)
    • Reuses the bundled Playwright driver — no npx required
  • Frame public API completion — Frame now at 100% coverage

    • frame.locator(selector) — create Locator scoped to a frame (was internal-only)
    • All 7 get_by_* methods (get_by_text, get_by_label, get_by_role, etc.)
    • evaluate_handle(expression) — returns ElementHandle from JS evaluation
    • child_frames() — returns child frames by scanning the connection registry
    • Properties: name(), page(), parent_frame(), is_detached()
    • frame.page() back-reference set lazily when Page accesses its main frame
  • FrameLocator class — locate elements inside iframes using Playwright's internal:control=enter-frame selector engine

    • page.frame_locator(selector) / locator.frame_locator(selector) — entry points
    • frame_locator.locator(selector) — create Locator inside iframe
    • frame_locator.frame_locator(selector) — nested iframes
    • All 7 get_by_* methods (get_by_text, get_by_label, get_by_role, etc.)
    • first(), last(), nth(index) — composition for multiple matching iframes
    • owner() — Locator for the iframe element itself
  • ConnectionExt extension trait — typed object retrieval via connection.get_typed::<T>(guid).await?, eliminating boilerplate get_object + as_any().downcast_ref::<T>() pattern

  • downcast_parent<T>() helper — one-line parent type resolution replacing manual parent + downcast chains

  • Error::TypeMismatch — structured error variant with guid, expected type, and actual type for better diagnostics

Breaking Changes

  • MSRV bumped from 1.85 to 1.88 — transitive dependencies (icu_*, image, time, zip) now require Rust 1.88
  • ConnectionLike trait uses #[async_trait] — methods migrated from manual Pin<Box<dyn Future>> returns to idiomatic async fn. Any code implementing ConnectionLike directly must update method signatures (internal server infrastructure, not user-facing API).

Fixed

  • 15 broken rustdoc links — all intra-doc links now resolve correctly (qualified paths for cross-module references)

Changed

  • Security & quality CIcargo audit and cargo deny run on every push to main and weekly; mutation testing moved from test.yml to dedicated security.yml with weekly schedule + release tag triggers; MSRV check (Rust 1.85) in test.yml
  • deny.toml — license compliance (Apache-2.0 compatible), crate bans, source restrictions, duplicate detection
  • cargo vet — supply chain review with trusted imports from 7 organizations; new dependencies require audit
  • SLSA provenance — release artifacts include signed build attestations via actions/attest-build-provenance
  • Fuzz targetscargo-fuzz targets for parse_value, serialize_argument, parse_result (protocol parsing layer)
  • BrowserContext event handlers — context-level event subscriptions (fire before page handlers)
    • on_page(handler) — fires when new page created in context
    • on_close(handler) — fires when context is closed
    • on_request(handler) / on_request_finished(handler) / on_request_failed(handler) — network events from any page
    • on_response(handler) — response events from any page
  • expect_page() / expect_close() — promise-based event waiting with timeout
    • expect_page(timeout) — returns EventWaiter<Page> that resolves when a new page is created
    • expect_close(timeout) — returns EventWaiter<()> that resolves when the context closes
    • EventWaiter<T> — generic one-shot waiter backed by tokio::sync::oneshot with configurable timeout (default 30s)
  • on_dialog(handler) — context-level dialog handler, fires before page handlers
  • expose_function() / expose_binding() — JS→Rust callback bridge on both BrowserContext and Page
    • expose_function(name, callback) — inject a Rust function callable from JS as window[name](...)
    • expose_binding(name, callback) — same with source info (note: needsHandle: true not yet supported)
    • BindingCall protocol object for handling JS→Rust invocations
  • Added async-trait as a dependency

v0.9.0

27 Mar 22:51

Choose a tag to compare

Added

  • Back-reference properties — navigate the protocol object hierarchy from child to parent
    • dialog.page() — returns the Page that owns the dialog (via protocol parent)
    • download.page() — returns the Page that triggered the download (stored at construction)
    • response.request() — returns the Request that triggered the response (via ResponseObject parent)
    • response.frame() — returns the Frame that initiated the request (delegates to request.frame())
    • request.frame() — returns the Frame that initiated the request (eagerly resolved from initializer GUID)
  • Response server info — inspect connection and TLS details
    • response.security_details() — TLS/SSL certificate info (SecurityDetails: issuer, protocol, subject_name, valid_from, valid_to); returns None for HTTP
    • response.server_addr() — server IP address and port (RemoteAddr); returns None for cached responses
    • response.finished() — wait for response to finish loading (currently returns immediately for goto/reload responses)
  • Request completion methods — full request lifecycle access
    • request.redirected_from() / request.redirected_to() — navigate the redirect chain (eagerly resolved from initializer)
    • request.response() — get the matching Response via RPC
    • request.sizes() — resource size info (RequestSizes: request_body_size, request_headers_size, response_body_size, response_headers_size)
  • New types: SecurityDetails, RemoteAddr, RequestSizes (exported from playwright_rs::protocol)
  • Page assertionsexpect_page(&page) now supports title and URL assertions
    • to_have_title(expected) / to_have_title_regex(pattern) — assert page title with auto-retry
    • to_have_url(expected) / to_have_url_regex(pattern) — assert page URL with auto-retry
    • .not() negation and .with_timeout() supported (matching locator assertion pattern)

Breaking Changes

  • Response struct fields are now privateresponse.url, response.status, response.status_text, response.ok, response.headers are no longer accessible as public fields. Use the existing accessor methods instead: response.url(), response.status(), response.status_text(), response.ok(), response.headers(). These methods were already available; only direct field access is removed.
  • Download::from_artifact is now pub(crate) — this was an internal constructor not intended for public use.

Fixed

  • Request parent type corrected — Request's parent in the Playwright protocol is Page (not Frame as previously assumed). The request.frame() method now correctly resolves the frame from the initializer's frame GUID via the connection registry.

v0.8.7

24 Mar 23:28

Choose a tag to compare

Added

  • Locator advanced methodstap(), evaluate(), evaluate_all(), drag_to(), wait_for(), dispatch_event(), bounding_box(), scroll_into_view_if_needed()
    • tap(options) — touch-tap on an element (requires has_touch: true context); TapOptions builder with force, modifiers, position, timeout, trial
    • evaluate(expression, arg) — run a JavaScript function with the element as first argument, returns typed R: DeserializeOwned
    • evaluate_all(expression, arg) — run a JavaScript function with all matching elements as an array, returns typed R: DeserializeOwned
    • drag_to(target, options) — drag this element to another; DragToOptions builder with force, source_position, target_position, timeout, trial
    • wait_for(options) — wait for element to reach a state (Visible, Hidden, Attached, Detached); WaitForOptions with state and timeout
    • dispatch_event(type, event_init) — fire DOM events with optional initialization data
    • bounding_box() — get element dimensions and position (x, y, width, height)
    • scroll_into_view_if_needed() — scroll element into viewport
    • page property — back-reference to the owning Page from any Locator
  • TLS backend features — Expose native-tls, rustls-tls-native-roots, and rustls-tls-webpki-roots features for choosing TLS implementation (PR #41). Defaults to native-tls.
  • Locator filtering & compositionfilter(), and_(), or_() methods for narrowing and combining locators
    • filter(FilterOptions) — narrow by has_text, has_not_text, has (child locator), has_not
    • and_(locator) — match elements satisfying both locators
    • or_(locator) — match elements satisfying either locator
  • Locator interaction methodsfocus(), blur(), press_sequentially(), all_inner_texts(), all_text_contents()
    • focus() / blur() — set or remove keyboard focus on an element
    • press_sequentially(text, options) — type characters one by one with optional delay
    • all_inner_texts() / all_text_contents() — bulk text retrieval from all matching elements
    • dispatch_event(type, event_init) — fire DOM events with optional initialization data
    • bounding_box() — get element dimensions and position (x, y, width, height)
    • scroll_into_view_if_needed() — scroll element into viewport
  • BrowserContext runtime setters — configure context after creation
    • cookies(urls) — retrieve cookies, optionally filtered by URL
    • clear_cookies(options) — remove cookies with optional name/domain/path filters
    • set_extra_http_headers(headers) — add HTTP headers to all requests
    • grant_permissions(permissions, options) — grant browser permissions (geolocation, camera, etc.)
    • clear_permissions() — revoke all granted permissions
    • set_geolocation(geolocation) — override device geolocation, or pass None to clear
    • set_offline(offline) — toggle offline mode
  • Page methodsbring_to_front(), viewport_size(), set_extra_http_headers(), emulate_media(), pdf(), add_script_tag()
    • bring_to_front() — activate the page tab
    • viewport_size() — get current viewport dimensions (returns None if no_viewport context)
    • set_extra_http_headers(headers) — add HTTP headers to all page requests
    • emulate_media(options) — override CSS media type, color scheme, reduced motion, forced colors
    • pdf(options) — generate PDF (Chromium only), with full options (margins, scale, landscape, etc.)
    • add_script_tag(options) — inject JavaScript via URL, file path, or inline content
  • Page timeout & stateset_default_timeout(), set_default_navigation_timeout(), is_closed(), frames()
    • set_default_timeout(ms) / set_default_navigation_timeout(ms) — configure default timeouts for actions and navigation
    • is_closed() — check if page has been closed (tracks close events from server)
    • frames() — list page frames (currently main frame only; iframe enumeration planned)
  • BrowserContext timeout defaultsset_default_timeout(), set_default_navigation_timeout()
    • Propagates to all existing pages and newly created pages in the context
  • Response body accessbody(), text(), json(), all_headers(), header_value(), headers_array()
    • body() — response body as raw bytes
    • text() — response body as UTF-8 string
    • json::<T>() — parse response body as typed JSON (T: DeserializeOwned)
    • all_headers() — all response headers as HashMap (merges duplicates)
    • header_value(name) — get a single header value by name
    • headers_array() — all headers as Vec<HeaderEntry> preserving duplicates
  • Request propertiesheaders(), post_data(), post_data_buffer(), post_data_json(), failure(), all_headers(), header_value(), headers_array(), timing()
    • headers() — request headers as HashMap (from initializer)
    • post_data() / post_data_buffer() — request body as string or bytes (base64-decoded)
    • post_data_json::<T>() — parse request body as typed JSON
    • failure() — error text if request failed (set on requestFailed event)
    • all_headers() / header_value() / headers_array() — full raw headers via RPC
    • timing()ResourceTiming with 9 timing fields (extracted from Response on requestFinished)

Changed

  • Playwright driver upgraded to 1.58.2 (from 1.56.1) — includes WebKit 26.0, Chromium 133, Firefox 135

Fixed

  • WebKit launchPersistentContext now works — Closes #39. Upgraded Playwright driver resolves "Browser started with no default context" error on macOS ARM64
  • docs.rs build — Pin docs.rs to nightly-2025-05-01 to work around generic-array 0.14 incompatibility with Rust 1.92+ (doc_auto_cfg removal)

v0.8.6

14 Mar 14:15

Choose a tag to compare

Fixed

  • docs.rs build — Skip Playwright driver download when building on docs.rs (no network access needed for documentation)
  • Imprecise dependency versions — Pin workspace dependencies to minor versions (e.g., serde = "1.0" instead of "1")

v0.8.5

14 Mar 13:49

Choose a tag to compare

Added

  • ignore_default_args for persistent contexts - Added ignore_default_args option to BrowserContextOptions for use with launch_persistent_context_with_options() (Issue #38)
    • IgnoreDefaultArgs::Bool(true) - Playwright does not pass its own default args
    • IgnoreDefaultArgs::Array(vec) - Filters out specific default arguments
    • Applies same ignoreDefaultArgsignoreAllDefaultArgs protocol normalization as LaunchOptions
    • Matches Playwright's official launchPersistentContext API
  • Page network event listeners - Subscribe to network events on individual pages (PR #37)
    • page.on_request(handler) - Fires when a request is issued
    • page.on_response(handler) - Fires when a response is received
    • page.on_request_finished(handler) - Fires when a request completes successfully
    • page.on_request_failed(handler) - Fires when a request fails
    • Lazy subscription: events are only subscribed when a handler is registered
    • Works with iframes and sub-resources
  • Response accessor methods - response.status(), response.status_text(), response.url() (PR #37)
  • page.go_back() / page.go_forward() - History navigation with optional timeout and wait_until options
  • page.set_content(html) - Set page HTML content directly, with optional timeout and wait_until options
  • page.wait_for_load_state(state) - Wait for load, domcontentloaded, or networkidle states
  • page.wait_for_url(url) - Wait for navigation to a matching URL (exact string or glob pattern)
  • locator.is_hidden() / locator.is_disabled() - Negative state checks complementing is_visible() and is_enabled()
  • to_have_screenshot() visual regression assertion (Issue #35)
    • expect(locator).to_have_screenshot(path, options) — compare locator screenshot against baseline
    • expect_page(&page).to_have_screenshot(path, options) — page-level screenshot comparison
    • Auto-creates baseline on first run, compares on subsequent runs
    • max_diff_pixels / max_diff_pixel_ratio — configurable tolerance
    • threshold — per-pixel color distance tolerance (default 0.2)
    • animations: Disabled — freeze CSS animations/transitions before capture
    • mask — overlay locators with pink (#FF00FF) to exclude dynamic content
    • update_snapshots — force baseline update
    • Generates diff image on failure highlighting differences in red
    • Auto-retry with timeout (default 5s), matching Playwright's assertion pattern

Fixed

  • Replace unwrap() with graceful error handling in network event dispatch (Issue #40)

v0.8.4

01 Mar 13:53

Choose a tag to compare

Added

  • get_by_* locators - Modern Playwright locator methods for finding elements by user-facing attributes
    • get_by_text(text, exact) - Find by text content
    • get_by_label(text, exact) - Find form controls by associated label
    • get_by_placeholder(text, exact) - Find inputs by placeholder text
    • get_by_alt_text(text, exact) - Find images by alt text
    • get_by_title(text, exact) - Find elements by title attribute
    • get_by_test_id(test_id) - Find elements by data-testid attribute (always exact)
    • get_by_role(role, options) - Find elements by ARIA role with optional name, checked, disabled, expanded, selected, level, pressed, include_hidden filters
    • All methods available on both Page and Locator (chainable)
    • Case-insensitive substring matching by default (exact=false), case-sensitive exact with exact=true
    • AriaRole enum with 81 ARIA roles for compile-time safety
    • GetByRoleOptions struct for role-based filtering
  • connect_over_cdp - Connect to Chrome DevTools Protocol endpoints (Issue #32)
    • browser_type.connect_over_cdp(endpoint_url, options) - Connect to remote Chrome via CDP
    • Supports browserless, Chrome with --remote-debugging-port, and other CDP services
    • Accepts optional headers, timeout, and slow_mo options
    • Chromium-only (returns error for Firefox/WebKit)
  • Locator.all() - Iterate over all matching elements (Issue #33)
    • locator.all() returns Vec<Locator>, one per matching element
    • Empty vec for non-matching selectors (no error)
    • Matches Playwright's locator.all() API
  • Improved error messages - All locator methods now include the selector in error messages (Issue #33)
    • Timeout errors show [selector: div.page-number > span:last-child] instead of generic messages
    • Applied to all query methods (text_content, get_attribute, etc.) and action methods (click, fill, etc.)
  • BrowserContext proxy support - Added proxy option to BrowserContextOptions for per-context proxy configuration (PR #29, Issue #28)
    • Enables rotating proxies without creating new browser instances
    • Supports HTTP and SOCKS proxies with optional authentication
  • Complete Route API - Full network interception parity with Playwright (Issue #36)
    • route.fallback(overrides) - Continue to next matching handler (handler chaining)
    • route.fetch(options) - Fetch actual response for inspection/modification before fulfilling
    • FetchResponse type with status(), ok(), headers(), body(), text(), json() methods
    • FetchOptions builder for customizing fetch requests (method, headers, post_data, timeout)
  • Context-level routing - BrowserContext.route(), unroute(), unroute_all() for routing across all pages in a context
  • Page unroute methods - page.unroute(pattern) and page.unroute_all() for removing route handlers
  • APIRequestContext - Internal implementation for route.fetch() via BrowserContext's request context
    • Handles fetch → fetchResponseBody → disposeAPIResponse protocol flow
    • Automatic base64 encoding/decoding for request and response bodies
  • UnrouteBehavior enum - Control behavior when removing route handlers

Fixed

  • no_viewport(true) / --start-maximized not working - Fixed protocol field name for viewport disabling (Issue #34)
    • no_viewport now correctly serializes as noDefaultViewport (matching the Playwright protocol)
    • Previously serialized as noViewport which the server silently ignored
    • Enables --start-maximized with no_viewport(true) to produce maximized browser windows

v0.8.3

26 Jan 04:09

Choose a tag to compare

Added

  • PLAYWRIGHT_VERSION constant - Exposes bundled Playwright driver version (1.56.1) as a public constant for version-aware browser installation (Issue #27)
  • Helpful browser installation errors - Detects missing browser errors and provides actionable guidance (Issue #27)
  • Page.content() - Returns full HTML content of the page including DOCTYPE (Issue #23)
    • page.content() - Retrieves complete HTML markup
    • frame.content() - Frame-level implementation for consistency with Playwright API
  • Page.set_viewport_size() - Dynamically resize viewport for responsive testing (Issue #24)
    • page.set_viewport_size(viewport) - Set viewport to specific width/height
    • Enables testing mobile, tablet, and desktop layouts within a single page session

Fixed

  • page.url() hash navigation - URL now correctly includes hash fragment after anchor clicks (Issue #26)
    • Frame now handles "navigated" events to track URL changes including hash updates
    • Page delegates to main frame for URL (matches playwright-python/JS behavior)

Changed

  • Rust Edition 2024 - Upgraded to Rust Edition 2024, requiring Rust 1.85+
  • README documentation - Added comprehensive browser installation section (Issue #25)