xref: /plugin/combo/vendor/php-webdriver/webdriver/lib/Remote/RemoteMouse.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
1*04fd306cSNickeau<?php
2*04fd306cSNickeau
3*04fd306cSNickeaunamespace Facebook\WebDriver\Remote;
4*04fd306cSNickeau
5*04fd306cSNickeauuse Facebook\WebDriver\Interactions\Internal\WebDriverCoordinates;
6*04fd306cSNickeauuse Facebook\WebDriver\WebDriverMouse;
7*04fd306cSNickeau
8*04fd306cSNickeau/**
9*04fd306cSNickeau * Execute mouse commands for RemoteWebDriver.
10*04fd306cSNickeau */
11*04fd306cSNickeauclass RemoteMouse implements WebDriverMouse
12*04fd306cSNickeau{
13*04fd306cSNickeau    /** @internal */
14*04fd306cSNickeau    const BUTTON_LEFT = 0;
15*04fd306cSNickeau    /** @internal */
16*04fd306cSNickeau    const BUTTON_MIDDLE = 1;
17*04fd306cSNickeau    /** @internal */
18*04fd306cSNickeau    const BUTTON_RIGHT = 2;
19*04fd306cSNickeau
20*04fd306cSNickeau    /**
21*04fd306cSNickeau     * @var RemoteExecuteMethod
22*04fd306cSNickeau     */
23*04fd306cSNickeau    private $executor;
24*04fd306cSNickeau    /**
25*04fd306cSNickeau     * @var bool
26*04fd306cSNickeau     */
27*04fd306cSNickeau    private $isW3cCompliant;
28*04fd306cSNickeau
29*04fd306cSNickeau    /**
30*04fd306cSNickeau     * @param RemoteExecuteMethod $executor
31*04fd306cSNickeau     * @param bool $isW3cCompliant
32*04fd306cSNickeau     */
33*04fd306cSNickeau    public function __construct(RemoteExecuteMethod $executor, $isW3cCompliant = false)
34*04fd306cSNickeau    {
35*04fd306cSNickeau        $this->executor = $executor;
36*04fd306cSNickeau        $this->isW3cCompliant = $isW3cCompliant;
37*04fd306cSNickeau    }
38*04fd306cSNickeau
39*04fd306cSNickeau    /**
40*04fd306cSNickeau     * @param null|WebDriverCoordinates $where
41*04fd306cSNickeau     *
42*04fd306cSNickeau     * @return RemoteMouse
43*04fd306cSNickeau     */
44*04fd306cSNickeau    public function click(WebDriverCoordinates $where = null)
45*04fd306cSNickeau    {
46*04fd306cSNickeau        if ($this->isW3cCompliant) {
47*04fd306cSNickeau            $moveAction = $where ? [$this->createMoveAction($where)] : [];
48*04fd306cSNickeau            $this->executor->execute(DriverCommand::ACTIONS, [
49*04fd306cSNickeau                'actions' => [
50*04fd306cSNickeau                    [
51*04fd306cSNickeau                        'type' => 'pointer',
52*04fd306cSNickeau                        'id' => 'mouse',
53*04fd306cSNickeau                        'parameters' => ['pointerType' => 'mouse'],
54*04fd306cSNickeau                        'actions' => array_merge($moveAction, $this->createClickActions()),
55*04fd306cSNickeau                    ],
56*04fd306cSNickeau                ],
57*04fd306cSNickeau            ]);
58*04fd306cSNickeau
59*04fd306cSNickeau            return $this;
60*04fd306cSNickeau        }
61*04fd306cSNickeau
62*04fd306cSNickeau        $this->moveIfNeeded($where);
63*04fd306cSNickeau        $this->executor->execute(DriverCommand::CLICK, [
64*04fd306cSNickeau            'button' => self::BUTTON_LEFT,
65*04fd306cSNickeau        ]);
66*04fd306cSNickeau
67*04fd306cSNickeau        return $this;
68*04fd306cSNickeau    }
69*04fd306cSNickeau
70*04fd306cSNickeau    /**
71*04fd306cSNickeau     * @param WebDriverCoordinates $where
72*04fd306cSNickeau     *
73*04fd306cSNickeau     * @return RemoteMouse
74*04fd306cSNickeau     */
75*04fd306cSNickeau    public function contextClick(WebDriverCoordinates $where = null)
76*04fd306cSNickeau    {
77*04fd306cSNickeau        if ($this->isW3cCompliant) {
78*04fd306cSNickeau            $moveAction = $where ? [$this->createMoveAction($where)] : [];
79*04fd306cSNickeau            $this->executor->execute(DriverCommand::ACTIONS, [
80*04fd306cSNickeau                'actions' => [
81*04fd306cSNickeau                    [
82*04fd306cSNickeau                        'type' => 'pointer',
83*04fd306cSNickeau                        'id' => 'mouse',
84*04fd306cSNickeau                        'parameters' => ['pointerType' => 'mouse'],
85*04fd306cSNickeau                        'actions' => array_merge($moveAction, [
86*04fd306cSNickeau                            [
87*04fd306cSNickeau                                'type' => 'pointerDown',
88*04fd306cSNickeau                                'button' => self::BUTTON_RIGHT,
89*04fd306cSNickeau                            ],
90*04fd306cSNickeau                            [
91*04fd306cSNickeau                                'type' => 'pointerUp',
92*04fd306cSNickeau                                'button' => self::BUTTON_RIGHT,
93*04fd306cSNickeau                            ],
94*04fd306cSNickeau                        ]),
95*04fd306cSNickeau                    ],
96*04fd306cSNickeau                ],
97*04fd306cSNickeau            ]);
98*04fd306cSNickeau
99*04fd306cSNickeau            return $this;
100*04fd306cSNickeau        }
101*04fd306cSNickeau
102*04fd306cSNickeau        $this->moveIfNeeded($where);
103*04fd306cSNickeau        $this->executor->execute(DriverCommand::CLICK, [
104*04fd306cSNickeau            'button' => self::BUTTON_RIGHT,
105*04fd306cSNickeau        ]);
106*04fd306cSNickeau
107*04fd306cSNickeau        return $this;
108*04fd306cSNickeau    }
109*04fd306cSNickeau
110*04fd306cSNickeau    /**
111*04fd306cSNickeau     * @param WebDriverCoordinates $where
112*04fd306cSNickeau     *
113*04fd306cSNickeau     * @return RemoteMouse
114*04fd306cSNickeau     */
115*04fd306cSNickeau    public function doubleClick(WebDriverCoordinates $where = null)
116*04fd306cSNickeau    {
117*04fd306cSNickeau        if ($this->isW3cCompliant) {
118*04fd306cSNickeau            $clickActions = $this->createClickActions();
119*04fd306cSNickeau            $moveAction = $where === null ? [] : [$this->createMoveAction($where)];
120*04fd306cSNickeau            $this->executor->execute(DriverCommand::ACTIONS, [
121*04fd306cSNickeau                'actions' => [
122*04fd306cSNickeau                    [
123*04fd306cSNickeau                        'type' => 'pointer',
124*04fd306cSNickeau                        'id' => 'mouse',
125*04fd306cSNickeau                        'parameters' => ['pointerType' => 'mouse'],
126*04fd306cSNickeau                        'actions' => array_merge($moveAction, $clickActions, $clickActions),
127*04fd306cSNickeau                    ],
128*04fd306cSNickeau                ],
129*04fd306cSNickeau            ]);
130*04fd306cSNickeau
131*04fd306cSNickeau            return $this;
132*04fd306cSNickeau        }
133*04fd306cSNickeau
134*04fd306cSNickeau        $this->moveIfNeeded($where);
135*04fd306cSNickeau        $this->executor->execute(DriverCommand::DOUBLE_CLICK);
136*04fd306cSNickeau
137*04fd306cSNickeau        return $this;
138*04fd306cSNickeau    }
139*04fd306cSNickeau
140*04fd306cSNickeau    /**
141*04fd306cSNickeau     * @param WebDriverCoordinates $where
142*04fd306cSNickeau     *
143*04fd306cSNickeau     * @return RemoteMouse
144*04fd306cSNickeau     */
145*04fd306cSNickeau    public function mouseDown(WebDriverCoordinates $where = null)
146*04fd306cSNickeau    {
147*04fd306cSNickeau        if ($this->isW3cCompliant) {
148*04fd306cSNickeau            $this->executor->execute(DriverCommand::ACTIONS, [
149*04fd306cSNickeau                'actions' => [
150*04fd306cSNickeau                    [
151*04fd306cSNickeau                        'type' => 'pointer',
152*04fd306cSNickeau                        'id' => 'mouse',
153*04fd306cSNickeau                        'parameters' => ['pointerType' => 'mouse'],
154*04fd306cSNickeau                        'actions' => [
155*04fd306cSNickeau                            $this->createMoveAction($where),
156*04fd306cSNickeau                            [
157*04fd306cSNickeau                                'type' => 'pointerDown',
158*04fd306cSNickeau                                'button' => self::BUTTON_LEFT,
159*04fd306cSNickeau                            ],
160*04fd306cSNickeau                        ],
161*04fd306cSNickeau                    ],
162*04fd306cSNickeau                ],
163*04fd306cSNickeau            ]);
164*04fd306cSNickeau
165*04fd306cSNickeau            return $this;
166*04fd306cSNickeau        }
167*04fd306cSNickeau
168*04fd306cSNickeau        $this->moveIfNeeded($where);
169*04fd306cSNickeau        $this->executor->execute(DriverCommand::MOUSE_DOWN);
170*04fd306cSNickeau
171*04fd306cSNickeau        return $this;
172*04fd306cSNickeau    }
173*04fd306cSNickeau
174*04fd306cSNickeau    /**
175*04fd306cSNickeau     * @param WebDriverCoordinates $where
176*04fd306cSNickeau     * @param int|null $x_offset
177*04fd306cSNickeau     * @param int|null $y_offset
178*04fd306cSNickeau     *
179*04fd306cSNickeau     * @return RemoteMouse
180*04fd306cSNickeau     */
181*04fd306cSNickeau    public function mouseMove(
182*04fd306cSNickeau        WebDriverCoordinates $where = null,
183*04fd306cSNickeau        $x_offset = null,
184*04fd306cSNickeau        $y_offset = null
185*04fd306cSNickeau    ) {
186*04fd306cSNickeau        if ($this->isW3cCompliant) {
187*04fd306cSNickeau            $this->executor->execute(DriverCommand::ACTIONS, [
188*04fd306cSNickeau                'actions' => [
189*04fd306cSNickeau                    [
190*04fd306cSNickeau                        'type' => 'pointer',
191*04fd306cSNickeau                        'id' => 'mouse',
192*04fd306cSNickeau                        'parameters' => ['pointerType' => 'mouse'],
193*04fd306cSNickeau                        'actions' => [$this->createMoveAction($where, $x_offset, $y_offset)],
194*04fd306cSNickeau                    ],
195*04fd306cSNickeau                ],
196*04fd306cSNickeau            ]);
197*04fd306cSNickeau
198*04fd306cSNickeau            return $this;
199*04fd306cSNickeau        }
200*04fd306cSNickeau
201*04fd306cSNickeau        $params = [];
202*04fd306cSNickeau        if ($where !== null) {
203*04fd306cSNickeau            $params['element'] = $where->getAuxiliary();
204*04fd306cSNickeau        }
205*04fd306cSNickeau        if ($x_offset !== null) {
206*04fd306cSNickeau            $params['xoffset'] = $x_offset;
207*04fd306cSNickeau        }
208*04fd306cSNickeau        if ($y_offset !== null) {
209*04fd306cSNickeau            $params['yoffset'] = $y_offset;
210*04fd306cSNickeau        }
211*04fd306cSNickeau
212*04fd306cSNickeau        $this->executor->execute(DriverCommand::MOVE_TO, $params);
213*04fd306cSNickeau
214*04fd306cSNickeau        return $this;
215*04fd306cSNickeau    }
216*04fd306cSNickeau
217*04fd306cSNickeau    /**
218*04fd306cSNickeau     * @param WebDriverCoordinates $where
219*04fd306cSNickeau     *
220*04fd306cSNickeau     * @return RemoteMouse
221*04fd306cSNickeau     */
222*04fd306cSNickeau    public function mouseUp(WebDriverCoordinates $where = null)
223*04fd306cSNickeau    {
224*04fd306cSNickeau        if ($this->isW3cCompliant) {
225*04fd306cSNickeau            $moveAction = $where ? [$this->createMoveAction($where)] : [];
226*04fd306cSNickeau
227*04fd306cSNickeau            $this->executor->execute(DriverCommand::ACTIONS, [
228*04fd306cSNickeau                'actions' => [
229*04fd306cSNickeau                    [
230*04fd306cSNickeau                        'type' => 'pointer',
231*04fd306cSNickeau                        'id' => 'mouse',
232*04fd306cSNickeau                        'parameters' => ['pointerType' => 'mouse'],
233*04fd306cSNickeau                        'actions' => array_merge($moveAction, [
234*04fd306cSNickeau                            [
235*04fd306cSNickeau                                'type' => 'pointerUp',
236*04fd306cSNickeau                                'button' => self::BUTTON_LEFT,
237*04fd306cSNickeau                            ],
238*04fd306cSNickeau                        ]),
239*04fd306cSNickeau                    ],
240*04fd306cSNickeau                ],
241*04fd306cSNickeau            ]);
242*04fd306cSNickeau
243*04fd306cSNickeau            return $this;
244*04fd306cSNickeau        }
245*04fd306cSNickeau
246*04fd306cSNickeau        $this->moveIfNeeded($where);
247*04fd306cSNickeau        $this->executor->execute(DriverCommand::MOUSE_UP);
248*04fd306cSNickeau
249*04fd306cSNickeau        return $this;
250*04fd306cSNickeau    }
251*04fd306cSNickeau
252*04fd306cSNickeau    /**
253*04fd306cSNickeau     * @param WebDriverCoordinates $where
254*04fd306cSNickeau     */
255*04fd306cSNickeau    protected function moveIfNeeded(WebDriverCoordinates $where = null)
256*04fd306cSNickeau    {
257*04fd306cSNickeau        if ($where) {
258*04fd306cSNickeau            $this->mouseMove($where);
259*04fd306cSNickeau        }
260*04fd306cSNickeau    }
261*04fd306cSNickeau
262*04fd306cSNickeau    /**
263*04fd306cSNickeau     * @param WebDriverCoordinates $where
264*04fd306cSNickeau     * @param int|null $x_offset
265*04fd306cSNickeau     * @param int|null $y_offset
266*04fd306cSNickeau     *
267*04fd306cSNickeau     * @return array
268*04fd306cSNickeau     */
269*04fd306cSNickeau    private function createMoveAction(
270*04fd306cSNickeau        WebDriverCoordinates $where = null,
271*04fd306cSNickeau        $x_offset = null,
272*04fd306cSNickeau        $y_offset = null
273*04fd306cSNickeau    ) {
274*04fd306cSNickeau        $move_action = [
275*04fd306cSNickeau            'type' => 'pointerMove',
276*04fd306cSNickeau            'duration' => 100, // to simulate human delay
277*04fd306cSNickeau            'x' => $x_offset === null ? 0 : $x_offset,
278*04fd306cSNickeau            'y' => $y_offset === null ? 0 : $y_offset,
279*04fd306cSNickeau        ];
280*04fd306cSNickeau
281*04fd306cSNickeau        if ($where !== null) {
282*04fd306cSNickeau            $move_action['origin'] = [JsonWireCompat::WEB_DRIVER_ELEMENT_IDENTIFIER => $where->getAuxiliary()];
283*04fd306cSNickeau        } else {
284*04fd306cSNickeau            $move_action['origin'] = 'pointer';
285*04fd306cSNickeau        }
286*04fd306cSNickeau
287*04fd306cSNickeau        return $move_action;
288*04fd306cSNickeau    }
289*04fd306cSNickeau
290*04fd306cSNickeau    /**
291*04fd306cSNickeau     * @return array
292*04fd306cSNickeau     */
293*04fd306cSNickeau    private function createClickActions()
294*04fd306cSNickeau    {
295*04fd306cSNickeau        return [
296*04fd306cSNickeau            [
297*04fd306cSNickeau                'type' => 'pointerDown',
298*04fd306cSNickeau                'button' => self::BUTTON_LEFT,
299*04fd306cSNickeau            ],
300*04fd306cSNickeau            [
301*04fd306cSNickeau                'type' => 'pointerUp',
302*04fd306cSNickeau                'button' => self::BUTTON_LEFT,
303*04fd306cSNickeau            ],
304*04fd306cSNickeau        ];
305*04fd306cSNickeau    }
306*04fd306cSNickeau}
307