Skip to content

Testing AJAX

When to Use

You need automated tests for AJAX functionality to prevent regressions.

Pattern

// Functional test for AJAX (BrowserTestBase)
namespace Drupal\Tests\my_module\FunctionalJavascript;

use Drupal\FunctionalJavascriptTests\WebDriverTestBase;

class AjaxFormTest extends WebDriverTestBase {
  protected static $modules = ['my_module'];
  protected $defaultTheme = 'stark';

  public function testDependentFields() {
    // Visit form
    $this->drupalGet('/my-module/ajax-form');

    // Wait for page load
    $page = $this->getSession()->getPage();
    $assert = $this->assertSession();

    // Initially subcategory should be empty
    $assert->fieldExists('subcategory');
    $this->assertEmpty($page->findField('subcategory')->getValue());

    // Select category
    $page->selectFieldOption('category', 'electronics');

    // Wait for AJAX to complete
    $assert->assertWaitOnAjaxRequest();

    // Verify subcategory populated
    $subcategory_field = $page->findField('subcategory');
    $this->assertNotEmpty($subcategory_field->getValue());

    // Verify specific option exists
    $assert->optionExists('subcategory', 'Laptops');
  }

  public function testAjaxContentUpdate() {
    $this->drupalGet('/my-module/ajax-page');

    $page = $this->getSession()->getPage();
    $assert = $this->assertSession();

    // Click AJAX button
    $page->pressButton('Load Content');

    // Wait for AJAX
    $assert->assertWaitOnAjaxRequest();

    // Verify content updated
    $assert->elementContains('css', '#content-wrapper', 'New content loaded');
  }

  public function testAjaxErrors() {
    $this->drupalGet('/my-module/ajax-form');

    $page = $this->getSession()->getPage();
    $assert = $this->assertSession();

    // Trigger AJAX without required field
    $page->pressButton('Submit');

    $assert->assertWaitOnAjaxRequest();

    // Verify error message appears
    $assert->pageTextContains('Email field is required');
  }
}

Reference: core/tests/Drupal/FunctionalJavascriptTests/Ajax/AjaxFormPageCacheTest.php

Common Mistakes

  • Not extending WebDriverTestBase → Use FunctionalJavascriptTests namespace for AJAX tests, not BrowserTestBase
  • Forgetting assertWaitOnAjaxRequest() → Tests check before AJAX completes; always wait
  • Not setting $defaultTheme → Tests fail in Drupal 11+; set theme explicitly
  • Testing only happy path → Test validation errors, access control, edge cases
  • Not cleaning up test data → Tests leave database changes; use transactions or manual cleanup

See Also