Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Mink Selenium2 Driver Laravel Package

lullabot/mink-selenium2-driver

A Selenium 2 (WebDriver) browser driver for Mink, letting PHP acceptance tests control real browsers via WebDriver. Maintained by Lullabot for Drupal and Behat testing, it runs JavaScript-driven scenarios and integrates with Mink sessions and selectors.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a drop-in replacement for behat/mink-selenium2-driver, not a new API. Lullabot forked the abandoned upstream to keep it working on PHP 8.1+ (Drupal core is the main consumer). The driver class keeps the original FQCN, so your code and config never mention Lullabot anywhere.

composer remove --dev behat/mink-selenium2-driver   # never install both
composer require --dev lullabot/mink-selenium2-driver
# typical trio for a Behat suite
composer require --dev behat/mink behat/mink-extension behat/behat

Confirm the swap really happened:

composer show lullabot/mink-selenium2-driver   # check the `replace` clause lists behat/mink-selenium2-driver

First use case — decide if you need it at all. A plain Laravel app should use Dusk; it talks to ChromeDriver via php-webdriver directly and integrates with the framework. Reach for this package only when:

  • you already have a Gherkin/Behat suite (stakeholder-readable .feature files, or a suite ported from Drupal), or
  • you need a .feature spec shared across a Laravel backend and a Drupal/legacy frontend.

Where to look first: vendor/lullabot/mink-selenium2-driver/src/Selenium2Driver.php (methods getWebDriver(), getScreenshot(), setTimeouts(), attachFile()) and vendor/behat/mink-extension/behat.yml.dist for the config schema.

Minimal working setup:

# behat.yml
default:
  suites:
    web:
      contexts: [App\Tests\Behat\FeatureContext]
  extensions:
    Behat\MinkExtension:
      base_url: http://127.0.0.1:8000
      default_session: selenium2
      javascript_session: selenium2
      selenium2:
        wd_host: http://127.0.0.1:4444
        browser: chrome
        capabilities:
          browserName: chrome
          "goog:chromeOptions":
            args: ["--headless=new", "--no-sandbox", "--disable-dev-shm-usage"]
docker run -d -p 4444:4444 -p 7900:7900 selenium/standalone-chrome:latest
php artisan serve --port=8000 &
vendor/bin/behat --tags=@javascript

Implementation Patterns

Session without Behat. Useful inside a Pest/PHPUnit test or an Artisan command when you want Mink's portable element API:

use Behat\Mink\Driver\Selenium2Driver;
use Behat\Mink\Session;

$driver  = new Selenium2Driver('chrome', [
    'goog:chromeOptions' => ['args' => ['--headless=new', '--no-sandbox']],
], 'http://127.0.0.1:4444');

$session = new Session($driver);
$session->start();
$session->visit('http://localhost:8000/login');
$session->getPage()->fillField('email', '[email protected]');
$session->getPage()->pressButton('Sign in');

Tag-driven JS. Keep default_session: selenium2 off for speed and attach @javascript only to features that need a real browser; MinkExtension switches to the Selenium session automatically.

Waiting. Never sleep(). Prefer Mink's built-ins, which poll:

$session->wait(5000, "document.querySelector('[data-testid=toast]') !== null");
$button = $session->getPage()->waitFor(10, fn ($page) => $page->findButton('Save'));

Escape hatch to the raw WebDriver — this is the 20% of cases Mink doesn't model (alerts, logs, multi-tab, CDP):

$wd = $session->getDriver()->getWebDriver();   // php-webdriver RemoteWebDriver
$wd->switchTo()->alert()->accept();
$wd->switchTo()->window($wd->getWindowHandles()[1]);
$entries = $wd->manage()->getLog('browser');    // needs goog:loggingPrefs capability

Screenshots on failure — the highest-value hook you'll write, since this driver has no built-in artifact handling:

use Behat\Behat\Hook\Scope\AfterStepScope;

/** @AfterStep */
public function screenshotOnFailure(AfterStepScope $scope): void
{
    if ($scope->getTestResult()->isPassed()) {
        return;
    }
    $dir  = storage_path('app/behat');
    $name = preg_replace('/[^a-z0-9]+/i', '-', $scope->getStep()->getText());
    file_put_contents("$dir/{$name}.png", $this->getSession()->getDriver()->getScreenshot());
}

getScreenshot() returns decoded PNG bytes, not base64 — write it straight to disk and attach it in CI.

Page objects over selectors. Wrap Mink's NodeElement in small classes with data-testid lookups ($page->find('css', '[data-testid=cart-total]')). CSS through find('css', …) is far more stable against Blade/Vue re-renders than XPath, and XPath is where 80% of flaky locators in ported Drupal suites come from.

DB state. Point the suite at a dedicated connection — --env=testing with sqlite-in-memory works only if your Behat process and php artisan serve share it, which they won't. Use a real MySQL/Postgres test DB and RefreshDatabase-equivalent truncation between scenarios.

Extension point. Subclass Selenium2Driver to override getWebDriver() (e.g. to add default capabilities or retry connection) and register your class in your own DI instead of relying on MinkExtension.

Gotchas and Tips

  • wd_host and the /wd/hub suffix. Selenium 4 dropped the JSON Wire endpoint; http://localhost:4444/wd/hub may 404. Use http://selenium:4444 (no path) with a current php-webdriver. This is the #1 cause of "cannot connect to Selenium".
  • Container networking. localhost:4444 inside your PHP container is not the Selenium container. Use the Compose service name, and remember the PHP process is the client — Selenium does not need to reach your app, but the browser does, so base_url must be resolvable from inside the Selenium container (often http://nginx or host.docker.internal, not 127.0.0.1).
  • attachFile() resolves paths on the browser host, not the PHP host. In Docker, bind-mount your fixtures into the Selenium container or uploads silently fail with a confusing "file not found".
  • Capability keys changed for W3C. chromeOptions/chrome (old) vs goog:chromeOptions (W3C). Selenium 4 + php-webdriver ≥1.12 expects the prefixed form; mixing them produces a browser that launches but ignores --headless.
  • Stale elements. Any DOM mutation invalidates NodeElement handles. After an AJAX action, re-query from $session->getPage() — don't cache elements in properties.
  • Class collision risk. Because it reuses Behat\Mink\Driver\Selenium2Driver, leaving the upstream package installed (directly or transitively) gives you duplicate-class or autoload-ordering surprises. composer why behat/mink-selenium2-driver after install; if anything still pulls it, add an explicit replace in your root composer.json.
  • Headless flags are mandatory in CI, not optional: --no-sandbox --disable-dev-shm-usage --window-size=1440,900. Without the last one, responsive breakpoints silently flip your layout and locators vanish.
  • Debugging. Run non-headless with selenium/standalone-chrome and watch via VNC (http://localhost:7900, password secret), or use selenium/standalone-chrome-debug for an interactive session. On failure, $wd->getCurrentURL(), $wd->getPageSource(), and getLog('browser') usually identify the issue faster than re-running.
  • No Laravel integration. No .env config, no Artisan command, no RefreshDatabase, no exception rendering. Budget for a FeatureContext base class that handles bootstrapping, DB resets, and artifact capture — that glue is the real cost of choosing Mink over Dusk.
  • Bus factor. 2 stars, 0 dependents, last release 2024-08-08. Treat it as a maintenance fork: pin the exact version in composer.json, keep your driver usage confined to one class in your test suite, and watch upstream — if behat/mink-selenium2-driver ever resumes releases, swapping back should be a one-line change. Do not build bespoke features on top of this driver's internals.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager