selenium_rs/
element.rs

1/*! 
2
3    Element enables most of the site interaction, and wraps user interactions such as typing text and clicking
4    on things. Note that each element is tied to the specific session (currently, we
5    can't hold on to the same element across sessions).
6
7
8    # Example - Inspecting attributes of an element 
9
10    ```rust 
11        use selenium_rs::webdriver::{Selector, Browser, WebDriver};
12        use selenium_rs::element::Element;
13
14        let mut driver = WebDriver::new(Browser::Chrome);
15        driver.start_session();
16        driver.navigate("http://www.google.com");
17        let search_form =  driver.find_element(Selector::CSS, "#searchform").unwrap();
18
19        assert!(search_form.get_css_value("min-width").unwrap() == "980px");
20    ```
21*/
22
23use element_structs::*;
24use reqwest;
25use utils::construct_url;
26
27/// Element provides an interface from which to inspect and interact with the requested elements
28/// on the page. The general flow involves navigating to your webpage in question, and then
29/// requesting a specific element through the query API, and then using the returned element to
30/// inspect the element on the page
31#[derive(Debug)]
32pub struct Element<'a> {
33    element_id: String,
34    session_id: String,
35    client: &'a reqwest::Client,
36}
37
38impl<'a> Element<'a> {
39    pub fn new(element_id: String, session_id: String, client: &'a reqwest::Client) -> Element<'a> {
40        Element {
41            element_id,
42            session_id,
43            client,
44        }
45    }
46}
47
48// Contains implementation for attribute interaction for the element
49impl<'a> Element<'a> {
50    pub fn is_selected(&self) -> reqwest::Result<bool> {
51        let url = construct_url(vec![
52            "session/",
53            &(self.session_id.clone() + "/"),
54            "element/",
55            &(self.element_id.clone() + "/"),
56            "selected",
57        ]);
58        let response: SelectedResponse = self.client.get(url).send()?.error_for_status()?.json()?;
59        Ok(response.value)
60    }
61
62    /// gets an element attribute for the given element
63    pub fn get_attribute(&self, attribute: &str) -> reqwest::Result<String> {
64        let url = construct_url(vec![
65            "session/",
66            &(self.session_id.clone() + "/"),
67            "element/",
68            &(self.element_id.clone() + "/"),
69            "attribute/",
70            attribute,
71        ]);
72        let result: AttributeResponse = self.client.get(url).send()?.error_for_status()?.json()?;
73
74        Ok(result.value)
75    }
76
77    /// retrieves the property value for the given element, if it exists
78    pub fn get_property(&self, property: &str) -> reqwest::Result<String> {
79        let url = construct_url(vec![
80            "session/",
81            &(self.session_id.clone() + "/"),
82            "element/",
83            &(self.element_id.clone() + "/"),
84            "property/",
85            property,
86        ]);
87        let result: AttributeResponse = self.client.get(url).send()?.error_for_status()?.json()?;
88
89        Ok(result.value)
90    }
91
92    /// Gets a css property for the given element, if it exists
93    pub fn get_css_value(&self, css_property: &str) -> reqwest::Result<String> {
94        let url = construct_url(vec![
95            "session/",
96            &(self.session_id.clone() + "/"),
97            "element/",
98            &(self.element_id.clone() + "/"),
99            "css/",
100            css_property,
101        ]);
102        let result: AttributeResponse = self.client.get(url).send()?.error_for_status()?.json()?;
103
104        Ok(result.value)
105    }
106
107    /// Gets the text for a given element, if it exists or makes sense
108    pub fn get_text(&self) -> reqwest::Result<String> {
109        let url = construct_url(vec![
110            "session/",
111            &(self.session_id.clone() + "/"),
112            "element/",
113            &(self.element_id.clone() + "/"),
114            "text",
115        ]);
116        let result: AttributeResponse = self.client.get(url).send()?.error_for_status()?.json()?;
117
118        Ok(result.value)
119    }
120}
121
122// Implements Element Interactability
123
124impl<'a> Element<'a> {
125    pub fn click(&self) -> reqwest::Result<()> {
126        let url = construct_url(vec![
127            "session/",
128            &(self.session_id.clone() + "/"),
129            "element/",
130            &(self.element_id.clone() + "/"),
131            "click",
132        ]);
133        self.client.post(url).send()?.error_for_status()?;
134        Ok(())
135    }
136
137    /// Clears a content editable element's text value, or returns an error
138    pub fn clear(&self) -> reqwest::Result<()> {
139        let url = construct_url(vec![
140            "session/",
141            &(self.session_id.clone() + "/"),
142            "element/",
143            &(self.element_id.clone() + "/"),
144            "clear",
145        ]);
146        self.client.post(url).send()?.error_for_status()?;
147
148        Ok(())
149    }
150
151    /// Tries to type into a content editable element
152    pub fn type_text(&self, input: &str) -> reqwest::Result<()> {
153        let url = construct_url(vec![
154            "session/",
155            &(self.session_id.clone() + "/"),
156            "element/",
157            &(self.element_id.clone() + "/"),
158            "value",
159        ]);
160
161        println!("{:?}", url);
162
163        let data = ValueRequest::new(input);
164        self.client
165            .post(url)
166            .json(&data)
167            .send()?
168            .error_for_status()?;
169
170        Ok(())
171    }
172}