mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Rework webdriver session (#38225)
Reimplement webdriver session for better match to spec: - Add `create_session`: [spec](https://www.w3.org/TR/webdriver2/#dfn-create-a-session) - Refactor `handle_new_session` - Replace `PageLoadStrategy` string by enum --------- Signed-off-by: batu_hoang <hoang.binh.trong@huawei.com>
This commit is contained in:
parent
ae69646371
commit
f5ee72f89a
6 changed files with 314 additions and 202 deletions
|
@ -27,7 +27,7 @@ impl ServoCapabilities {
|
|||
set_window_rect: true,
|
||||
strict_file_interactability: false,
|
||||
accept_proxy: false,
|
||||
accept_custom: false,
|
||||
accept_custom: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,13 @@ impl BrowserCapabilities for ServoCapabilities {
|
|||
Ok(self.set_window_rect)
|
||||
}
|
||||
|
||||
fn strict_file_interactability(&mut self, _: &Capabilities) -> WebDriverResult<bool> {
|
||||
fn strict_file_interactability(&mut self, value: &Capabilities) -> WebDriverResult<bool> {
|
||||
if let Some(Value::Bool(strict_file_interactability)) =
|
||||
value.get("strictFileInteractability")
|
||||
{
|
||||
self.strict_file_interactability = *strict_file_interactability;
|
||||
}
|
||||
|
||||
Ok(self.strict_file_interactability)
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
mod actions;
|
||||
mod capabilities;
|
||||
mod session;
|
||||
mod timeout;
|
||||
mod user_prompt;
|
||||
|
||||
use std::borrow::ToOwned;
|
||||
|
@ -67,9 +69,9 @@ use webdriver::response::{
|
|||
use webdriver::server::{self, Session, SessionTeardownKind, WebDriverHandler};
|
||||
|
||||
use crate::actions::{ActionItem, InputSourceState, PointerInputState};
|
||||
use crate::user_prompt::{
|
||||
UserPromptHandler, default_unhandled_prompt_behavior, deserialize_unhandled_prompt_behaviour,
|
||||
};
|
||||
use crate::session::PageLoadStrategy;
|
||||
use crate::timeout::TimeoutsConfiguration;
|
||||
use crate::user_prompt::UserPromptHandler;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct WebDriverMessageIdGenerator {
|
||||
|
@ -173,18 +175,9 @@ pub struct WebDriverSession {
|
|||
/// <https://www.w3.org/TR/webdriver2/#dfn-window-handles>
|
||||
window_handles: HashMap<WebViewId, String>,
|
||||
|
||||
/// Time to wait for injected scripts to run before interrupting them. A [`None`] value
|
||||
/// specifies that the script should run indefinitely.
|
||||
script_timeout: Option<u64>,
|
||||
timeouts: TimeoutsConfiguration,
|
||||
|
||||
/// Time to wait for a page to finish loading upon navigation.
|
||||
load_timeout: u64,
|
||||
|
||||
/// Time to wait for the element location strategy when retrieving elements, and when
|
||||
/// waiting for an element to become interactable.
|
||||
implicit_wait_timeout: u64,
|
||||
|
||||
page_loading_strategy: String,
|
||||
page_loading_strategy: PageLoadStrategy,
|
||||
|
||||
strict_file_interactability: bool,
|
||||
|
||||
|
@ -207,17 +200,11 @@ impl WebDriverSession {
|
|||
id: Uuid::new_v4(),
|
||||
webview_id,
|
||||
browsing_context_id,
|
||||
|
||||
window_handles,
|
||||
|
||||
script_timeout: Some(30_000),
|
||||
load_timeout: 300_000,
|
||||
implicit_wait_timeout: 0,
|
||||
|
||||
page_loading_strategy: "normal".to_string(),
|
||||
timeouts: TimeoutsConfiguration::default(),
|
||||
page_loading_strategy: PageLoadStrategy::Normal,
|
||||
strict_file_interactability: false,
|
||||
user_prompt_handler: UserPromptHandler::new(),
|
||||
|
||||
input_state_table: RefCell::new(HashMap::new()),
|
||||
input_cancel_list: RefCell::new(Vec::new()),
|
||||
}
|
||||
|
@ -562,143 +549,53 @@ impl Handler {
|
|||
thread::sleep(Duration::from_secs(seconds));
|
||||
}
|
||||
|
||||
let mut servo_capabilities = ServoCapabilities::new();
|
||||
let processed_capabilities = parameters.match_browser(&mut servo_capabilities)?;
|
||||
|
||||
// Step 1. If the list of active HTTP sessions is not empty
|
||||
// return error with error code session not created.
|
||||
if self.session.is_some() {
|
||||
Err(WebDriverError::new(
|
||||
return Err(WebDriverError::new(
|
||||
ErrorStatus::SessionNotCreated,
|
||||
"Session already created",
|
||||
))
|
||||
} else {
|
||||
match processed_capabilities {
|
||||
Some(mut processed) => {
|
||||
let webview_id = self.focus_webview_id()?;
|
||||
let browsing_context_id = BrowsingContextId::from(webview_id);
|
||||
let mut session = WebDriverSession::new(browsing_context_id, webview_id);
|
||||
));
|
||||
}
|
||||
|
||||
match processed.get("pageLoadStrategy") {
|
||||
Some(strategy) => session.page_loading_strategy = strategy.to_string(),
|
||||
// Step 2. Skip because the step is only applied to an intermediary node.
|
||||
// Step 3. Skip since all sessions are http for now.
|
||||
|
||||
// Step 4. Let capabilities be the result of trying to process capabilities
|
||||
let mut servo_capabilities = ServoCapabilities::new();
|
||||
let processed_capabilities = parameters.match_browser(&mut servo_capabilities)?;
|
||||
|
||||
// Step 5. If capabilities's is null, return error with error code session not created.
|
||||
let mut capabilities = match processed_capabilities {
|
||||
Some(capabilities) => capabilities,
|
||||
None => {
|
||||
processed.insert(
|
||||
"pageLoadStrategy".to_string(),
|
||||
json!(session.page_loading_strategy),
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
match processed.get("strictFileInteractability") {
|
||||
Some(strict_file_interactability) => {
|
||||
session.strict_file_interactability =
|
||||
strict_file_interactability.as_bool().unwrap()
|
||||
},
|
||||
None => {
|
||||
processed.insert(
|
||||
"strictFileInteractability".to_string(),
|
||||
json!(session.strict_file_interactability),
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
match processed.get("proxy") {
|
||||
Some(_) => (),
|
||||
None => {
|
||||
processed.insert("proxy".to_string(), json!({}));
|
||||
},
|
||||
}
|
||||
|
||||
if let Some(timeouts) = processed.get("timeouts") {
|
||||
if let Some(script_timeout_value) = timeouts.get("script") {
|
||||
session.script_timeout = script_timeout_value.as_u64();
|
||||
}
|
||||
if let Some(load_timeout_value) = timeouts.get("pageLoad") {
|
||||
if let Some(load_timeout) = load_timeout_value.as_u64() {
|
||||
session.load_timeout = load_timeout;
|
||||
}
|
||||
}
|
||||
if let Some(implicit_wait_timeout_value) = timeouts.get("implicit") {
|
||||
if let Some(implicit_wait_timeout) =
|
||||
implicit_wait_timeout_value.as_u64()
|
||||
{
|
||||
session.implicit_wait_timeout = implicit_wait_timeout;
|
||||
}
|
||||
}
|
||||
}
|
||||
processed.insert(
|
||||
"timeouts".to_string(),
|
||||
json!({
|
||||
"script": session.script_timeout,
|
||||
"pageLoad": session.load_timeout,
|
||||
"implicit": session.implicit_wait_timeout,
|
||||
}),
|
||||
);
|
||||
|
||||
match processed.get("acceptInsecureCerts") {
|
||||
Some(_accept_insecure_certs) => {
|
||||
// FIXME do something here?
|
||||
},
|
||||
None => {
|
||||
processed.insert(
|
||||
"acceptInsecureCerts".to_string(),
|
||||
json!(servo_capabilities.accept_insecure_certs),
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
match processed.get("unhandledPromptBehavior") {
|
||||
Some(unhandled_prompt_behavior) => {
|
||||
session.user_prompt_handler = deserialize_unhandled_prompt_behaviour(
|
||||
unhandled_prompt_behavior.clone(),
|
||||
)?;
|
||||
},
|
||||
None => {
|
||||
processed.insert(
|
||||
"unhandledPromptBehavior".to_string(),
|
||||
json!(default_unhandled_prompt_behavior()),
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
processed.insert(
|
||||
"browserName".to_string(),
|
||||
json!(servo_capabilities.browser_name),
|
||||
);
|
||||
processed.insert(
|
||||
"browserVersion".to_string(),
|
||||
json!(servo_capabilities.browser_version),
|
||||
);
|
||||
processed.insert(
|
||||
"platformName".to_string(),
|
||||
json!(
|
||||
servo_capabilities
|
||||
.platform_name
|
||||
.unwrap_or("unknown".to_string())
|
||||
),
|
||||
);
|
||||
processed.insert(
|
||||
"setWindowRect".to_string(),
|
||||
json!(servo_capabilities.set_window_rect),
|
||||
);
|
||||
processed.insert(
|
||||
"userAgent".to_string(),
|
||||
servo_config::pref!(user_agent).into(),
|
||||
);
|
||||
|
||||
let response =
|
||||
NewSessionResponse::new(session.id.to_string(), Value::Object(processed));
|
||||
self.session = Some(session);
|
||||
Ok(WebDriverResponse::NewSession(response))
|
||||
},
|
||||
// Step 5. If capabilities's is null,
|
||||
// return error with error code session not created.
|
||||
None => Err(WebDriverError::new(
|
||||
return Err(WebDriverError::new(
|
||||
ErrorStatus::SessionNotCreated,
|
||||
"Session not created due to invalid capabilities",
|
||||
)),
|
||||
}
|
||||
}
|
||||
));
|
||||
},
|
||||
};
|
||||
|
||||
// Step 6. Create a session
|
||||
// Step 8. Set session' current top-level browsing context
|
||||
let webview_id = self.focus_webview_id()?;
|
||||
let browsing_context_id = BrowsingContextId::from(webview_id);
|
||||
// Create and append session to the handler
|
||||
let session_id = self.create_session(
|
||||
&mut capabilities,
|
||||
&servo_capabilities,
|
||||
webview_id,
|
||||
browsing_context_id,
|
||||
)?;
|
||||
|
||||
// Step 7. Let response be a JSON Object initialized with session's session ID and capabilities
|
||||
let response = NewSessionResponse::new(session_id.to_string(), Value::Object(capabilities));
|
||||
|
||||
// Step 9. Set the request queue to a new queue.
|
||||
// Skip here because the requests are handled in the external crate.
|
||||
|
||||
// Step 10. Return success with data body
|
||||
Ok(WebDriverResponse::NewSession(response))
|
||||
}
|
||||
|
||||
fn handle_delete_session(&mut self) -> WebDriverResult<WebDriverResponse> {
|
||||
|
@ -798,7 +695,7 @@ impl Handler {
|
|||
|
||||
// Step 1. If session's page loading strategy is "none",
|
||||
// return success with data null.
|
||||
if session.page_loading_strategy == "none" {
|
||||
if session.page_loading_strategy == PageLoadStrategy::None {
|
||||
return Ok(WebDriverResponse::Void);
|
||||
}
|
||||
|
||||
|
@ -812,7 +709,7 @@ impl Handler {
|
|||
}
|
||||
|
||||
// Step 3. let timeout be the session's page load timeout.
|
||||
let timeout = self.session()?.load_timeout;
|
||||
let timeout = self.session()?.timeouts.page_load;
|
||||
|
||||
// TODO: Step 4. Implement timer parameter
|
||||
|
||||
|
@ -1886,9 +1783,9 @@ impl Handler {
|
|||
.ok_or(WebDriverError::new(ErrorStatus::SessionNotCreated, ""))?;
|
||||
|
||||
let timeouts = TimeoutsResponse {
|
||||
script: session.script_timeout,
|
||||
page_load: session.load_timeout,
|
||||
implicit: session.implicit_wait_timeout,
|
||||
script: session.timeouts.script,
|
||||
page_load: session.timeouts.page_load,
|
||||
implicit: session.timeouts.implicit_wait,
|
||||
};
|
||||
|
||||
Ok(WebDriverResponse::Timeouts(timeouts))
|
||||
|
@ -1904,13 +1801,13 @@ impl Handler {
|
|||
.ok_or(WebDriverError::new(ErrorStatus::SessionNotCreated, ""))?;
|
||||
|
||||
if let Some(timeout) = parameters.script {
|
||||
session.script_timeout = timeout;
|
||||
session.timeouts.script = timeout;
|
||||
}
|
||||
if let Some(timeout) = parameters.page_load {
|
||||
session.load_timeout = timeout
|
||||
session.timeouts.page_load = timeout
|
||||
}
|
||||
if let Some(timeout) = parameters.implicit {
|
||||
session.implicit_wait_timeout = timeout
|
||||
session.timeouts.implicit_wait = timeout
|
||||
}
|
||||
|
||||
Ok(WebDriverResponse::Void)
|
||||
|
@ -2054,7 +1951,7 @@ impl Handler {
|
|||
.collect();
|
||||
args_string.push("resolve".to_string());
|
||||
|
||||
let timeout_script = if let Some(script_timeout) = self.session()?.script_timeout {
|
||||
let timeout_script = if let Some(script_timeout) = self.session()?.timeouts.script {
|
||||
format!("setTimeout(webdriverTimeout, {});", script_timeout)
|
||||
} else {
|
||||
"".into()
|
||||
|
|
173
components/webdriver_server/session.rs
Normal file
173
components/webdriver_server/session.rs
Normal file
|
@ -0,0 +1,173 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use base::id::{BrowsingContextId, WebViewId};
|
||||
use serde_json::{Map, Value, json};
|
||||
use uuid::Uuid;
|
||||
use webdriver::error::WebDriverResult;
|
||||
|
||||
use crate::capabilities::ServoCapabilities;
|
||||
use crate::timeout::{deserialize_as_timeouts_configuration, serialize_timeouts_configuration};
|
||||
use crate::user_prompt::{
|
||||
default_unhandled_prompt_behavior, deserialize_unhandled_prompt_behaviour,
|
||||
};
|
||||
use crate::{Handler, WebDriverSession};
|
||||
|
||||
#[derive(Debug, PartialEq, serde::Serialize)]
|
||||
pub enum PageLoadStrategy {
|
||||
None,
|
||||
Eager,
|
||||
Normal,
|
||||
}
|
||||
|
||||
// Need a different implementation for ToString than Display
|
||||
#[allow(clippy::to_string_trait_impl)]
|
||||
impl ToString for PageLoadStrategy {
|
||||
fn to_string(&self) -> String {
|
||||
match self {
|
||||
PageLoadStrategy::None => String::from("none"),
|
||||
PageLoadStrategy::Eager => String::from("eager"),
|
||||
PageLoadStrategy::Normal => String::from("normal"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Handler {
|
||||
/// <https://w3c.github.io/webdriver/#dfn-create-a-session>
|
||||
pub(crate) fn create_session(
|
||||
&mut self,
|
||||
capabilities: &mut Map<String, Value>,
|
||||
servo_capabilities: &ServoCapabilities,
|
||||
webview_id: WebViewId,
|
||||
browsing_context_id: BrowsingContextId,
|
||||
) -> WebDriverResult<Uuid> {
|
||||
// Step 2. Let session be a new session
|
||||
let mut session = WebDriverSession::new(browsing_context_id, webview_id);
|
||||
|
||||
// Step 3. Let proxy be the result of getting property "proxy" from capabilities
|
||||
match capabilities.get("proxy") {
|
||||
// Proxy is a proxy configuration object
|
||||
Some(_) => {
|
||||
// TODO:
|
||||
// Take implementation-defined steps to set the user agent proxy
|
||||
// using the extracted proxy configuration.
|
||||
// If the defined proxy cannot be configured return error with error code
|
||||
// session not created. Otherwise set the has proxy configuration flag to true.
|
||||
},
|
||||
// Otherwise, set a property of capabilities with name "proxy"
|
||||
// and a value that is a new JSON Object.
|
||||
None => {
|
||||
capabilities.insert(String::from("proxy"), json!({}));
|
||||
},
|
||||
}
|
||||
|
||||
// Step 4. If capabilites has a property named "acceptInsecureCerts"
|
||||
match capabilities.get("acceptInsecureCerts") {
|
||||
Some(_accept_insecure_certs) => {
|
||||
// TODO: Set the endpoint node's accept insecure TLS flag
|
||||
},
|
||||
None => {
|
||||
capabilities.insert(String::from("acceptInsecureCerts"), json!(false));
|
||||
},
|
||||
}
|
||||
|
||||
// Step 5. Let user prompt handler capability be the result of
|
||||
// getting property "unhandledPromptBehavior" from capabilities
|
||||
match capabilities.get("unhandledPromptBehavior") {
|
||||
// Step 6. If user prompt handler capability is not undefined
|
||||
Some(unhandled_prompt_behavior) => {
|
||||
session.user_prompt_handler =
|
||||
deserialize_unhandled_prompt_behaviour(unhandled_prompt_behavior.clone())?;
|
||||
},
|
||||
// Step 7. Let serialized user prompt handler be serialize the user prompt handler.
|
||||
// Step 8. Set a property on capabilities with the name "unhandledPromptBehavior",
|
||||
// and the value serialized user prompt handler.
|
||||
// Ignore because the user prompt handler is already in the capabilities object
|
||||
None => {
|
||||
capabilities.insert(
|
||||
String::from("unhandledPromptBehavior"),
|
||||
json!(default_unhandled_prompt_behavior()),
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
// TODO: flag is http by default for now
|
||||
// Step 9. If flags contains "http"
|
||||
// Step 9.1. Let strategy be the result of getting property "pageLoadStrategy" from capabilities.
|
||||
match capabilities.get("pageLoadStrategy") {
|
||||
// If strategy is a string, set the session's page loading strategy to strategy.
|
||||
Some(strategy) => match strategy.to_string().as_str() {
|
||||
"none" => session.page_loading_strategy = PageLoadStrategy::None,
|
||||
"eager" => session.page_loading_strategy = PageLoadStrategy::Eager,
|
||||
_ => session.page_loading_strategy = PageLoadStrategy::Normal,
|
||||
},
|
||||
// Otherwise, set the page loading strategy to normal and set a property of capabilities
|
||||
// with name "pageLoadStrategy" and value "normal".
|
||||
None => {
|
||||
capabilities.insert(
|
||||
String::from("pageLoadStrategy"),
|
||||
json!(session.page_loading_strategy.to_string()),
|
||||
);
|
||||
session.page_loading_strategy = PageLoadStrategy::Normal;
|
||||
},
|
||||
}
|
||||
|
||||
// Step 9.2. Let strictFileInteractability be the result of getting property
|
||||
// "strictFileInteractability" from capabilities
|
||||
if let Some(Value::Bool(strict_file_interactability)) =
|
||||
capabilities.get("strictFileInteractability")
|
||||
{
|
||||
session.strict_file_interactability = *strict_file_interactability;
|
||||
}
|
||||
|
||||
// Step 9.3. Let timeouts be the result of getting a property "timeouts" from capabilities.
|
||||
// If timeouts is not undefined, set session's session timeouts to timeouts.
|
||||
if let Some(timeouts) = capabilities.get("timeouts") {
|
||||
session.timeouts = deserialize_as_timeouts_configuration(timeouts)?;
|
||||
}
|
||||
|
||||
// Step 9.4 Set a property on capabilities with name "timeouts"
|
||||
// and value serialize the timeouts configuration with session's session timeouts.
|
||||
capabilities.insert(
|
||||
"timeouts".to_string(),
|
||||
json!(serialize_timeouts_configuration(&session.timeouts)),
|
||||
);
|
||||
|
||||
// Step 10. Process any extension capabilities in capabilities in an implementation-defined manner
|
||||
// Nothing to processed
|
||||
|
||||
// Step 11. Run any WebDriver new session algorithm defined in external specifications
|
||||
capabilities.insert(
|
||||
"browserName".to_string(),
|
||||
json!(servo_capabilities.browser_name),
|
||||
);
|
||||
capabilities.insert(
|
||||
"browserVersion".to_string(),
|
||||
json!(servo_capabilities.browser_version),
|
||||
);
|
||||
capabilities.insert(
|
||||
"platformName".to_string(),
|
||||
json!(
|
||||
servo_capabilities
|
||||
.platform_name
|
||||
.clone()
|
||||
.unwrap_or("unknown".to_string())
|
||||
),
|
||||
);
|
||||
capabilities.insert(
|
||||
"setWindowRect".to_string(),
|
||||
json!(servo_capabilities.set_window_rect),
|
||||
);
|
||||
capabilities.insert(
|
||||
"userAgent".to_string(),
|
||||
servo_config::pref!(user_agent).into(),
|
||||
);
|
||||
|
||||
// Step 12. Append session to active sessions
|
||||
let id = session.id;
|
||||
self.session = Some(session);
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
}
|
78
components/webdriver_server/timeout.rs
Normal file
78
components/webdriver_server/timeout.rs
Normal file
|
@ -0,0 +1,78 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use serde_json::Value;
|
||||
use webdriver::error::{ErrorStatus, WebDriverError, WebDriverResult};
|
||||
|
||||
pub(crate) struct TimeoutsConfiguration {
|
||||
pub script: Option<u64>,
|
||||
pub page_load: u64,
|
||||
pub implicit_wait: u64,
|
||||
}
|
||||
|
||||
impl Default for TimeoutsConfiguration {
|
||||
fn default() -> Self {
|
||||
TimeoutsConfiguration {
|
||||
script: Some(30_000),
|
||||
page_load: 300_000,
|
||||
implicit_wait: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <https://w3c.github.io/webdriver/#dfn-deserialize-as-timeouts-configuration>
|
||||
pub(crate) fn deserialize_as_timeouts_configuration(
|
||||
timeouts: &Value,
|
||||
) -> WebDriverResult<TimeoutsConfiguration> {
|
||||
if let Value::Object(map) = timeouts {
|
||||
let mut config = TimeoutsConfiguration::default();
|
||||
for (key, value) in map {
|
||||
match key.as_str() {
|
||||
"implicit" => {
|
||||
config.implicit_wait = value.as_f64().ok_or_else(|| {
|
||||
WebDriverError::new(
|
||||
ErrorStatus::InvalidArgument,
|
||||
"Invalid implicit timeout",
|
||||
)
|
||||
})? as u64;
|
||||
},
|
||||
"pageLoad" => {
|
||||
config.page_load = value.as_f64().ok_or_else(|| {
|
||||
WebDriverError::new(
|
||||
ErrorStatus::InvalidArgument,
|
||||
"Invalid page load timeout",
|
||||
)
|
||||
})? as u64;
|
||||
},
|
||||
"script" => {
|
||||
config.script = Some(value.as_f64().ok_or_else(|| {
|
||||
WebDriverError::new(ErrorStatus::InvalidArgument, "Invalid script timeout")
|
||||
})? as u64);
|
||||
},
|
||||
_ => {
|
||||
return Err(WebDriverError::new(
|
||||
ErrorStatus::UnknownCommand,
|
||||
"Unknown timeout key",
|
||||
));
|
||||
},
|
||||
}
|
||||
}
|
||||
Ok(config)
|
||||
} else {
|
||||
Err(WebDriverError::new(
|
||||
ErrorStatus::InvalidArgument,
|
||||
"Expected an object for timeouts",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn serialize_timeouts_configuration(timeouts: &TimeoutsConfiguration) -> Value {
|
||||
let mut map = serde_json::Map::new();
|
||||
if let Some(script_timeout) = timeouts.script {
|
||||
map.insert("script".to_string(), Value::from(script_timeout));
|
||||
}
|
||||
map.insert("pageLoad".to_string(), Value::from(timeouts.page_load));
|
||||
map.insert("implicit".to_string(), Value::from(timeouts.implicit_wait));
|
||||
Value::Object(map)
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
[create_alwaysMatch.py]
|
||||
[test_valid[timeouts-value12\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_valid[strictFileInteractability-True\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_valid[test:extension-False\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_valid[test:extension-abc\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_valid[test:extension-123\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_valid[test:extension-value22\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_valid[test:extension-value23\]]
|
||||
expected: FAIL
|
|
@ -1,21 +0,0 @@
|
|||
[create_firstMatch.py]
|
||||
[test_valid[timeouts-value12\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_valid[strictFileInteractability-True\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_valid[test:extension-False\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_valid[test:extension-abc\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_valid[test:extension-123\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_valid[test:extension-value22\]]
|
||||
expected: FAIL
|
||||
|
||||
[test_valid[test:extension-value23\]]
|
||||
expected: FAIL
|
Loading…
Add table
Add a link
Reference in a new issue