1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
// WaitForOptions and WaitForState types
//
// Provides configuration for wait_for actions, matching Playwright's API.
use serde::Serialize;
/// The state to wait for when using [`Locator::wait_for()`](crate::protocol::Locator::wait_for).
///
/// Matches Playwright's `WaitForSelectorState` across all language bindings.
///
/// See: <https://playwright.dev/docs/api/class-locator#locator-wait-for>
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum WaitForState {
/// Wait for the element to be present in the DOM (attached).
Attached,
/// Wait for the element to be removed from the DOM.
Detached,
/// Wait for the element to be visible (the default).
Visible,
/// Wait for the element to be hidden (invisible or not in the DOM).
Hidden,
}
/// Options for [`Locator::wait_for()`](crate::protocol::Locator::wait_for).
///
/// Configuration for waiting until an element satisfies a given state condition.
/// If no state is specified, defaults to `Visible`.
///
/// Use the builder pattern to construct options:
///
/// # Example
///
/// ```ignore
/// use playwright_rs::{WaitForOptions, WaitForState};
///
/// // Wait until the element is visible
/// let options = WaitForOptions::builder()
/// .state(WaitForState::Visible)
/// .build();
///
/// // Wait until the element is hidden, with a custom timeout
/// let options = WaitForOptions::builder()
/// .state(WaitForState::Hidden)
/// .timeout(5000.0)
/// .build();
/// ```
///
/// See: <https://playwright.dev/docs/api/class-locator#locator-wait-for>
#[derive(Debug, Clone, Default)]
pub struct WaitForOptions {
/// The element state to wait for (defaults to `Visible` if not set)
pub state: Option<WaitForState>,
/// Maximum time in milliseconds
pub timeout: Option<f64>,
}
impl WaitForOptions {
/// Create a new builder for WaitForOptions
pub fn builder() -> WaitForOptionsBuilder {
WaitForOptionsBuilder::default()
}
/// Convert options to JSON value for protocol
pub(crate) fn to_json(&self) -> serde_json::Value {
let mut json = serde_json::json!({});
// Default to "visible" when no state is specified (matches Playwright behavior)
let state = self.state.unwrap_or(WaitForState::Visible);
json["state"] =
serde_json::to_value(state).expect("serialization of WaitForState cannot fail");
// Timeout is required in Playwright 1.56.1+
if let Some(timeout) = self.timeout {
json["timeout"] = serde_json::json!(timeout);
} else {
json["timeout"] = serde_json::json!(crate::DEFAULT_TIMEOUT_MS);
}
json
}
}
/// Builder for WaitForOptions
///
/// Provides a fluent API for constructing wait_for options.
#[derive(Debug, Clone, Default)]
pub struct WaitForOptionsBuilder {
state: Option<WaitForState>,
timeout: Option<f64>,
}
impl WaitForOptionsBuilder {
/// Set the element state to wait for
pub fn state(mut self, state: WaitForState) -> Self {
self.state = Some(state);
self
}
/// Set timeout in milliseconds
pub fn timeout(mut self, timeout: f64) -> Self {
self.timeout = Some(timeout);
self
}
/// Build the WaitForOptions
pub fn build(self) -> WaitForOptions {
WaitForOptions {
state: self.state,
timeout: self.timeout,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_wait_for_state_serialization() {
assert_eq!(
serde_json::to_string(&WaitForState::Attached).unwrap(),
"\"attached\""
);
assert_eq!(
serde_json::to_string(&WaitForState::Detached).unwrap(),
"\"detached\""
);
assert_eq!(
serde_json::to_string(&WaitForState::Visible).unwrap(),
"\"visible\""
);
assert_eq!(
serde_json::to_string(&WaitForState::Hidden).unwrap(),
"\"hidden\""
);
}
#[test]
fn test_wait_for_options_default_state() {
// When no state is set, to_json() should produce "visible"
let options = WaitForOptions::builder().build();
let json = options.to_json();
assert_eq!(json["state"], "visible");
assert!(json["timeout"].is_number());
}
#[test]
fn test_wait_for_options_all_states() {
for (state, expected) in &[
(WaitForState::Attached, "attached"),
(WaitForState::Detached, "detached"),
(WaitForState::Visible, "visible"),
(WaitForState::Hidden, "hidden"),
] {
let options = WaitForOptions::builder().state(*state).build();
let json = options.to_json();
assert_eq!(json["state"], *expected);
}
}
#[test]
fn test_wait_for_options_timeout() {
let options = WaitForOptions::builder().timeout(5000.0).build();
let json = options.to_json();
assert_eq!(json["timeout"], 5000.0);
}
}