use crate::service::Service;
use crate::result::{PebblesError,PebblesErrorDetails};
use std::rc::Rc;
use serde_json::{Value, json};
use serde::{ser::SerializeStruct, Serializer};
use rand_distr::{Triangular, Distribution};
#[derive(Debug)]
pub struct Rect {
pub x:i64,
pub y:i64,
pub width:i64,
pub height:i64,
}
pub struct WebElement {
service: Rc<Service>,
id:String,
}
impl WebElement {
pub fn new(service: Rc<Service>, id:&str) -> Self {
WebElement {
service,
id:id.to_string(),
}
}
pub fn rect(&self) -> Result<Rect, PebblesError> {
let json_rect: Value = self.service
.get(&format!("/element/{}/rect", self.id))?
.json::<Value>()?
["value"].clone();
Ok(Rect {
x: match json_rect["x"].as_f64() {
Some(value) => value as i64,
None => {
return Err(PebblesError::PhrasingError(PebblesErrorDetails::new(
"Invalid Rect values from webdriver.",
)))
}
},
y: match json_rect["y"].as_f64() {
Some(value) => value as i64,
None => {
return Err(PebblesError::PhrasingError(PebblesErrorDetails::new(
"Invalid Rect values from webdriver.",
)))
}
},
width: match json_rect["width"].as_f64() {
Some(value) => value as i64,
None => {
return Err(PebblesError::PhrasingError(PebblesErrorDetails::new(
"Invalid Rect values from webdriver.",
)))
}
},
height: match json_rect["height"].as_f64() {
Some(value) => value as i64,
None => {
return Err(PebblesError::PhrasingError(PebblesErrorDetails::new(
"Invalid Rect values from webdriver.",
)))
}
},
})
}
pub fn point(&self) -> Result<(i64, i64), PebblesError> {
let mut rng = rand::thread_rng();
let rect = self.rect()?;
let triangular_x = Triangular::new(0.0, rect.width as f64, rect.width as f64 / 2.0)
.map_err(|_| PebblesError::PhrasingError(
PebblesErrorDetails::new("Invalid Rect values from webdriver.")
))?;
let triangular_y = Triangular::new(0.0, rect.height as f64, rect.height as f64 / 2.0)
.map_err(|_| PebblesError::PhrasingError(
PebblesErrorDetails::new("Invalid Rect values from webdriver.")
))?;
Ok((triangular_x.sample(&mut rng) as i64, triangular_y.sample(&mut rng) as i64))
}
pub fn attribute(&self, name:&str) -> Result<Value, PebblesError> {
let java_script: &'static str = include_str!("attribute.js");
Ok(self
.service
.post(
"/execute/sync",
&json!({"script": format!("/* getAttribute */return ({}).apply(null, arguments);", java_script).as_str(), "args": [self, name]}),
)?
.json::<Value>()?["value"]
.clone())
}
}
impl std::fmt::Display for WebElement {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.id)
}
}
impl serde::Serialize for WebElement {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut state = serializer.serialize_struct("WebElement", 1)?;
state.serialize_field("element-6066-11e4-a52e-4f735466cecf", &self.id)?;
state.end()
}
}