Skip to content

Commit

Permalink
Wider W3C compatability fixes to match mink/driver-testsuite expectat…
Browse files Browse the repository at this point in the history
…ions
  • Loading branch information
justafish committed Oct 5, 2023
1 parent 676ba55 commit c998944
Show file tree
Hide file tree
Showing 6 changed files with 234 additions and 54 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ jobs:
mkdir ./logs
./vendor/bin/mink-test-server &> ./logs/mink-test-server.log &
# To run this locally, additionally mount a volume with the repo to retrieve test files
# e.g. -v /home/youruser/MinkSelenium2Driver:/home/youruser/MinkSelenium2Driver
- name: Start Selenium
run: |
docker run --net host --name selenium --volume /dev/shm:/dev/shm --shm-size 2g selenium/standalone-firefox:${{ matrix.selenium }} &> ./logs/selenium.log &
Expand Down
191 changes: 161 additions & 30 deletions src/Selenium2Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ private function executeJsOnElement(Element $element, string $script, bool $sync
'args' => [
[
'ELEMENT' => $element->getID(),
'element-6066-11e4-a52e-4f735466cecf' => $element->getID(),
Element::WEB_ELEMENT_ID => $element->getID(),

Check failure on line 339 in src/Selenium2Driver.php

View workflow job for this annotation

GitHub Actions / Static analysis

Access to undefined constant WebDriver\Element::WEB_ELEMENT_ID.
]
],
);
Expand Down Expand Up @@ -451,12 +451,41 @@ public function back()

public function switchToWindow(?string $name = null)
{
$this->getWebDriverSession()->focusWindow($name ?: '');
if ($this->isW3C()) {
$allHandles = $this->getWebDriverSession()->getWindowHandles();

Check failure on line 455 in src/Selenium2Driver.php

View workflow job for this annotation

GitHub Actions / Static analysis

Call to an undefined method WebDriver\Session::getWindowHandles().
foreach ($allHandles as $handle) {
$script = <<<JS
return window.name;
JS;

$this->getWebDriverSession()->focusWindow($handle);
$windowName = $this->getWebDriverSession()->execute(array('script' => $script, 'args' => array()));
if ($windowName === $name || (empty($name) && empty($windowName))) {
break;
}
}
}
else {
$this->getWebDriverSession()->focusWindow($name ?: '');
}
}

public function switchToIFrame(?string $name = null)
{
$this->getWebDriverSession()->frame(array('id' => $name));
if ($this->isW3C()) {
if (empty($name)) {
$this->getWebDriverSession()->frame(array('id' => null));
}
else {
$frameElement = $this->findElement("//iframe[@name='$name']");
$this->getWebDriverSession()->frame(array('id' => [
Element::WEB_ELEMENT_ID => $frameElement->getID(),

Check failure on line 482 in src/Selenium2Driver.php

View workflow job for this annotation

GitHub Actions / Static analysis

Access to undefined constant WebDriver\Element::WEB_ELEMENT_ID.
]));
}
}
else {
$this->getWebDriverSession()->frame(array('id' => $name));
}
}

public function setCookie(string $name, ?string $value = null)
Expand Down Expand Up @@ -586,11 +615,6 @@ public function getAttribute(string $xpath, string $name)
public function getValue(string $xpath)
{
$element = $this->findElement($xpath);
if ($this->isW3C()) {
// This method doesn't exist in older versions of php-webdriver.
/** @phpstan-ignore-next-line variable.undefined */
return $element->property('value');
}
$elementName = strtolower($element->name());
$elementType = strtolower($element->attribute('type') ?: '');

Expand Down Expand Up @@ -642,6 +666,12 @@ public function getValue(string $xpath)
return $this->executeJsOnElement($element, $script);
}

if ($this->isW3C()) {
// This method doesn't exist in older versions of php-webdriver.
/** @phpstan-ignore-next-line variable.undefined */
return $element->property('value');
}

return $element->attribute('value');
}

Expand Down Expand Up @@ -718,8 +748,16 @@ public function setValue(string $xpath, $value)
$value = strval($value);

