Install the package:
composer require oleg-andreyev/mink-phpwebdriver
Configure Mink in your Laravel project (typically in phpunit.xml or a test config file):
<php>
<server name="MINK_DRIVER_ARGS" value="{'browser':'chrome','host':'localhost','port':9515}"/>
</php>
Start WebDriver (e.g., Chrome):
./vendor/bin/phpwebdriver --browser=chrome --port=9515
(Use the provided start_webdriver.sh script from the repo for convenience.)
Write a basic test (using Laravel's BrowserKitTestingTrait or Mink integration):
use Facebook\WebDriver\WebDriverBy;
use Facebook\WebDriver\WebDriverExpectedCondition;
$session = $this->getSession();
$session->get('https://example.com');
$this->assertEquals('Example Domain', $session->findElement(WebDriverBy::id('example'))->getText());
use MinkPhpWebDriver\Driver;
$driver = new Driver([
'browser' => 'chrome',
'host' => 'localhost',
'port' => 9515,
]);
$mink = new Mink($driver);
$session = $mink->getSession();
Driver Initialization:
config/testing.php or via environment variables:
'mink' => [
'driver' => MinkPhpWebDriver\Driver::class,
'driver_args' => [
'browser' => env('BROWSER', 'chrome'),
'host' => env('WEBDRIVER_HOST', 'localhost'),
'port' => env('WEBDRIVER_PORT', 9515),
'headless' => env('HEADLESS', false),
],
],
Mink facade or inject the driver directly into tests.Session Management:
$session = $this->getSession();
$session->start();
// Test logic...
$session->quit();
Headless Mode:
$driver = new Driver([
'browser' => 'chrome',
'headless' => true,
]);
Screenshot Capture:
$session->addListener(new \MinkPhpWebDriver\Listener\ScreenshotListener());
storage/logs/mink-screenshots/ (configurable).Laravel Testing:
Extend Laravel\BrowserKitTesting\Concerns\ProvidesBrowserKitToApplication to include MinkPhpWebDriver:
use MinkPhpWebDriver\Driver;
protected function createApplication()
{
$app = parent::createApplication();
$app->make('mink')->setDriver(new Driver($this->driverArgs));
return $app;
}
Behat Integration: Use the MinkPhpWebdriverExtension for BDD:
# behat.yml
extensions:
MinkPhpWebdriverExtension:
browser: chrome
host: localhost
port: 9515
Parallel Testing: Spin up multiple WebDriver instances (e.g., Chrome + Firefox) for parallel test suites:
# Terminal 1
./vendor/bin/phpwebdriver --browser=chrome --port=9515
# Terminal 2
./vendor/bin/phpwebdriver --browser=firefox --port=9516
Driver Version Mismatches:
facebook/webdriver and browser drivers (e.g., ChromeDriver) are compatible.start_driver.sh script to auto-download matching drivers:
./vendor/bin/start_driver.sh chrome latest
Headless Mode Quirks:
--headless=new for v100+).--disable-gpu in some Docker environments:
$driver->setCapability('goog:chromeOptions', [
'args' => ['--headless', '--disable-gpu'],
]);
Session Leaks:
$session->quit() to avoid zombie sessions:
public function tearDown(): void
{
$this->getSession()->quit();
parent::tearDown();
}
Time Input Handling:
<input type="time"> may fail in older browsers. Use explicit JS:
$session->executeScript("document.querySelector('input[type=time]').value = '12:00'");
Firefox Prompts:
$alert = $session->wait(5, function () use ($session) {
return $session->getAlert();
});
$alert->accept();
Logs:
Enable verbose logging via MINK_DRIVER_ARGS:
'driver_args' => [
'browser' => 'chrome',
'logging' => ['browser' => 'ALL'],
],
Check logs in storage/logs/mink-*.log.
Network Issues:
Use host: 'localhost' for local testing, but switch to host: 'host.docker.internal' in Docker:
'driver_args' => ['host' => 'host.docker.internal'],
Element Interaction:
Use executeScript for complex interactions (e.g., drag-and-drop):
$session->executeScript("
const source = document.querySelector('#draggable');
const target = document.querySelector('#droppable');
source.dispatchEvent(new DragEvent('dragstart'));
target.dispatchEvent(new DragEvent('drop'));
");
Custom Capabilities: Override browser capabilities for advanced use cases:
$driver->setCapability('marionette', true); // Firefox
$driver->setCapability('excludeSwitches', ['enable-automation']); // Chrome
Event Listeners:
Extend \MinkPhpWebDriver\Listener\BaseListener to add custom hooks (e.g., for analytics):
class CustomListener extends BaseListener
{
public function onSessionStart(Session $session)
{
$session->executeScript("console.log('Test started')");
}
}
Driver Pooling:
Reuse sessions across tests by implementing a custom SessionManager:
$pool = new \MinkPhpWebDriver\SessionPool($driver);
$session = $pool->get('test-123'); // Reuses if exists
CI Optimization: Cache WebDriver binaries in CI (e.g., GitHub Actions):
- name: Cache WebDriver
uses: actions/cache@v3
with:
path: ~/.cache/webdriver
key: ${{ runner.os }}-webdriver-${{ hashFiles('**/composer.lock') }}
How can I help you explore Laravel packages today?