selenium_webdriver/
actions.rs

1use serde::{Serialize,Deserialize};
2use super::specialkey::*;
3use super::element::*;
4
5///Main actions struct
6/// 
7/// The Actions which should be permormed via the perform_actions and release_actions methods of the Browser instance,
8/// may consist of keys actions, scroll wheel actions and mouse actions. Once you construct the corresponding actions sequence
9/// it should be passed to the add_..._actions method to be added to the main Actions instance.
10/// When constructing complex scenarious with multiple input sources(key,mouse,wheel), you need to use pauses
11/// to syncronize actions and achieve more predictable result
12/// (see "https://www.w3.org/TR/webdriver/#actions" for more details).
13/// 
14/// The order of the adding input source to Actions may also influence the outcome.
15/// 
16/// # Examples
17/// ```
18/// # use selenium_webdriver::*;
19/// let mut mouse = ActionsMouse::new();
20/// let mut keys = ActionsKeys::new();
21/// mouse.press_mouse_button(MouseButton::Left).pause(0).release_mouse_button(MouseButton::Left);
22/// keys.pause(0).press_special_key(SpecialKey::Enter);
23/// let mut actions = Actions::new();
24/// actions.add_mouse_actions(mouse).add_key_actions(keys);
25/// ```
26
27#[derive(Serialize,Deserialize,Debug)]
28pub struct Actions{
29   pub(crate) actions:Vec<serde_json::Value>,
30}
31
32impl Actions{
33    pub fn new()->Actions{
34        Actions{
35            actions: vec![],
36        }
37    }
38    pub(crate) fn set_ids(&mut self){
39        let mut act_with_ids = vec![];
40        let len = self.actions.len();
41        for i in 0..len{
42            let mut st = serde_json::to_string(&self.actions[i]).unwrap();
43            st.pop();
44            let id = format!(r#","id":"{}"}}"#,i+1);
45            st.push_str(&id);
46            let v = serde_json::from_str(&st).unwrap();
47            act_with_ids.push(v);
48        }
49        self.actions = act_with_ids;
50    }
51    /// Add the key actions sequence to the global list of actions
52    /// 
53    /// # Examples
54    /// 
55    /// ```
56    /// # use selenium_webdriver::*;
57    /// 
58    /// let mut keys = ActionsKeys::new();
59    /// keys.press_special_key(SpecialKey::ShiftLeft).press_key("a");
60    /// let mut actions = Actions::new();
61    /// actions.add_key_actions(keys);
62    /// ```
63    pub fn add_key_actions(&mut self, key_actions:ActionsKeys)->&mut Self{
64        let temp_val = serde_json::to_string(&key_actions).unwrap();
65        let mut arr:Vec<u8> = temp_val.bytes().collect();
66        arr.remove(0);
67        arr.pop();
68        let temp_val = String::from_utf8(arr).unwrap();
69        let temp_string = format!(r#"{{"type":"key",{}}}"#,temp_val);
70        let val = serde_json::from_str(&temp_string).unwrap();
71        self.actions.push(val);
72        self
73    }
74    pub fn add_mouse_actions(&mut self,mouse_actions:ActionsMouse)->&mut Self{
75        let temp_val = serde_json::to_string(&mouse_actions).unwrap();
76        let mut arr:Vec<u8> = temp_val.bytes().collect();
77        arr.remove(0);
78        arr.pop();
79        let temp_val = String::from_utf8(arr).unwrap();
80        let temp_string = format!(r#"{{"type":"pointer",{}}}"#,temp_val);
81        let val = serde_json::from_str(&temp_string).unwrap();
82        self.actions.push(val);
83        self
84    }
85    pub fn add_wheel_actions(&mut self,wheel_actions:ActionsWheel)->&mut Self{
86        let temp_val = serde_json::to_string(&wheel_actions).unwrap();
87        let mut arr:Vec<u8> = temp_val.bytes().collect();
88        arr.remove(0);
89        arr.pop();
90        let temp_val = String::from_utf8(arr).unwrap();
91        let temp_string = format!(r#"{{"type":"wheel",{}}}"#,temp_val);
92        let val = serde_json::from_str(&temp_string).unwrap();
93        self.actions.push(val);
94        self
95    }
96}
97///Struct to create the key actions sequence
98#[derive(Serialize,Deserialize,Debug)]
99pub struct ActionsKeys{
100    pub(crate) actions:Vec<serde_json::Value>,
101}
102impl ActionsKeys{
103    pub fn new()->ActionsKeys{
104        ActionsKeys{
105            actions: vec![],
106        }
107    }
108    pub fn press_key(&mut self,key:&str)->&mut Self{
109       let json = format!(r#"{{"type":"keyDown","value":"{}"}}"#,key);
110       let val = serde_json::from_str(&json).unwrap();
111       self.actions.push(val);
112       self
113    }
114    pub fn release_key(&mut self,key:&str)->&mut Self{
115        let json = format!(r#"{{"type":"keyUp","value":"{}"}}"#,key);
116       let val = serde_json::from_str(&json).unwrap();
117       self.actions.push(val);
118       self
119    }
120    pub fn press_special_key(&mut self,spec_key:SpecialKey)->&mut Self{
121        let key = spec_key_to_string(spec_key);
122        let json = format!(r#"{{"type":"keyDown","value":"{}"}}"#,key);
123        let val = serde_json::from_str(&json).unwrap();
124        self.actions.push(val);
125        self
126    }
127    pub fn release_special_key(&mut self,spec_key:SpecialKey)->&mut Self{
128        let key = spec_key_to_string(spec_key);
129        let json = format!(r#"{{"type":"keyUp","value":"{}"}}"#,key);
130        let val = serde_json::from_str(&json).unwrap();
131        self.actions.push(val);
132        self
133    }
134    pub fn pause(&mut self,duration:u32)->&mut Self{
135        let json = format!(r#"{{"type":"pause","duration":{}}}"#,duration);
136        let val = serde_json::from_str(&json).unwrap();
137        self.actions.push(val);
138        self
139    }
140}
141fn spec_key_to_string(spec_key:SpecialKey)->&'static str{
142        match spec_key{
143            SpecialKey::ShiftLeft=>r"\uE008",
144            SpecialKey::ShiftRight=>r"\uE050",
145            SpecialKey::LeftCtrl=>r"\uE009",
146            SpecialKey::RightCtrl=>r"\uE051",
147            SpecialKey::F1=>r"\uE031",
148            SpecialKey::F2=>r"\uE032",
149            SpecialKey::F3=>r"\uE033",
150            SpecialKey::F4=>r"\uE034",
151            SpecialKey::F5=>r"\uE035",
152            SpecialKey::F6=>r"\uE036",
153            SpecialKey::F7=>r"\uE037",
154            SpecialKey::F8=>r"\uE038",
155            SpecialKey::F9=>r"\uE039",
156            SpecialKey::F10=>r"\uE03A",
157            SpecialKey::F11=>r"\uE03B",
158            SpecialKey::F12=>r"\uE03C",
159            SpecialKey::EndOne=>r"\uE010",
160            SpecialKey::HomeOne=>r"\uE011",
161            SpecialKey::EndTwo=>r"\uE056",
162            SpecialKey::HomeTwo=>r"\uE057",
163            SpecialKey::PageUpOne=>r"\uE00E",
164            SpecialKey::PageDownOne=>r"\uE00F",
165            SpecialKey::PageUpTwo=>r"\uE054",
166            SpecialKey::PageDownTwo=>r"\uE055",
167            SpecialKey::OSLeft=>r"\uE03D",
168            SpecialKey::OSRight=>r"\uE053",
169            SpecialKey::ZenkakuHankaku=>r"\uE040",
170            SpecialKey::AltLeft=>r"\uE00A",
171            SpecialKey::AltRight=>r"AltRight",
172            SpecialKey::ArrowLeftOne=>r"\uE012",
173            SpecialKey::ArrowRightOne=>r"\uE014",
174            SpecialKey::ArrowUpOne=>r"\uE013",
175            SpecialKey::ArrowDownOne=>r"\uE015",
176            SpecialKey::ArrowLeftTwo=>r"\uE058",
177            SpecialKey::ArrowRightTwo=>r"\uE05A",
178            SpecialKey::ArrowUpTwo=>r"\uE059",
179            SpecialKey::ArrowDownTwo=>r"\uE05B",
180            SpecialKey::InsertOne=>r"\uE016",
181            SpecialKey::InsertTwo=>r"\uE05C",
182            SpecialKey::DeleteOne=>r"\uE017",
183            SpecialKey::DeleteTwo=>r"\uE05D",
184            SpecialKey::Cancel=>r"\uE001",
185            SpecialKey::Help=>r"\uE002",
186            SpecialKey::Tab=>r"\uE004",
187            SpecialKey::Backspace=>r"\uE003",
188            SpecialKey::Clear=>r"\uE005",
189            SpecialKey::Return=>r"\uE006",
190            SpecialKey::Enter=>r"\uE006",
191            SpecialKey::Pause=>r"\uE00B",
192            SpecialKey::Escape=>r"\uE00C",
193            SpecialKey::Space=>r"\uE00D",
194            SpecialKey::Numpad0=>r"\uE05C",
195            SpecialKey::Numpad1=>r"\uE056",
196            SpecialKey::Numpad2=>r"\uE05B",
197            SpecialKey::Numpad3=>r"\uE055",
198            SpecialKey::Numpad4=>r"\uE058",
199            SpecialKey::Numpad5=>r"\uE01F",
200            SpecialKey::Numpad6=>r"\uE05A",
201            SpecialKey::Numpad7=>r"\uE057",
202            SpecialKey::Numpad8=>r"\uE059",
203            SpecialKey::Numpad9=>r"\uE054",
204            SpecialKey::NumpadAdd=>r"\uE025",
205            SpecialKey::NumpadComma=>r"\uE026",
206            SpecialKey::NumpadDecimal=>r"\uE05D",
207            SpecialKey::NumpadDivide=>r"\uE029",
208            SpecialKey::NumpadEnter=>r"\uE007",
209            SpecialKey::NumpadMultiply=>r"\uE024",
210            SpecialKey::NumpadSubtract=>r"\uE027",
211        }
212}
213///Struct to create the mouse actions sequence
214#[derive(Serialize,Deserialize,Debug)]
215pub struct ActionsMouse{
216    pub(crate) actions:Vec<serde_json::Value>,
217}
218impl ActionsMouse{
219    pub fn new()->ActionsMouse{
220        ActionsMouse{
221            actions: vec![],
222        }
223    }
224    pub fn pause(&mut self,duration:u32)->&mut Self{
225        let json = format!(r#"{{"type":"pause","duration":{}}}"#,duration);
226        let val = serde_json::from_str(&json).unwrap();
227        self.actions.push(val);
228        self
229    }
230    pub fn press_mouse_button(&mut self,button: MouseButton)->&mut Self{
231        let key = mouse_button_to_string(button);
232        let json = format!(r#"{{"type":"pointerDown","button":{}}}"#,key);
233        let val = serde_json::from_str(&json).unwrap();
234        self.actions.push(val);
235        self
236    }
237    pub fn release_mouse_button(&mut self,button: MouseButton)->&mut Self{
238        let key = mouse_button_to_string(button);
239        let json = format!(r#"{{"type":"pointerUp","button":{}}}"#,key);
240        let val = serde_json::from_str(&json).unwrap();
241        self.actions.push(val);
242        self
243    }
244    /// The point's coordinates are relative to the viewport, if x or y is larger
245    /// than the coordinate of the viewport, you will get an error calling
246    /// the perform_actions method of the Browser
247    pub fn move_mouse_to_point(&mut self, x: i32,y: i32)->&mut Self{
248        let json = format!(r#"{{"type":"pointerMove","duration":0,"origin":"viewport","x":{},"y":{}}}"#,x,y);
249        let val = serde_json::from_str(&json).unwrap();
250        self.actions.push(val);
251        self
252    }
253    /// Moves mouse to the center of the element. Will cause an error if the element is not in the viewport
254    pub fn move_mouse_to_element(&mut self,element:&Element)->&mut Self{
255        let el = element.get_element_rect().unwrap();
256        self.move_mouse_to_point(el.x as i32+el.width/2, el.y as i32 +el.height/2);
257        self
258    }
259    pub fn cancel_action(&mut self)->&mut Self{
260        let json =r#"{"type":"pointerCancel"}"#;
261        let val = serde_json::from_str(&json).unwrap();
262        self.actions.push(val);
263        self
264    }
265    ///Drag one element and drop it on another one.
266    pub fn drag_n_drop(&mut self,elem_to_drag:Element,elem_destination:Element)->&mut Self{
267        self.move_mouse_to_element(&elem_to_drag)
268        .press_mouse_button(MouseButton::Left)
269        .move_mouse_to_element(&elem_destination)
270        .release_mouse_button(MouseButton::Left);
271        self
272    }
273}
274fn mouse_button_to_string(button:MouseButton)->u8{
275    match button{
276        MouseButton::Left=>0,
277        MouseButton::Middle=>1,
278        MouseButton::Right=>2,
279        MouseButton::X1Back=>3,
280        MouseButton::X2Forward=>4
281    }
282}
283///Struct to create the wheel actions sequence
284#[derive(Serialize,Deserialize,Debug)]
285pub struct ActionsWheel{
286    pub(crate) actions:Vec<serde_json::Value>,
287}
288impl ActionsWheel{
289    pub fn new()->ActionsWheel{
290        ActionsWheel{
291            actions: vec![],
292        }
293    }
294    pub fn pause(&mut self,duration:u32)->&mut Self{
295        let json = format!(r#"{{"type":"pause","duration":{}}}"#,duration);
296        let val = serde_json::from_str(&json).unwrap();
297        self.actions.push(val);
298        self
299    }
300    ///Scroll by number of pixels (x-axis and y-axis) from a starting position within the viewport.
301    ///The value of pixels to scroll may be both positive and negative.
302    /// # Examples
303    /// ```
304    /// # use selenium_webdriver::*;
305    /// let mut wheel = ActionsWheel::new();
306    /// wheel.scroll(0, 0, 100, 100).scroll(100, 100, 100, 100);
307    /// ```
308    pub fn scroll(&mut self,
309                  init_x_position:i32,
310                  init_y_position:i32,
311                  x_axis_scroll:i32,
312                  y_axis_scroll:i32)->&mut Self{
313        let json = format!(r#"{{"type":"scroll",
314                            "x":{},
315                            "y":{},
316                            "deltaX":{},
317                            "deltaY":{}}}"#,init_x_position,init_y_position,x_axis_scroll,y_axis_scroll);
318        let val = serde_json::from_str(&json).unwrap();
319        self.actions.push(val);
320        self
321    }
322}
323
324mod actions_tests{
325    use super::*;
326    #[test]
327    fn actions_vec_lens() {
328        let mut ac = Actions::new();
329        let mut ma = ActionsMouse::new();
330        ma.press_mouse_button(MouseButton::Left);
331        ma.pause(5);
332        ma.press_mouse_button(MouseButton::Right);
333        assert!(ma.actions.len()==3);
334        ac.add_mouse_actions(ma);
335        assert!(ac.actions.len()==1);
336        }
337}