use crate::service::Service;
use crate::{raise, error};
use crate::rect::Rect;
use crate::result::{PebblesError,PebblesErrorDetails};
use std::rc::Rc;
use serde_json::{Value, json};
use serde::{ser::SerializeStruct, Serializer};
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 selected(&self) -> Result<bool, PebblesError> {
let json = self.service.get(&format!("/element/{}/selected", self.id))?
.json::<Value>()?;
let value = match json.get("value") {
Some(value) => value,
None => raise!(PebblesError::PhrasingError, "Invalid value for \"selected\" from webdriver."),
};
match value.as_bool() {
Some(value) => Ok(value),
None => raise!(PebblesError::PhrasingError, "Invalid value for \"selected\" from webdriver."),
}
}
pub fn rect(&self) -> Result<Rect, PebblesError> {
fn get_value_as_i64(json_value: &Value, key: &str) -> Result<i64, PebblesError> {
Ok(json_value.get(key)
.ok_or_else(|| error!(PebblesError::PhrasingError, "Invalid Rect values from webdriver.", json_value.clone()))?
.as_f64()
.ok_or_else(|| error!(PebblesError::PhrasingError, "Invalid Rect values from webdriver.", json_value.clone()))? as i64
)
}
let json_rect: Value = self.service
.get(&format!("/element/{}/rect", self.id))?
.json::<Value>()?
.get("value")
.ok_or_else(|| error!(PebblesError::PhrasingError, "Invalid Rect values from webdriver."))?
.clone();
Ok(Rect {
x: get_value_as_i64(&json_rect, "x")?,
y: get_value_as_i64(&json_rect, "y")?,
width: get_value_as_i64(&json_rect, "width")?,
height: get_value_as_i64(&json_rect, "height")?,
})
}
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())
}
}
use std::cmp::{ Ord, PartialOrd };
impl Ord for WebElement {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match self.rect() {
Ok(self_rect) => match other.rect() {
Ok(other_rect) => self_rect.y.cmp(&other_rect.y),
Err(_) => std::cmp::Ordering::Less,
},
Err(_) => std::cmp::Ordering::Greater,
}
}
}
impl PartialEq for WebElement {
fn eq(&self, other: &Self) -> bool {
match self.rect() {
Ok(self_rect) => match other.rect() {
Ok(other_rect) => self_rect.y == other_rect.y,
Err(_) => false,
},
Err(_) => false,
}
}
}
impl Eq for WebElement {}
impl PartialOrd for WebElement {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
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()
}
}