lw_webdriver/
elements.rs

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        // check if it is needed to select the tab
28        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
35        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        // TODO watch the bug
82        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}