selenium_webdriver/
browser.rs

1extern crate base64;
2
3use serde::{Serialize,Deserialize};
4use super::reqs::*;
5use std::collections::HashMap;
6use self::utils::*;
7use super::element::*;
8use super::actions::*;
9use super::specialkey::*;
10use super::chromeoptions::*;
11use super::firefoxoptions::*;
12use super::safarioptions::*;
13use super::capabilities::*;
14
15#[derive(Serialize,Deserialize)]
16struct Value{
17     value: Session,
18    
19}
20#[allow(non_snake_case)]
21#[derive(Serialize,Deserialize)]
22struct Session{
23    sessionId: String,
24}
25
26pub enum BrowserName{
27    Chrome,
28    Firefox,
29    Safari
30}
31/// Main crate struct
32/// 
33/// Contains methods for manipulating the browser session, internally making requests to the selenium server.
34/// All methods that create local sessions imply that the selenium server is running on port 4444
35#[derive(Debug)]
36pub struct Browser{
37    ip: String,
38    port:String,
39    session_url: String, //The session/ url for constructing other urls
40    go_to_url: String, //The url to a website of the test
41    timeouts_url: String,
42    back_url: String,
43    forward_url: String,
44    refresh_url:String,
45    title_url:String,
46    window_url:String,
47    window_handles_url:String,
48    window_new_url:String,
49    window_rect_url:String,
50    frame_url:String,
51    frame_parent_url:String,
52    window_maximize_url:String,
53    window_minimize_url:String,
54    window_fullscreen_url:String,
55    element_url:String,
56    element_active_url:String,
57    elements_url:String,
58    source_url:String,
59    execute_sync_url:String,
60    execute_async_url:String,
61    cookie_url:String,
62    actions_url:String,
63    alert_dismiss_url:String,
64    alert_accept_url:String,
65    alert_text_url:String,
66    screenshot_url:String,
67    print_page_url:String,
68}
69
70impl Browser{
71    /// Method to construct the Browser instance with basic session. Supports args for Chrome,
72    /// while for Firefox and Safari they will be ignored. To customize the Chrome and Firefox sessions pls use the corresponding
73    /// method start_..._session_with_options().
74    ///  
75    /// # Examples
76    /// ```
77    /// # use selenium_webdriver::*;
78    /// let mut browser = Browser::start_session(BrowserName::Chrome,vec!["--headless"]);
79    /// browser.close_browser();
80    /// ```
81    pub fn start_session(browser: BrowserName, args:Vec<&str>)->Browser{
82        let req_body = create_session_body_json(browser,args);
83        let response = send_request("127.0.0.1","4444",Method::POST, "wd/hub/session", cont_length_header(&req_body), &req_body).unwrap();
84        let resp_body = resp_body(response).unwrap();
85        let val: Value = serde_json::from_str(&resp_body).unwrap();
86        let sess_id = val.value.sessionId;
87        generate_browser_links("127.0.0.1","4444",&sess_id)
88    }
89    ///Allows to create a customized session with various capabilities. For details please check the docs for the Capabilities struct and its methods.
90    /// 
91    /// # Examples
92    /// ```
93    /// # use selenium_webdriver::*;
94    /// 
95    /// let mut ch_op = ChromeOptions::new();
96    /// ch_op.add_args(vec!["--headless","--window-size=500,1000"]);
97    /// ch_op.add_mobile_emulation(MobileDevice::standard_device("Nexus 6"));
98    /// 
99    /// let mut c = Capabilities::new(BrowserName::Chrome, "windows");
100    /// c.set_chrome_options(ch_op);
101    /// 
102    /// let mut br = Browser::start_session_with_capabilities(c).unwrap();
103    /// br.open("https://vk.com").unwrap();
104    /// br.take_screenshot("vk.png").unwrap();
105    /// br.close_browser().unwrap();
106    /// let res = std::fs::read("vk.png");
107    /// assert!(res.is_ok());
108    /// std::fs::remove_file("vk.png").unwrap();
109    /// ```
110    pub fn start_session_with_capabilities(capabilities: Capabilities)->Result<Browser,String>{
111        let body = capabilities.cap_string;
112        let response = send_request("127.0.0.1","4444",Method::POST, "wd/hub/session", cont_length_header(&body), &body).unwrap();
113        let resp_body = resp_body(response).unwrap();
114        let val: Value = serde_json::from_str(&resp_body).unwrap();
115        let sess_id = val.value.sessionId;
116        Ok(generate_browser_links("127.0.0.1","4444",&sess_id))
117    }
118    ///Does the same thing as the start_session_with_capabilities(),but for the remote session.
119    pub fn start_remote_session_with_capabilities(capabilities: Capabilities,ip:&str,port:&str)->Result<Browser,String>{
120        let body =capabilities.cap_string;
121        let response = send_request(ip,port,Method::POST, "wd/hub/session", cont_length_header(&body), &body).unwrap();
122        let resp_body = resp_body(response).unwrap();
123        let val: Value = serde_json::from_str(&resp_body).unwrap();
124        let sess_id = val.value.sessionId;
125        Ok(generate_browser_links(ip,port,&sess_id))
126    }    
127    ///Method to construct the Browser instance with basic remote session. Also intended to add chrome/firefox/safari options to the remote sessions.
128    pub fn start_remote_session(browser: BrowserName,platform:&str,ip:&str,port:&str)->Result<Browser,String>{
129        let browser = match browser{
130            BrowserName::Chrome=>"chrome",
131            BrowserName::Firefox=>"firefox",
132            BrowserName::Safari=>"safari",
133        };
134        let req_body = format!(r#"{{
135            "capabilities": {{
136                "alwaysMatch": {{
137                    "platformName": "{}"
138                }},
139                "firstMatch": [
140                    {{"browserName": "{}"}}
141                ]
142            }}
143        }}
144        "#,platform,browser);
145        let response = send_request(ip,port,Method::POST, "wd/hub/session", cont_length_header(&req_body), &req_body).unwrap();
146        let resp_body = resp_body(response).unwrap();
147        let val: Value = serde_json::from_str(&resp_body).unwrap();
148        let sess_id = val.value.sessionId;
149        Ok(generate_browser_links(ip,port,&sess_id))
150    }
151    ///Method to start the session customized with ChromeOptions
152    /// 
153    /// # Examples
154    /// ```
155    /// # use selenium_webdriver::*;
156    /// let mut ch = ChromeOptions::new();
157    /// let mob = MobileDevice::standard_device("Nexus 6");
158    /// ch.add_args(vec!["--headless","--window-size=400,600"]);
159    /// ch.add_mobile_emulation(mob);
160    /// let mut br = Browser::start_chrome_session_with_options(ch).unwrap();
161    /// let res = br.open("https://vk.com");
162    /// let res2 = br.close_browser();
163    /// assert!(res.is_ok()&&res2.is_ok());
164    /// 
165    /// ```
166    pub fn start_chrome_session_with_options(options:ChromeOptions)->Result<Browser,String>{
167        let body = create_json_body_for_session_with_chrome_options(options);
168        let resp = send_and_read_body ("127.0.0.1","4444",Method::POST, "wd/hub/session", cont_length_header(&body), &body);
169        if resp.contains("error"){return Err(resp);}
170        let val: Value = serde_json::from_str(&resp).unwrap();
171        let sess_id = val.value.sessionId;
172        Ok(generate_browser_links("127.0.0.1","4444",&sess_id))
173    }
174    /// Method to start the Firefox session adjusted with FirefoxOptions
175    /// Works similar to the ChromeOptions. For more info please check the FirefoxOptions docs.
176    pub fn start_firefox_session_with_options(options:FirefoxOptions)->Result<Browser,String>{
177        let body = create_json_body_for_session_with_firefox_options(options);
178        let resp = send_and_read_body ("127.0.0.1","4444",Method::POST, "wd/hub/session", cont_length_header(&body), &body);
179        if resp.contains("error"){return Err(resp);}
180        let val: Value = serde_json::from_str(&resp).unwrap();
181        let sess_id = val.value.sessionId;
182        Ok(generate_browser_links("127.0.0.1","4444",&sess_id))
183    }
184    /// Method to start the Safari with settings.
185    /// Works similar to the ChromeOptions and FFOptions. For more info please check the SafariOptions docs.
186    pub fn start_safari_session_with_options(options:SafariOptions)->Result<Browser,String>{
187        let body = create_json_body_for_session_with_safari_options(options);
188        let resp = send_and_read_body("127.0.0.1","4444",Method::POST, "wd/hub/session", cont_length_header(&body), &body);
189        if resp.contains("error"){return Err(resp);}
190        let val: Value = serde_json::from_str(&resp).unwrap();
191        let sess_id = val.value.sessionId;
192        Ok(generate_browser_links("127.0.0.1","4444",&sess_id))
193    }
194    ///Open a webpage or a local file
195    pub fn open(&self,uri:&str)->Result<(),String>{
196        let body = format!(r#"{{"url":"{}"}}"#,uri);
197        let resp = send_request(&self.ip,&self.port,Method::POST, &self.go_to_url, cont_length_header(&body), &body).unwrap();
198        if resp.contains("error"){return Err(resp);}
199        Ok(())
200    }
201    ///Get the url of the current page.
202    pub fn get_link(&self)->Result<String,String>{
203        let resp = resp_body(send_request(&self.ip,&self.port,Method::GET, &self.go_to_url, vec![], "").unwrap()).unwrap();
204        if resp.contains("error"){return Err(resp);}
205        Ok(parse_value(&resp).replace("\"",""))
206    }
207    ///Deletes current session. As the Browser struct needs dropping, 
208    ///it is better to call drop() after this method in long-multibrowser scenarios.  
209    pub fn close_browser(&mut self)->Result<(),String>{
210        let resp = send_request(&self.ip,&self.port,Method::DELETE, &self.session_url, vec![], "").unwrap();
211        if resp.contains("error"){return Err(resp);}
212        self.session_url = String::from("");
213        Ok(())
214    }
215    ///Returns the session timouts data
216    pub fn get_timeouts(&self)->Result<Timeouts,String>{
217        let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &self.timeouts_url, vec![], "");
218        if resp.contains("error"){return Err(resp);}
219        Ok(serde_json::from_str(&parse_value(&resp)).unwrap())
220    }
221    ///Change the session timouts data
222    pub fn set_timeouts(&self, timeouts: &Timeouts)->Result<(),&str>{
223        let timeouts_json = serde_json::to_string(timeouts).unwrap();
224        if let Ok(mess)= send_request(&self.ip,&self.port,Method::POST, &self.timeouts_url, cont_length_header(&timeouts_json), &timeouts_json){
225            if let Ok (body) = resp_body(mess){
226                if body.as_str() == r#"{"value":null}"#{
227                    return Ok(())
228                }
229            }
230        }
231        Err("The timeouts were not set correctly")
232    }
233    ///Return to the previous page
234    pub fn back(&self)->Result<(),String>{
235        let body = r#"{"return":true}"#;
236        let resp = send_request(&self.ip,&self.port,Method::POST,&self.back_url, cont_length_header(&body), &body).unwrap();
237        if resp.contains("error"){return Err(resp);}
238        Ok(())
239    }
240    pub fn forward(&self)->Result<(),String>{
241        let body = r#"{"forward":true}"#;
242        let resp = send_request(&self.ip,&self.port,Method::POST,&self.forward_url, cont_length_header(&body), &body).unwrap();
243        if resp.contains("error"){return Err(resp);}
244        Ok(())
245    }
246    pub fn refresh(&self)->Result<(),&str>{
247        let body = r#"{"refresh":true}"#;
248        if let Ok (mess) = send_request(&self.ip,&self.port,Method::POST,&self.refresh_url, cont_length_header(&body), &body){
249            if let Ok (body) = resp_body(mess){
250                if body.as_str()!=r#"{"value":null}"#{
251                   return Err("The refresh did not succeed")
252                }
253            }
254        }
255        Ok(())
256    }
257    ///Returns the title of the current tab
258    pub fn get_title(&self)->Result<String,String>{
259        let json = resp_body(send_request(&self.ip,&self.port,Method::GET, &self.title_url, vec![], "").unwrap()).unwrap();
260        if json.contains("error"){return Err(json);}    
261        Ok(parse_value(&json).replace("\"",""))
262    }
263    ///Returns the handle of the current window, which later may be used to switch to this window.
264    pub fn get_window_handle(&self)->Result<String,String>{
265        let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &self.window_url, vec![], "");
266        if resp.contains("error"){return Err(resp);}
267        Ok(parse_value(&resp).replace("\"",""))
268    }
269    ///Returns the handles of all open windows and tabs
270    pub fn get_window_handles(&self)->Result<Vec<String>,String>{
271       let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &self.window_handles_url, vec![], "");
272       if resp.contains("error"){return Err(resp);}
273       let resp = parse_value(&resp);
274       let res:Vec<String> = serde_json::from_str(&resp).unwrap();
275       Ok(res)
276    }
277    ///Switches to the window with the passed id
278    pub fn switch_to_window(&self, window_id: String)->Result<(),String>{
279        let body = format!(r#"{{"handle":"{}"}}"#,window_id);
280        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &self.window_url, cont_length_header(&body), &body);
281        if resp.as_str()==r#"{"value":null}"#{
282            Ok(())
283        }else{Err(resp)}
284    }
285    ///Opens a new window or a new tab depending on the window_type
286    pub fn new_window(&self, window_type: NewWindowType)->Result<(String,String),String>{
287        let body = match window_type{
288            NewWindowType::Tab=>r#"{"type":"tab"}"#,
289            NewWindowType::Window=>r#"{"type":"window"}"#,
290        };
291        let resp=send_and_read_body(&self.ip,&self.port,Method::POST, &self.window_new_url, cont_length_header(&body), &body);
292        if resp.contains("error"){return Err(resp);}
293        let resp = parse_value(&resp);
294        let map: HashMap<&str,String> = serde_json::from_str(&resp).unwrap();
295        let handle = map.get("handle").unwrap().clone();
296        let wtype = map.get("type").unwrap().clone();
297        Ok((handle,wtype))
298    }
299    ///Closes the window and returns the vector of the remaining window handles
300    pub fn close_window(&self)->Result<Vec<String>,String>{
301       let resp = send_and_read_body(&self.ip,&self.port,Method::DELETE, &self.window_url, vec![], "");
302       if resp.contains("error"){return Err(resp);}
303       let resp = parse_value(&resp);
304       let res:Vec<String> = serde_json::from_str(&resp).unwrap();
305       Ok(res)
306    }
307    ///Switches to the frame with a given id. For instance, if there are 4 frames and you wish to switch to the second one,
308    /// you should call this method like this - switch_to_frame_by_id(1).
309    pub fn switch_to_frame_by_id(&self, id: u64)->Result<(),String>{
310        let body = format!(r#"{{"id":{}}}"#,id);
311        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &self.frame_url, cont_length_header(&body), &body);
312        if resp.as_str()!=r#"{"value":null}"#{
313            return Err(resp);
314        }
315        Ok(())
316    }
317    pub fn switch_to_frame_by_element(&self, element:Element)->Result<(),String>{
318        let body = format!(r#"{{"id":{{"{}":"{}"}}}}"#,element.element_gr_id,element.element_id);
319        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &self.frame_url, cont_length_header(&body), &body);
320        if resp.as_str()!=r#"{"value":null}"#{
321            return Err(resp);
322        }
323        Ok(())
324
325    }
326    pub fn switch_to_parent_frame(&self)->Result<(),String>{
327        let body = r#"{}"#;
328        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &self.frame_parent_url, cont_length_header(&body), &body);
329        if resp.as_str()!=r#"{"value":null}"#{
330            return Err(resp);
331        }
332        Ok(())
333    }
334    pub fn get_active_element(&self)->Result<Element,String>{
335        let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &self.element_active_url, vec![], "");
336        if resp.contains("error"){return Err(resp);}
337        let resp = parse_value(&resp);
338        let map: HashMap<String,String> = serde_json::from_str(&resp).unwrap();
339        let res = map.iter().next().unwrap();
340        Ok(Element{
341            ip:self.ip.clone(),
342            port: self.port.clone(),
343            element_gr_id:res.0.clone(),
344            element_id:res.1.clone(),
345            element_url: format!("{}/element/{}",self.session_url,res.1.clone()),
346        })
347    }
348    ///If the locator matches several elements, it returns the first one
349    /// 
350    /// # Examples
351    /// ```
352    /// # use selenium_webdriver::*;
353    /// 
354    ///let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
355    ///br.open("https://vk.com").unwrap();
356    ///let el = br.find_element(LocatorStrategy::CSS("#ts_input")).unwrap();
357    ///let res = el.click(); 
358    ///br.close_browser().unwrap();
359    ///assert!(res.is_ok()); 
360    /// ```
361    pub fn find_element(&self,loc_strategy:LocatorStrategy)->Result<Element,String>{
362        let body = body_for_find_element(loc_strategy);
363        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &self.element_url, cont_length_header(&body), &body);
364        if resp.contains("error"){return Err(resp);}
365        let resp = parse_value(&resp);
366        let map: HashMap<String,String> = serde_json::from_str(&resp).unwrap();
367        let res = map.iter().next().unwrap();
368        Ok(Element{
369            ip:self.ip.clone(),
370            port: self.port.clone(),
371            element_gr_id:res.0.clone(),
372            element_id:res.1.clone(),
373            element_url: format!("{}/element/{}",self.session_url,res.1.clone()),
374        })
375    }
376    pub fn find_elements(&self,loc_strategy:LocatorStrategy)->Result<Vec<Element>,String>{
377        let mut result = vec![];
378        let body = body_for_find_element(loc_strategy);
379        let resp=send_and_read_body(&self.ip,&self.port,Method::POST, &self.elements_url, cont_length_header(&body), &body);
380        if resp.contains("error"){return Err(resp);}
381        let resp = parse_value(&resp);
382        let map: Vec<HashMap<String,String>> = serde_json::from_str(&resp).unwrap();
383        let element_ur = format!("{}/element",self.session_url);
384        for i in map{
385            let element_ur = element_ur.clone();
386            let res = i.iter().next().unwrap();
387            result.push(Element{
388                ip:self.ip.clone(),
389                port: self.port.clone(),
390            element_gr_id:res.0.clone(),
391            element_id:res.1.clone(),
392            element_url:format!("{}/{}",element_ur,res.1.clone()),
393            });
394        }
395        Ok(result)
396    }
397    ///Returns the WindowRect instance which contains the information about the position and size of the current window
398    pub fn get_window_rect(&self)->Result<WindowRect,String>{
399        let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &self.window_rect_url, vec![], "");
400        if resp.contains("error"){return Err(resp);}
401        let map:HashMap<&str,WindowRect> = serde_json::from_str(&resp).unwrap();
402        Ok(map.get("value").unwrap().clone())
403    }
404    ///Allow to resize the window and change it's position
405    pub fn set_sindow_rect(&self, window_rect:&WindowRect)->Result<WindowRect,String>{
406        let body = serde_json::to_string(window_rect).unwrap();
407        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &self.window_rect_url, cont_length_header(&body), &body);
408        let resp = parse_value(&resp);
409        let map:Result<WindowRect,serde_json::Error> = serde_json::from_str(&resp);
410        match map{
411            Ok(cont)=>{
412                Ok(cont)
413            },
414            Err(message)=>Err(message.to_string()),
415        }
416                
417    }
418    pub fn maximize_window(&self)->Result<WindowRect,String>{
419        let body = r#"{}"#;
420        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &self.window_maximize_url, cont_length_header(&body), &body);
421        let resp = parse_value(&resp);
422        if resp.contains("height")&&resp.contains("width"){
423            let res: WindowRect = serde_json::from_str(&resp).unwrap();
424            Ok(res)
425        }else{Err(resp)}
426
427    }
428    pub fn minimize_window(&self)->Result<WindowRect,String>{
429        let body = r#"{}"#;
430        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &self.window_minimize_url, cont_length_header(&body), &body);
431        let resp = parse_value(&resp);
432        if resp.contains("height")&&resp.contains("width"){
433            let res: WindowRect = serde_json::from_str(&resp).unwrap();
434            Ok(res)
435        }else{Err(resp)}
436    }
437    pub fn fullscreen(&self)->Result<WindowRect,String>{
438        let body = r#"{}"#;
439        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &self.window_fullscreen_url, cont_length_header(&body), &body);
440        let resp = parse_value(&resp);
441        if resp.contains("height"){
442            Ok(serde_json::from_str(&resp).unwrap())
443        } else {Err(resp)}
444    }
445    ///Returns the page source code
446    pub fn source(&self)->Result<String,String>{
447        let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &self.source_url, vec![], "");
448        if resp.contains("error"){return Err(resp);}
449        let map:HashMap<&str,String> = serde_json::from_str(&resp).unwrap();
450        Ok(map.get("value").unwrap().clone())
451    }
452    ///Return the vector with all the cookies that the browser is holding at the moment
453    pub fn get_all_cookies(&self)->Result<Vec<Cookie>,String>{
454        let mut result: Vec<Cookie> = vec![];
455        let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &self.cookie_url, vec![], "");
456        if resp.contains("error"){return Err(resp);}
457        let map:HashMap<&str,Vec<serde_json::Value>> = serde_json::from_str(&resp).unwrap();
458        for v in map.get("value").unwrap(){
459            result.push(from_value_to_cookie(v));
460        }  
461        Ok(result)
462    }
463    ///Returns the information on a particular cookie
464    pub fn get_cookie(&self,cookie_name:&str)->Result<Cookie,String>{
465        let url = format!("{}/{}",self.cookie_url,cookie_name);
466        let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &url, vec![], "");
467        if resp.contains("domain")&&resp.contains("expiry")&&resp.contains("name"){
468            let map:HashMap<&str,serde_json::Value> = serde_json::from_str(&resp).unwrap();
469            let v = map.get(&"value").unwrap();
470            return Ok(from_value_to_cookie(v));
471        }
472        Err(resp)
473    }
474    pub fn add_cookie(&self,cookie:Cookie)->Result<(),String>{
475        let cook = serde_json::to_string(&cookie).unwrap();
476        let body =format!(r#"{{"cookie": {} }}"#,cook);
477        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &self.cookie_url, cont_length_header(&body), &body);
478        if resp==r#"{"value":null}"#{
479            return Ok(());
480        }
481        Err(resp)
482    }
483    pub fn delete_cookie(&self,cookie_name:&str)->Result<(),String>{
484        let uri = format!("{}/{}",self.cookie_url,cookie_name);
485        let resp = send_and_read_body(&self.ip,&self.port,Method::DELETE, &uri, vec![], "");
486        if resp==r#"{"value":null}"#{
487            return Ok(());
488        }
489        Err(resp)
490    }
491    pub fn delete_all_cookies(&self)->Result<(),String>{
492        let resp = send_and_read_body(&self.ip,&self.port,Method::DELETE, &self.cookie_url, vec![], "");
493        if resp==r#"{"value":null}"#{
494            return Ok(());
495        }
496        Err(resp)
497    }
498    ///The path should be absolute with the extension
499    /// 
500    /// # Examples
501    /// ```
502    /// # use selenium_webdriver::*;
503    /// let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=7680,4320"]);
504    /// br.open("https://vk.com").unwrap();
505    /// br.take_screenshot("screen.png").unwrap();
506    /// br.close_browser().unwrap();
507    /// # std::fs::remove_file("screen.png").unwrap();
508    /// ```
509    pub fn take_screenshot(&self,path:&str)->Result<(),String>{
510        if let Ok(resp) = send_request_screensh(Method::GET, &self.screenshot_url, vec![], ""){
511             if let Ok(new) = base64::decode(resp){
512                match std::fs::write(path,new){
513                    Ok(())=>return Ok(()),
514                    Err(message)=> return Err(message.to_string()),
515                }
516             }
517        }
518        Err(String::from("Could not take a screenshot"))     
519    }
520    pub fn take_element_screenshot(&self,elem:&Element,path: &str)->Result<(),String>{
521        let uri = format!("{}/{}/screenshot",self.element_url,elem.element_id);
522        if let Ok(resp) = send_request_screensh(Method::GET, &uri, vec![], ""){
523            if let Ok(new) = base64::decode(resp){
524                match std::fs::write(path,new){
525                    Ok(())=>return Ok(()),
526                    Err(message)=>return Err(message.to_string())
527                }
528            }
529        }
530        Err(String::from("Could not take a screenshot")) 
531    }
532    /// Executes the sync fun in the browser. In case the argument is a string, it should be a raw string or should incluse escapes with double quotes
533    /// For example, if the args list you want to pass is [5,"Jack", 15], the vector should be ["5",r#"Jack"#,"15"]
534    pub fn execute_sync(&self, script: &str, args: &Vec<&str>)->Result<String,String>{
535        let args = gen_script_args(args);
536        let body = format!(r#"{{"script":"{}","args":{}}}"#,script,args);
537        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &self.execute_sync_url, cont_length_header(&body), &body);
538        if resp.contains("error"){
539            return Err(resp);
540        }
541        Ok(resp)
542    }
543    ///Executes the async fun in the browser. The args should be passed similarly to the execute_sync fn.
544    pub fn execute_async(&self, script: &str, args: &Vec<&str>)->Result<String,String>{
545        let args = gen_script_args(args);
546        let body = format!(r#"{{"script":"{}","args":{}}}"#,script,args);
547        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &self.execute_async_url, cont_length_header(&body), &body);
548        if resp.contains("error"){
549            return Err(resp);
550        }
551        Ok(resp)
552    }
553    ///Prints out the page. If you want to print it to pdf, use headless mode. The structs PrintSettings,Page and Margin allow you to customize the print.
554    pub fn print(&self,print_settings:&PrintSettings,path:&str)->Result<(),String>{
555        let pr_set_body = serde_json::to_string(&print_settings).unwrap();
556        let resp = send_request_screensh(Method::POST, &self.print_page_url, cont_length_header(&pr_set_body), &pr_set_body).unwrap();
557        let new = base64::decode(resp).unwrap();
558        std::fs::write(path,new).unwrap();
559        Ok(())
560    }
561    
562}
563
564impl Browser{
565    pub fn dismiss_alert(&self)->Result<(),String>{
566        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &self.alert_dismiss_url, cont_length_header("{}"), "{}");
567        if resp ==r#"{"value":null}"#{Ok(())}else{Err(resp)}
568    }
569    pub fn allow_alert(&self)->Result<(),String>{
570        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &self.alert_accept_url, cont_length_header("{}"), "{}");
571        if resp ==r#"{"value":null}"#{Ok(())}else{Err(resp)}
572    }
573    pub fn get_alert_text(&self)->Result<String,String>{
574        let resp = send_and_read_body(&self.ip,&self.port,Method::GET, &self.alert_text_url, vec![], "");
575        if resp.contains("error"){return Err(resp);}
576        let map:HashMap<&str,String> = serde_json::from_str(&resp).unwrap();
577        Ok((*map.get("value").unwrap()).to_string())
578    }
579    pub fn send_alert_text(&self,text:&str)->Result<(),String>{
580        let body =format!(r#"{{"text":{}}}"#,text) ;
581        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &self.alert_dismiss_url, cont_length_header(&body), &body);
582        if resp.contains("error"){return Err(resp);}
583        Ok(())
584    }
585    /// Pls see the Actions struct page to learn how to properly construct the Actions instance. 
586    /// # Examples
587    /// ```
588    /// # use selenium_webdriver::*;
589    /// let mut actions = Actions::new();
590    /// let mut actions_keys = ActionsKeys::new();
591    /// actions_keys.press_special_key(SpecialKey::ShiftLeft);
592    /// actions_keys.press_key("a");
593    /// actions.add_key_actions(actions_keys);
594    /// let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=1000,500"]);
595    /// br.open("https:vk.com/").unwrap();
596    /// br.find_element(LocatorStrategy::CSS("#ts_input")).unwrap().click().unwrap();
597    /// br.perform_actions(actions);
598    /// br.close_browser().unwrap();
599    /// ``` 
600    pub fn perform_actions(&self,actions:Actions)->Result<(),String>{
601        let mut actions = actions;
602        actions.set_ids();
603        let body = serde_json::to_string(&actions).unwrap();
604        let resp = send_and_read_body(&self.ip,&self.port,Method::POST, &self.actions_url, cont_length_header(&body), &body);
605        if resp.contains("error"){return Err(resp);}
606        Ok(())
607    }
608    ///Releases all the actions present in the current session's internal state.
609    ///While the key actions are performed just after calling the perform_actions method,
610    ///for instance, mouse actions are performed only after calling this method.
611    pub fn release_actions(&self)->Result<(),String>{
612        let resp = send_and_read_body(&self.ip,&self.port,Method::DELETE, &self.actions_url, vec![], "");
613        if resp.contains("error"){return Err(resp);}
614        Ok(())
615    }
616}
617pub (self) mod utils{
618    use super::*;
619    pub (super) fn generate_browser_links(ip:&str,port:&str,sess_id:&str)->Browser{
620        Browser{
621            port:String::from(port),
622            ip:String::from(ip),
623            session_url:format!("wd/hub/session/{}",sess_id),
624            go_to_url: format!("wd/hub/session/{}/url",sess_id),
625            timeouts_url: format!("wd/hub/session/{}/timeouts",sess_id),
626            back_url: format!("wd/hub/session/{}/back",sess_id),
627            forward_url: format!("wd/hub/session/{}/forward",sess_id),
628            refresh_url:format!("wd/hub/session/{}/refresh",sess_id),
629            title_url:format!("wd/hub/session/{}/title",sess_id),
630            window_url:format!("wd/hub/session/{}/window",sess_id),
631            window_handles_url:format!("wd/hub/session/{}/window/handles",sess_id),
632            window_new_url:format!("wd/hub/session/{}/window/new",sess_id),
633            window_rect_url:format!("wd/hub/session/{}/window/rect",sess_id),
634            frame_url:format!("wd/hub/session/{}/frame",sess_id),
635            frame_parent_url:format!("wd/hub/session/{}/frame/parent",sess_id),
636            window_maximize_url:format!("wd/hub/session/{}/window/maximize",sess_id),
637            window_minimize_url:format!("wd/hub/session/{}/window/minimize",sess_id),
638            window_fullscreen_url:format!("wd/hub/session/{}/window/fullscreen",sess_id),
639            element_url:format!("wd/hub/session/{}/element",sess_id),
640            element_active_url:format!("wd/hub/session/{}/element/active",sess_id),
641            elements_url:format!("wd/hub/session/{}/elements",sess_id),
642            source_url:format!("wd/hub/session/{}/source",sess_id),
643            execute_sync_url:format!("wd/hub/session/{}/execute/sync",sess_id),
644            execute_async_url:format!("wd/hub/session/{}/execute/async",sess_id),
645            cookie_url:format!("wd/hub/session/{}/cookie",sess_id),
646            actions_url:format!("wd/hub/session/{}/actions",sess_id),
647            alert_dismiss_url:format!("wd/hub/session/{}/alert/dismiss",sess_id),
648            alert_accept_url:format!("wd/hub/session/{}/alert/accept",sess_id),
649            alert_text_url:format!("wd/hub/session/{}/alert/text",sess_id),
650            screenshot_url:format!("wd/hub/session/{}/screenshot",sess_id),
651            print_page_url:format!("wd/hub/session/{}/print",sess_id),
652        }
653    }
654    pub (super) fn create_session_body_json(browser:BrowserName,args:Vec<&str>)->String{
655            match browser{
656                BrowserName::Chrome=> create_chrome_session(args),
657                BrowserName::Firefox=>create_firefox_session(),
658                BrowserName::Safari=>create_safari_session(),
659            }
660    }
661    pub (super) fn create_chrome_session(args:Vec<&str>)->String{
662            let one=format!(r#"{{"capabilities": {{"alwaysMatch":{{"platformName":"{}"}}"#,std::env::consts::OS);
663            let args = gen_args(args);
664            let two=format!(r#"{},"firstMatch":[{{"browserName":"chrome","goog:chromeOptions":{{"args":{}}}}}]}}}}"#,one,args);
665            two
666    }
667    pub (super) fn create_firefox_session()->String{
668        let one=format!(r#"{{"capabilities": {{"alwaysMatch":{{"platformName":"{}"}}"#,std::env::consts::OS);
669        let two=format!(r#"{},"firstMatch":[{{"browserName":"firefox"}}]}}}}"#,one);
670        two
671    }
672    pub (super) fn create_safari_session()->String{
673        let one=format!(r#"{{"capabilities": {{"alwaysMatch":{{"platformName":"{}"}}"#,std::env::consts::OS);
674        let two=format!(r#"{},"firstMatch":[{{"browserName":"safari"}}]}}}}"#,one);
675        two
676    }
677    pub (super) fn create_json_body_for_session_with_chrome_options(chrome_options:ChromeOptions)->String{
678        let mut options = chrome_options.string_for_session;
679        options.pop();
680        options.pop();
681        options.push('}');
682        let base_string = format!(r#"{{
683            "capabilities": {{
684                "alwaysMatch": {{
685                    "platformName": "{}"
686                }},
687                "firstMatch": [
688                    {{"browserName": "chrome",
689                        {}
690                    }}
691                ]
692            }}
693        }}"#,std::env::consts::OS,options);
694        base_string
695    }
696    pub (super) fn create_json_body_for_session_with_firefox_options(ff_options:FirefoxOptions)->String{
697        let mut options = ff_options.string_for_session;
698        options.pop();
699        options.pop();
700        options.push('}');
701        let base_string = format!(r#"{{
702            "capabilities": {{
703                "alwaysMatch": {{
704                    "platformName": "{}"
705                }},
706                "firstMatch": [
707                    {{"browserName": "firefox",
708                        {}
709                    }}
710                ]
711            }}
712        }}"#,std::env::consts::OS,options);
713        base_string
714    }
715    pub (super) fn create_json_body_for_session_with_safari_options(saf_options:SafariOptions)->String{
716        let base_string = format!(r#"
717        {{
718            "capabilities":{{
719                "alwaysMatch":
720                    {{
721                        "platformName":"{}",
722                        "browserName":"safari",
723                        {}
724                    }}
725            }}
726        }}"#,std::env::consts::OS,saf_options.base_string);
727        base_string
728    }
729    pub (super) fn gen_args(args:Vec<&str>)->String{
730            if args.len()==0{
731                return String::from("[]");
732            }
733            let mut result = String::from("[");
734            for arg in args{
735                result.push_str("\"");
736                result.push_str(arg);
737                result.push_str("\"");
738                result.push_str(",");
739            }
740            result.pop();
741            result.push_str("]");
742            result
743    }
744    pub (super) fn gen_script_args(args:&Vec<&str>)->String{
745        if args.len()==0{
746            return String::from("[]");
747        }
748        let mut result = String::from("[");
749        let temp_result = args.join(",");
750        result.push_str(&temp_result);
751        result.push_str("]");
752        result
753    }
754    pub (super) fn from_value_to_cookie(val: &serde_json::Value)->Cookie{
755        let name = String::from(val["name"].as_str().unwrap());
756        let value = String::from(val["value"].as_str().unwrap());
757        let mut domain = String::from("");
758        let mut expiry = 0;
759        let mut http_only = false;
760        let mut path = String::from("");
761        let mut secure = false;
762        let mut same_site = String::from("");
763        if let Some(dom) = val["domain"].as_str(){
764            domain=String::from(dom);
765        }
766        if let Some(exp) = val["expiry"].as_u64(){
767            expiry=exp;
768        }
769        if let Some(http) = val["httpOnly"].as_bool(){
770            http_only=http;
771        }
772        if let Some(pat) = val["path"].as_str(){
773            path=String::from(pat);
774        }
775        if let Some(sec) = val["secure"].as_bool(){
776            secure = sec;
777        }
778        if let Some(same) = val["sameSite"].as_str(){
779            same_site=String::from(same);
780        }
781        Cookie{name,value,path,expiry,secure,domain,httpOnly: http_only,sameSite:same_site}
782    }
783}
784
785///Needed to call the new_window method
786pub enum NewWindowType{
787    Tab,
788    Window
789}
790///Utility struct representing window height,width,x-axis and y-axis
791#[derive(Serialize,Deserialize,Debug,PartialEq,Clone)]
792pub struct WindowRect{
793    pub(self)height:i32,
794    pub(self)width:i32,
795    pub(self)x:i32,
796    pub(self)y:i32
797}
798impl WindowRect{
799    pub fn new(height:i32,width:i32,x:i32,y:i32)->WindowRect{
800        WindowRect{ height, width, x, y}
801    }
802}
803///Utility struct to manage session cookies
804/// 
805/// Includes two constructor methods and getters/setters for adjustments
806#[allow(non_snake_case)]
807#[derive(Serialize,Deserialize,Debug,Clone)]
808pub struct Cookie{
809    pub(self)domain:String,
810    pub(self)expiry: u64,
811    pub(self)httpOnly:bool,
812    pub(self)name:String,
813    pub(self)path:String,
814    pub(self)secure:bool,
815    pub(self)value:String,
816    pub(self)sameSite:String,
817}
818
819impl Cookie{
820    ///Create a cookie and initialize all its fields
821    pub fn new_all(domain:String, expiry:u64,same_site:String, http_only:bool,name:String,path:String,secure:bool,value:String)->Self{
822        Cookie{
823            domain,
824            expiry,
825            httpOnly: http_only,
826            name,
827            path,
828            sameSite:same_site,
829            secure,
830            value
831        }
832    }
833    ///Create default cookie and set only name and value
834    pub fn new(name:String,value:String)->Self{
835        Cookie{name,value,..Default::default()}
836    }
837
838    pub fn get_domain(&self)->String{self.domain.clone()}
839    pub fn get_expiry(&self)->u64{self.expiry}
840    pub fn get_http_only(&self)->bool{self.httpOnly}
841    pub fn get_name(&self)->String{self.name.clone()}
842    pub fn get_path(&self)->String{self.path.clone()}
843    pub fn get_secure(&self)->bool{self.secure}
844    pub fn get_value(&self)->String{self.value.clone()}
845    pub fn get_same_site(&self)->String{self.sameSite.clone()}
846
847
848    pub fn set_domain(&mut self, domain:String){self.domain=domain;}
849    pub fn set_expiry(&mut self, expiry: u64){self.expiry=expiry;}
850    pub fn set_http_only(&mut self, http_only:bool){self.httpOnly=http_only;}
851    pub fn set_path(&mut self, path: String){self.path=path;}
852    pub fn set_secure(&mut self, secure: bool){self.secure=secure;}
853    pub fn set_same_site(&mut self, same_site:String){self.sameSite=same_site;}
854}
855impl Default for Cookie{
856    fn default()->Self{
857        Cookie{
858            domain:"".to_string(),
859            expiry: 0,
860            httpOnly: false,
861            name:"".to_string(),
862            path:"".to_string(),
863            secure:false,
864            value:"".to_string(),
865            sameSite:"None".to_string(),
866        }
867    }
868}
869///Utility struct to manage the session's implicit, page load and script timeouts
870#[allow(non_snake_case)]
871#[derive(Serialize,Deserialize,Debug,PartialEq)]
872pub struct Timeouts{
873    implicit:u32,
874    pageLoad:u32,
875    script:u32,
876}
877impl Timeouts{
878    ///Instantiates the Timeouts with all fields set
879    pub fn set_all (implicit: u32, page_load: u32,script:u32)->Timeouts{
880        Timeouts{
881            implicit,
882            pageLoad: page_load,
883            script
884        }
885    }
886    ///Instantiates the Timeouts with default timouts of a chrome session
887    pub fn new ()->Timeouts{
888        Timeouts{
889            implicit:0,
890            pageLoad: 300000,
891            script: 30000,
892        }
893    }
894    pub fn set_implicit(&mut self,implicit:u32){
895        self.implicit=implicit;
896    }
897    pub fn set_page_load(&mut self,page_load:u32){
898        self.pageLoad=page_load;
899    }
900    pub fn set_script(&mut self,script:u32){
901        self.script=script;
902    }
903
904}
905///Main struct for print settings
906/// 
907/// Has the default method with default WebDriver print settings and getters/setters for print adjustment.
908#[allow(non_snake_case)]
909#[derive(Serialize,Deserialize,Debug)]
910pub struct PrintSettings{
911    orientation:String,
912    scale: f32,
913    background: bool,
914    page: Page,
915    margin: Margin,
916    shrinkToFit: bool,
917    pages: Vec<u32>
918}
919impl PrintSettings{
920    pub fn new(orientation: Orientation,scale: f32,background:bool,page:Page,margin:Margin,shrink_tf:bool,pages:Vec<u32>)->Self{
921        if scale<0.1||scale>2.0{panic!("The condotion (0.1<=scale<= 2.0) is not fulfilled");}
922        let orientation = match orientation{
923            Orientation::PORTRAIT=>String::from("portrait"),
924            Orientation::LANDSCAPE=>String::from("landscape"),
925        };
926        PrintSettings{orientation,scale,background,page,margin,shrinkToFit: shrink_tf,pages}
927    }
928    pub fn set_orientation(&mut self,orientation: Orientation){
929        self.orientation = match orientation{
930            Orientation::PORTRAIT=>String::from("portrait"),
931            Orientation::LANDSCAPE=>String::from("landscape"),
932        };
933    }
934    ///Should be between 0.1 and 2.0 inclusively
935    pub fn set_scale(&mut self,scale:f32){
936        if scale<0.1||scale>2.0{panic!("The condotion (0.1<=scale<= 2.0) is not fulfilled");}
937        self.scale=scale;}
938    ///Flags to include the background or not
939    pub fn set_background(&mut self,background: bool){self.background=background;}
940    pub fn set_page(&mut self,page:Page){self.page=page;}
941    pub fn set_margin(&mut self,margin:Margin){self.margin=margin;}
942    ///Flags whether the webpage should be shrunk if it does not fit the print page
943    pub fn set_shrink_to_fit(&mut self,shr_to_fit:bool){self.shrinkToFit = shr_to_fit;}
944    ///Sets the page range for printing
945    pub fn set_pages(&mut self,pages:Vec<u32>){self.pages=pages;}
946}
947
948impl Default for PrintSettings{
949    fn default()->Self{
950        PrintSettings{
951            orientation:String::from("portrait"),
952            scale: 1.0,
953            background: false,
954            page: Page::default(),
955            margin: Margin::default(),
956            shrinkToFit: true,
957            pages: vec![] 
958        }
959    }
960}
961///One of the PrintSettings fields
962/// 
963/// Includes the info about the page size
964#[derive(Serialize,Deserialize,Debug)]
965pub struct Page{
966    width:f32,
967    height:f32,
968}
969impl Page{
970    pub fn new(width:f32, height: f32)->Self{
971        if width<0.0||height<0.0{panic!("Width and height can't be less then 0.0");}
972        Page{width,height}
973    }
974    pub fn set_width(&mut self,width:f32){
975        if width<0.0{panic!("Width cannot be less then 0.0");}
976        self.width = width;
977    }
978    pub fn set_height(&mut self,height:f32){
979        if height<0.0{panic!("Height cannot be less then 0.0");}
980        self.height = height;
981    }
982}
983impl Default for Page{
984    fn default()->Self{
985        Page{width:21.59,height:27.94}
986    }
987}
988/// One of the PrintSettings fields
989/// 
990/// Includes the info on margin sizes
991#[derive(Serialize,Deserialize,Debug)]
992pub struct Margin{
993    top:u32,
994    bottom:u32,
995    left:u32,
996    right:u32,
997}
998impl Margin{
999    pub fn new(top:u32,bottom:u32,left:u32,right:u32)->Self{
1000        Margin{
1001            top,bottom,left,right
1002        }
1003    }
1004    pub fn set_top(&mut self,top:u32){self.top=top;}
1005    pub fn set_bottom(&mut self,bottom:u32){self.bottom=bottom}
1006    pub fn set_left(&mut self,left:u32){self.left=left;}
1007    pub fn set_right(&mut self,right:u32){self.right=right;}
1008}
1009impl Default for Margin{
1010    fn default()->Self{
1011        Margin{
1012            top:1,
1013            bottom:1,
1014            left:1,
1015            right:1,
1016        }
1017    }
1018}
1019///Needed for the PrintSettings struct
1020pub enum Orientation{
1021    PORTRAIT,
1022    LANDSCAPE
1023}
1024
1025//TESTS
1026mod core_fns_tests{
1027
1028    use super::*;
1029    use super::Element;
1030    use std::env::*;
1031    #[test]
1032    fn create_session() {
1033        let mut browser = Browser::start_session(BrowserName::Chrome,vec!["--headless"]);
1034        let sess:String; 
1035        {let mut iter = browser.session_url.split("/");
1036        iter.next();
1037        iter.next();
1038        iter.next();
1039        sess = iter.next().unwrap().to_string();}
1040        browser.close_browser().unwrap();
1041        
1042        assert_eq!(32,sess.len());
1043    }
1044    #[test]
1045    fn go_to_vk() {
1046        let mut browser = Browser::start_session(BrowserName::Chrome, vec!["--headless"]);
1047        browser.open("https://vk.com").unwrap();
1048        let link = browser.get_link().unwrap();
1049        browser.close_browser().unwrap();
1050        assert_eq!(link,"https://vk.com/");
1051    }
1052    #[test]
1053    #[should_panic]
1054    fn close_browser() {
1055        let mut browser = Browser::start_session(BrowserName::Chrome, vec!["--headless"]);
1056        browser.open("http://localhost:4444/wd/hub/status").unwrap();
1057        browser.close_browser().unwrap();        
1058        let a = browser.get_link().unwrap();
1059        if a.contains("invalid"){panic!("Invalid session id");}
1060    }
1061    #[test]
1062    fn args() {
1063        let a = vec!["--headless","--window-size=800,400"];        
1064        assert!(gen_args(a)==String::from("[\"--headless\",\"--window-size=800,400\"]"));
1065    }
1066    #[test]
1067    fn get_timeouts() {
1068        let timeouts:Timeouts;
1069        {
1070            let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1071            timeouts= br.get_timeouts().unwrap();
1072            br.close_browser().unwrap();
1073        }
1074        assert!(timeouts.implicit==0&&timeouts.script==30000);
1075    }
1076    #[test]
1077    fn set_timeouts() {
1078        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1079        let timeouts = Timeouts::set_all(1000, 3000, 300000);
1080        assert!(br.set_timeouts(&timeouts)==Ok(()));
1081        br.close_browser().unwrap();
1082    }
1083    #[test]
1084    fn check_timouts_init() {
1085        let mut t = Timeouts::new();
1086        assert_eq!(t,Timeouts{implicit:0,pageLoad:300000,script:30000});
1087        t.set_implicit(1);
1088        assert_eq!(t,Timeouts{implicit:1,pageLoad:300000,script:30000});
1089        t.set_page_load(1);
1090        assert_eq!(t,Timeouts{implicit:1,pageLoad:1,script:30000});
1091        t.set_script(1);
1092        assert_eq!(t,Timeouts{implicit:1,pageLoad:1,script:1});
1093    }
1094    #[test]
1095    fn back_test() {
1096        let link: String;
1097        {let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1098        br.open("https://vk.com/").unwrap();
1099        br.open("https://m.facebook.com/").unwrap();
1100        br.back().unwrap();
1101        link = br.get_link().unwrap();
1102        br.close_browser().unwrap();}
1103        assert_eq!(link.as_str(),"https://vk.com/");
1104    }
1105    #[test]
1106    fn forward_test() {
1107        let link: String;
1108        {let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1109        br.open("https://vk.com/").unwrap();
1110        br.open("https://m.facebook.com/").unwrap();
1111        br.back().unwrap();
1112        br.forward().unwrap();
1113        link = br.get_link().unwrap();        
1114        br.close_browser().unwrap();}
1115        assert_eq!(&link,"https://m.facebook.com/");
1116    }
1117    #[test]
1118    fn refresh_test() {
1119        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1120        br.open("https://vk.com/").unwrap();
1121        assert_eq!(br.refresh(),Ok(()));
1122        br.close_browser().unwrap();
1123    }
1124    #[test]
1125    fn get_title_test() {
1126        let title:String;
1127        {let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1128        br.open("https://www.w3.org/TR/webdriver/").unwrap();
1129        title =br.get_title().unwrap();
1130        br.close_browser().unwrap();}
1131        assert_eq!(title,String::from("WebDriver"));
1132        
1133    }
1134    #[test]
1135    fn window_handle() {
1136        let handle: String;
1137        {let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1138        br.open("https://vk.com").unwrap();
1139        handle = br.get_window_handle().unwrap();
1140        br.close_browser().unwrap();}
1141        assert!(handle.starts_with("CDwindow"));
1142        
1143    }
1144    #[test]
1145    fn switch_window(){
1146        let res :Result<(),String>;
1147        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1148        br.open("https://vk.com").unwrap();
1149        let handle = br.get_window_handle().unwrap();
1150        res = br.switch_to_window(handle);assert_eq!(Ok(()),res);
1151        br.close_browser().unwrap();
1152    }
1153    #[test]
1154    fn get_handles() {
1155        let handles;
1156        {
1157            let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1158            br.open("https://vk.com").unwrap();
1159            handles = br.get_window_handles();
1160            br.close_browser().unwrap();
1161        }
1162        let len = handles.unwrap().len();
1163        assert_eq!(len,1);
1164    }
1165    #[test]
1166    fn close_window() {
1167        let handles;
1168        {
1169            let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1170            br.open("https://vk.com").unwrap();
1171            handles = br.close_window();
1172            br.close_browser().unwrap();
1173        }
1174        assert_eq!(handles.unwrap().len(),0);
1175    }
1176    #[test]
1177    fn new_window(){
1178        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1179        let wind = br.new_window(NewWindowType::Tab).unwrap();
1180        assert!(wind.1=="tab"&&br.get_window_handles().unwrap().len()==2);
1181        br.close_browser().unwrap();
1182    }
1183    #[test]
1184    fn sw_to_frame_by_id() {
1185        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1186        br.open("https://bash.im").unwrap();
1187        let res = br.switch_to_frame_by_id(0);
1188        br.close_browser().unwrap();
1189        assert_eq!(res,Ok(()));
1190
1191    }
1192    #[test]
1193    fn sw_t_fr_by_el() {
1194        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1195        br.open("https://vk.com").unwrap();
1196        let el = br.find_element(LocatorStrategy::CSS("#quick_login_frame")).unwrap();
1197        let res = br.switch_to_frame_by_element(el);
1198        br.close_browser().unwrap();
1199        assert_eq!(res,Ok(()));
1200    }
1201    #[test]
1202    fn find_element() {
1203        let el;
1204        {
1205        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1206        br.open("https://vk.com").unwrap();
1207        el = br.find_element(LocatorStrategy::CSS("#ts_input")).unwrap();
1208        br.close_browser().unwrap();
1209        }
1210        let tr =el.element_gr_id.contains("element"); 
1211        assert!(tr);
1212    }
1213    #[test]
1214    fn find_els() {
1215        let el;
1216        {
1217        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1218        br.open("https://vk.com").unwrap();
1219        el = br.find_elements(LocatorStrategy::CSS("div")).unwrap();
1220        br.close_browser().unwrap();
1221        }
1222        let len = el.len();
1223        assert!(len>2);
1224    }
1225    #[test]
1226    fn sw_to_par_fr() {
1227        let res;
1228        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1229        br.open("https://vk.com").unwrap();
1230        res = br.switch_to_parent_frame();
1231        br.close_browser().unwrap(); 
1232        assert_eq!(res, Ok(()));
1233    }
1234    #[test]
1235    fn get_wind_rect() {
1236        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1237        let wr = br.get_window_rect().unwrap();
1238        br.close_browser().unwrap();
1239        assert!(wr==WindowRect{height:200,width:400,x:0,y:0});
1240    }
1241    #[test]
1242    fn set_wind_rect(){
1243        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1244        let wr = WindowRect{height:600, width:1000,x:250,y:250};
1245        let wr_new = br.set_sindow_rect(&wr).unwrap();
1246        br.close_browser().unwrap();
1247        assert_eq!(wr,wr_new);
1248        
1249    }
1250    #[test]
1251    fn maximize() {
1252        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1253        let a = br.maximize_window().unwrap();
1254        br.close_browser().unwrap();
1255        let wr = WindowRect{height:200, width:400,x:0,y:0};
1256        assert_eq!(a,wr);
1257    }
1258    #[test]
1259    fn parse_val_test() {
1260        let resp = r#"{
1261       "value": {
1262       "dftg43rert34tert-34trte-243f-4":
1263       {
1264        "id": 333
1265        }
1266      }
1267     }"#;
1268       let res = parse_value(resp);
1269       assert_eq!(res,"{\"dftg43rert34tert-34trte-243f-4\":{\"id\":333}}");
1270    }
1271    #[test]
1272    fn fullsize() {
1273        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1274        let a = br.fullscreen().unwrap();
1275        br.close_browser().unwrap();
1276        assert!(a.x==0&&a.y==0);
1277    }
1278
1279    #[test]
1280    fn src() {
1281        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1282        br.open("http://localhost:4444/wd/hub/status").unwrap();
1283        let a = br.source().unwrap();
1284        br.close_browser().unwrap();
1285        assert!(a.contains("html")&&a.contains("head"))
1286    }
1287
1288    #[test]
1289    fn script_test() {
1290        let script = "return 3+2";
1291        let res = vec!["5",r#""Hello""#];
1292        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1293        let res = br.execute_sync(script, &res).unwrap();
1294        br.close_browser().unwrap();
1295        assert!(res.contains("5"));
1296    }
1297    
1298    #[test]
1299    fn cookies() {
1300        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1301        br.open("https://vk.com").unwrap();
1302        let cook = br.get_all_cookies().unwrap();
1303        br.close_browser().unwrap();
1304        assert!(cook.len()>1);
1305    }
1306
1307    #[test]
1308    fn get_cookie() {
1309        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1310        br.open("https://vk.com").unwrap();
1311        let c = br.get_cookie("tmr_lvidTS").unwrap();
1312        br.close_browser().unwrap();
1313        assert_eq!(c.httpOnly,false);
1314    }
1315
1316    #[test]
1317    fn add_cookie() {
1318        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1319        br.open("https://vk.com").unwrap();
1320        let cook = Cookie::new_all(String::from(""), 1000, String::from("Lax"), false, String::from("tmr_detect"), String::from(""), false, String::from("0%7C1604223632022"));
1321        assert_eq!(br.add_cookie(cook),Ok(()));
1322        br.close_browser().unwrap();
1323    }
1324
1325    #[test]
1326    fn z_del_all_cook() {
1327        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1328        br.open("https://vk.com").unwrap();
1329        br.delete_all_cookies().unwrap();
1330        let cook = br.get_all_cookies().unwrap();
1331        br.close_browser().unwrap();
1332        assert_eq!(cook.len(),0);
1333    }
1334    #[test]
1335    fn t_del_cookie() {
1336        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1337        br.open("https://vk.com").unwrap();
1338        let r = br.delete_cookie("remixjsp");
1339        br.close_browser().unwrap();
1340        assert!(r==Ok(()));
1341    }
1342    #[test]
1343    fn screensh() {
1344        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=7680,4320"]);
1345        br.open("https://vk.com").unwrap();
1346        br.take_screenshot("screen.png").unwrap();
1347        br.close_browser().unwrap();
1348        let arr=std::fs::read("screen.png").unwrap().len();
1349        assert!(arr>0);
1350        std::fs::remove_file("screen.png").unwrap();
1351    }
1352    #[test]
1353    fn el_screensh() {
1354        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=800,600"]);
1355        br.open("https://vk.com").unwrap();
1356        let el = br.find_element(LocatorStrategy::CSS("#ts_input")).unwrap();
1357        br.take_element_screenshot(&el,"element.png").unwrap();
1358        br.close_browser().unwrap();
1359        let arr=std::fs::read("element.png").unwrap().len();
1360        assert!(arr>0);
1361        std::fs::remove_file("element.png").unwrap();
1362    }
1363    #[test]
1364    fn pr_page() {
1365        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=2400,1200"]);
1366        br.open("https://vk.com").unwrap();
1367        let mut p  = PrintSettings::default();
1368        p.set_orientation(Orientation::LANDSCAPE);
1369        p.set_pages(vec![1,2]);
1370        br.print(&p, "page.pdf").unwrap();
1371        br.close_browser().unwrap();
1372        let arr=std::fs::read("page.pdf").unwrap().len();
1373        assert!(arr>0);
1374        std::fs::remove_file("page.pdf").unwrap();
1375    }
1376
1377    #[test]
1378    fn alerts() {
1379        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1380        br.open("https://vk.com").unwrap();
1381        let resp = br.dismiss_alert().is_err();
1382        let resp2 = br.allow_alert().is_err();
1383        br.close_browser().unwrap();
1384        assert!(resp&&resp2);
1385    }
1386    #[test]
1387    fn get_send_alert_text() {
1388        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1389        br.open("https://vk.com").unwrap();
1390        let resp = br.get_alert_text().is_err();
1391        let resp2 = br.send_alert_text("I am the text").is_err();
1392        br.close_browser().unwrap();
1393        assert!(resp&&resp2);
1394    }
1395    #[test]
1396    fn active_el() {
1397        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless"]);
1398        br.open("https://vk.com").unwrap();
1399        let a = br.get_active_element().unwrap();
1400        br.close_browser().unwrap();
1401        assert!(a.element_gr_id.contains("element"));
1402    }
1403    #[test]
1404    fn find_sub_el() {
1405        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1406        br.open("https://vk.com").unwrap();
1407        let par_el= br.find_element(LocatorStrategy::CSS("#top_nav")).unwrap();
1408        let a = par_el.find_element_from_self(LocatorStrategy::CSS(".HeaderNav__item")).unwrap();
1409        br.close_browser().unwrap();
1410        assert!(a.element_gr_id.contains("element"));
1411    }
1412    #[test]
1413    fn sub_els() {
1414        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1415        br.open("https://bash.im").unwrap();
1416        let par_el= br.find_element(LocatorStrategy::CSS("section.quotes")).unwrap();
1417        let a = par_el.find_elements_from_self(LocatorStrategy::CSS(".quote")).unwrap();
1418        br.close_browser().unwrap();
1419        let len  = a.len();
1420        assert!(len>2);
1421    }
1422    #[test]
1423    fn is_sel() {
1424        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1425        br.open("https://vk.com").unwrap();
1426        let el= br.find_element(LocatorStrategy::CSS("#ts_input")).unwrap();
1427        let res = el.is_selected().unwrap();
1428        br.close_browser().unwrap();
1429        assert!(res==false);
1430    }
1431    #[test]
1432    fn get_arrtib() {
1433        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1434        br.open("https://vk.com").unwrap();
1435        let el= br.find_element(LocatorStrategy::CSS(".placeholder_content")).unwrap();
1436        let res = el.get_attribute("aria-hidde").unwrap();
1437        let res2 = el.get_attribute("aria-hidden").unwrap();
1438        br.close_browser().unwrap();
1439        assert!(res.as_str()=="null");
1440        assert!(res2.as_str()=="true");
1441    }
1442    #[test]
1443    fn get_property() {
1444        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1445        br.open("https://vk.com").unwrap();
1446        let el= br.find_element(LocatorStrategy::CSS("#index_login_form")).unwrap();
1447        let res_len = el.get_property("attributes").unwrap().len();
1448        let res_null = el.get_property("attributes2").unwrap();
1449        br.close_browser().unwrap();
1450        assert!(res_len>5000&&res_null.as_str()=="null");
1451    }
1452    #[test]
1453    fn get_css_property() {
1454        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1455        br.open("https://vk.com").unwrap();
1456        let el= br.find_element(LocatorStrategy::CSS("#index_login_form")).unwrap();
1457        let res = el.get_css_value("color").unwrap().contains("rgba");
1458        br.close_browser().unwrap();
1459        assert!(res);
1460    }
1461    #[test]
1462    fn get_el_text() {
1463        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1464        br.open("https://vk.com").unwrap();
1465        let el= br.find_element(LocatorStrategy::CSS("#index_login_form")).unwrap();
1466        let res = el.get_element_text().unwrap().contains("error");
1467        br.close_browser().unwrap();
1468        assert!(!res);
1469    }
1470    #[test]
1471    fn get_el_tag() {
1472        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1473        br.open("https://vk.com").unwrap();
1474        let el= br.find_element(LocatorStrategy::CSS("#index_login_form")).unwrap();
1475        let res = el.get_tag_name().unwrap().contains("error");
1476        br.close_browser().unwrap();
1477        assert!(!res);
1478    }
1479    #[test]
1480    fn get_el_rect() {
1481        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1482        br.open("https://vk.com").unwrap();
1483        let el= br.find_element(LocatorStrategy::CSS("#index_login_form")).unwrap();
1484        let res = el.get_element_rect().unwrap();
1485        br.close_browser().unwrap();
1486        assert!(res.height==140);
1487    }
1488    #[test]
1489    fn el_is_enabled() {
1490        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1491        br.open("https://vk.com").unwrap();
1492        let el= br.find_element(LocatorStrategy::CSS("#index_login_form")).unwrap();
1493        let res = el.is_enabled().unwrap();
1494        br.close_browser().unwrap();
1495        assert!(res);
1496    }
1497    #[test]
1498    fn get_comp_role() {
1499        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1500        br.open("https://vk.com").unwrap();
1501        let el= br.find_element(LocatorStrategy::CSS("#index_login_form")).unwrap();
1502        let res = el.get_computed_role();
1503        let res2 = el.get_computed_label();
1504        dbg!(&res);
1505        dbg!(&res2);
1506        br.close_browser().unwrap();
1507        assert!(res.is_err()&&res2.is_err());
1508    }
1509    #[test]
1510    fn click_test() {
1511        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1512        br.open("https://vk.com").unwrap();
1513        let el= br.find_element(LocatorStrategy::CSS("#index_login_form")).unwrap();
1514        let res = el.click();
1515        br.close_browser().unwrap();
1516        assert_eq!(res,Ok(()))
1517    }
1518    #[test]
1519    fn el_send_k() {
1520        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1521        br.open("https://vk.com").unwrap();
1522        let el= br.find_element(LocatorStrategy::CSS("#ts_input")).unwrap();
1523        el.send_keys("Sup!").unwrap();
1524        br.close_browser().unwrap();
1525    }
1526    #[test]
1527    fn el_clear() {
1528        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1529        br.open("https://vk.com").unwrap();
1530        let el= br.find_element(LocatorStrategy::CSS("#ts_input")).unwrap();
1531        let _ = el.send_keys("Sup!");
1532        el.clear_element().unwrap();
1533        br.close_browser().unwrap();
1534    }
1535    #[test]
1536    fn rel_actions() {
1537        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=400,200"]);
1538        let res1 = br.release_actions();
1539        br.close_browser().unwrap();
1540        let res2 = br.release_actions();
1541        assert!(res1.is_ok()&&res2.is_err());
1542    }
1543    #[test]
1544    fn per_f_ac_with_keys() {
1545        let mut actions = Actions::new();
1546        let mut actions_keys = ActionsKeys::new();
1547        actions_keys.press_special_key(SpecialKey::ShiftLeft);
1548        actions_keys.press_key("a");
1549        actions_keys.release_special_key(SpecialKey::ShiftLeft);
1550        actions_keys.press_key("b");
1551        actions.add_key_actions(actions_keys);
1552        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=1000,500"]);
1553        br.open("https:vk.com/").unwrap();
1554        br.find_element(LocatorStrategy::CSS("#ts_input")).unwrap().click().unwrap();
1555        let res = br.perform_actions(actions);
1556        br.close_browser().unwrap();
1557        assert!(res.is_ok());
1558    }
1559    #[test]
1560    fn perf_mouse_act() {
1561        let mut actions = Actions::new();
1562        let mut actions_keys = ActionsMouse::new();
1563        actions_keys.press_mouse_button(MouseButton::Left);
1564        actions_keys.pause(10);
1565        actions_keys.move_mouse_to_point(200,300);
1566        actions_keys.press_mouse_button(MouseButton::Right);
1567        actions.add_mouse_actions(actions_keys);
1568        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=1000,500"]);
1569        br.open("https:vk.com/").unwrap();
1570        let res = br.perform_actions(actions);
1571        let res2 = br.release_actions();
1572        br.close_browser().unwrap();
1573        assert!(res.is_ok()&&res2.is_ok());
1574    }
1575    #[test]
1576    fn keys_and_mouse_acts() {
1577        let mut actions = Actions::new();
1578        let mut keys = ActionsKeys::new();
1579        let mut mouse = ActionsMouse::new();
1580        keys.press_special_key(SpecialKey::ShiftLeft);
1581        keys.press_key("a");
1582        keys.release_special_key(SpecialKey::ShiftLeft);
1583        keys.press_key("b");
1584        mouse.pause(0);
1585        mouse.pause(0);
1586        mouse.press_mouse_button(MouseButton::Left);
1587        mouse.move_mouse_to_point(200,300);
1588        mouse.press_mouse_button(MouseButton::Right);
1589        actions.add_key_actions(keys);
1590        actions.add_mouse_actions(mouse);
1591        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=1000,500"]);
1592        br.open("https:vk.com/").unwrap();
1593        let res = br.perform_actions(actions);
1594        let res2 = br.release_actions();
1595        br.close_browser().unwrap();
1596        assert!(res.is_ok()&&res2.is_ok());       
1597    }
1598    #[test]
1599    fn wheel_ac() {
1600        let mut actions = Actions::new();
1601        let mut wheel = ActionsWheel::new();
1602        wheel.scroll(0, 0, 100, 100).scroll(100, 100, 100, 100);
1603        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=600,400"]);
1604        br.open("https://yandex.ru/").unwrap();
1605        actions.add_wheel_actions(wheel);
1606        let res = br.perform_actions(actions);
1607        br.close_browser().unwrap();
1608        assert!(res.is_ok());
1609    }
1610    #[test]
1611    fn move_mouse_to_el() {
1612        let mut actions = Actions::new();
1613        let mut mouse = ActionsMouse::new();
1614        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=600,400"]);
1615        br.open("https://vk.com").unwrap();
1616        let el = br.find_element(LocatorStrategy::CSS("#ts_input")).unwrap();    
1617        mouse.move_mouse_to_element(&el).press_mouse_button(MouseButton::Left);
1618        actions.add_mouse_actions(mouse);
1619        let res = br.perform_actions(actions);
1620        let res2 = br.release_actions();
1621        br.close_browser().unwrap();
1622        assert!(res.is_ok());
1623        assert!(res2.is_ok());
1624    }
1625    #[test]
1626    fn dranddrop() {
1627        let mut br = Browser::start_session(BrowserName::Chrome,  vec!["--headless","--window-size=1500,800"]);
1628        br.open("http://webdriveruniversity.com/Actions/index.html").unwrap();
1629        let mut actions = Actions::new();
1630        let mut mouse = ActionsMouse::new();
1631         let el = br.find_element(LocatorStrategy::CSS("div#draggable")).unwrap();
1632        let el_dest = br.find_element(LocatorStrategy::CSS("div#droppable")).unwrap(); 
1633        mouse.drag_n_drop(el, el_dest);
1634        actions.add_mouse_actions(mouse);
1635        let res = br.perform_actions(actions);
1636        let res2 = br.release_actions();
1637        br.close_browser().unwrap();
1638        assert!(res.is_ok());
1639        assert!(res2.is_ok());        
1640    }
1641}
1642mod additional_tests{
1643    use super::*;
1644    #[test]
1645    fn brow_chrome_opts() {
1646        let mut ch = ChromeOptions::new();
1647        let mob = MobileDevice::standard_device("Nexus 6");
1648        ch.add_args(vec!["--headless","--window-size=400,600"]);
1649        ch.add_mobile_emulation(mob);
1650        let mut br = Browser::start_chrome_session_with_options(ch).unwrap();
1651        let res = br.open("https://vk.com");
1652        let res2 = br.close_browser();
1653        assert!(res.is_ok()&&res2.is_ok());
1654    }
1655    #[test]
1656    fn brow_firefox_opts() {
1657        let mut ff = FirefoxOptions::new();
1658        ff.add_args(vec!["-headless","-devtools"]);
1659        let mut map = HashMap::new();
1660        map.insert("MOZ_HEADLESS_WIDTH", "600");
1661        map.insert("MOZ_HEADLESS_HEIGHT", "400");
1662        ff.add_env(map);
1663        let mut br = Browser::start_firefox_session_with_options(ff).unwrap();
1664        let res = br.open("https://vk.com");
1665        let res2 = br.close_browser();
1666        assert!(res.is_ok()&&res2.is_ok());
1667    }
1668    #[test]
1669    fn rem_lin_chr() {
1670        let mut br = Browser::start_remote_session(BrowserName::Chrome, "linux", "192.168.1.67","4444").unwrap();
1671        br.open("https://vk.com").unwrap();
1672        br.back().unwrap();
1673        br.close_browser().unwrap();
1674    }
1675    #[test]
1676    fn brow_cap() {
1677        let mut ch_op = ChromeOptions::new();
1678        ch_op.add_args(vec!["--headless","--window-size=500,1000"]);
1679        ch_op.add_mobile_emulation(MobileDevice::standard_device("Nexus 6"));
1680        let mut c = Capabilities::new(BrowserName::Chrome, "windows");
1681        c.set_chrome_options(ch_op);
1682        let mut br = Browser::start_session_with_capabilities(c).unwrap();
1683        br.open("https://vk.com").unwrap();
1684        br.take_screenshot("vk.png").unwrap();
1685        br.close_browser().unwrap();
1686        let res = std::fs::read("vk.png");
1687        assert!(res.is_ok());
1688        std::fs::remove_file("vk.png").unwrap();
1689    }
1690    #[test]
1691    fn brow_cap_remote() {
1692        let mut ch_op = ChromeOptions::new();
1693        ch_op.add_args(vec!["--headless","--window-size=500,1000"]);
1694        ch_op.add_mobile_emulation(MobileDevice::standard_device("Nexus 6"));
1695        let mut c = Capabilities::new(BrowserName::Chrome, "linux");
1696        c.set_chrome_options(ch_op);
1697        let mut br = Browser::start_remote_session_with_capabilities(c,"192.168.1.67","4444").unwrap();
1698        br.open("https://vk.com").unwrap();
1699        br.open("https://github.com").unwrap();
1700        let link = br.get_link().unwrap();
1701        assert!(link.contains("hub"));
1702        br.close_browser().unwrap();
1703    }
1704}
1705mod safari_tests{
1706    use super::*;
1707    #[test]
1708    #[cfg(target_os="macos")]
1709    fn saf_open_vk() {
1710        let mut br = Browser::start_session(BrowserName::Safari, vec![]);
1711        br.open("https://vk.com").unwrap();
1712        br.close_browser().unwrap();
1713    }
1714    #[test]
1715    #[cfg(target_os="macos")]
1716    fn saf_forward() {
1717        let link: String;
1718        {let mut br = Browser::start_session(BrowserName::Safari,vec![]);
1719        br.open("https://vk.com/").unwrap();
1720        br.open("https://m.facebook.com/").unwrap();
1721        br.back().unwrap();
1722        br.forward().unwrap();
1723        link = br.get_link().unwrap();        
1724        br.close_browser().unwrap();}
1725        assert!(link.contains("facebook"));
1726    }
1727    #[test]
1728    #[cfg(target_os="macos")]
1729    fn saf_diagn() {
1730        let mut saf_op = SafariOptions::new();
1731        saf_op.enable_diagnose();
1732        let mut br = Browser::start_safari_session_with_options(saf_op).unwrap();
1733        br.open("https://vk.com/").unwrap();
1734        br.close_browser().unwrap();
1735    }
1736    #[test]
1737    #[cfg(target_os="macos")]
1738    fn saf_inspe() {
1739        let mut saf_op = SafariOptions::new();
1740        saf_op.enable_automatic_inspection();
1741        let mut br = Browser::start_safari_session_with_options(saf_op).unwrap();
1742        br.open("https://vk.com/").unwrap();
1743        br.close_browser().unwrap();
1744    }
1745    #[test]
1746    #[cfg(target_os="macos")]
1747    fn saf_profi() {
1748        let mut saf_op = SafariOptions::new();
1749        saf_op.enable_automatic_profiling();
1750        let mut br = Browser::start_safari_session_with_options(saf_op).unwrap();
1751        br.open("https://vk.com/").unwrap();
1752        br.close_browser().unwrap();
1753    }
1754}