thirtyfour/common/capabilities/
desiredcapabilities.rsuse serde::Serialize;
use serde_json::{json, to_value, Value};
use crate::common::capabilities::chrome::ChromeCapabilities;
use crate::common::capabilities::edge::EdgeCapabilities;
use crate::common::capabilities::firefox::FirefoxCapabilities;
use crate::common::capabilities::ie::InternetExplorerCapabilities;
use crate::common::capabilities::opera::OperaCapabilities;
use crate::common::capabilities::safari::SafariCapabilities;
use crate::error::WebDriverResult;
use crate::Capabilities;
const W3C_CAPABILITY_NAMES: &[&str] = &[
"acceptInsecureCerts",
"browserName",
"browserVersion",
"platformName",
"pageLoadStrategy",
"proxy",
"setWindowRect",
"timeouts",
"unhandledPromptBehavior",
"strictFileInteractability",
];
const OSS_W3C_CONVERSION: &[(&str, &str)] = &[
("acceptSslCerts", "acceptInsecureCerts"),
("version", "browserVersion"),
("platform", "platformName"),
];
pub fn make_w3c_caps(caps: &Value) -> Value {
let mut always_match = json!({});
if let Some(caps_map) = caps.as_object() {
for (k, v) in caps_map.iter() {
if !v.is_null() {
for (k_from, k_to) in OSS_W3C_CONVERSION {
if k_from == k {
always_match[k_to] = v.clone();
}
}
}
if W3C_CAPABILITY_NAMES.contains(&k.as_str()) || k.contains(':') {
always_match[k] = v.clone();
}
}
}
json!({
"firstMatch": [{}], "alwaysMatch": always_match
})
}
fn merge(a: &mut Value, b: Value) {
match (a, b) {
(a @ &mut Value::Object(_), Value::Object(b)) => {
let a = a.as_object_mut().unwrap();
for (k, v) in b {
merge(a.entry(k).or_insert(Value::Null), v);
}
}
(a, b) => *a = b,
}
}
#[derive(Debug, Clone, Serialize)]
#[serde(transparent)]
pub struct DesiredCapabilities {
capabilities: Capabilities,
}
impl Default for DesiredCapabilities {
fn default() -> Self {
Self {
capabilities: serde_json::Map::new(),
}
}
}
impl DesiredCapabilities {
pub fn new() -> Self {
Self::default()
}
pub fn firefox() -> FirefoxCapabilities {
FirefoxCapabilities::new()
}
pub fn internet_explorer() -> InternetExplorerCapabilities {
InternetExplorerCapabilities::new()
}
pub fn edge() -> EdgeCapabilities {
EdgeCapabilities::new()
}
pub fn chrome() -> ChromeCapabilities {
ChromeCapabilities::new()
}
pub fn opera() -> OperaCapabilities {
OperaCapabilities::new()
}
pub fn safari() -> SafariCapabilities {
SafariCapabilities::new()
}
}
impl From<DesiredCapabilities> for Capabilities {
fn from(caps: DesiredCapabilities) -> Capabilities {
caps.capabilities
}
}
pub trait CapabilitiesHelper {
fn _get(&self, key: &str) -> Option<&Value>;
fn _get_mut(&mut self, key: &str) -> Option<&mut Value>;
fn _set(&mut self, key: String, value: Value);
fn add<T>(&mut self, key: &str, value: T) -> WebDriverResult<()>
where
T: Serialize,
{
self._set(key.to_string(), to_value(value)?);
Ok(())
}
fn add_subkey<T>(&mut self, key: &str, subkey: &str, value: T) -> WebDriverResult<()>
where
T: Serialize,
{
match self._get_mut(key) {
Some(v) => {
v[subkey] = to_value(value)?;
}
None => self._set(key.to_string(), json!({ subkey: value })),
}
Ok(())
}
fn remove_subkey(&mut self, key: &str, subkey: &str) -> WebDriverResult<()> {
if let Some(Value::Object(v)) = &mut self._get_mut(key) {
v.remove(subkey);
}
Ok(())
}
fn update(&mut self, key: &str, value: Value) {
assert!(value.is_object());
let merged = match self._get_mut(key) {
Some(x) => {
merge(x, value);
x.clone()
}
None => value,
};
self._set(key.to_string(), merged);
}
fn set_version(&mut self, version: &str) -> WebDriverResult<()> {
self.add("version", version)
}
fn set_platform(&mut self, platform: &str) -> WebDriverResult<()> {
self.add("platform", platform)
}
fn set_javascript_enabled(&mut self, enabled: bool) -> WebDriverResult<()> {
self.add("javascriptEnabled", enabled)
}
fn set_database_enabled(&mut self, enabled: bool) -> WebDriverResult<()> {
self.add("databaseEnabled", enabled)
}
fn set_location_context_enabled(&mut self, enabled: bool) -> WebDriverResult<()> {
self.add("locationContextEnabled", enabled)
}
fn set_application_cache_enabled(&mut self, enabled: bool) -> WebDriverResult<()> {
self.add("applicationCacheEnabled", enabled)
}
fn set_browser_connection_enabled(&mut self, enabled: bool) -> WebDriverResult<()> {
self.add("browserConnectionEnabled", enabled)
}
fn set_web_storage_enabled(&mut self, enabled: bool) -> WebDriverResult<()> {
self.add("webStorageEnabled", enabled)
}
fn accept_ssl_certs(&mut self, enabled: bool) -> WebDriverResult<()> {
self.add("acceptSslCerts", enabled)
}
fn set_rotatable(&mut self, enabled: bool) -> WebDriverResult<()> {
self.add("rotatable", enabled)
}
fn set_native_events(&mut self, enabled: bool) -> WebDriverResult<()> {
self.add("nativeEvents", enabled)
}
fn set_proxy(&mut self, proxy: Proxy) -> WebDriverResult<()> {
self.add("proxy", proxy)
}
fn set_unexpected_alert_behaviour(&mut self, behaviour: AlertBehaviour) -> WebDriverResult<()> {
self.add("unexpectedAlertBehaviour", behaviour)
}
fn set_element_scroll_behaviour(&mut self, behaviour: ScrollBehaviour) -> WebDriverResult<()> {
self.add("elementScrollBehavior", behaviour)
}
fn handles_alerts(&self) -> Option<bool> {
self._get("handlesAlerts").and_then(|x| x.as_bool())
}
fn css_selectors_enabled(&self) -> Option<bool> {
self._get("cssSelectorsEnabled").and_then(|x| x.as_bool())
}
}
impl CapabilitiesHelper for Capabilities {
fn _get(&self, key: &str) -> Option<&Value> {
self.get(key)
}
fn _get_mut(&mut self, key: &str) -> Option<&mut Value> {
self.get_mut(key)
}
fn _set(&mut self, key: String, value: Value) {
self.insert(key, value);
}
}
#[derive(Debug, Clone, Serialize)]
#[serde(tag = "proxyType", rename_all = "lowercase")]
pub enum Proxy {
Direct,
#[serde(rename_all = "camelCase")]
Manual {
#[serde(skip_serializing_if = "Option::is_none")]
ftp_proxy: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
http_proxy: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
ssl_proxy: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
socks_proxy: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
socks_version: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
socks_username: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
socks_password: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
no_proxy: Option<String>,
},
#[serde(rename = "pac")]
AutoConfig {
#[serde(rename = "proxyAutoconfigUrl")]
url: String,
},
AutoDetect,
System,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum AlertBehaviour {
Accept,
Dismiss,
Ignore,
}
#[derive(Debug, Clone, Serialize)]
#[repr(u8)]
pub enum ScrollBehaviour {
Top = 0,
Bottom = 1,
}
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum PageLoadStrategy {
Normal,
Eager,
None,
}