From da03000bd6a406631f6a320575d824194549223e Mon Sep 17 00:00:00 2001 From: Christian Sciberras Date: Sat, 11 Jan 2025 22:21:51 +0100 Subject: [PATCH 1/4] Fix D&D on Selenium 3 --- src/Selenium2Driver.php | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/Selenium2Driver.php b/src/Selenium2Driver.php index fe8b1650..f8cbb966 100755 --- a/src/Selenium2Driver.php +++ b/src/Selenium2Driver.php @@ -1008,33 +1008,31 @@ public function dragTo(string $sourceXpath, string $destinationXpath) )); $script = <<executeJsOnElement($source, $script); - $this->getWebDriverSession()->buttondown(); - if ($destination->getID() !== $source->getID()) { + if ($destination->getID() === $source->getID()) { + $this->getWebDriverSession()->click(0); + } else { + $this->getWebDriverSession()->buttondown(); $this->getWebDriverSession()->moveto(array( 'element' => $destination->getID() )); + $this->getWebDriverSession()->buttonup(); } - $this->getWebDriverSession()->buttonup(); $script = <<executeJsOnElement($destination, $script); From 9fb6d9cd6f9e8e664a5473c2776ca15bc140c280 Mon Sep 17 00:00:00 2001 From: Christian Sciberras Date: Sun, 19 Jan 2025 18:20:26 +0100 Subject: [PATCH 2/4] Replace selenium events with js events --- src/Selenium2Driver.php | 79 +++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 35 deletions(-) diff --git a/src/Selenium2Driver.php b/src/Selenium2Driver.php index 5f218eb2..3b79d2f9 100755 --- a/src/Selenium2Driver.php +++ b/src/Selenium2Driver.php @@ -1025,42 +1025,51 @@ public function keyUp(string $xpath, $char, ?string $modifier = null) public function dragTo(string $sourceXpath, string $destinationXpath) { - $source = $this->findElement($sourceXpath); - $destination = $this->findElement($destinationXpath); - - $this->getWebDriverSession()->moveto(array( - 'element' => $source->getID() - )); - - $script = <<executeJsOnElement($source, $script); - - if ($destination->getID() === $source->getID()) { - $this->getWebDriverSession()->click(0); - } else { - $this->getWebDriverSession()->buttondown(); - $this->getWebDriverSession()->moveto(array( - 'element' => $destination->getID() - )); - $this->getWebDriverSession()->buttonup(); - } - - $script = <<findElement($sourceXpath); + $target = $this->findElement($destinationXpath); + + $this->getWebDriverSession()->moveto(['element' => $source->getID()]); + + $this->executeJsOnElement($source, <<<'JS' + (function (sourceElement) { + var withPointerEvents = 'PointerEvent' in window; + window['__minkDragAndDropSourceElement'] = sourceElement; + + withPointerEvents && sourceElement.dispatchEvent(new PointerEvent('pointerdown', {bubbles: true, cancelable: true})); + sourceElement.dispatchEvent(new MouseEvent('mousedown', {bubbles: true, cancelable: true})); + sourceElement.dispatchEvent(new DragEvent('dragstart', {bubbles: true, cancelable: true})); + withPointerEvents && sourceElement.dispatchEvent(new PointerEvent('pointercancel', {bubbles: true, cancelable: true})); + withPointerEvents && sourceElement.dispatchEvent(new PointerEvent('pointerout', {bubbles: true, cancelable: true})); + withPointerEvents && sourceElement.dispatchEvent(new PointerEvent('pointerleave', {bubbles: true, cancelable: true})); + }({{ELEMENT}})); +JS + ); - window['__minkDragAndDropSourceElement'].dispatchEvent(new DragEvent('dragend', {bubbles: true, cancelable: true})); -}({{ELEMENT}})); -JS; - $this->executeJsOnElement($destination, $script); + $this->getWebDriverSession()->moveto(['element' => $target->getID()]); + + $this->executeJsOnElement($target, <<<'JS' + (function (targetElement) { + var withPointerEvents = 'PointerEvent' in window; + var sourceElement = window['__minkDragAndDropSourceElement']; + + withPointerEvents && targetElement.dispatchEvent(new PointerEvent('pointerover', {bubbles: true, cancelable: true})); + withPointerEvents && targetElement.dispatchEvent(new PointerEvent('pointerenter', {bubbles: true, cancelable: true})); + sourceElement.dispatchEvent(new MouseEvent('mouseout', {bubbles: true, cancelable: true})); + sourceElement.dispatchEvent(new MouseEvent('mouseleave', {bubbles: true, cancelable: true})); + targetElement.dispatchEvent(new MouseEvent('mouseover', {bubbles: true, cancelable: true})); + targetElement.dispatchEvent(new MouseEvent('mouseenter', {bubbles: true, cancelable: true})); + targetElement.dispatchEvent(new MouseEvent('mousemove', {bubbles: true, cancelable: true})); + withPointerEvents && targetElement.dispatchEvent(new PointerEvent('pointerout', {bubbles: true, cancelable: true})); + withPointerEvents && targetElement.dispatchEvent(new PointerEvent('pointerleave', {bubbles: true, cancelable: true})); + targetElement.dispatchEvent(new MouseEvent('mouseout', {bubbles: true, cancelable: true})); + targetElement.dispatchEvent(new MouseEvent('mouseleave', {bubbles: true, cancelable: true})); + sourceElement.dispatchEvent(new DragEvent('drag', {bubbles: true, cancelable: true})); + targetElement.dispatchEvent(new DragEvent('dragover', {bubbles: true, cancelable: true})); + targetElement.dispatchEvent(new DragEvent('drop', {bubbles: true, cancelable: true})); + sourceElement.dispatchEvent(new DragEvent('dragend', {bubbles: true, cancelable: true})); + }({{ELEMENT}})); +JS + ); } public function executeScript(string $script) From 984f3545bb5b65da79918094cbf2325b1fbbdcfa Mon Sep 17 00:00:00 2001 From: Christian Sciberras Date: Sun, 19 Jan 2025 19:22:40 +0100 Subject: [PATCH 3/4] Simplify code --- src/Selenium2Driver.php | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/src/Selenium2Driver.php b/src/Selenium2Driver.php index 3b79d2f9..940fedb8 100755 --- a/src/Selenium2Driver.php +++ b/src/Selenium2Driver.php @@ -1029,40 +1029,24 @@ public function dragTo(string $sourceXpath, string $destinationXpath) $target = $this->findElement($destinationXpath); $this->getWebDriverSession()->moveto(['element' => $source->getID()]); + $this->getWebDriverSession()->buttondown(); $this->executeJsOnElement($source, <<<'JS' (function (sourceElement) { - var withPointerEvents = 'PointerEvent' in window; window['__minkDragAndDropSourceElement'] = sourceElement; - withPointerEvents && sourceElement.dispatchEvent(new PointerEvent('pointerdown', {bubbles: true, cancelable: true})); - sourceElement.dispatchEvent(new MouseEvent('mousedown', {bubbles: true, cancelable: true})); sourceElement.dispatchEvent(new DragEvent('dragstart', {bubbles: true, cancelable: true})); - withPointerEvents && sourceElement.dispatchEvent(new PointerEvent('pointercancel', {bubbles: true, cancelable: true})); - withPointerEvents && sourceElement.dispatchEvent(new PointerEvent('pointerout', {bubbles: true, cancelable: true})); - withPointerEvents && sourceElement.dispatchEvent(new PointerEvent('pointerleave', {bubbles: true, cancelable: true})); }({{ELEMENT}})); JS ); $this->getWebDriverSession()->moveto(['element' => $target->getID()]); + $this->getWebDriverSession()->buttonup(); $this->executeJsOnElement($target, <<<'JS' (function (targetElement) { - var withPointerEvents = 'PointerEvent' in window; var sourceElement = window['__minkDragAndDropSourceElement']; - withPointerEvents && targetElement.dispatchEvent(new PointerEvent('pointerover', {bubbles: true, cancelable: true})); - withPointerEvents && targetElement.dispatchEvent(new PointerEvent('pointerenter', {bubbles: true, cancelable: true})); - sourceElement.dispatchEvent(new MouseEvent('mouseout', {bubbles: true, cancelable: true})); - sourceElement.dispatchEvent(new MouseEvent('mouseleave', {bubbles: true, cancelable: true})); - targetElement.dispatchEvent(new MouseEvent('mouseover', {bubbles: true, cancelable: true})); - targetElement.dispatchEvent(new MouseEvent('mouseenter', {bubbles: true, cancelable: true})); - targetElement.dispatchEvent(new MouseEvent('mousemove', {bubbles: true, cancelable: true})); - withPointerEvents && targetElement.dispatchEvent(new PointerEvent('pointerout', {bubbles: true, cancelable: true})); - withPointerEvents && targetElement.dispatchEvent(new PointerEvent('pointerleave', {bubbles: true, cancelable: true})); - targetElement.dispatchEvent(new MouseEvent('mouseout', {bubbles: true, cancelable: true})); - targetElement.dispatchEvent(new MouseEvent('mouseleave', {bubbles: true, cancelable: true})); sourceElement.dispatchEvent(new DragEvent('drag', {bubbles: true, cancelable: true})); targetElement.dispatchEvent(new DragEvent('dragover', {bubbles: true, cancelable: true})); targetElement.dispatchEvent(new DragEvent('drop', {bubbles: true, cancelable: true})); From 2ca5e2672a162a90cfd11d6b58c79f2559d4122b Mon Sep 17 00:00:00 2001 From: Christian Sciberras Date: Sun, 19 Jan 2025 22:17:05 +0100 Subject: [PATCH 4/4] Change array syntax --- src/Selenium2Driver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Selenium2Driver.php b/src/Selenium2Driver.php index 940fedb8..543ff273 100755 --- a/src/Selenium2Driver.php +++ b/src/Selenium2Driver.php @@ -1028,7 +1028,7 @@ public function dragTo(string $sourceXpath, string $destinationXpath) $source = $this->findElement($sourceXpath); $target = $this->findElement($destinationXpath); - $this->getWebDriverSession()->moveto(['element' => $source->getID()]); + $this->getWebDriverSession()->moveto(array('element' => $source->getID())); $this->getWebDriverSession()->buttondown(); $this->executeJsOnElement($source, <<<'JS' @@ -1040,7 +1040,7 @@ public function dragTo(string $sourceXpath, string $destinationXpath) JS ); - $this->getWebDriverSession()->moveto(['element' => $target->getID()]); + $this->getWebDriverSession()->moveto(array('element' => $target->getID())); $this->getWebDriverSession()->buttonup(); $this->executeJsOnElement($target, <<<'JS'