Skip to content

playwright-rs 0.19.0

Choose a tag to compare

@github-actions github-actions released this 27 Sep 11:04
· 91 commits to main since this release

Added

  • Chainable setters where an option struct had none, or was missing some. AddLocatorHandlerOptions gains times and no_wait_after; HighlightOptions gains style; StartJSCoverageOptions gains reset_on_navigation and report_anonymous_scripts; StartCSSCoverageOptions gains reset_on_navigation; WebSocketRouteCloseOptions gains code and reason; RouteFromHarOptions gains the update_content and update_mode it lacked. These structs are #[non_exhaustive], so outside the crate those fields could only be set by building default() and mutating field by field. AccessibilitySnapshotOptions deliberately gets none: its two fields are ignored, which its docs now say.

Changed

  • The build script assembles the driver into the user cache, not the build directory. The path is the one playwright-rs install already wrote and the runtime already probed (~/.cache/playwright-rust/<version>/ on Linux, ~/Library/Caches on macOS, %LOCALAPPDATA% on Windows), so one download serves every target directory, cargo-mutants copy, and workspace on a machine instead of one per dependency hash. Deleting the cache reassembles on the next build. PLAYWRIGHT_DRIVER_CACHE_DIR and PLAYWRIGHT_SKIP_DRIVER_DOWNLOAD are unchanged; in CI, cache that directory alongside the browsers and drop the cache-dir knob. ADR 0007 records why this breaks cargo's write-only-to-OUT_DIR convention on purpose.
  • Error::ServerNotFound now says what became of the bundled driver. The build script assembles the driver at compile time, and when that download fails in a consumer's build nothing tells them: cargo shows a dependency's cargo:warning lines to nobody, the crate compiles, and the first launch fails with a message that said to npm install playwright. The message now reports the build-time outcome recorded by build.rs (the download failed, it was skipped with PLAYWRIGHT_SKIP_DRIVER_DOWNLOAD, or the assembled driver has since gone missing from the directory it names) and the ways to get one: rebuilding, playwright-rs install, or PLAYWRIGHT_DRIVER_PATH. The variant itself is unchanged, so code matching on it still compiles.

Removed

  • The Claude Code plugin channel for the agent skill. The .claude-plugin/ manifests are gone, so /plugin install playwright-rs@playwright-rust no longer resolves and an existing plugin install will not see further updates. The skill ships through one channel now: npx skills add padamson/playwright-rust, refreshed with npx skills update. The skill's own metadata.version is the update gate consumers compare against, and the version guard checks only that.

Fixed

  • A triggered locator handler no longer stalls the action that tripped it until its timeout. After running the handler the crate told the server to resume with a method name the driver does not have (resolveLocatorHandler; the protocol calls it resolveLocatorHandlerNoReply), the rejection was discarded, and the parked click or fill waited out its full timeout and failed. Present since the feature shipped in 0.12.0; the existing test removed the overlay before acting, so no handler ever fired under test. The resume is now sent in every case, including a handler that panics or a trigger for a uid the page no longer knows, and a failed resume is logged at warn.
  • add_locator_handler with times: Some(0) is now a no-op, as upstream's is. The invocation counter was decremented past zero on the first trigger: a debug build panicked inside the dispatch task while it held the handler registry lock, so every later locator-handler call on that page panicked too; a release build wrapped to u32::MAX and the "zero times" handler ran on every trigger, forever. Counted handlers still run exactly times times and are unregistered on the last one.
  • A locator handler that returns an error keeps its registration, so the next actionability check retries it, matching upstream. It used to be unregistered as if it had succeeded.
  • Download::path() returns the downloaded file. It asked the driver for path, a method the Artifact channel does not have; the protocol calls it pathAfterFinished. Every call failed with a protocol error since the method shipped, and no test called it.
  • Routed WebSockets work end to end. WebSocketRoute sent connectToServer and close, neither of which exists on its channel (the protocol has connect and closePage), and it listened for a close event that the server never emits (closePage and closeServer are the real ones). It also never forwarded traffic: upstream's client does the proxying itself once connect_to_server is called, so page messages now go to the server, server messages and closes go to the page, and a page-side close closes the server side, unless an on_message or on_close handler takes over. A handler that neither connects nor closes now leaves the page's socket open (ensureOpened), so a mocked socket can be written to. The route tests called connect_to_server inside handlers whose errors were only logged; they now assert the server's echo reaches the page, and a new test mocks replies without a server. WebSocketRoute::is_connected() is new.
  • set_default_timeout and set_default_navigation_timeout no longer send the driver a command it does not have. Each call also sent setDefaultTimeoutNoReply or setDefaultNavigationTimeoutNoReply, which no driver this crate has shipped defines (upstream dropped them when it moved the defaults client-side); the rejection was logged at warn on every call. The defaults were, and are, applied client-side to each call that takes a timeout, as upstream does, so behavior is unchanged apart from the log line.
  • remove_locator_handler on a selector with no handler is a no-op, matching upstream; it used to fail with a protocol error, which a times(0) registration or an exhausted counted handler always left behind.