viewpoint_core/page/locator/queries/
mod.rs1use super::selector::js_string_literal;
6use super::Locator;
7use crate::error::LocatorError;
8
9impl<'a> Locator<'a> {
10 pub async fn text_content(&self) -> Result<Option<String>, LocatorError> {
16 let info = self.query_element_info().await?;
17 Ok(info.text)
18 }
19
20 pub async fn is_visible(&self) -> Result<bool, LocatorError> {
26 let info = self.query_element_info().await?;
27 Ok(info.visible.unwrap_or(false))
28 }
29
30 pub async fn is_checked(&self) -> Result<bool, LocatorError> {
36 let js = format!(
37 r"(function() {{
38 const elements = {};
39 if (elements.length === 0) return {{ found: false, checked: false }};
40 const el = elements[0];
41 return {{ found: true, checked: el.checked || false }};
42 }})()",
43 self.selector.to_js_expression()
44 );
45
46 let result = self.evaluate_js(&js).await?;
47 let checked: bool = result
48 .get("checked")
49 .and_then(serde_json::Value::as_bool)
50 .unwrap_or(false);
51 Ok(checked)
52 }
53
54 pub async fn count(&self) -> Result<usize, LocatorError> {
60 let info = self.query_element_info().await?;
61 Ok(info.count)
62 }
63
64 pub async fn all(&self) -> Result<Vec<Locator<'a>>, LocatorError> {
81 let count = self.count().await?;
82 let mut locators = Vec::with_capacity(count);
83 for i in 0..count {
84 locators.push(self.nth(i as i32));
85 }
86 Ok(locators)
87 }
88
89 pub async fn all_inner_texts(&self) -> Result<Vec<String>, LocatorError> {
105 let js = format!(
106 r"(function() {{
107 const elements = Array.from({});
108 return elements.map(el => el.innerText || '');
109 }})()",
110 self.selector.to_js_expression()
111 );
112
113 let result = self.evaluate_js(&js).await?;
114
115 result
116 .as_array()
117 .map(|arr| {
118 arr.iter()
119 .map(|v| v.as_str().unwrap_or("").to_string())
120 .collect()
121 })
122 .ok_or_else(|| LocatorError::EvaluationError("Expected array result".to_string()))
123 }
124
125 pub async fn all_text_contents(&self) -> Result<Vec<String>, LocatorError> {
141 let js = format!(
142 r"(function() {{
143 const elements = Array.from({});
144 return elements.map(el => el.textContent || '');
145 }})()",
146 self.selector.to_js_expression()
147 );
148
149 let result = self.evaluate_js(&js).await?;
150
151 result
152 .as_array()
153 .map(|arr| {
154 arr.iter()
155 .map(|v| v.as_str().unwrap_or("").to_string())
156 .collect()
157 })
158 .ok_or_else(|| LocatorError::EvaluationError("Expected array result".to_string()))
159 }
160
161 pub async fn inner_text(&self) -> Result<String, LocatorError> {
169 let js = format!(
170 r"(function() {{
171 const elements = {};
172 if (elements.length === 0) return {{ found: false }};
173 return {{ found: true, text: elements[0].innerText || '' }};
174 }})()",
175 self.selector.to_js_expression()
176 );
177
178 let result = self.evaluate_js(&js).await?;
179
180 let found = result.get("found").and_then(serde_json::Value::as_bool).unwrap_or(false);
181 if !found {
182 return Err(LocatorError::NotFound(format!("{:?}", self.selector)));
183 }
184
185 Ok(result
186 .get("text")
187 .and_then(|v| v.as_str())
188 .unwrap_or("")
189 .to_string())
190 }
191
192 pub async fn get_attribute(&self, name: &str) -> Result<Option<String>, LocatorError> {
198 let js = format!(
199 r"(function() {{
200 const elements = {};
201 if (elements.length === 0) return {{ found: false }};
202 const attr = elements[0].getAttribute({});
203 return {{ found: true, value: attr }};
204 }})()",
205 self.selector.to_js_expression(),
206 js_string_literal(name)
207 );
208
209 let result = self.evaluate_js(&js).await?;
210
211 let found = result.get("found").and_then(serde_json::Value::as_bool).unwrap_or(false);
212 if !found {
213 return Err(LocatorError::NotFound(format!("{:?}", self.selector)));
214 }
215
216 Ok(result
217 .get("value")
218 .and_then(|v| if v.is_null() { None } else { v.as_str() })
219 .map(std::string::ToString::to_string))
220 }
221
222 pub async fn input_value(&self) -> Result<String, LocatorError> {
230 let js = format!(
231 r"(function() {{
232 const elements = {};
233 if (elements.length === 0) return {{ found: false }};
234 const el = elements[0];
235 return {{ found: true, value: el.value || '' }};
236 }})()",
237 self.selector.to_js_expression()
238 );
239
240 let result = self.evaluate_js(&js).await?;
241
242 let found = result.get("found").and_then(serde_json::Value::as_bool).unwrap_or(false);
243 if !found {
244 return Err(LocatorError::NotFound(format!("{:?}", self.selector)));
245 }
246
247 Ok(result
248 .get("value")
249 .and_then(|v| v.as_str())
250 .unwrap_or("")
251 .to_string())
252 }
253}