Weave Code
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

Laravel Dom Assertions Laravel Package

sinnbeck/laravel-dom-assertions

Extra DOM assertion helpers for Laravel HTTP tests. Assert elements, text, forms, selects, and datalists with more precision than assertSee/SeeText. Works with Livewire and Blade views/components; includes quick existence checks and a method reference.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require sinnbeck/laravel-dom-assertions --dev
    

    (For Laravel 9/PHP 8.0, use ^2.0)

  2. First Use Case: Replace basic assertSee with granular DOM assertions in a test:

    $this->get('/dashboard')
        ->assertElementExists('#user-profile', fn (AssertElement $el) => $el->is('div'));
    
  3. Where to Look First:

    • Method Reference in the README for available assertions.
    • AssertElement class docs (via IDE autocompletion) for fluent API details.
    • Example tests in the tests directory.

Implementation Patterns

Core Workflows

  1. Element Assertions:

    // Basic existence
    $this->get('/')->assertElementExists('header');
    
    // Fluent assertions
    $this->get('/')->assertElementExists('header', fn (AssertElement $el) => [
        $el->is('header'),
        $el->has('class', 'main-header'),
        $el->containsText('Welcome'),
    ]);
    
  2. Form-Specific Tests:

    $this->get('/login')->assertFormExists('#login-form', fn (AssertForm $form) => [
        $form->hasAction('/auth/login')
            ->hasMethod('post')
            ->containsInput(['name' => 'email'])
            ->containsButton(['type' => 'submit']),
    ]);
    
  3. Nested Assertions:

    $this->get('/products')->assertElementExists('#product-list', fn (AssertElement $list) => [
        $list->each('li.product', fn (AssertElement $item) => [
            $item->contains('h3.title'),
            $item->find('.price', fn (AssertElement $price) => $price->containsText('$')),
        ]),
    ]);
    

Integration Tips

  • Livewire: Use assertElementExists() to verify dynamic updates:
    $this->livewire(ProfileComponent::class)
        ->assertElementExists('#livewire-updated', fn ($el) => $el->containsText('Updated!'));
    
  • Blade Components: Test component-specific selectors:
    $this->get('/')->assertElementExists('x-app', fn ($el) => $el->contains('x-data'));
    
  • API + Frontend: Chain with API assertions:
    $response = $this->postJson('/api/users')->assertCreated();
    $this->get('/users')->assertElementExists('#user-1', fn ($el) => $el->containsText($response['name']));
    

Magic Methods

Leverage shortcuts for common patterns:

// Instead of:
$assert->is('div')->has('class', 'foo');

// Use:
$assert->isDiv()->hasClass('foo');

// For forms:
$form->hasEnctype('multipart/form-data'); // Shortcut for has('enctype', '...')

Gotchas and Tips

Pitfalls

  1. Selector Specificity:

    • Overly broad selectors (e.g., div) may match unintended elements. Prefer IDs or unique classes.
    • Fix: Use each() to validate all matches:
      $assert->each('div.card', fn ($el) => $el->has('data-id'));
      
  2. Whitespace Normalization:

    • Global config (normalize_whitespace) may hide subtle text mismatches.
    • Fix: Explicitly disable for critical tests:
      $assert->containsText('Exact Match', normalizeWhitespace: false);
      
  3. Livewire/Alpine Attributes:

    • Dynamic attributes (e.g., x-data) may change between tests.
    • Fix: Use partial matches or regex:
      $assert->has('x-data', '/\{.*\}/');
      
  4. Form Method Spoofing:

    • hasMethod('PUT') auto-detects spoofed methods, but may fail if the form lacks a method attribute.
    • Fix: Explicitly check for spoofing:
      $form->hasMethod('PUT')->hasSpoofMethod('PUT');
      

Debugging

  • Inspect DOM: Use assertElementExists() with no closure to validate the parsed DOM structure.
  • Dump Assertions: Temporarily add dd($element->getDOMNode()) inside closures to debug node structures.
  • Test Isolation: Clear caches (php artisan optimize:clear) if tests fail intermittently due to stale views.

Extension Points

  1. Custom Assertions: Extend the AssertElement class to add domain-specific methods:

    class CustomAssertElement extends AssertElement {
        public function hasAlpineData(string $key) {
            return $this->has('x-data', fn ($value) => str_contains($value, $key));
        }
    }
    

    Register via service provider.

  2. Config Overrides: Publish the config to customize defaults:

    php artisan vendor:publish --tag=dom-assertions-config
    

    Modify normalize_whitespace or add custom selectors.

  3. Rector Rules: Use the provided Rector rules to auto-convert legacy assertSee to DOM assertions:

    vendor/bin/rector process src --dry-run
    

Performance

  • Avoid Over-Nesting: Deeply nested find() calls can slow tests. Prefer direct selectors where possible.
  • Reuse Responses: Cache responses for multi-step assertions:
    $response = $this->get('/');
    $response->assertElementExists('#header');
    $response->assertElementExists('#footer');
    
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.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky