Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement driver initializer #56

Merged
merged 5 commits into from
Jan 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions src/WebdriverClassicDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@
use Facebook\WebDriver\WebDriverSelect;
use JetBrains\PhpStorm\Language;

/**
* @phpstan-type TWebDriverInstantiator callable(string $driverHost, DesiredCapabilities $capabilities): RemoteWebDriver
*/
class WebdriverClassicDriver extends CoreDriver
{
public const DEFAULT_BROWSER = WebDriverBrowserType::CHROME;
Expand Down Expand Up @@ -81,19 +84,27 @@ class WebdriverClassicDriver extends CoreDriver

private string $webDriverHost;

/**
* @var TWebDriverInstantiator
*/
private $webDriverInstantiator;

private ?string $initialWindowHandle = null;

/**
* @param string $browserName One of 'edge', 'firefox', 'chrome' or any one of {@see WebDriverBrowserType} constants.
* @param TWebDriverInstantiator|null $webDriverInstantiator
*/
public function __construct(
string $browserName = self::DEFAULT_BROWSER,
array $desiredCapabilities = [],
string $webDriverHost = 'http://localhost:4444/wd/hub'
string $webDriverHost = 'http://localhost:4444/wd/hub',
?callable $webDriverInstantiator = null
) {
$this->browserName = $browserName;
$this->desiredCapabilities = $this->initCapabilities($desiredCapabilities);
$this->webDriverHost = $webDriverHost;
$this->webDriverInstantiator = $webDriverInstantiator ?? [self::class, 'instantiateWebDriver'];
}

// <editor-fold desc="Implementation">
Expand Down Expand Up @@ -751,7 +762,7 @@ public function setTimeouts(array $timeouts): void

// </editor-fold>

// <editor-fold desc="Private Utilities">
// <editor-fold desc="Extension Points">

/**
* @throws DriverException
Expand All @@ -762,7 +773,7 @@ protected function createWebDriver(): void
throw new DriverException('Base driver has already been created');
}

$this->webDriver = RemoteWebDriver::create($this->webDriverHost, $this->getDesiredCapabilities());
$this->webDriver = ($this->webDriverInstantiator)($this->webDriverHost, $this->desiredCapabilities);
uuf6429 marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand All @@ -777,9 +788,13 @@ protected function getWebDriver(): RemoteWebDriver
throw new DriverException('Base driver has not been created');
}

protected function getDesiredCapabilities(): array
// </editor-fold>

// <editor-fold desc="Private Utilities">

private static function instantiateWebDriver(string $driverHost, DesiredCapabilities $capabilities): RemoteWebDriver
{
return $this->desiredCapabilities->toArray();
return RemoteWebDriver::create($driverHost, $capabilities);
}

private function getNormalisedBrowserName(): string
Expand Down
42 changes: 18 additions & 24 deletions tests/Custom/CapabilityTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@

namespace Mink\WebdriverClassicDriver\Tests\Custom;

use Mink\WebdriverClassicDriver\Tests\WebDriverMockingTrait;
use Mink\WebdriverClassicDriver\WebdriverClassicDriver;

class CapabilityTest extends \PHPUnit\Framework\TestCase
{
use WebDriverMockingTrait;

/**
* @param array<string, mixed> $desiredCapabilities
* @param array<string, mixed> $expectedCapabilities
Expand All @@ -14,9 +17,22 @@ class CapabilityTest extends \PHPUnit\Framework\TestCase
*/
public function testThatCapabilitiesAreAsExpected(string $browserName, array $desiredCapabilities, array $expectedCapabilities): void
{
$driver = $this->createDriverExposingCapabilities($browserName, $desiredCapabilities);
$mockWebDriver = $this->createMockWebDriver();

$actualCapabilities = null;
$driver = new WebdriverClassicDriver(
$browserName,
$desiredCapabilities,
'example.com',
function ($host, $capabilities) use (&$actualCapabilities, $mockWebDriver) {
$actualCapabilities = $capabilities->toArray();
return $mockWebDriver;
}
);

$driver->start();

$this->assertSame($expectedCapabilities, $driver->capabilities);
$this->assertSame($expectedCapabilities, $actualCapabilities);
}

public static function capabilitiesDataProvider(): iterable
Expand Down Expand Up @@ -78,26 +94,4 @@ public static function capabilitiesDataProvider(): iterable
],
];
}