if (in_array($elementName, array('input', 'textarea'))) {
$existingValueLength = strlen($element->attribute('value'));
$value = str_repeat(Key::BACKSPACE . Key::DELETE, $existingValueLength) . $value;
if ($this->isW3C() && $elementName === 'textarea') {
// Backspace doesn't work for textareas for some reason, and
// sending ->clear() will trigger a change event.
$element->postValue(array('text' => Key::CONTROL . 'a'));
$element->postValue(array('text' => Key::DELETE));
}
else {
$existingValueLength = strlen($element->attribute('value'));
$value = str_repeat(Key::BACKSPACE . Key::DELETE, $existingValueLength) . $value;
}
}

if ($this->isW3C()) {
Expand Down Expand Up @@ -827,14 +865,58 @@ private function clickOnElement(Element $element): void

public function doubleClick(string $xpath)
{
$this->mouseOver($xpath);
$this->getWebDriverSession()->doubleclick();
if ($this->isW3C()) {
$actions = array(
'actions' => [
[
'type' => 'pointer',
'id' => 'mouse1',
'parameters' => ['pointerType' => 'mouse'],
'actions' => [
['type' => 'pointerMove', 'duration' => 0, 'origin' => [Element::WEB_ELEMENT_ID => $this->findElement($xpath)->getID()], 'x' => 0, 'y' => 0],

Check failure on line 876 in src/Selenium2Driver.php

View workflow job for this annotation

GitHub Actions / Static analysis

Access to undefined constant WebDriver\Element::WEB_ELEMENT_ID.
['type' => 'pointerDown', "button" => 0],
['type' => 'pointerUp', "button" => 0],
['type' => 'pause', 'duration' => 10],
['type' => 'pointerDown', "button" => 0],
['type' => 'pointerUp', "button" => 0],
],
],
],
);
$this->getWebDriverSession()->postActions($actions);

Check failure on line 886 in src/Selenium2Driver.php

View workflow job for this annotation

GitHub Actions / Static analysis

Call to an undefined method WebDriver\Session::postActions().
$this->getWebDriverSession()->deleteActions();

Check failure on line 887 in src/Selenium2Driver.php

View workflow job for this annotation

GitHub Actions / Static analysis

Call to an undefined method WebDriver\Session::deleteActions().
}
else {
$this->mouseOver($xpath);
$this->getWebDriverSession()->doubleclick();
}
}

public function rightClick(string $xpath)
{
$this->mouseOver($xpath);
$this->getWebDriverSession()->click(array('button' => 2));
if ($this->isW3C()) {
$actions = array(
'actions' => [
[
'type' => 'pointer',
'id' => 'mouse1',
'parameters' => ['pointerType' => 'mouse'],
'actions' => [
['type' => 'pointerMove', 'duration' => 0, 'origin' => [Element::WEB_ELEMENT_ID => $this->findElement($xpath)->getID()], 'x' => 0, 'y' => 0],

Check failure on line 905 in src/Selenium2Driver.php

View workflow job for this annotation

GitHub Actions / Static analysis

Access to undefined constant WebDriver\Element::WEB_ELEMENT_ID.
['type' => 'pointerDown', "button" => 2],
['type' => 'pause', 'duration' => 500],
['type' => 'pointerUp', "button" => 2],
],
],
],
);
$this->getWebDriverSession()->postActions($actions);

Check failure on line 913 in src/Selenium2Driver.php

View workflow job for this annotation

GitHub Actions / Static analysis

Call to an undefined method WebDriver\Session::postActions().
$this->getWebDriverSession()->deleteActions();

Check failure on line 914 in src/Selenium2Driver.php

View workflow job for this annotation

GitHub Actions / Static analysis

Call to an undefined method WebDriver\Session::deleteActions().
}
else {
$this->mouseOver($xpath);
$this->getWebDriverSession()->click(array('button' => 2));
}
}

public function attachFile(string $xpath, string $path)
Expand Down Expand Up @@ -867,9 +949,27 @@ public function isVisible(string $xpath)

public function mouseOver(string $xpath)
{
$this->getWebDriverSession()->moveto(array(
'element' => $this->findElement($xpath)->getID()
));
if ($this->isW3C()) {
$actions = array(
'actions' => [
[
'type' => 'pointer',
'id' => 'mouse1',
'parameters' => ['pointerType' => 'mouse'],
'actions' => [
['type' => 'pointerMove', 'duration' => 0, 'origin' => [Element::WEB_ELEMENT_ID => $this->findElement($xpath)->getID()], 'x' => 0, 'y' => 0],

Check failure on line 960 in src/Selenium2Driver.php

View workflow job for this annotation

GitHub Actions / Static analysis

Access to undefined constant WebDriver\Element::WEB_ELEMENT_ID.
],
],
],
);
$this->getWebDriverSession()->postActions($actions);
$this->getWebDriverSession()->deleteActions();
}
else {
$this->getWebDriverSession()->moveto(array(
'element' => $this->findElement($xpath)->getID()
));
}
}

public function focus(string $xpath)
Expand Down Expand Up @@ -905,11 +1005,31 @@ public function dragTo(string $sourceXpath, string $destinationXpath)
$source = $this->findElement($sourceXpath);
$destination = $this->findElement($destinationXpath);

$this->getWebDriverSession()->moveto(array(
'element' => $source->getID()
));
if ($this->isW3C()) {
$actions = array(
'actions' => [
[
'type' => 'pointer',
'id' => 'mouse1',
'parameters' => ['pointerType' => 'mouse'],
'actions' => [
['type' => 'pointerMove', 'duration' => 0, 'origin' => [Element::WEB_ELEMENT_ID => $this->findElement($sourceXpath)->getID()], 'x' => 0, 'y' => 0],
['type' => 'pointerDown', "button" => 0],
['type' => 'pointerMove', 'duration' => 0, 'origin' => [Element::WEB_ELEMENT_ID => $this->findElement($destinationXpath)->getID()], 'x' => 0, 'y' => 0],
['type' => 'pointerUp', "button" => 0],
],
],
],
);
$this->getWebDriverSession()->postActions($actions);
$this->getWebDriverSession()->deleteActions();
}
else {
$this->getWebDriverSession()->moveto(array(
'element' => $source->getID()
));

$script = <<<JS
$script = <<<JS
(function (element) {
var event = document.createEvent("HTMLEvents");
Expand All @@ -919,15 +1039,15 @@ public function dragTo(string $sourceXpath, string $destinationXpath)
element.dispatchEvent(event);
}({{ELEMENT}}));
JS;
$this->withSyn()->executeJsOnElement($source, $script);
$this->withSyn()->executeJsOnElement($source, $script);

$this->getWebDriverSession()->buttondown();
$this->getWebDriverSession()->moveto(array(
'element' => $destination->getID()
));
$this->getWebDriverSession()->buttonup();
$this->getWebDriverSession()->buttondown();
$this->getWebDriverSession()->moveto(array(
'element' => $destination->getID()
));
$this->getWebDriverSession()->buttonup();

$script = <<<JS
$script = <<<JS
(function (element) {
var event = document.createEvent("HTMLEvents");
Expand All @@ -937,7 +1057,8 @@ public function dragTo(string $sourceXpath, string $destinationXpath)
element.dispatchEvent(event);
}({{ELEMENT}}));
JS;
$this->withSyn()->executeJsOnElement($destination, $script);
$this->withSyn()->executeJsOnElement($destination, $script);
}
}

