instaclick/php-webdriver
PHP client for Selenium WebDriver, enabling browser automation and end-to-end testing from PHP. Control Chrome/Firefox/RemoteWebDriver, manage sessions, elements, waits, and actions, with support for Selenium Grid and popular testing frameworks.
Installation:
composer require instaclick/php-webdriver
Ensure your project uses PHP 5.3+ (or higher if possible).
Basic Usage:
use Instaclick\WebDriver\RemoteWebDriver;
$host = 'http://localhost:4444/wd/hub'; // Default Selenium Grid URL
$driver = RemoteWebDriver::create($host);
// Example: Open a URL and find an element
$driver->get('https://example.com');
$element = $driver->findElement(WebDriverBy::name('q')); // Search input
$element->sendKeys('Laravel' . \Instaclick\WebDriver\Keys::ENTER);
First Use Case: Automate a login flow for a Laravel app’s admin panel:
$driver->get(env('APP_URL') . '/admin/login');
$driver->findElement(WebDriverBy::name('email'))->sendKeys('admin@example.com');
$driver->findElement(WebDriverBy::name('password'))->sendKeys('secure123');
$driver->findElement(WebDriverBy::cssSelector('button[type="submit"]'))->click();
Page Object Model (POM): Encapsulate interactions in reusable classes:
class LoginPage {
private $driver;
public function __construct(RemoteWebDriver $driver) {
$this->driver = $driver;
}
public function login(string $email, string $password) {
$this->driver->findElement(WebDriverBy::name('email'))->sendKeys($email);
$this->driver->findElement(WebDriverBy::name('password'))->sendKeys($password);
$this->driver->findElement(WebDriverBy::cssSelector('button[type="submit"]'))->click();
}
}
Integration with Laravel:
Bind the driver to Laravel’s service container in AppServiceProvider:
public function register() {
$this->app->singleton(RemoteWebDriver::class, function ($app) {
return RemoteWebDriver::create('http://selenium:4444/wd/hub');
});
}
Use dependency injection in controllers/tests:
public function testLogin(RemoteWebDriver $driver) {
$loginPage = new LoginPage($driver);
$loginPage->login('admin@example.com', 'secure123');
}
Cross-Browser Testing: Dynamically switch capabilities:
$capabilities = DesiredCapabilities::chrome();
$capabilities->setCapability('browserName', 'firefox');
$driver = RemoteWebDriver::create($host, $capabilities);
Async Testing:
Use WebDriverWait for dynamic content:
$wait = new WebDriverWait($driver, 10);
$wait->until(WebDriverExpectedCondition::presenceOfElementLocated(WebDriverBy::id('flash-message')));
Session Management:
try {
$element->click();
} catch (StaleElementReferenceException $e) {
$element = $driver->findElement(WebDriverBy::id('dynamic-element'));
$element->click();
}
Headless Mode:
$capabilities->setCapability('goog:loggingPrefs', ['performance' => 'ALL']);
$capabilities->setCapability('browserName', 'chrome');
$capabilities->setCapability('chromeOptions', [
'args' => ['--disable-blink-features=AutomationControlled']
]);
Slow Tests:
$driver->manage()->timeouts()->implicitlyWait(2); // 2 seconds
XPath/CSS Selectors:
data-testid attributes or unique IDs. Use By::xpath("//*[@data-testid='submit']").Logs: Enable verbose logging to diagnose issues:
$driver->manage()->logs()->get('browser');
Or configure the driver with logging:
$driver = RemoteWebDriver::create($host, [], [
'loggingLevel' => \Monolog\Logger::DEBUG
]);
Screenshots: Capture screenshots on failure:
try {
$element->click();
} catch (Exception $e) {
$driver->takeScreenshot('screenshot.png');
throw $e;
}
Network Conditions: Simulate slow networks for testing:
$capabilities->setCapability('chromeOptions', [
'args' => ['--net-conditions=Latency=200']
]);
Custom Commands: Extend the driver with custom methods:
class ExtendedWebDriver extends RemoteWebDriver {
public function scrollToBottom() {
$this->executeScript("window.scrollTo(0, document.body.scrollHeight);");
}
}
Hooks for Laravel: Use Laravel events to trigger tests (e.g., after deployment):
// In a service provider
Event::listen('deployed', function () {
$driver = app(RemoteWebDriver::class);
// Run smoke tests
});
Docker Integration:
Use docker-compose.yml to spin up Selenium:
services:
selenium:
image: selenium/standalone-chrome
ports:
- "4444:4444"
How can I help you explore Laravel packages today?