Skip to content

Commit 15dde79

Browse files
committedAug 25, 2023
Do not fail on fatal error on unexpected response when getting element(s)
1 parent a16a2ba commit 15dde79

File tree

8 files changed

+60
-24
lines changed

8 files changed

+60
-24
lines changed
 

‎CHANGELOG.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ This project versioning adheres to [Semantic Versioning](http://semver.org/).
66
- Capability key `ChromeOptions::CAPABILITY_W3C` used to set ChromeOptions is now deprecated in favor of `ChromeOptions::CAPABILITY`, which now also contains the W3C compatible value (`goog:chromeOptions`).
77
- ChromeOptions are now passed to the driver always as a W3C compatible key `goog:chromeOptions`, even in the deprecated OSS JsonWire payload (as ChromeDriver [supports](https://bugs.chromium.org/p/chromedriver/issues/detail?id=1786) this since 2017).
88

9+
### Fixed
10+
- Handle unexpected response when getting element(s) by throwing an exception, not triggering fatal error.
11+
912
## 1.14.0 - 2023-02-09
1013
### Added
11-
- `PhpWebDriverExceptionInterface` as a common interface to identify all exceptions thrown in php-webdriver
14+
- `PhpWebDriverExceptionInterface` as a common interface to identify all exceptions thrown in php-webdriver.
1215

1316
### Changed
1417
- Require PHP ^7.3.

‎lib/Exception/Internal/UnexpectedResponseException.php

+10
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@ public static function forError(string $message): self
1414
return new self($message);
1515
}
1616

17+
public static function forElementNotArray($response): self
18+
{
19+
return new self(
20+
sprintf(
21+
"Unexpected server response for getting an element. Expected array, but the response was: '%s'\n",
22+
print_r($response, true)
23+
)
24+
);
25+
}
26+
1727
public static function forJsonDecodingError(int $jsonLastError, string $rawResults): self
1828
{
1929
return new self(

‎lib/Remote/JsonWireCompat.php

+11-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Facebook\WebDriver\Remote;
44

5+
use Facebook\WebDriver\Exception\Internal\UnexpectedResponseException;
56
use Facebook\WebDriver\WebDriverBy;
67

78
/**
@@ -18,8 +19,17 @@ abstract class JsonWireCompat
1819
*/
1920
public const WEB_DRIVER_ELEMENT_IDENTIFIER = 'element-6066-11e4-a52e-4f735466cecf';
2021

21-
public static function getElement(array $rawElement)
22+
/**
23+
* @param mixed $rawElement Value is validated to by an array, exception is thrown otherwise
24+
* @throws UnexpectedResponseException When value of other type than array is given
25+
*/
26+
public static function getElement($rawElement)
2227
{
28+
// The method intentionally accept mixed, so that assertion of the rawElement format could be done on one place
29+
if (!is_array($rawElement)) {
30+
throw UnexpectedResponseException::forElementNotArray($rawElement);
31+
}
32+
2333
if (array_key_exists(self::WEB_DRIVER_ELEMENT_IDENTIFIER, $rawElement)) {
2434
// W3C's WebDriver
2535
return $rawElement[self::WEB_DRIVER_ELEMENT_IDENTIFIER];

‎lib/Remote/RemoteWebDriver.php

+2-6
Original file line numberDiff line numberDiff line change
@@ -219,10 +219,6 @@ public function findElement(WebDriverBy $by)
219219
JsonWireCompat::getUsing($by, $this->isW3cCompliant)
220220
);
221221

222-
if ($raw_element === null) {
223-
throw UnexpectedResponseException::forError('Unexpected server response to findElement command');
224-
}
225-
226222
return $this->newElement(JsonWireCompat::getElement($raw_element));
227223
}
228224

@@ -239,8 +235,8 @@ public function findElements(WebDriverBy $by)
239235
JsonWireCompat::getUsing($by, $this->isW3cCompliant)
240236
);
241237

242-
if ($raw_elements === null) {
243-
throw UnexpectedResponseException::forError('Unexpected server response to findElements command');
238+
if (!is_array($raw_elements)) {
239+
throw UnexpectedResponseException::forError('Server response to findElements command is not an array');
244240
}
245241

246242
$elements = [];

‎lib/Remote/RemoteWebElement.php

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Facebook\WebDriver\Exception\ElementNotInteractableException;
66
use Facebook\WebDriver\Exception\Internal\IOException;
77
use Facebook\WebDriver\Exception\Internal\LogicException;
8+
use Facebook\WebDriver\Exception\Internal\UnexpectedResponseException;
89
use Facebook\WebDriver\Exception\PhpWebDriverExceptionInterface;
910
use Facebook\WebDriver\Exception\UnsupportedOperationException;
1011
use Facebook\WebDriver\Interactions\Internal\WebDriverCoordinates;
@@ -131,6 +132,10 @@ public function findElements(WebDriverBy $by)
131132
$params
132133
);
133134

135+
if (!is_array($raw_elements)) {
136+
throw UnexpectedResponseException::forError('Server response to findChildElements command is not an array');
137+
}
138+
134139
$elements = [];
135140
foreach ($raw_elements as $raw_element) {
136141
$elements[] = $this->newElement(JsonWireCompat::getElement($raw_element));

‎lib/Remote/ShadowRoot.php

+7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Facebook\WebDriver\Remote;
44

5+
use Facebook\WebDriver\Exception\Internal\UnexpectedResponseException;
56
use Facebook\WebDriver\Exception\UnknownErrorException;
67
use Facebook\WebDriver\WebDriverBy;
78
use Facebook\WebDriver\WebDriverElement;
@@ -73,6 +74,12 @@ public function findElements(WebDriverBy $locator)
7374
$params
7475
);
7576

77+
if (!is_array($rawElements)) {
78+
throw UnexpectedResponseException::forError(
79+
'Server response to findElementsFromShadowRoot command is not an array'
80+
);
81+
}
82+
7683
$elements = [];
7784
foreach ($rawElements as $rawElement) {
7885
$elements[] = new RemoteWebElement($this->executor, JsonWireCompat::getElement($rawElement), true);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Facebook\WebDriver\Remote;
4+
5+
use Facebook\WebDriver\Exception\Internal\UnexpectedResponseException;
6+
use PHPUnit\Framework\TestCase;
7+
8+
class JsonWireCompatTest extends TestCase
9+
{
10+
public function testShouldThrowExceptionWhenElementIsNotArray()
11+
{
12+
$this->expectException(UnexpectedResponseException::class);
13+
$this->expectExceptionMessage('Unexpected server response for getting an element. Expected array');
14+
15+
JsonWireCompat::getElement(null);
16+
}
17+
}

‎tests/unit/Remote/RemoteWebDriverTest.php

+4-16
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,11 @@ public function testShouldCreateWebDriverWaitInstance(): void
114114
}
115115

116116
/**
117-
* @covers ::findElement
118117
* @covers ::findElements
119118
* @covers \Facebook\WebDriver\Exception\Internal\UnexpectedResponseException
120-
* @dataProvider provideMethods
121119
*/
122-
public function testShouldThrowExceptionOnUnexpectedNullValueFromRemoteEnd(
123-
string $method,
124-
string $expectedExceptionMessage
125-
): void {
120+
public function testShouldThrowExceptionOnUnexpectedValueFromRemoteEndWhenFindingElements(): void
121+
{
126122
$executorMock = $this->createMock(HttpCommandExecutor::class);
127123
$executorMock->expects($this->once())
128124
->method('execute')
@@ -132,15 +128,7 @@ public function testShouldThrowExceptionOnUnexpectedNullValueFromRemoteEnd(
132128
$this->driver->setCommandExecutor($executorMock);
133129

134130
$this->expectException(UnexpectedResponseException::class);
135-
$this->expectExceptionMessage($expectedExceptionMessage);
136-
call_user_func([$this->driver, $method], $this->createMock(WebDriverBy::class));
137-
}
138-
139-
public function provideMethods(): array
140-
{
141-
return [
142-
['findElement', 'Unexpected server response to findElement command'],
143-
['findElements', 'Unexpected server response to findElements command'],
144-
];
131+
$this->expectExceptionMessage('Server response to findElements command is not an array');
132+
$this->driver->findElements($this->createMock(WebDriverBy::class));
145133
}
146134
}

0 commit comments

Comments
 (0)
Please sign in to comment.