use crate::error;
#[cfg(doc)]
use crate::Client;
use http::Method;
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
use std::convert::TryFrom;
use std::fmt;
use std::fmt::Debug;
use std::time::Duration;
use url::{ParseError, Url};
use webdriver::command::TimeoutsParameters;
pub trait WebDriverCompatibleCommand: Debug {
fn endpoint(
&self,
base_url: &url::Url,
session_id: Option<&str>,
) -> Result<url::Url, url::ParseError>;
fn method_and_body(&self, request_url: &url::Url) -> (http::Method, Option<String>);
fn is_new_session(&self) -> bool {
false
}
fn is_legacy(&self) -> bool {
false
}
}
impl<T> WebDriverCompatibleCommand for &T
where
T: WebDriverCompatibleCommand,
{
fn endpoint(&self, base_url: &Url, session_id: Option<&str>) -> Result<Url, ParseError> {
T::endpoint(self, base_url, session_id)
}
fn method_and_body(&self, request_url: &Url) -> (Method, Option<String>) {
T::method_and_body(self, request_url)
}
fn is_new_session(&self) -> bool {
T::is_new_session(self)
}
fn is_legacy(&self) -> bool {
T::is_legacy(self)
}
}
impl<T> WebDriverCompatibleCommand for Box<T>
where
T: WebDriverCompatibleCommand,
{
fn endpoint(&self, base_url: &Url, session_id: Option<&str>) -> Result<Url, ParseError> {
T::endpoint(self, base_url, session_id)
}
fn method_and_body(&self, request_url: &Url) -> (Method, Option<String>) {
T::method_and_body(self, request_url)
}
fn is_new_session(&self) -> bool {
T::is_new_session(self)
}
fn is_legacy(&self) -> bool {
T::is_legacy(self)
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct WindowHandle(String);
impl From<WindowHandle> for String {
fn from(w: WindowHandle) -> Self {
w.0
}
}
impl<'a> TryFrom<Cow<'a, str>> for WindowHandle {
type Error = error::InvalidWindowHandle;
fn try_from(s: Cow<'a, str>) -> Result<Self, Self::Error> {
if s != "current" {
Ok(Self(s.into_owned()))
} else {
Err(error::InvalidWindowHandle)
}
}
}
impl TryFrom<String> for WindowHandle {
type Error = error::InvalidWindowHandle;
fn try_from(s: String) -> Result<Self, Self::Error> {
Self::try_from(Cow::Owned(s))
}
}
impl TryFrom<&str> for WindowHandle {
type Error = error::InvalidWindowHandle;
fn try_from(s: &str) -> Result<Self, Self::Error> {
Self::try_from(Cow::Borrowed(s))
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum NewWindowType {
Tab,
Window,
}
impl fmt::Display for NewWindowType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Tab => write!(f, "tab"),
Self::Window => write!(f, "window"),
}
}
}
pub type Capabilities = serde_json::Map<String, serde_json::Value>;
#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
pub enum Locator<'a> {
Css(&'a str),
Id(&'a str),
LinkText(&'a str),
XPath(&'a str),
}
impl<'a> Locator<'a> {
pub(crate) fn into_parameters(self) -> webdriver::command::LocatorParameters {
use webdriver::command::LocatorParameters;
use webdriver::common::LocatorStrategy;
match self {
Locator::Css(s) => LocatorParameters {
using: LocatorStrategy::CSSSelector,
value: s.to_string(),
},
Locator::Id(s) => LocatorParameters {
using: LocatorStrategy::XPath,
value: format!("//*[@id=\"{}\"]", s),
},
Locator::XPath(s) => LocatorParameters {
using: LocatorStrategy::XPath,
value: s.to_string(),
},
Locator::LinkText(s) => LocatorParameters {
using: LocatorStrategy::LinkText,
value: s.to_string(),
},
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WebDriverStatus {
pub ready: bool,
pub message: String,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct TimeoutConfiguration {
#[serde(skip_serializing_if = "Option::is_none")]
script: Option<u64>,
#[serde(rename = "pageLoad", skip_serializing_if = "Option::is_none")]
page_load: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
implicit: Option<u64>,
}
impl Default for TimeoutConfiguration {
fn default() -> Self {
TimeoutConfiguration::new(
Some(Duration::from_secs(60)),
Some(Duration::from_secs(60)),
Some(Duration::from_secs(0)),
)
}
}
impl TimeoutConfiguration {
pub fn new(
script: Option<Duration>,
page_load: Option<Duration>,
implicit: Option<Duration>,
) -> Self {
TimeoutConfiguration {
script: script.map(|x| x.as_millis() as u64),
page_load: page_load.map(|x| x.as_millis() as u64),
implicit: implicit.map(|x| x.as_millis() as u64),
}
}
pub fn script(&self) -> Option<Duration> {
self.script.map(Duration::from_millis)
}
pub fn set_script(&mut self, timeout: Option<Duration>) {
self.script = timeout.map(|x| x.as_millis() as u64);
}
pub fn page_load(&self) -> Option<Duration> {
self.page_load.map(Duration::from_millis)
}
pub fn set_page_load(&mut self, timeout: Option<Duration>) {
self.page_load = timeout.map(|x| x.as_millis() as u64);
}
pub fn implicit(&self) -> Option<Duration> {
self.implicit.map(Duration::from_millis)
}
pub fn set_implicit(&mut self, timeout: Option<Duration>) {
self.implicit = timeout.map(|x| x.as_millis() as u64);
}
}
impl TimeoutConfiguration {
pub(crate) fn into_params(self) -> TimeoutsParameters {
TimeoutsParameters {
script: self.script.map(Some),
page_load: self.page_load,
implicit: self.implicit,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct NewSessionResponse {
#[serde(rename = "sessionId")]
session_id: String,
capabilities: Option<Capabilities>,
}
impl NewSessionResponse {
pub fn session_id(&self) -> &str {
&self.session_id
}
pub fn capabilities(&self) -> Option<&Capabilities> {
self.capabilities.as_ref()
}
pub(crate) fn from_wd(nsr: webdriver::response::NewSessionResponse) -> Self {
NewSessionResponse {
session_id: nsr.session_id,
capabilities: nsr.capabilities.as_object().cloned(),
}
}
}
pub use crate::print::{
PrintConfiguration, PrintConfigurationBuilder, PrintMargins, PrintOrientation, PrintPageRange,
PrintSize,
};