viewpoint_core/page/locator/queries/
text.rs1use viewpoint_cdp::protocol::dom::BackendNodeId;
4use viewpoint_js::js;
5
6use super::super::Locator;
7use super::super::Selector;
8use crate::error::LocatorError;
9
10impl Locator<'_> {
11 pub async fn all_inner_texts(&self) -> Result<Vec<String>, LocatorError> {
32 if let Selector::Ref(ref_str) = &self.selector {
34 let backend_node_id = self.page.get_backend_node_id_for_ref(ref_str)?;
35 return self.all_inner_texts_by_backend_id(backend_node_id).await;
36 }
37
38 if let Selector::BackendNodeId(backend_node_id) = &self.selector {
40 return self.all_inner_texts_by_backend_id(*backend_node_id).await;
41 }
42
43 let selector_expr = self.selector.to_js_expression();
44 let js_code = js! {
45 (function() {
46 const elements = Array.from(@{selector_expr});
47 return elements.map(el => el.innerText || "");
48 })()
49 };
50
51 let result = self.evaluate_js(&js_code).await?;
52
53 result
54 .as_array()
55 .map(|arr| {
56 arr.iter()
57 .map(|v| v.as_str().unwrap_or("").to_string())
58 .collect()
59 })
60 .ok_or_else(|| LocatorError::EvaluationError("Expected array result".to_string()))
61 }
62
63 pub(super) async fn all_inner_texts_by_backend_id(
65 &self,
66 backend_node_id: BackendNodeId,
67 ) -> Result<Vec<String>, LocatorError> {
68 let js_fn = js! {
69 (function() {
70 return [this.innerText || ""];
71 })
72 };
73 let js_fn = js_fn.trim_start_matches('(').trim_end_matches(')');
75
76 let result = self
77 .call_function_on_backend_id(backend_node_id, js_fn)
78 .await?;
79
80 result
81 .as_array()
82 .map(|arr| {
83 arr.iter()
84 .map(|v| v.as_str().unwrap_or("").to_string())
85 .collect()
86 })
87 .ok_or_else(|| LocatorError::EvaluationError("Expected array result".to_string()))
88 }
89
90 pub async fn all_text_contents(&self) -> Result<Vec<String>, LocatorError> {
111 if let Selector::Ref(ref_str) = &self.selector {
113 let backend_node_id = self.page.get_backend_node_id_for_ref(ref_str)?;
114 return self.all_text_contents_by_backend_id(backend_node_id).await;
115 }
116
117 if let Selector::BackendNodeId(backend_node_id) = &self.selector {
119 return self.all_text_contents_by_backend_id(*backend_node_id).await;
120 }
121
122 let selector_expr = self.selector.to_js_expression();
123 let js_code = js! {
124 (function() {
125 const elements = Array.from(@{selector_expr});
126 return elements.map(el => el.textContent || "");
127 })()
128 };
129
130 let result = self.evaluate_js(&js_code).await?;
131
132 result
133 .as_array()
134 .map(|arr| {
135 arr.iter()
136 .map(|v| v.as_str().unwrap_or("").to_string())
137 .collect()
138 })
139 .ok_or_else(|| LocatorError::EvaluationError("Expected array result".to_string()))
140 }
141
142 pub(super) async fn all_text_contents_by_backend_id(
144 &self,
145 backend_node_id: BackendNodeId,
146 ) -> Result<Vec<String>, LocatorError> {
147 let js_fn = js! {
148 (function() {
149 return [this.textContent || ""];
150 })
151 };
152 let js_fn = js_fn.trim_start_matches('(').trim_end_matches(')');
154
155 let result = self
156 .call_function_on_backend_id(backend_node_id, js_fn)
157 .await?;
158
159 result
160 .as_array()
161 .map(|arr| {
162 arr.iter()
163 .map(|v| v.as_str().unwrap_or("").to_string())
164 .collect()
165 })
166 .ok_or_else(|| LocatorError::EvaluationError("Expected array result".to_string()))
167 }
168
169 pub async fn inner_text(&self) -> Result<String, LocatorError> {
177 if let Selector::Ref(ref_str) = &self.selector {
179 let backend_node_id = self.page.get_backend_node_id_for_ref(ref_str)?;
180 return self.inner_text_by_backend_id(backend_node_id).await;
181 }
182
183 if let Selector::BackendNodeId(backend_node_id) = &self.selector {
185 return self.inner_text_by_backend_id(*backend_node_id).await;
186 }
187
188 let selector_expr = self.selector.to_js_expression();
189 let js_code = js! {
190 (function() {
191 const elements = @{selector_expr};
192 if (elements.length === 0) return { found: false };
193 return { found: true, text: elements[0].innerText || "" };
194 })()
195 };
196
197 let result = self.evaluate_js(&js_code).await?;
198
199 let found = result
200 .get("found")
201 .and_then(serde_json::Value::as_bool)
202 .unwrap_or(false);
203 if !found {
204 return Err(LocatorError::NotFound(format!("{:?}", self.selector)));
205 }
206
207 Ok(result
208 .get("text")
209 .and_then(|v| v.as_str())
210 .unwrap_or("")
211 .to_string())
212 }
213
214 pub(super) async fn inner_text_by_backend_id(
216 &self,
217 backend_node_id: BackendNodeId,
218 ) -> Result<String, LocatorError> {
219 let js_fn = js! {
220 (function() {
221 return { text: this.innerText || "" };
222 })
223 };
224 let js_fn = js_fn.trim_start_matches('(').trim_end_matches(')');
226
227 let result = self
228 .call_function_on_backend_id(backend_node_id, js_fn)
229 .await?;
230
231 Ok(result
232 .get("text")
233 .and_then(|v| v.as_str())
234 .unwrap_or("")
235 .to_string())
236 }
237}