Fluent DOM assertions with Pest-like syntax for Laravel tests using PHP 8.4's Dom\HTMLDocument.
Find a file
2026-02-03 20:09:15 +01:00
.github Add Github CI 2026-02-03 19:54:33 +01:00
src Code style 2026-02-03 18:55:05 +00:00
tests Fix DomAssertTest 2026-02-03 19:58:48 +01:00
.gitignore Init 2026-02-03 19:50:54 +01:00
composer.json Fix composer.json 2026-02-03 20:09:15 +01:00
LICENSE.md Init 2026-02-03 19:50:54 +01:00
phpstan.neon Init 2026-02-03 19:50:54 +01:00
phpunit.xml Init 2026-02-03 19:50:54 +01:00
pint.json Init 2026-02-03 19:50:54 +01:00
README.md Update Readme 2026-02-03 20:04:43 +01:00

Laravel Assert DOM

Latest Version on Packagist Software License Total Downloads

Fluent DOM assertions with Pest-like syntax for Laravel tests using PHP 8.4's Dom\HTMLDocument.

Requirements

  • PHP 8.4+
  • Laravel 11+

Installation

composer require pxlrbt/laravel-assert-dom --dev

Register the mixin in your tests/Pest.php:

use Illuminate\Testing\TestResponse;
use pxlrbt\LaravelAssertDom\AssertDomMixin;

protected function setUp(): void
{
    parent::setUp();

    TestResponse::mixin(new AssertDomMixin());
}

Usage

Basic Assertions

$response->assertDom('.card', fn (DomAssert $el) => $el
    ->text()->toEqual('Hello World')
    ->attribute('id')->toEqual('main-card')
);

Text Content

$response->assertDom('.message', fn (DomAssert $el) => $el
    ->text()->toEqual('Welcome')
    ->text()->toContain('Welc')
    ->text()->toMatch('/Welcome/')
    ->text()->toBeEmpty()
);

Inner HTML

$response->assertDom('.content', fn (DomAssert $el) => $el
    ->html()->toContain('<strong>')
    ->html()->toEqual('<strong>Test</strong>')
);

Attributes

$response->assertDom('button', fn (DomAssert $el) => $el
    ->attribute('type')->toEqual('submit')
    ->attribute('disabled')->toExist()
    ->attribute('aria-hidden')->not->toExist()
);

Convenience Methods

$response->assertDom('.user', fn (DomAssert $el) => $el
    ->class()->toContain('active')
    ->class()->not->toContain('hidden')
    ->data('user-id')->toEqual('123')
    ->value()->toEqual('John Doe')
);

Tag Name

$response->assertDom('.container', fn (DomAssert $el) => $el
    ->toBeTag('div')
    ->not->toBeTag('span')
);

Child Elements

$response->assertDom('.profile', fn (DomAssert $el) => $el
    ->toHave('.avatar')
    ->not->toHave('.error')
);

Count Children

$response->assertDom('.user-list', fn (DomAssert $el) => $el
    ->toHave('li', 3)
    ->toHaveCount(5)
);

Nested Assertions

$response->assertDom('.user-list', fn (DomAssert $el) => $el
    ->toHave('li', fn (DomAssert $item) => $item
        ->class()->toContain('item')
        ->text()->toContain('User')
    )
);

Negation

All string assertions support negation via ->not:

$response->assertDom('.profile', fn (DomAssert $el) => $el
    ->text()->toContain('John')
    ->text()->not->toContain('Jane')
    ->class()->not->toContain('hidden')
    ->attribute('disabled')->not->toExist()
);

Assert All Matched Elements

$response->assertDomAll('.card', fn (DomAssert $el) => $el
    ->class()->toContain('card-item')
    ->toHave('.title')
);

Fluent Chaining

All assertions return the parent DomAssert instance, enabling fluent chains:

$response->assertDom('.card', fn (DomAssert $el) => $el
    ->toBeTag('div')
    ->attribute('id')->toEqual('main')
    ->class()->toContain('active')
    ->class()->not->toContain('hidden')
    ->data('count')->toEqual('5')
    ->toHave('strong')
    ->not->toHave('.error')
    ->text()->toContain('Hello')
);

Similar Packages

License

MIT