selenium_webdriver/
element.rs

1use super::reqs::*;
2use std::collections::HashMap;
3use serde::{Serialize,Deserialize};
4
5///WebElement
6/// 
7/// Provides methods to interact with page elements.
8#[derive(Debug)]
9pub struct Element{
10    pub(crate)ip:String,
11    pub(crate)port:String,
12    pub(crate)element_gr_id: String,
13    pub(crate)element_id: String,
14    pub(crate)element_url: String,
15}
16impl Element{
17    ///Returns the first child element which is found using the locator.
18    pub fn find_element_from_self(&self,locator:LocatorStrategy)->Result<Element,String>{
19        let url = format!("{}/element",self.element_url);
20        let body = body_for_find_element(locator);
21        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &url, cont_length_header(&body), &body);
22        if resp.contains("error"){return Err(resp);}
23        let resp = parse_value(&resp);
24        let map: HashMap<String,String> = serde_json::from_str(&resp).unwrap();
25        let res = map.iter().next().unwrap();
26        let el_url = self.element_url.split("/element").next().unwrap();
27        Ok(Element{
28            ip:self.ip.clone(),
29            port:self.port.clone(),
30            element_gr_id:res.0.clone(),
31            element_id:res.1.clone(),
32            element_url: format!("{}/element/{}",el_url,res.1.clone()),
33        })
34    }
35    ///Returns all children elements which are found using the locator.
36    pub fn find_elements_from_self(&self,locator:LocatorStrategy)->Result<Vec<Element>,String>{
37        let mut result = vec![];
38        let url = format!("{}/elements",self.element_url);
39        let body = body_for_find_element(locator);
40        let resp=send_and_read_body(&self.ip,&self.port,Method::POST, &url, cont_length_header(&body), &body);
41        if resp.contains("error"){return Err(resp);}
42        let resp = parse_value(&resp);
43        let map: Vec<HashMap<String,String>> = serde_json::from_str(&resp).unwrap();
44        let element_ur = self.element_url.split("/element").next().unwrap();
45        for i in map{
46            let element_ur = element_ur.clone();
47            let res = i.iter().next().unwrap();
48            result.push(Element{
49            ip:self.ip.clone(),
50            port:self.port.clone(),
51            element_gr_id:res.0.clone(),
52            element_id:res.1.clone(),
53            element_url:format!("{}/element/{}",element_ur,res.1.clone()),
54            });
55        }
56        Ok(result)
57    }
58    pub fn is_selected(&self)->Result<bool,String>{
59        let url = format!("{}/selected",self.element_url) ;
60        let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &url, vec![], "");
61        if resp.contains("error"){return Err(resp);}
62        let map: HashMap<&str,bool> = serde_json::from_str(&resp).unwrap();
63        Ok(*map.get("value").unwrap())
64    }
65    pub fn get_attribute(&self,attribute_name: &str)->Result<String,String>{
66        let url = format!("{}/attribute/{}",self.element_url,attribute_name);
67        let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &url, vec![], "");
68        if resp.contains("error"){return Err(resp);}
69        if resp.as_bytes()==br#"{"value":null}"#{return Ok("null".to_string());}
70        let map:HashMap<&str,String> = serde_json::from_str(&resp).unwrap();
71        Ok((*map.get("value").unwrap()).clone())
72    }
73    ///Due to the large number of structure variants that may be returned by this function,
74    /// parsing the String response to the necessary type is left for the lib users
75    pub fn get_property(&self,property_name:&str)->Result<String,String>{
76        let url = format!("{}/property/{}",self.element_url,property_name);
77        let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &url, vec![], "");
78        if resp.contains("error"){return Err(resp);}
79        if resp.as_bytes()==br#"{"value":null}"#{
80            return Ok(String::from("null"));
81        }else{Ok(resp)}
82
83    }
84    ///The logic behind returning json is the same as for get_property method
85    pub fn get_css_value(&self,css_property_name:&str)->Result<String,String>{
86        let url = format!("{}/css/{}",self.element_url,css_property_name);
87        let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &url, vec![], "");
88        if resp.contains("error"){return Err(resp);}else{Ok(resp)}      
89    }
90    pub fn get_element_text(&self)->Result<String,String>{
91        let url = format!("{}/text",self.element_url);
92        let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &url, vec![], "");
93        if resp.contains("error"){return Err(resp);}
94        let map: HashMap<&str,String> = serde_json::from_str(&resp).unwrap();
95        Ok((*map.get("value").unwrap()).clone())
96    }
97    pub fn get_tag_name(&self)->Result<String,String>{
98        let url = format!("{}/name",self.element_url);
99        let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &url, vec![], "");
100        if resp.contains("error"){return Err(resp);}
101        let map: HashMap<&str,String> = serde_json::from_str(&resp).unwrap();
102        Ok((*map.get("value").unwrap()).clone())
103    }
104    ///Returns the element's size(hight,width) and position(x-axis and y-axis)
105    pub fn get_element_rect(&self)->Result<ElementRect,String>{
106        let url = format!("{}/rect",self.element_url);
107        let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &url, vec![], "");
108        if resp.contains("error"){return Err(resp);}
109        let map: HashMap<&str,ElementRect> = serde_json::from_str(&resp).unwrap();
110        Ok((*map.get("value").unwrap()).clone())
111    }
112    pub fn is_enabled(&self)->Result<bool,String>{
113        let url = format!("{}/enabled",self.element_url);
114        let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &url, vec![], "");
115        if resp.contains("error"){return Err(resp);}
116        let map: HashMap<&str,bool> = serde_json::from_str(&resp).unwrap();
117        Ok(*map.get("value").unwrap())
118    }
119    ///As of 06.11.2020 computed role and computed label are not implemented
120    /// by chrome and geckodrivers, so this method will only be returning errors for now
121    pub fn get_computed_role(&self)->Result<String,String>{
122        let url = format!("{}/computedrole",self.element_url);
123        let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &url, vec![], "");
124        if resp.contains("error"){return Err(resp);}
125        let map: HashMap<&str,String> = serde_json::from_str(&resp).unwrap();
126        Ok((*map.get("value").unwrap()).clone())
127    }
128    ///See above
129    pub fn get_computed_label(&self)->Result<String,String>{
130        let url = format!("{}/computedlabel",self.element_url);
131        let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &url, vec![], "");
132        if resp.contains("error"){return Err(resp);}
133        let map: HashMap<&str,String> = serde_json::from_str(&resp).unwrap();
134        Ok((*map.get("value").unwrap()).clone())
135    }
136    pub fn click(&self)->Result<(),String>{
137        let body = r#"{}"#;
138        let url = format!("{}/click",self.element_url);
139        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &url, cont_length_header(&body), &body);
140        if resp.contains("error"){return Err(resp);}
141        Ok(())
142
143    }
144    ///Clears any element text
145    pub fn clear_element(&self)->Result<(),String>{
146        let body = r#"{}"#;
147        let url = format!("{}/clear",self.element_url);
148        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &url, cont_length_header(&body), &body);
149        if resp.contains("error"){return Err(resp);}
150        Ok(())
151    }
152    ///Sends the text to the element if it is possibe for the element, otherwise, returns error
153    /// # Examples
154    /// ```
155    /// # use selenium_webdriver::*;
156    /// let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
157    /// br.open("https://vk.com").unwrap();
158    /// let el= br.find_element(LocatorStrategy::CSS("#ts_input")).unwrap();
159    /// el.send_keys("Sup!").unwrap();
160    /// br.close_browser().unwrap();
161    /// ```
162    pub fn send_keys(&self,message:&str)->Result<(),String>{
163        let body = format!(r#"{{"text":"{}"}}"#,message);
164        let url = format!("{}/value",self.element_url);
165        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &url, cont_length_header(&body), &body);
166        if resp.contains("error"){return Err(resp);}
167        Ok(())
168
169    }
170}
171///Encapsulates WebElement's hight,width and left-upper corner x-axis and y-axis coordinates
172#[derive(Deserialize,Serialize,Clone,Debug)]
173pub struct ElementRect{
174    pub(crate)height:i32,
175    pub(crate)width:i32,
176    pub(crate)x:f32,
177    pub(crate)y:f32,
178}