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