Skip to content

Commit 4f4011a

Browse files
committed
Upgrade phpstan; increase phpstan level; fix a few bugs
1 parent ca55cde commit 4f4011a

File tree

8 files changed

+88
-15
lines changed

8 files changed

+88
-15
lines changed

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
},
2121
"require-dev": {
2222
"mink/driver-testsuite": "dev-master",
23-
"phpstan/phpstan": "^1.10",
24-
"phpstan/phpstan-phpunit": "^1.3",
23+
"phpstan/phpstan": "^2",
24+
"phpstan/phpstan-phpunit": "^2",
2525
"phpunit/phpunit": "^9.6.8",
2626
"symfony/error-handler": "^5.4 || ^6.0 || ^7.0",
2727
"symfony/process": "^5.4 || ^6.0 || ^7.0",

phpstan.dist.neon

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
parameters:
2-
level: 8
2+
level: 10
33
paths:
44
- src
55
- tests
6-
checkMissingIterableValueType: false
76
treatPhpDocTypesAsCertain: false
7+
stubFiles:
8+
- stubs/WebDriverTimeouts.stub
9+
- stubs/RemoteWebDriver.stub
810

911
includes:
1012
- vendor/phpstan/phpstan-phpunit/extension.neon

src/WebdriverClassicDriver.php

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ class WebdriverClassicDriver extends CoreDriver
7777

7878
private DesiredCapabilities $desiredCapabilities;
7979

80+
/**
81+
* @var array{script?: null|numeric, implicit?: null|numeric, page?: null|numeric}
82+
*/
8083
private array $timeouts = [];
8184

8285
private string $webDriverHost;
@@ -85,6 +88,7 @@ class WebdriverClassicDriver extends CoreDriver
8588

8689
/**
8790
* @param string $browserName One of 'edge', 'firefox', 'chrome' or any one of {@see WebDriverBrowserType} constants.
91+
* @param array<string, mixed> $desiredCapabilities
8892
*/
8993
public function __construct(
9094
string $browserName = self::DEFAULT_BROWSER,
@@ -262,7 +266,7 @@ public function getWindowNames(): array
262266

263267
public function getWindowName(): string
264268
{
265-
$name = (string)$this->evaluateScript('window.name');
269+
$name = $this->getAsString($this->evaluateScript('window.name'), 'Window name');
266270

267271
if ($name === '') {
268272
$name = self::W3C_WINDOW_HANDLE_PREFIX . $this->getWebDriver()->getWindowHandle();
@@ -299,22 +303,22 @@ public function getText(
299303
return str_replace(
300304
["\r\n", "\r", "\n"],
301305
' ',
302-
$this->getElementDomProperty($this->findElement($xpath), 'innerText')
306+
$this->getAsString($this->getElementDomProperty($this->findElement($xpath), 'innerText'), 'The element\'s innerText')
303307
);
304308
}
305309

306310
public function getHtml(
307311
#[Language('XPath')]
308312
string $xpath
309313
): string {
310-
return $this->getElementDomProperty($this->findElement($xpath), 'innerHTML');
314+
return $this->getAsString($this->getElementDomProperty($this->findElement($xpath), 'innerHTML'), 'The element\'s innerHTML');
311315
}
312316

313317
public function getOuterHtml(
314318
#[Language('XPath')]
315319
string $xpath
316320
): string {
317-
return $this->getElementDomProperty($this->findElement($xpath), 'outerHTML');
321+
return $this->getAsString($this->getElementDomProperty($this->findElement($xpath), 'outerHTML'), 'The element\'s outerHTML');
318322
}
319323

320324
public function getAttribute(
@@ -326,9 +330,13 @@ public function getAttribute(
326330
// so we cannot use webdriver api for this. See also: https://w3c.github.io/webdriver/#dfn-get-element-attribute
327331
$escapedName = $this->jsonEncode($name, 'get attribute', 'attribute name');
328332
$script = "return arguments[0].getAttribute($escapedName)";
329-
return $this->executeJsOnXpath($xpath, $script);
333+
$result = $this->executeJsOnXpath($xpath, $script);
334+
return $result === null ? null : $this->getAsString($result, "The element's $name attribute");
330335
}
331336

337+
/**
338+
* @return array<array-key, mixed>|bool|mixed|string|null
339+
*/
332340
public function getValue(
333341
#[Language('XPath')]
334342
string $xpath
@@ -369,6 +377,9 @@ public function getValue(
369377
}
370378
}
371379

380+
/**
381+
* @param array<array-key, mixed>|bool|mixed|string|null $value
382+
*/
372383
public function setValue(
373384
#[Language('XPath')]
374385
string $xpath,
@@ -386,7 +397,7 @@ public function setValue(
386397
if (is_array($value)) {
387398
$this->deselectAllOptions($element);
388399
foreach ($value as $option) {
389-
$this->selectOptionOnElement($element, $option, true);
400+
$this->selectOptionOnElement($element, $this->getAsString($option, 'Option value'), true);
390401
}
391402
return;
392403
}
@@ -736,7 +747,7 @@ public function getWebDriverSessionId(): ?string
736747
/**
737748
* Sets the timeouts to apply to the webdriver session
738749
*
739-
* @param array $timeouts The session timeout settings: Array of {script, implicit, page} => time in milliseconds
750+
* @param array{script?: numeric, implicit?: numeric, page?: numeric} $timeouts The session timeout settings: Array of {script, implicit, page} => time in milliseconds
740751
* @throws DriverException
741752
* @api
742753
*/
@@ -785,6 +796,8 @@ private function getNormalisedBrowserName(): string
785796
/**
786797
* Detect and assign appropriate browser capabilities
787798
*
799+
* @param array<string, mixed> $desiredCapabilities
800+
*
788801
* @see https://github.com/SeleniumHQ/selenium/wiki/DesiredCapabilities
789802
*/
790803
private function initCapabilities(array $desiredCapabilities): DesiredCapabilities
@@ -1227,5 +1240,20 @@ private function getElementDomProperty(RemoteWebElement $element, string $proper
12271240
}
12281241
}
12291242

1243+
/**
1244+
* @param mixed $value
1245+
*/
1246+
private function getAsString($value, string $name): string
1247+
{
1248+
if (!is_scalar($value)) {
1249+
$actualType = gettype($value);
1250+
throw new \RuntimeException(
1251+
"$name should be a string or at least a scalar value, but received `$actualType` instead"
1252+
);
1253+
}
1254+
1255+
return (string)$value;
1256+
}
1257+
12301258
// </editor-fold>
12311259
}

stubs/RemoteWebDriver.stub

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Facebook\WebDriver\Remote;
4+
5+
interface RemoteWebDriver
6+
{
7+
/**
8+
* @return list<string>
9+
*/
10+
public function getWindowHandles(): array;
11+
}

stubs/WebDriverTimeouts.stub

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Facebook\WebDriver;
4+
5+
/**
6+
* To be removed after {@see https://github.com/php-webdriver/php-webdriver/pull/1120} is merged.
7+
*/
8+
interface WebDriverTimeouts
9+
{
10+
/**
11+
* @param null|int|float $seconds Wait time in seconds.
12+
*/
13+
public function implicitlyWait($seconds): self;
14+
15+
/**
16+
* @param null|int|float $seconds Wait time in seconds.
17+
*/
18+
public function setScriptTimeout($seconds): self;
19+
20+
/**
21+
* @param null|int|float $seconds Wait time in seconds.
22+
*/
23+
public function pageLoadTimeout($seconds): self;
24+
}

tests/Custom/TimeoutTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ public function testDeprecatedShortPageLoadTimeoutThrowsException(string $type):
6565
$this->driver->visit($this->pathTo('/page_load.php?sleep=2'));
6666
}
6767

68+
/**
69+
* @return iterable<array{type: string}>
70+
*/
6871
public static function deprecatedPageLoadDataProvider(): iterable
6972
{
7073
yield 'selenium 3 style' => ['type' => 'pageLoad'];

tests/WebdriverClassicConfig.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ public static function getInstance(): self
2121

2222
public function createDriver(): WebdriverClassicDriver
2323
{
24-
$seleniumHost = $_SERVER['DRIVER_URL'];
24+
$seleniumHost = $_SERVER['DRIVER_URL'] ?? null;
25+
if (!is_string($seleniumHost)) {
26+
throw new \RuntimeException('Selenium host must be specified (as a string) in $_SERVER[DRIVER_URL].');
27+
}
2528

2629
return new WebdriverClassicDriver($this->getBrowserName(), [], $seleniumHost);
2730
}

tests/bootstrap.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@
44

55
use Symfony\Component\Process\Process;
66

7-
$minkTestServerPort = isset($_SERVER['WEB_FIXTURES_HOST'])
8-
? parse_url($_SERVER['WEB_FIXTURES_HOST'], PHP_URL_PORT)
9-
: '8002';
7+
$fixturesHost = $_SERVER['WEB_FIXTURES_HOST'] ?? '//host:8002';
8+
if (!is_string($fixturesHost)) {
9+
throw new RuntimeException('The fixtures host must be specified in $_SERVER[WEB_FIXTURES_HOST] as a string');
10+
}
11+
$minkTestServerPort = parse_url($fixturesHost, PHP_URL_PORT);
1012

1113
$minkTestServer = new Process([
1214
PHP_BINARY,

0 commit comments

Comments
 (0)