1use crate::tab::*;
2use crate::error::*;
3use crate::enums::{Selector, WebdriverObject};
4use json::*;
5use std::result::Result;
6use log::{debug, info, warn, error};
7use std::rc::Rc;
8use crate::http_requests::{execute_script_sync, click_on_element, get_element_text, send_text_to_element, get_selected_tab, select_tab,
9 get_element_attribute, get_element_css_value, get_element_property, get_element_tag_name, is_element_enabled, get_element_rect};
10
11pub struct Element {
12 id: String,
13 session_id: Rc<String>,
14 tab_id: Rc<String>
15}
16
17impl Element {
18 pub fn new(id: String, session_id: Rc<String>, tab_id: Rc<String>) -> Self {
19 Element{
20 id,
21 session_id,
22 tab_id
23 }
24 }
25
26 fn select_tab(&self) -> Result<(), WebdriverError> {
27 if let Ok(id) = get_selected_tab(&self.session_id) {
29 if id == *self.tab_id {
30 return Ok(());
31 }
32 }
33
34 select_tab(&self.session_id, &self.tab_id)
36 }
37
38 pub fn type_text(&mut self, text: &str) -> Result<(), WebdriverError> {
39 self.select_tab()?;
40 send_text_to_element(&self.session_id, &self.id, text)
41 }
42
43 pub fn get_text(&self) -> Result<String, WebdriverError> {
44 self.select_tab()?;
45 get_element_text(&self.session_id, &self.id)
46 }
47
48 pub fn get_attribute(&self, attribute_name: &str) -> Result<String, WebdriverError> {
49 self.select_tab()?;
50 get_element_attribute(&self.session_id, &self.id, attribute_name)
51 }
52
53 pub fn get_tag_name(&self) -> Result<String, WebdriverError> {
54 self.select_tab()?;
55 get_element_tag_name(&self.session_id, &self.id)
56 }
57
58 pub fn get_css_value(&self, property_name: &str) -> Result<String, WebdriverError> {
59 self.select_tab()?;
60 get_element_css_value(&self.session_id, &self.id, property_name)
61 }
62
63 pub fn get_property(&self, property_name: &str) -> Result<String, WebdriverError> {
64 self.select_tab()?;
65 get_element_property(&self.session_id, &self.id, property_name)
66 }
67
68 pub fn get_rect(&self) -> Result<((usize, usize), (usize, usize)), WebdriverError> {
69 self.select_tab()?;
70 get_element_rect(&self.session_id, &self.id)
71 }
72
73 pub fn is_enabled(&self) -> Result<bool, WebdriverError> {
74 self.select_tab()?;
75 is_element_enabled(&self.session_id, &self.id)
76 }
77
78 pub fn click(&mut self) -> Result<(), WebdriverError> {
79 self.select_tab()?;
80
81 warn!("Using javascript click because of a bug in geckodriver where and error hapen but is not reported to us.");
83 if let Ok(()) = execute_script_sync(&self.session_id, "arguments[0].click();", vec![self.as_json_object()]) {
84 return Ok(());
85 } else {
86 error!("Failed to click with javascript. Using normal method.");
87 }
88
89 match click_on_element(&self.session_id, &self.id) {
90 Ok(()) => {
91 Ok(())
92 }
93 Err(error) if error == WebdriverError::ElementNotInteractable || error == WebdriverError::ElementClickIntercepted => {
94 Ok(())
95 },
96 Err(error) => {
97 return Err(error)
98 }
99 }
100 }
101
102 pub fn as_json_object(&self) -> JsonValue {
103 object!{ "element-6066-11e4-a52e-4f735466cecf" => self.id.as_str() }
104 }
105
106 pub fn scroll_into_view(&self) -> Result<(), WebdriverError> {
107 execute_script_sync(&self.session_id, "arguments[0].scrollIntoView();", vec![self.as_json_object()])
108 }
109}
110
111impl PartialEq for Element {
112 fn eq(&self, other: &Self) -> bool {
113 self.get_id() == other.get_id()
114 }
115}
116
117impl WebdriverObject for Element {
118 fn get_id(&self) -> &String {
119 &self.id
120 }
121}