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;
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
27pub(crate) struct TimeoutsConfiguration {
28    pub(crate) script: Option<u64>,
29    pub(crate) page_load: Option<u64>,
30    pub(crate) implicit_wait: Option<u64>,
31    pub(crate) sleep_interval: u64,
32}
33
34impl Default for TimeoutsConfiguration {
35    fn default() -> Self {
36        TimeoutsConfiguration {
37            script: Some(DEFAULT_SCRIPT_TIMEOUT),
38            page_load: Some(DEFAULT_PAGE_LOAD_TIMEOUT),
39            implicit_wait: Some(DEFAULT_IMPLICIT_WAIT),
40            sleep_interval: 10,
41        }
42    }
43}
44
45/// <https://w3c.github.io/webdriver/#dfn-deserialize-as-timeouts-configuration>
46pub(crate) fn deserialize_as_timeouts_configuration(
47    timeouts: &Value,
48) -> WebDriverResult<TimeoutsConfiguration> {
49    if let Value::Object(map) = timeouts {
50        let mut config = TimeoutsConfiguration::default();
51
52        // Step 3: For each key → value in timeouts:
53        for (key, value) in map {
54            // Step 3.1: If «"script", "pageLoad", "implicit"» does not contain key, then continue.
55            let target = match key.as_str() {
56                "implicit" => &mut config.implicit_wait,
57                "pageLoad" => &mut config.page_load,
58                "script" => &mut config.script,
59                _ => continue,
60            };
61
62            // Step 3.2: If value is neither null nor a number greater than or equal to 0
63            // and less than or equal to the maximum safe integer return error with error
64            // code invalid argument.
65            // Step 3.3: Run the substeps matching key:
66            //  - "script": Set configuration's script timeout to value.
67            //  - "pageLoad": Set configuration's page load timeout to value.
68            //  - "implicit": Set configuration's implicit wait timeout to value.
69            *target = match value {
70                Value::Null => None,
71                _ => Some(value.as_f64().ok_or_else(|| {
72                    WebDriverError::new(ErrorStatus::InvalidArgument, "Invalid value for {key}")
73                })? as u64),
74            };
75        }
76
77        Ok(config)
78    } else {
79        Err(WebDriverError::new(
80            ErrorStatus::InvalidArgument,
81            "Expected an object for timeouts",
82        ))
83    }
84}
85
86pub(crate) fn serialize_timeouts_configuration(timeouts: &TimeoutsConfiguration) -> Value {
87    let mut map = serde_json::Map::new();
88    map.insert("script".to_string(), Value::from(timeouts.script));
89    map.insert("pageLoad".to_string(), Value::from(timeouts.page_load));
90    map.insert("implicit".to_string(), Value::from(timeouts.implicit_wait));
91    Value::Object(map)
92}