JavaScript Tests with WebDriverTestBase
When to Use
Testing JavaScript interactions, AJAX callbacks, dynamic DOM manipulation requiring a real browser.
Decision
| Feature | BrowserTestBase | WebDriverTestBase |
|---|---|---|
| HTTP simulation | Yes (BrowserKit) | Yes (Real browser) |
| JavaScript execution | No | Yes |
| AJAX/fetch requests | No | Yes |
| DOM events (click, hover, etc.) | No | Yes |
| Speed (seconds per test) | 10-30 | 20-60 |
| Setup complexity | Low | High (requires chromedriver) |
Use WebDriverTestBase when: JavaScript behavior is essential to test, AJAX interactions, complex UI widgets.
Pattern
Basic JavaScript test structure:
namespace Drupal\Tests\my_module\FunctionalJavascript;
use Drupal\FunctionalJavascriptTests\WebDriverTestBase;
class AjaxFormTest extends WebDriverTestBase {
protected $defaultTheme = 'stark';
protected static $modules = ['my_module'];
public function testAjaxCallback(): void {
$this->drupalLogin($this->rootUser);
$this->drupalGet('my-form');
$page = $this->getSession()->getPage();
$assert = $this->assertSession();
// Trigger AJAX
$page->selectFieldOption('category', 'books');
$assert->waitForElement('css', '.subcategory-wrapper');
// Assert AJAX result
$assert->fieldExists('subcategory');
$assert->optionExists('subcategory', 'Fiction');
}
}
Waiting for JavaScript operations:
// Wait for element to appear
$this->assertSession()->waitForElement('css', '#ajax-result');
// Wait for element to disappear
$this->assertSession()->waitForElementRemoved('css', '.loading-spinner');
// Wait for text
$this->assertSession()->waitForText('Operation complete');
// Custom wait condition
$this->getSession()->wait(5000, "jQuery('.target').length > 0");
File location: modules/my_module/tests/src/FunctionalJavascript/AjaxFormTest.php
Reference: /core/tests/Drupal/FunctionalJavascriptTests/WebDriverTestBase.php
Common Mistakes
- Not starting chromedriver before running tests -- "Could not connect to host" failure
- Using https:// in SIMPLETEST_BASE_URL -- "invalid cookie domain" exception (use http://)
- Not waiting for AJAX operations -- test runs ahead of browser, assertions fail intermittently
- Hardcoding wait times
sleep(2)-- flaky tests (usewaitForElement()instead) - Disabling CSS animations with
$disableCssAnimations = FALSEwithout reason -- tests fail on timing issues
See Also
- Browser Tests with BrowserTestBase
- Test Traits & Utilities
- Reference:
/core/tests/Drupal/FunctionalJavascriptTests/WebDriverTestBase.php - Running PHPUnit JavaScript tests | Drupal.org