$npx -y skills add edutrul/drupal-ai --skill drupal-dttDrupal Test Traits (DTT) ExistingSite tests — testing against a live Drupal site, creating content, asserting pages, and running tests with DDEV.
| 1 | # Drupal Test Traits (DTT) — ExistingSite Tests |
| 2 | |
| 3 | ## When to Use |
| 4 | |
| 5 | - Testing against a real, running Drupal site |
| 6 | - Smoke tests and integration tests against production-like data |
| 7 | - When you need real content, config, and users |
| 8 | - Regression tests for bugs found in production |
| 9 | |
| 10 | ## Basic Structure |
| 11 | |
| 12 | ```php |
| 13 | // tests/src/ExistingSite/MyFeatureTest.php |
| 14 | namespace Drupal\Tests\my_module\ExistingSite; |
| 15 | |
| 16 | use weitzman\DrupalTestTraits\ExistingSiteBase; |
| 17 | |
| 18 | /** |
| 19 | * Tests My Feature on an existing site. |
| 20 | * |
| 21 | * @group my_module |
| 22 | * @group existing_site |
| 23 | */ |
| 24 | final class MyFeatureTest extends ExistingSiteBase { |
| 25 | |
| 26 | public function testHomepageLoads(): void { |
| 27 | $this->drupalGet('/'); |
| 28 | $this->assertSession()->statusCodeEquals(200); |
| 29 | $this->assertSession()->pageTextContains('Welcome'); |
| 30 | } |
| 31 | |
| 32 | public function testArticleCreation(): void { |
| 33 | // Create a user with role |
| 34 | $user = $this->createUser(); |
| 35 | $user->addRole('editor'); |
| 36 | $user->save(); |
| 37 | $this->drupalLogin($user); |
| 38 | |
| 39 | // Create a node |
| 40 | $node = $this->createNode([ |
| 41 | 'type' => 'article', |
| 42 | 'title' => 'Test Article', |
| 43 | 'status' => 1, |
| 44 | ]); |
| 45 | |
| 46 | $this->drupalGet('/node/' . $node->id()); |
| 47 | $this->assertSession()->statusCodeEquals(200); |
| 48 | $this->assertSession()->pageTextContains('Test Article'); |
| 49 | } |
| 50 | |
| 51 | public function testFormSubmission(): void { |
| 52 | $this->drupalGet('/contact'); |
| 53 | $this->assertSession()->statusCodeEquals(200); |
| 54 | |
| 55 | $this->submitForm([ |
| 56 | 'name' => 'Test User', |
| 57 | 'mail' => 'test@example.com', |
| 58 | 'message[0][value]' => 'Test message', |
| 59 | ], 'Send message'); |
| 60 | |
| 61 | $this->assertSession()->pageTextContains('Your message has been sent.'); |
| 62 | } |
| 63 | |
| 64 | } |
| 65 | ``` |
| 66 | |
| 67 | ## Common Assertions |
| 68 | |
| 69 | ```php |
| 70 | // HTTP status |
| 71 | $this->assertSession()->statusCodeEquals(200); |
| 72 | $this->assertSession()->statusCodeEquals(403); |
| 73 | $this->assertSession()->statusCodeEquals(404); |
| 74 | |
| 75 | // Page content |
| 76 | $this->assertSession()->pageTextContains('Expected text'); |
| 77 | $this->assertSession()->pageTextNotContains('Missing text'); |
| 78 | |
| 79 | // Elements |
| 80 | $this->assertSession()->elementExists('css', '.my-class'); |
| 81 | $this->assertSession()->elementTextContains('css', 'h1', 'Page Title'); |
| 82 | $this->assertSession()->linkExists('My Link'); |
| 83 | $this->assertSession()->linkByHrefExists('/my-path'); |
| 84 | |
| 85 | // Fields |
| 86 | $this->assertSession()->fieldExists('edit-title-0-value'); |
| 87 | $this->assertSession()->fieldValueEquals('edit-title-0-value', 'My Title'); |
| 88 | |
| 89 | // Response headers |
| 90 | $this->assertSession()->responseHeaderContains('X-Drupal-Cache', 'HIT'); |
| 91 | ``` |
| 92 | |
| 93 | ## Helpers |
| 94 | |
| 95 | ```php |
| 96 | // Navigate to URL |
| 97 | $this->drupalGet('/path'); |
| 98 | $this->drupalGet(Url::fromRoute('my_module.page')); |
| 99 | |
| 100 | // Login |
| 101 | $this->drupalLogin($user); |
| 102 | $this->drupalLogout(); |
| 103 | |
| 104 | // Create content (automatically cleaned up after test) |
| 105 | $node = $this->createNode(['type' => 'article', 'title' => 'Test']); |
| 106 | $user = $this->createUser([], NULL, FALSE, ['mail' => 'test@test.com']); |
| 107 | $term = $this->createTerm($vocabulary); |
| 108 | |
| 109 | // Submit form |
| 110 | $this->submitForm(['field_name' => 'value'], 'Submit button label'); |
| 111 | |
| 112 | // Click link |
| 113 | $this->clickLink('Link text'); |
| 114 | |
| 115 | // Find element |
| 116 | $page = $this->getSession()->getPage(); |
| 117 | $element = $page->find('css', '.my-selector'); |
| 118 | ``` |
| 119 | |
| 120 | ## Running Tests |
| 121 | |
| 122 | ```bash |
| 123 | # Run all DTT tests |
| 124 | ddev exec vendor/bin/phpunit tests/ |
| 125 | |
| 126 | # Run specific test |
| 127 | ddev exec vendor/bin/phpunit tests/src/ExistingSite/MyFeatureTest.php |
| 128 | |
| 129 | # Run with group filter |
| 130 | ddev exec vendor/bin/phpunit tests/ --group my_module |
| 131 | |
| 132 | # Verbose output |
| 133 | ddev exec vendor/bin/phpunit tests/ --verbose |
| 134 | ``` |