/**
* @param string $browserName
* @param array<string, mixed> $desiredCapabilities
* @return WebdriverClassicDriver&object{capabilities: array<string, mixed>}
*/
private function createDriverExposingCapabilities(string $browserName, array $desiredCapabilities = []): WebdriverClassicDriver
{
return new class($browserName, $desiredCapabilities) extends WebdriverClassicDriver {
/**
* @var array<string, mixed>
*/
public array $capabilities;

public function __construct(string $browserName, array $desiredCapabilities)
{
parent::__construct($browserName, $desiredCapabilities);

$this->capabilities = $this->getDesiredCapabilities();
}
};
}
}
25 changes: 11 additions & 14 deletions tests/Custom/WebDriverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
namespace Mink\WebdriverClassicDriver\Tests\Custom;

use Behat\Mink\Exception\DriverException;
use Mink\WebdriverClassicDriver\Tests\WebDriverMockingTrait;
use Mink\WebdriverClassicDriver\WebdriverClassicDriver;

class WebDriverTest extends TestCase
{
use WebDriverMockingTrait;

public function testDriverMustBeStartedBeforeUse(): void
{
$this->expectException(DriverException::class);
Expand Down Expand Up @@ -35,11 +38,9 @@ public function testStartedDriverCannotBeSubsequentlyStarted(): void

public function testDriverCatchesUpstreamErrorsDuringStart(): void
{
$driver = $this->createPartialMock(WebdriverClassicDriver::class, ['createWebDriver', 'getWebDriver']);
$driver
->expects($this->once())
->method('createWebDriver')
->willThrowException(new \RuntimeException('An upstream error'));
$driver = new WebdriverClassicDriver('fake browser', [], 'example.com', function () {
throw new \RuntimeException('An upstream error');
});

$this->expectException(DriverException::class);
$this->expectExceptionMessage('Could not start driver: An upstream error');
Expand All @@ -49,15 +50,11 @@ public function testDriverCatchesUpstreamErrorsDuringStart(): void

public function testDriverCatchesUpstreamErrorsDuringStop(): void
{
$driver = $this->createPartialMock(WebdriverClassicDriver::class, ['createWebDriver', 'isStarted', 'getWebDriver']);
$driver
->expects($this->once())
->method('isStarted')
->willReturn(true);
$driver
->expects($this->once())
->method('getWebDriver')
->willThrowException(new \RuntimeException('An upstream error'));
$mockWebDriver = $this->createMockWebDriver();
$mockWebDriver->method('quit')->willThrowException(new \RuntimeException('An upstream error'));
$driver = new WebdriverClassicDriver('fake browser', [], 'example.com', fn() => $mockWebDriver);

$driver->start();

$this->expectException(DriverException::class);
$this->expectExceptionMessage('Could not close connection: An upstream error');
Expand Down
34 changes: 34 additions & 0 deletions tests/WebDriverMockingTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

namespace Mink\WebdriverClassicDriver\Tests;

use Facebook\WebDriver\Remote\RemoteWebDriver;
use Facebook\WebDriver\WebDriverOptions;
use Facebook\WebDriver\WebDriverTimeouts;
use PHPUnit\Framework\MockObject\MockObject;

trait WebDriverMockingTrait
{
/**
* @template T
* @param class-string<T> $class
* @return T&MockObject
*/
abstract function createMock(string $class): object;

/**
* @return RemoteWebDriver&MockObject
*/
private function createMockWebDriver(): RemoteWebDriver
{
$mockWebDriverTimeouts = $this->createMock(WebDriverTimeouts::class);

$mockWebDriverOptions = $this->createMock(WebDriverOptions::class);
$mockWebDriverOptions->method('timeouts')->willReturn($mockWebDriverTimeouts);

$mockWebDriver = $this->createMock(RemoteWebDriver::class);
$mockWebDriver->method('manage')->willReturn($mockWebDriverOptions);

return $mockWebDriver;
}
}
Loading