webdriver_server/timeout.rs
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use std::time::Duration;
6
7use serde_json::{Value, json};
8use webdriver::error::{ErrorStatus, WebDriverError, WebDriverResult};
9
10/// Initial script timeout from
11/// <https://w3c.github.io/webdriver/#dfn-timeouts-configuration>.
12pub(crate) const DEFAULT_SCRIPT_TIMEOUT: u64 = 30_000;
13
14/// Initial page load timeout from
15/// <https://w3c.github.io/webdriver/#dfn-timeouts-configuration>.
16pub(crate) const DEFAULT_PAGE_LOAD_TIMEOUT: u64 = 300_000;
17
18/// Initial initial wait timeout from
19/// <https://w3c.github.io/webdriver/#dfn-timeouts-configuration>.
20pub(crate) const DEFAULT_IMPLICIT_WAIT: u64 = 0;
21
22/// An amount of time to wait before considering that a screenshot has timed out.
23/// If after 10 seconds the screenshot cannot be taken, assume that the test has
24/// timed out.
25pub(crate) const SCREENSHOT_TIMEOUT: Duration = Duration::from_secs(10);
26
27/// <https://w3c.github.io/webdriver/#dfn-timeouts-configuration>
28/// A `None` timeout means waiting indefinitely.
29pub(crate) struct TimeoutsConfiguration {
30 pub(crate) script: Option<u64>,
31 pub(crate) page_load: Option<u64>,
32 pub(crate) implicit_wait: Option<u64>,
33 pub(crate) sleep_interval: u64,
34}
35
36impl Default for TimeoutsConfiguration {
37 fn default() -> Self {
38 TimeoutsConfiguration {
39 script: Some(DEFAULT_SCRIPT_TIMEOUT),
40 page_load: Some(DEFAULT_PAGE_LOAD_TIMEOUT),
41 implicit_wait: Some(DEFAULT_IMPLICIT_WAIT),
42 sleep_interval: 10,
43 }
44 }
45}
46
47/// <https://w3c.github.io/webdriver/#dfn-deserialize-as-timeouts-configuration>
48pub(crate) fn deserialize_as_timeouts_configuration(
49 timeouts: &Value,
50) -> WebDriverResult<TimeoutsConfiguration> {
51 if let Value::Object(map) = timeouts {
52 let mut config = TimeoutsConfiguration::default();
53
54 // Step 3: For each key → value in timeouts:
55 for (key, value) in map {
56 // Step 3.1: If «"script", "pageLoad", "implicit"» does not contain key, then continue.
57 let target = match key.as_str() {
58 "implicit" => &mut config.implicit_wait,
59 "pageLoad" => &mut config.page_load,
60 "script" => &mut config.script,
61 _ => continue,
62 };
63
64 // Step 3.2: If value is neither null nor a number greater than or equal to 0
65 // and less than or equal to the maximum safe integer return error with error
66 // code invalid argument.
67 // Step 3.3: Run the substeps matching key:
68 // - "script": Set configuration's script timeout to value.
69 // - "pageLoad": Set configuration's page load timeout to value.
70 // - "implicit": Set configuration's implicit wait timeout to value.
71 *target = match value {
72 Value::Null => None,
73 Value::Number(num) => Some(
74 num.as_f64()
75 .expect("Number already validated when parsing requests")
76 as u64,
77 ),
78 _ => unreachable!("This has been validated when parsing requests"),
79 };
80 }
81
82 Ok(config)
83 } else {
84 Err(WebDriverError::new(
85 ErrorStatus::InvalidArgument,
86 "Expected an object for timeouts",
87 ))
88 }
89}
90
91/// <https://w3c.github.io/webdriver/#dfn-serialize-the-timeouts-configuration>
92pub(crate) fn serialize_timeouts_configuration(timeouts: &TimeoutsConfiguration) -> Value {
93 json!({
94 "script": timeouts.script,
95 "pageLoad": timeouts.page_load,
96 "implicit": timeouts.implicit_wait,
97 })
98}