Skip to content

Commit 38248d6

Browse files
committed
Convert element to NodeElement from execute result
1 parent e5f8421 commit 38248d6

File tree

2 files changed

+88
-12
lines changed

2 files changed

+88
-12
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
"php": ">=7.2",
2323
"ext-json": "*",
2424
"behat/mink": "^1.9@dev",
25-
"instaclick/php-webdriver": "^1.4"
25+
"instaclick/php-webdriver": "^1.4.13"
2626
},
2727
"require-dev": {
2828
"mink/driver-testsuite": "dev-master",

src/Selenium2Driver.php

Lines changed: 87 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
namespace Behat\Mink\Driver;
1212

13+
use Behat\Mink\Element\NodeElement;
1314
use Behat\Mink\Exception\DriverException;
1415
use Behat\Mink\Selector\Xpath\Escaper;
1516
use WebDriver\Element;
@@ -27,6 +28,8 @@
2728
*/
2829
class Selenium2Driver extends CoreDriver
2930
{
31+
public const XPATH_WEBDRIVER_ELEMENT_PREFIX = 'webdriver-element--JZPOYwW6bl1bVmyK--';
32+
3033
/**
3134
* Whether the browser has been started
3235
* @var boolean
@@ -246,6 +249,68 @@ protected static function charToOptions($char, $modifier = null)
246249
return json_encode($options);
247250
}
248251

252+
/**
253+
* Serialize execute arguments (containing web elements)
254+
*
255+
* @see https://w3c.github.io/webdriver/#executing-script
256+
*
257+
* @param array $args
258+
*
259+
* @return array
260+
*/
261+
private function serializeExecuteArguments(array $args)
262+
{
263+
foreach ($args as $k => $v) {
264+
if ($v instanceof NodeElement) {
265+
if (strpos($v->getXpath(), self::XPATH_WEBDRIVER_ELEMENT_PREFIX) === 0) {
266+
[$elementUrlEncoded, $elementIdEncoded] = explode(
267+
'--',
268+
substr($v->getXpath(), strlen(self::XPATH_WEBDRIVER_ELEMENT_PREFIX)),
269+
2
270+
);
271+
272+
$args[$k] = new Element(base64_decode($elementUrlEncoded), base64_decode($elementIdEncoded));
273+
} else {
274+
$args[$k] = $this->findElement($v->getXpath());
275+
}
276+
} elseif (is_array($v)) {
277+
$args[$k] = $this->serializeExecuteArguments($v);
278+
}
279+
}
280+
281+
return $args;
282+
}
283+
284+
/**
285+
* Unserialize execute result (containing web elements)
286+
*
287+
* @param mixed $data
288+
*
289+
* @return mixed
290+
*/
291+
private function unserializeExecuteResult($data)
292+
{
293+
if ($data instanceof Element) {
294+
$minkSession = \Closure::bind(function () {
295+
return $this->session;
296+
}, $this, CoreDriver::class)();
297+
298+
return new NodeElement(
299+
self::XPATH_WEBDRIVER_ELEMENT_PREFIX
300+
. base64_encode($data->getURL())
301+
. '--'
302+
. base64_encode($data->getID()),
303+
$minkSession
304+
);
305+
} elseif (is_array($data)) {
306+
foreach ($data as $k => $v) {
307+
$data[$k] = $this->unserializeExecuteResult($v);
308+
}
309+
}
310+
311+
return $data;
312+
}
313+
249314
/**
250315
* Executes JS on a given element - pass in a js script string and {{ELEMENT}} will
251316
* be replaced with a reference to the result of the $xpath query
@@ -281,14 +346,14 @@ private function executeJsOnElement(Element $element, $script, $sync = true)
281346

282347
$options = array(
283348
'script' => $script,
284-
'args' => array(array('ELEMENT' => $element->getID())),
349+
'args' => array(array('ELEMENT' => $element)),
285350
);
286351

287-
if ($sync) {
288-
return $this->wdSession->execute($options);
289-
}
352+
$result = $sync
353+
? $this->wdSession->execute($options)
354+
: $this->wdSession->execute_async($options);
290355

291-
return $this->wdSession->execute_async($options);
356+
return $this->unserializeExecuteResult($result);
292357
}
293358

294359
/**
@@ -951,39 +1016,50 @@ public function dragTo($sourceXpath, $destinationXpath)
9511016
/**
9521017
* {@inheritdoc}
9531018
*/
954-
public function executeScript($script)
1019+
public function executeScript($script, array $args = [])
9551020
{
9561021
if (preg_match('/^function[\s\(]/', $script)) {
9571022
$script = preg_replace('/;$/', '', $script);
9581023
$script = '(' . $script . ')';
9591024
}
9601025

961-
$this->wdSession->execute(array('script' => $script, 'args' => array()));
1026+
$this->wdSession->execute(array(
1027+
'script' => $script,
1028+
'args' => $this->serializeExecuteArguments($args),
1029+
));
9621030
}
9631031

9641032
/**
9651033
* {@inheritdoc}
9661034
*/
967-
public function evaluateScript($script)
1035+
public function evaluateScript($script, array $args = [])
9681036
{
9691037
if (0 !== strpos(trim($script), 'return ')) {
9701038
$script = 'return ' . $script;
9711039
}
9721040

973-
return $this->wdSession->execute(array('script' => $script, 'args' => array()));
1041+
$result = $this->wdSession->execute(array(
1042+
'script' => $script,
1043+
'args' => $this->serializeExecuteArguments($args),
1044+
));
1045+
1046+
return $this->unserializeExecuteResult($result);
9741047
}
9751048

9761049
/**
9771050
* {@inheritdoc}
9781051
*/
979-
public function wait($timeout, $condition)
1052+
public function wait($timeout, $condition, array $args = [])
9801053
{
9811054
$script = 'return (' . rtrim($condition, " \t\n\r;") . ');';
9821055
$start = microtime(true);
9831056
$end = $start + $timeout / 1000.0;
9841057

9851058
do {
986-
$result = $this->wdSession->execute(array('script' => $script, 'args' => array()));
1059+
$result = $this->wdSession->execute(array(
1060+
'script' => $script,
1061+
'args' => $this->serializeExecuteArguments($args),
1062+
));
9871063
if ($result) {
9881064
break;
9891065
}

0 commit comments

Comments
 (0)