use fantoccini::elements::Element;
use std::error::Error;
use serde_json::json;
use crate::session::session::BrowserSession;
pub struct WebElement
{
pub element:Element,
}
impl WebElement
{
pub async fn click(&self)->Result<(),Box<dyn Error>>
{
self.element.click().await?;
Ok(())
}
pub async fn type_text(&self, text: &str) -> Result<(), Box<dyn Error>> {
self.element.send_keys(text).await?;
Ok(())
}
pub async fn get_text(&self) -> Result<String, Box<dyn Error>> {
let text = self.element.text().await?;
Ok(text)
}
pub async fn get_attribute(&self, attr: &str) -> Result<Option<String>, Box<dyn Error>> {
let value = self.element.attr(attr).await?;
Ok(value)
}
pub async fn wait_for(&self, timeout: u64) -> Result<(), Box<dyn Error>> {
let mut elapsed = 0;
while elapsed < timeout {
match self.element.attr("id").await {
Ok(Some(_)) => return Ok(()),
_ => {
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
elapsed += 1;
}
}
}
Err("Element not found within the timeout period".into())
}
pub async fn is_visible(&self) -> Result<bool, Box<dyn Error>> {
Ok(self.element.is_displayed().await?)
}
pub async fn is_enabled(&self) -> Result<bool, Box<dyn Error>> {
Ok(self.element.is_enabled().await?)
}
pub async fn clear(&self) -> Result<(), Box<dyn Error>> {
self.element.clear().await?;
Ok(())
}
pub async fn send_keys(&self, keys: &str) -> Result<(), Box<dyn Error>> {
self.element.send_keys(keys).await?;
Ok(())
}
pub async fn scroll_into_view(&self) -> Result<(), Box<dyn Error>> {
let element_ref = self.element.element_id().clone();
self.element.clone()
.client()
.execute(
"arguments[0].scrollIntoView({ behavior: 'smooth', block: 'center' });",
vec![json!(*element_ref)],
)
.await?;
Ok(())
}
pub async fn is_displayed(&self) -> Result<bool, Box<dyn Error>> {
let element_ref = self.element.element_id().to_string(); let client = self.element.clone().client(); let result = client
.execute(
"return arguments[0].offsetWidth > 0 && arguments[0].offsetHeight > 0;",
vec![json!(element_ref)],
)
.await?;
if let Some(is_visible) = result.as_bool() {
Ok(is_visible)
} else {
Ok(false) }
}
}
#[cfg(test)]
mod tests {
use super::*;
use tokio;
#[tokio::test]
async fn test_linkedin_login() {
let mut session = BrowserSession::new("https://www.linkedin.com/login").await.unwrap();
let username_field = session.find_element("input#username").await.unwrap();
username_field.type_text("harshapalnati@gmail.com").await.unwrap();
let password_field = session.find_element("input#password").await.unwrap();
password_field.type_text("Harsha@0811").await.unwrap();
let sign_in_button = session.find_element("button.btn__primary--large").await.unwrap();
sign_in_button.click().await.unwrap();
session.close().await.unwrap();
}
}