1 <?php
2 
3 namespace Facebook\WebDriver\Interactions;
4 
5 use Facebook\WebDriver\Interactions\Internal\WebDriverButtonReleaseAction;
6 use Facebook\WebDriver\Interactions\Internal\WebDriverClickAction;
7 use Facebook\WebDriver\Interactions\Internal\WebDriverClickAndHoldAction;
8 use Facebook\WebDriver\Interactions\Internal\WebDriverContextClickAction;
9 use Facebook\WebDriver\Interactions\Internal\WebDriverDoubleClickAction;
10 use Facebook\WebDriver\Interactions\Internal\WebDriverKeyDownAction;
11 use Facebook\WebDriver\Interactions\Internal\WebDriverKeyUpAction;
12 use Facebook\WebDriver\Interactions\Internal\WebDriverMouseMoveAction;
13 use Facebook\WebDriver\Interactions\Internal\WebDriverMoveToOffsetAction;
14 use Facebook\WebDriver\Interactions\Internal\WebDriverSendKeysAction;
15 use Facebook\WebDriver\WebDriverElement;
16 use Facebook\WebDriver\WebDriverHasInputDevices;
17 
18 /**
19  * WebDriver action builder. It implements the builder pattern.
20  */
21 class WebDriverActions
22 {
23     protected $driver;
24     protected $keyboard;
25     protected $mouse;
26     protected $action;
27 
28     /**
29      * @param WebDriverHasInputDevices $driver
30      */
31     public function __construct(WebDriverHasInputDevices $driver)
32     {
33         $this->driver = $driver;
34         $this->keyboard = $driver->getKeyboard();
35         $this->mouse = $driver->getMouse();
36         $this->action = new WebDriverCompositeAction();
37     }
38 
39     /**
40      * A convenience method for performing the actions without calling build().
41      */
42     public function perform()
43     {
44         $this->action->perform();
45     }
46 
47     /**
48      * Mouse click.
49      * If $element is provided, move to the middle of the element first.
50      *
51      * @param WebDriverElement $element
52      * @return WebDriverActions
53      */
54     public function click(WebDriverElement $element = null)
55     {
56         $this->action->addAction(
57             new WebDriverClickAction($this->mouse, $element)
58         );
59 
60         return $this;
61     }
62 
63     /**
64      * Mouse click and hold.
65      * If $element is provided, move to the middle of the element first.
66      *
67      * @param WebDriverElement $element
68      * @return WebDriverActions
69      */
70     public function clickAndHold(WebDriverElement $element = null)
71     {
72         $this->action->addAction(
73             new WebDriverClickAndHoldAction($this->mouse, $element)
74         );
75 
76         return $this;
77     }
78 
79     /**
80      * Context-click (right click).
81      * If $element is provided, move to the middle of the element first.
82      *
83      * @param WebDriverElement $element
84      * @return WebDriverActions
85      */
86     public function contextClick(WebDriverElement $element = null)
87     {
88         $this->action->addAction(
89             new WebDriverContextClickAction($this->mouse, $element)
90         );
91 
92         return $this;
93     }
94 
95     /**
96      * Double click.
97      * If $element is provided, move to the middle of the element first.
98      *
99      * @param WebDriverElement $element
100      * @return WebDriverActions
101      */
102     public function doubleClick(WebDriverElement $element = null)
103     {
104         $this->action->addAction(
105             new WebDriverDoubleClickAction($this->mouse, $element)
106         );
107 
108         return $this;
109     }
110 
111     /**
112      * Drag and drop from $source to $target.
113      *
114      * @param WebDriverElement $source
115      * @param WebDriverElement $target
116      * @return WebDriverActions
117      */
118     public function dragAndDrop(WebDriverElement $source, WebDriverElement $target)
119     {
120         $this->action->addAction(
121             new WebDriverClickAndHoldAction($this->mouse, $source)
122         );
123         $this->action->addAction(
124             new WebDriverMouseMoveAction($this->mouse, $target)
125         );
126         $this->action->addAction(
127             new WebDriverButtonReleaseAction($this->mouse, $target)
128         );
129 
130         return $this;
131     }
132 
133     /**
134      * Drag $source and drop by offset ($x_offset, $y_offset).
135      *
136      * @param WebDriverElement $source
137      * @param int $x_offset
138      * @param int $y_offset
139      * @return WebDriverActions
140      */
141     public function dragAndDropBy(WebDriverElement $source, $x_offset, $y_offset)
142     {
143         $this->action->addAction(
144             new WebDriverClickAndHoldAction($this->mouse, $source)
145         );
146         $this->action->addAction(
147             new WebDriverMoveToOffsetAction($this->mouse, null, $x_offset, $y_offset)
148         );
149         $this->action->addAction(
150             new WebDriverButtonReleaseAction($this->mouse, null)
151         );
152 
153         return $this;
154     }
155 
156     /**
157      * Mouse move by offset.
158      *
159      * @param int $x_offset
160      * @param int $y_offset
161      * @return WebDriverActions
162      */
163     public function moveByOffset($x_offset, $y_offset)
164     {
165         $this->action->addAction(
166             new WebDriverMoveToOffsetAction($this->mouse, null, $x_offset, $y_offset)
167         );
168 
169         return $this;
170     }
171 
172     /**
173      * Move to the middle of the given WebDriverElement.
174      * Extra shift, calculated from the top-left corner of the element, can be set by passing $x_offset and $y_offset
175      * parameters.
176      *
177      * @param WebDriverElement $element
178      * @param int $x_offset
179      * @param int $y_offset
180      * @return WebDriverActions
181      */
182     public function moveToElement(WebDriverElement $element, $x_offset = null, $y_offset = null)
183     {
184         $this->action->addAction(new WebDriverMoveToOffsetAction(
185             $this->mouse,
186             $element,
187             $x_offset,
188             $y_offset
189         ));
190 
191         return $this;
192     }
193 
194     /**
195      * Release the mouse button.
196      * If $element is provided, move to the middle of the element first.
197      *
198      * @param WebDriverElement $element
199      * @return WebDriverActions
200      */
201     public function release(WebDriverElement $element = null)
202     {
203         $this->action->addAction(
204             new WebDriverButtonReleaseAction($this->mouse, $element)
205         );
206 
207         return $this;
208     }
209 
210     /**
211      * Press a key on keyboard.
212      * If $element is provided, focus on that element first.
213      *
214      * @see WebDriverKeys for special keys like CONTROL, ALT, etc.
215      * @param WebDriverElement $element
216      * @param string $key
217      * @return WebDriverActions
218      */
219     public function keyDown(WebDriverElement $element = null, $key = null)
220     {
221         $this->action->addAction(
222             new WebDriverKeyDownAction($this->keyboard, $this->mouse, $element, $key)
223         );
224 
225         return $this;
226     }
227 
228     /**
229      * Release a key on keyboard.
230      * If $element is provided, focus on that element first.
231      *
232      * @see WebDriverKeys for special keys like CONTROL, ALT, etc.
233      * @param WebDriverElement $element
234      * @param string $key
235      * @return WebDriverActions
236      */
237     public function keyUp(WebDriverElement $element = null, $key = null)
238     {
239         $this->action->addAction(
240             new WebDriverKeyUpAction($this->keyboard, $this->mouse, $element, $key)
241         );
242 
243         return $this;
244     }
245 
246     /**
247      * Send keys by keyboard.
248      * If $element is provided, focus on that element first (using single mouse click).
249      *
250      * @see WebDriverKeys for special keys like CONTROL, ALT, etc.
251      * @param WebDriverElement $element
252      * @param string $keys
253      * @return WebDriverActions
254      */
255     public function sendKeys(WebDriverElement $element = null, $keys = null)
256     {
257         $this->action->addAction(
258             new WebDriverSendKeysAction(
259                 $this->keyboard,
260                 $this->mouse,
261                 $element,
262                 $keys
263             )
264         );
265 
266         return $this;
267     }
268 }
269