limit_cli/tools/browser/client_ext/
waiting.rs1use crate::tools::browser::executor::BrowserError;
4
5pub trait WaitingExt {
7 fn wait_for(
9 &self,
10 condition: &str,
11 ) -> impl std::future::Future<Output = Result<(), BrowserError>> + Send;
12
13 fn wait_for_text(
15 &self,
16 text: &str,
17 ) -> impl std::future::Future<Output = Result<(), BrowserError>> + Send;
18
19 fn wait_for_url(
21 &self,
22 pattern: &str,
23 ) -> impl std::future::Future<Output = Result<(), BrowserError>> + Send;
24
25 fn wait_for_load(
27 &self,
28 state: &str,
29 ) -> impl std::future::Future<Output = Result<(), BrowserError>> + Send;
30
31 fn wait_for_download(
33 &self,
34 path: Option<&str>,
35 ) -> impl std::future::Future<Output = Result<String, BrowserError>> + Send;
36
37 fn wait_for_fn(
39 &self,
40 js: &str,
41 ) -> impl std::future::Future<Output = Result<(), BrowserError>> + Send;
42
43 fn wait_for_state(
45 &self,
46 selector: &str,
47 state: &str,
48 ) -> impl std::future::Future<Output = Result<(), BrowserError>> + Send;
49}
50
51impl WaitingExt for super::super::BrowserClient {
52 async fn wait_for(&self, condition: &str) -> Result<(), BrowserError> {
53 if condition.is_empty() {
54 return Err(BrowserError::InvalidArguments(
55 "Condition cannot be empty".to_string(),
56 ));
57 }
58
59 let output = self.executor().execute(&["wait", condition]).await?;
60
61 if output.success {
62 Ok(())
63 } else {
64 Err(BrowserError::Other(format!(
65 "Wait condition not met: {}",
66 output.stderr
67 )))
68 }
69 }
70
71 async fn wait_for_text(&self, text: &str) -> Result<(), BrowserError> {
72 if text.is_empty() {
73 return Err(BrowserError::InvalidArguments(
74 "Text cannot be empty".to_string(),
75 ));
76 }
77
78 let output = self.executor().execute(&["wait", "--text", text]).await?;
79
80 if output.success {
81 Ok(())
82 } else {
83 Err(BrowserError::Other(format!(
84 "Text not found: {}",
85 output.stderr
86 )))
87 }
88 }
89
90 async fn wait_for_url(&self, pattern: &str) -> Result<(), BrowserError> {
91 if pattern.is_empty() {
92 return Err(BrowserError::InvalidArguments(
93 "URL pattern cannot be empty".to_string(),
94 ));
95 }
96
97 let output = self.executor().execute(&["wait", "--url", pattern]).await?;
98
99 if output.success {
100 Ok(())
101 } else {
102 Err(BrowserError::Other(format!(
103 "URL pattern not matched: {}",
104 output.stderr
105 )))
106 }
107 }
108
109 async fn wait_for_load(&self, state: &str) -> Result<(), BrowserError> {
110 let valid_states = ["networkidle", "domcontentloaded", "load"];
111 if !valid_states.contains(&state) {
112 return Err(BrowserError::InvalidArguments(format!(
113 "Invalid load state '{}'. Valid states: {}",
114 state,
115 valid_states.join(", ")
116 )));
117 }
118
119 let output = self.executor().execute(&["wait", "--load", state]).await?;
120
121 if output.success {
122 Ok(())
123 } else {
124 Err(BrowserError::Other(format!(
125 "Load state not reached: {}",
126 output.stderr
127 )))
128 }
129 }
130
131 async fn wait_for_download(&self, path: Option<&str>) -> Result<String, BrowserError> {
132 let output = if let Some(p) = path {
133 self.executor().execute(&["wait", "--download", p]).await?
134 } else {
135 self.executor().execute(&["wait", "--download"]).await?
136 };
137
138 if output.success {
139 Ok(output.stdout.trim().to_string())
140 } else {
141 Err(BrowserError::Other(format!(
142 "Download wait failed: {}",
143 output.stderr
144 )))
145 }
146 }
147
148 async fn wait_for_fn(&self, js: &str) -> Result<(), BrowserError> {
149 if js.is_empty() {
150 return Err(BrowserError::InvalidArguments(
151 "JavaScript function cannot be empty".to_string(),
152 ));
153 }
154
155 let output = self.executor().execute(&["wait", "--fn", js]).await?;
156
157 if output.success {
158 Ok(())
159 } else {
160 Err(BrowserError::Other(format!(
161 "JavaScript condition not met: {}",
162 output.stderr
163 )))
164 }
165 }
166
167 async fn wait_for_state(&self, selector: &str, state: &str) -> Result<(), BrowserError> {
168 let valid_states = [
169 "visible", "hidden", "attached", "detached", "enabled", "disabled",
170 ];
171 if !valid_states.contains(&state) {
172 return Err(BrowserError::InvalidArguments(format!(
173 "Invalid state '{}'. Valid states: {}",
174 state,
175 valid_states.join(", ")
176 )));
177 }
178
179 if selector.is_empty() {
180 return Err(BrowserError::InvalidArguments(
181 "Selector cannot be empty".to_string(),
182 ));
183 }
184
185 let output = self
186 .executor()
187 .execute(&["wait", "--state", state, selector])
188 .await?;
189
190 if output.success {
191 Ok(())
192 } else {
193 Err(BrowserError::Other(format!(
194 "Element state not reached: {}",
195 output.stderr
196 )))
197 }
198 }
199}