xcelerate_core/
element.rs1use crate::page::Page;
2use crate::error::XcelerateResult;
3use std::sync::Arc;
4
5#[derive(uniffi::Object)]
7pub struct Element {
8 pub(crate) page: Arc<Page>,
9 pub(crate) object_id: String,
10}
11
12#[uniffi::export(async_runtime = "tokio")]
13impl Element {
14 pub async fn click(self: Arc<Self>) -> XcelerateResult<Arc<Self>> {
16 self.call_js("function() { this.click(); }".to_string()).await?;
17 Ok(self)
18 }
19
20 pub async fn type_text(self: Arc<Self>, text: String) -> XcelerateResult<Arc<Self>> {
21 self.clone().focus().await?;
23
24 for c in text.chars() {
26 let mut params = browser_protocol::input::DispatchKeyEventParams {
27 type_: "char".into(),
28 ..Default::default()
29 };
30 params.text = Some(c.to_string());
31 params.unmodifiedText = Some(c.to_string());
32
33 self.page.client.execute_with_session(
34 Some(&self.page.session_id),
35 params
36 ).await?;
37
38 tokio::time::sleep(std::time::Duration::from_millis(50)).await;
40 }
41
42 Ok(self)
43 }
44
45 pub async fn hover(self: Arc<Self>) -> XcelerateResult<Arc<Self>> {
47 self.call_js("function() { this.dispatchEvent(new MouseEvent('mouseover', { bubbles: true })); }".to_string()).await?;
48 Ok(self)
49 }
50
51 pub async fn focus(self: Arc<Self>) -> XcelerateResult<Arc<Self>> {
53 self.call_js("function() { this.focus(); }".to_string()).await?;
54 Ok(self)
55 }
56
57 pub async fn text(&self) -> XcelerateResult<String> {
59 let res = self.call_js("function() { return this.innerText; }".to_string()).await?;
60 Ok(res.result.value.and_then(|v| v.as_str().map(|s| s.to_string())).unwrap_or_default())
61 }
62
63 pub async fn attribute(&self, name: String) -> XcelerateResult<Option<String>> {
65 let js = format!("function() {{ return this.getAttribute('{}'); }}", name);
66 let res = self.call_js(js).await?;
67 Ok(res.result.value.and_then(|v| v.as_str().map(|s| s.to_string())))
68 }
69
70 pub async fn inner_html(&self) -> XcelerateResult<String> {
72 let res = self.call_js("function() { return this.innerHTML; }".to_string()).await?;
73 Ok(res.result.value.and_then(|v| v.as_str().map(|s| s.to_string())).unwrap_or_default())
74 }
75}
76
77impl Element {
78 async fn call_js(&self, js: String) -> XcelerateResult<js_protocol::runtime::CallFunctionOnReturns> {
80 self.page.client.execute_with_session(
81 Some(&self.page.session_id),
82 js_protocol::runtime::CallFunctionOnParams {
83 functionDeclaration: js,
84 objectId: Some(self.object_id.clone()),
85 ..Default::default()
86 }
87 ).await
88 }
89}