public function executeScript(string $script)
Expand Down Expand Up @@ -996,7 +1117,17 @@ public function resizeWindow(int $width, int $height, ?string $name = null)

public function submitForm(string $xpath)
{
$this->findElement($xpath)->submit();
if ($this->isW3C()) {
$script = <<<JS
var node = {{ELEMENT}};
node.submit();
JS;

$this->executeJsOnElement($this->findElement($xpath), $script);
}
else {
$this->findElement($xpath)->submit();
}
}

public function maximizeWindow(?string $name = null)
Expand Down
10 changes: 9 additions & 1 deletion tests/Custom/DesiredCapabilitiesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
namespace Behat\Mink\Tests\Driver\Custom;

use Behat\Mink\Driver\Selenium2Driver;
use Behat\Mink\Exception\Exception;
use Behat\Mink\Tests\Driver\TestCase;

class DesiredCapabilitiesTest extends TestCase
{

public function testGetDesiredCapabilities()
{
$caps = array(
Expand Down Expand Up @@ -47,6 +49,12 @@ public function testSetDesiredCapabilities()

$this->expectException('\Behat\Mink\Exception\DriverException');
$this->expectExceptionMessage('Unable to set desiredCapabilities, the session has already started');
$driver->setDesiredCapabilities($caps);
try {
$driver->setDesiredCapabilities($caps);
}
catch (Exception $e) {
$session->stop();
throw $e;
}
}
}
Loading

0 comments on commit c998944

Please sign in to comment.