1use std::{sync::Arc, time::Duration};
2
3use thirtyfour::{error::WebDriverResult, extensions::query::ElementPollerWithTimeout};
4use typed_builder::TypedBuilder;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TypedBuilder)]
8pub struct ElementQueryWaitConfig {
9 #[builder(setter(into))]
20 timeout: Duration,
21
22 #[builder(setter(into))]
33 interval: Duration,
34}
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
38pub enum ElementQueryWaitConfigError {
39 #[error("Element query wait poll interval must be non-zero.")]
41 ZeroInterval,
42}
43
44impl ElementQueryWaitConfig {
45 #[must_use]
51 pub const fn new(timeout: Duration, interval: Duration) -> Self {
52 Self { timeout, interval }
53 }
54
55 pub fn try_new(
62 timeout: Duration,
63 interval: Duration,
64 ) -> Result<Self, ElementQueryWaitConfigError> {
65 if interval.is_zero() {
66 return Err(ElementQueryWaitConfigError::ZeroInterval);
67 }
68
69 Ok(Self { timeout, interval })
70 }
71
72 #[must_use]
74 pub const fn timeout(self) -> Duration {
75 self.timeout
76 }
77
78 #[must_use]
80 pub const fn interval(self) -> Duration {
81 self.interval
82 }
83
84 pub(crate) fn into_thirtyfour_webdriver_config(
85 self,
86 ) -> WebDriverResult<thirtyfour::common::config::WebDriverConfig> {
87 thirtyfour::common::config::WebDriverConfig::builder()
88 .poller(Arc::new(ElementPollerWithTimeout::new(
89 self.timeout,
90 self.interval,
91 )))
92 .build()
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99 use assertr::prelude::*;
100
101 #[test]
102 fn builder_preserves_timeout_and_interval() {
103 let wait = ElementQueryWaitConfig::builder()
104 .timeout(Duration::from_secs(10))
105 .interval(Duration::from_millis(250))
106 .build();
107
108 assert_that!(wait.timeout()).is_equal_to(Duration::from_secs(10));
109 assert_that!(wait.interval()).is_equal_to(Duration::from_millis(250));
110 }
111
112 #[test]
113 fn builder_preserves_zero_interval_for_trusted_callers() {
114 let wait = ElementQueryWaitConfig::builder()
115 .timeout(Duration::from_secs(10))
116 .interval(Duration::ZERO)
117 .build();
118
119 assert_that!(wait.interval()).is_equal_to(Duration::ZERO);
120 }
121
122 #[test]
123 fn try_new_accepts_non_zero_interval() {
124 let wait =
125 ElementQueryWaitConfig::try_new(Duration::from_secs(10), Duration::from_millis(250))
126 .expect("non-zero interval should be accepted");
127
128 assert_that!(wait.timeout()).is_equal_to(Duration::from_secs(10));
129 assert_that!(wait.interval()).is_equal_to(Duration::from_millis(250));
130 }
131
132 #[test]
133 fn try_new_rejects_zero_interval() {
134 let err = ElementQueryWaitConfig::try_new(Duration::from_secs(10), Duration::ZERO)
135 .expect_err("zero interval should be rejected");
136
137 assert_that!(err).is_equal_to(ElementQueryWaitConfigError::ZeroInterval);
138 }
139
140 #[test]
141 fn new_preserves_zero_interval_for_const_trusted_callers() {
142 const WAIT: ElementQueryWaitConfig =
143 ElementQueryWaitConfig::new(Duration::from_secs(10), Duration::ZERO);
144
145 assert_that!(WAIT.interval()).is_equal_to(Duration::ZERO);
146 }
147}