WebDriverconstruction: builder APIWebDriverConfig::reqwest_timeout→request_timeoutCapabilitiesis now a newtypeCapabilitiesHelperoverhaulinsert_browser_option→set_browser_optionAlertandSwitchTotypes removed- Removed deprecated method names
- Privatised public fields
- Newly deprecated:
extensions::cdp - Examples and doctests now use
anyhow
The Chrome DevTools Protocol layer was rewritten in this release,
but the legacy thirtyfour::extensions::cdp::ChromeDevTools path is
kept (deprecated) so existing CDP code keeps compiling. See the
deprecation notes at the end of this guide for what's been marked for
removal.
WebDriver::new_with_config and WebDriver::new_with_config_and_client
have been replaced by WebDriver::builder, which returns a
WebDriverBuilder that implements IntoFuture (so .await opens the
session). WebDriver::new still works as the simple two-arg shortcut.
// Before:
use thirtyfour::common::config::WebDriverConfig;
let config = WebDriverConfig::builder()
.reqwest_timeout(Duration::from_secs(30))
.user_agent("my-app/1.0")
.build()?;
let driver = WebDriver::new_with_config("http://localhost:4444", caps, config).await?;
// After:
let driver = WebDriver::builder("http://localhost:4444", caps)
.request_timeout(Duration::from_secs(30))
.user_agent("my-app/1.0")
.await?;A custom HttpClient is now supplied via .client(...) on the
builder rather than a separate new_with_config_and_client constructor.
The field, the WebDriverConfig builder method, and the
WebDriverBuilder method are all renamed: the timeout applies to any
HttpClient implementation, not just the default reqwest-based one.
// Before:
let config = WebDriverConfig::builder()
.reqwest_timeout(Duration::from_secs(30))
.build()?;
let timeout = config.reqwest_timeout;
// After:
let config = WebDriverConfig::builder()
.request_timeout(Duration::from_secs(30))
.build()?;
let timeout = config.request_timeout;Capabilities used to be a type alias for serde_json::Map<String, Value>.
It's now a #[serde(transparent)] newtype with its own inherent
get / get_mut / set / remove / contains_key / len / is_empty /
iter methods. The wire format is unchanged.
The most likely breakage is caps.insert(key, value) (which came from
the underlying Map). The replacement is caps.set(key, value)?,
which serialises any T: Serialize and returns WebDriverResult<()>.
// Before:
use serde_json::json;
let mut caps = Capabilities::new();
caps.insert("browserName".to_string(), json!("chrome"));
// After:
let mut caps = Capabilities::new();
caps.set("browserName", "chrome")?;If you genuinely need a serde_json::Map, Capabilities is From<Map>
and Into<Value>, and iter() returns the underlying map's iterator.
The CapabilitiesHelper trait used to require three private-looking
hook methods (_get, _get_mut, insert_base_capability) on every
implementor. It now has a blanket impl on
AsRef<Capabilities> + AsMut<Capabilities>, and its accessors are
renamed to match the inherent API on Capabilities:
| Before | After |
|---|---|
_get(key) |
get(key) |
_get_mut(key) |
get_mut(key) |
set_base_capability(k, v) |
set(k, v) |
insert_base_capability(...) |
(removed — use as_mut().set(...)) |
If you have a custom capability wrapper, replace the manual
CapabilitiesHelper for MyCaps impl with AsRef/AsMut impls — the
trait then comes for free.
// Before:
impl CapabilitiesHelper for MyCaps {
fn _get(&self, key: &str) -> Option<&Value> { self.inner._get(key) }
fn _get_mut(&mut self, key: &str) -> Option<&mut Value> { self.inner._get_mut(key) }
fn insert_base_capability(&mut self, key: String, value: Value) {
self.inner.insert_base_capability(key, value);
}
}
// After:
impl AsRef<Capabilities> for MyCaps {
fn as_ref(&self) -> &Capabilities { &self.inner }
}
impl AsMut<Capabilities> for MyCaps {
fn as_mut(&mut self) -> &mut Capabilities { &mut self.inner }
}BrowserCapabilitiesHelper::set_browser_option is the new name for
the old insert_browser_option, for consistency with the set naming
used elsewhere. Behaviour is unchanged.
// Before:
caps.insert_browser_option("binary", "/path/to/chrome")?;
// After:
caps.set_browser_option("binary", "/path/to/chrome")?;Every method on Alert and SwitchTo had been a deprecated forwarder
since 0.30.0. Both types are now gone, along with the prelude
re-exports. Use the equivalent methods on WebDriver directly:
| Before | After |
|---|---|
driver.switch_to().active_element().await |
driver.active_element().await |
driver.switch_to().alert().text().await |
driver.get_alert_text().await |
driver.switch_to().alert().accept().await |
driver.accept_alert().await |
driver.switch_to().alert().dismiss().await |
driver.dismiss_alert().await |
.alert().send_keys(...).await |
driver.send_alert_text(...).await |
.default_content().await |
driver.enter_default_frame().await |
.frame_number(n).await |
driver.enter_frame(n).await |
.frame_element(&el).await |
el.clone().enter_frame().await |
.parent_frame().await |
driver.enter_parent_frame().await |
.new_window().await / .new_tab().await |
driver.new_window().await / new_tab() |
.window(handle).await |
driver.switch_to_window(handle).await |
.window_name(name).await |
driver.switch_to_named_window(name).await |
The following method names — all marked deprecated in 0.30.x or 0.32.x — have been removed. Use the new names that are already in the codebase:
| Removed | Replacement |
|---|---|
WebElement::rectangle |
rect |
WebElement::get_property |
prop |
WebElement::get_attribute |
attr |
WebElement::get_css_property |
css_value |
WebElement::find_element |
find |
WebElement::find_elements |
find_all |
SessionHandle::close |
close_window |
SessionHandle::page_source |
source |
SessionHandle::find_element |
find |
SessionHandle::find_elements |
find_all |
SessionHandle::execute_script |
execute |
SessionHandle::execute_script_async |
execute_async |
SessionHandle::current_window_handle |
window |
SessionHandle::window_handles |
windows |
SessionHandle::set_timeouts |
update_timeouts |
SessionHandle::get_cookies |
get_all_cookies |
SessionHandle::get_cookie |
get_named_cookie |
SessionHandle::switch_to |
switch_to_* methods |
ScriptRet::value |
json |
ScriptRet::get_element |
element |
ScriptRet::get_elements |
elements |
ElementQuery::all |
all_from_selector |
ElementQuery::all_required |
all_from_selector_required |
DesiredCapabilities::accept_ssl_certs |
accept_insecure_certs |
WebDriverConfig::default_user_agent() |
WebDriverConfig::DEFAULT_USER_AGENT constant |
The redundant pub fields on WebDriver and WebElement are now
pub(crate). Use the accessor methods instead:
| Before | After |
|---|---|
driver.handle |
driver.handle() |
element.handle |
element.handle() |
element.element_id |
element.element_id() (already existed) |
SessionHandle::new() and the unused intermediate constructors
(new_with_config, new_with_config_and_guard) are also private now —
the only path to a SessionHandle is via WebDriver::new,
WebDriver::builder, or WebDriver::managed.
The legacy thirtyfour::extensions::cdp module is now deprecated in
favour of the new thirtyfour::cdp module. Existing code keeps
compiling; new code should migrate.
| Deprecated | Replacement |
|---|---|
extensions::cdp::ChromeDevTools |
Cdp via WebDriver::cdp |
ChromeDevTools::execute_cdp / execute_cdp_with_params |
Cdp::send / Cdp::send_raw |
extensions::cdp::NetworkConditions / ConnectionType |
equivalents in cdp::domains::network |
extensions::cdp::ChromeCommand |
(internal — no replacement needed) |
// Before:
use thirtyfour::extensions::cdp::ChromeDevTools;
let dev = ChromeDevTools::new(driver.handle.clone());
let v = dev.execute_cdp("Browser.getVersion").await?;
let ua = v["userAgent"].as_str().unwrap();
// After:
let info = driver.cdp().browser().get_version().await?;
let ua = info.user_agent;The extensions::cdp::NetworkConditions wrapper specifically targets
chromedriver's /chromium/network_conditions vendor endpoint
(snake_case fields). The new cdp::domains::network::NetworkConditions
goes through the standard CDP Network.emulateNetworkConditions
command and is portable across Chrome, Edge, Brave and Opera.
The color-eyre dev-dependency has been replaced with anyhow in the
examples and the two doctest snippets in the README and lib.rs. This
is purely a docs/example change and doesn't affect the public API, but
if you copied a snippet verbatim you'll see anyhow::Result<()> where
it used to say color_eyre::Result<()>.