{"id":15014463,"url":"https://github.com/sinnbeck/laravel-dom-assertions","last_synced_at":"2025-04-05T21:08:39.820Z","repository":{"id":61689813,"uuid":"553573780","full_name":"sinnbeck/laravel-dom-assertions","owner":"sinnbeck","description":"Adds DOM assertions to laravels test responses","archived":false,"fork":false,"pushed_at":"2024-08-28T06:27:30.000Z","size":129,"stargazers_count":95,"open_issues_count":2,"forks_count":7,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-29T20:04:46.607Z","etag":null,"topics":["laravel","pestphp","php","phpunit","testing"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sinnbeck.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-18T12:28:29.000Z","updated_at":"2025-01-30T20:21:09.000Z","dependencies_parsed_at":"2024-06-17T13:54:02.623Z","dependency_job_id":"3785e826-590a-4513-8dd9-471f03647a1e","html_url":"https://github.com/sinnbeck/laravel-dom-assertions","commit_stats":{"total_commits":135,"total_committers":11,"mean_commits":"12.272727272727273","dds":0.3925925925925926,"last_synced_commit":"21956026c2d78e7e1ee1df32f5e438c86376658f"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sinnbeck%2Flaravel-dom-assertions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sinnbeck%2Flaravel-dom-assertions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sinnbeck%2Flaravel-dom-assertions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sinnbeck%2Flaravel-dom-assertions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sinnbeck","download_url":"https://codeload.github.com/sinnbeck/laravel-dom-assertions/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247399877,"owners_count":20932876,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["laravel","pestphp","php","phpunit","testing"],"created_at":"2024-09-24T19:45:39.898Z","updated_at":"2025-04-05T21:08:39.804Z","avatar_url":"https://github.com/sinnbeck.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DOM Assertions for Laravel\n\n[![Latest Version on Packagist](https://img.shields.io/packagist/v/sinnbeck/laravel-dom-assertions.svg?style=flat-square)](https://packagist.org/packages/sinnbeck/laravel-dom-assertions)\n[![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/sinnbeck/laravel-dom-assertions/run-tests.yml?branch=main\u0026label=tests\u0026style=flat-square)](https://github.com/sinnbeck/laravel-dom-assertions/actions?query=workflow%3Arun-tests+branch%3Amain)\n[![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/sinnbeck/laravel-dom-assertions/fix-php-cs.yml?branch=main\u0026label=code%20style\u0026style=flat-square)](https://github.com/sinnbeck/laravel-dom-assertions/actions?query=workflow%3A\"Fix+PHP+code+style+issues\"+branch%3Amain)\n[![Total Downloads](https://img.shields.io/packagist/dt/sinnbeck/laravel-dom-assertions.svg?style=flat-square)](https://packagist.org/packages/sinnbeck/laravel-dom-assertions)\n\nThis package provides some extra assertion helpers to use in HTTP Tests. If you have ever needed more control over your view assertions than `assertSee`, `assertSeeInOrder`, `assertSeeText`, `assertSeeTextInOrder`, `assertDontSee`, and `assertDontSeeText` then this is the package for you.\n\n## Installation\n\nYou can install the package via composer:\n\n```bash\ncomposer require sinnbeck/laravel-dom-assertions --dev\n```\n\n## Example\n\nImagine we have a view with this html\n```html\n\u003cnav\u003e\n    \u003cul\u003e\n        @foreach ($menuItems as $menuItem)\n            \u003cli @class([\n                \"p-3 text-white\",\n                \"text-blue-500 active\" =\u003e Route::is($menuItem-\u003eroute)\n            ])\u003e\n            \u003ca href=\"{{route($menuItem-\u003eroute)}}\"\u003e{{$menuItem-\u003ename}}\u003c/a\u003e\n        \u003c/li\u003e\n        @endforeach\n    \u003c/ul\u003e\n\u003c/nav\u003e\n```\nNow we want to make sure that the correct menu item is selected when on this route. \nWe could try with some regex to match it, but it might be easily break.\n```php\n$response = $this-\u003eget(route('about'))\n    -\u003eassertOk();\n$this-\u003eassertMatchesRegularExpression(\n    '/\u003cli(.)*class=\"(.)*active(.)*\"\u003e(.|\\n)*About(.|\\n)*?\u003c\\/li\u003e/',\n    $response-\u003egetContent()\n);\n```\nBut this can be very brittle, and a simple linebreak can cause it to fail.\n\nWith this package you can now use an expressive syntax like this.\n```php\n$this-\u003eget(route('about'))\n    -\u003eassertOk()\n    -\u003eassertElementExists('nav \u003e ul', function(\\Sinnbeck\\DomAssertions\\Asserts\\AssertElement $ul) {\n        $ul-\u003econtains('li', [\n            'class' =\u003e 'active',\n            'text' =\u003e 'About'\n        ]);\n        $ul-\u003edoesntContain('li', [\n            'class' =\u003e 'active',\n            'text' =\u003e 'Home'\n        ]);\n    });\n```\n## Usage\n\n### Testing the DOM\nWhen calling a route in a test you might want to make sure that the view contains certain elements. To test this you can use the `-\u003eassertElementExists()` method on the test response.\nThe following will ensure that there is a body tag in the parsed response. Be aware that this package assumes a proper html structure and will wrap your html in a html, head and body tag if they are missing!\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertElementExists();\n```\nIn case you want to get a specific element on the page, you can supply a css selector as the first argument to get a specific one.\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertElementExists('#nav');\n```\nThe second argument of `-\u003eassertElementExists()` is a closure that receives an instance of `\\Sinnbeck\\DomAssertions\\Asserts\\AssertElement`. This allows you to assert things about the element itself. Here we are asserting that the element is a `div`.\n\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertElementExists('#overview', function (AssertElement $assert) {\n        $assert-\u003eis('div');\n    });\n```\nJust like with forms you can assert that certain attributes are present\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertElementExists('#overview', function (AssertElement $assert) {\n        $assert-\u003ehas('x-data', '{foo: 1}');\n    });\n```\nor doesnt exist\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertElementExists('#overview', function (AssertElement $assert) {\n        $assert-\u003edoesntHave('x-data', '{foo: 2}');\n    });\n```\nYou can also ensure that certain children exist.\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertElementExists('#overview', function (AssertElement $assert) {\n        $assert-\u003econtains('div');\n    });\n```\nIf you need to be more specific you can use a css selector.\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertElementExists('#overview', function (AssertElement $assert) {\n        $assert-\u003econtains('div:nth-of-type(3)');\n    });\n```\nYou can also check that the child element has certain attributes.\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertElementExists('#overview', function (AssertElement $assert) {\n        $assert-\u003econtains('li.list-item', [\n            'x-data' =\u003e 'foobar'\n        ]);\n    });\n```\nor ensure that certain children does not exist\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertElementExists('#overview', function (AssertElement $assert) {\n        $assert-\u003edoesntContain('li.list-item', [\n            'x-data' =\u003e 'foobar'\n        ]);\n    });\n```\nContains also allow a third argument to specify how many times the element should be matched.\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertElementExists('#overview', function (AssertElement $assert) {\n        $assert-\u003econtains('li.list-item', [\n            'x-data' =\u003e 'foobar'\n        ], 3);\n    });\n```\nIf you just want to check for the element type you can leave out the second argument.\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertElementExists('#overview', function (AssertElement $assert) {\n        $assert-\u003econtains('li.list-item', 3);\n    });\n```\nYou can also find a certain element and do assertions on it. Be aware that it will only check the first matching element.\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertElementExists('#overview', function (AssertElement $assert) {\n        $assert-\u003efind('li.list-item');\n    });\n```\nYou can add a closure as the second argument which receives an instance of `\\Sinnbeck\\DomAssertions\\Asserts\\AssertElement`.\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertElementExists('#overview', function (AssertElement $assert) {\n        $assert-\u003efind('li.nth-of-type(3)', function (AssertElement $element) {\n            $element-\u003eis('li');\n        });\n    });\n```\nIf you want to make an assertion against all elements that match the selection, you may use 'each'.\n\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertElementExists('#overview', function (AssertElement $assert) {\n        $assert-\u003eeach('li', function (AssertElement $element) {\n            $element-\u003ehas('class', 'list-item');\n        });\n    });\n```\n\nYou can also infinitely assert down the dom structure.\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertElementExists(function (AssertElement $element) {\n        $element-\u003efind('div', function (AssertElement $element) {\n            $element-\u003eis('div');\n            $element-\u003efind('p', function (AssertElement $element) {\n                $element-\u003eis('p');\n                $element-\u003efind('#label', function (AssertElement $element) {\n                    $element-\u003eis('span');\n                });\n            });\n            $element-\u003efind('p:nth-of-type(2)', function (AssertElement $element) {\n                $element-\u003eis('p');\n                $element-\u003efind('.sub-header', function (AssertElement $element) {\n                    $element-\u003eis('h4');\n                });\n            });\n        });\n    });\n```\n\n### Testing forms\nTesting forms allows using all the dom asserts from above, but has a few special helpers to help test for forms.\nInstead of using `-\u003eassertElementExists()` we will use `-\u003eassertFormExists()` method on the test response.\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertFormExists();\n```\nThe `-\u003eassertFormExists()` method will check the first form it finds. In case you have more than one form, and want to use a different form that the first, you can supply a css selector as the first argument to get a specific one.\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertFormExists('#users-form');\n```\nIf there is more than one hit, it will return the first matching form.\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertFormExists(null, 'nav .logout-form');\n```\nThe second argument of `-\u003eassertFormExists()` is a closure that receives an instance of `\\Sinnbeck\\DomAssertions\\Asserts\\AssertForm`. This allows you to assert things about the form itself. Here we are asserting that it has a certain action and method\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertFormExists('#form1', function (AssertForm $form) {\n        $form-\u003ehasAction('/logout')\n            -\u003ehasMethod('post');\n    });\n```\nIf you leave out the css selector, it will automatically default to finding the first form on the page\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertFormExists(function (AssertForm $form) {\n        $form-\u003ehasAction('/logout')\n            -\u003ehasMethod('post');\n    });\n```\n\nYou can also check for csrf and method spoofing\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertFormExists(function (AssertForm $form) {\n        $form-\u003ehasAction('/update-user')\n            -\u003ehasMethod('post')\n            -\u003ehasCSRF()\n            -\u003ehasSpoofMethod('PUT');\n    });\n```\nChecking for methods other than GET and POST will automatically forward the call to `-\u003ehasSpoofMethod()`\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertFormExists(function (AssertForm $form) {\n        $form-\u003ehasMethod('PUT');\n    });\n```\nOr even arbitrary attributes\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertFormExists(function (AssertForm $form) {\n        $form-\u003ehas('x-data', 'foo')\n        $form-\u003ehasEnctype('multipart/form-data'); //it also works with magic methods\n    });\n```\n\nYou can also easily test for inputs or text areas \n```php\n$this-\u003eget('/some-route')\n    -\u003eassertFormExists(function (AssertForm $form) {\n        $form-\u003econtainsInput([\n            'name' =\u003e 'first_name',\n            'value' =\u003e 'Gunnar',\n        ])\n        -\u003econtainsTextarea([\n            'name' =\u003e 'comment',\n            'value' =\u003e '...',\n        ]);\n    });\n```\nOr arbitrary children\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertFormExists(function (AssertForm $form) {\n        $form-\u003econtains('label', [\n            'for' =\u003e 'username',\n        ])\n        -\u003econtainsButton([ //or use a magic method\n            'type' =\u003e 'submit',\n        ]);\n    });\n```\nYou can also ensure that certain children does not exist.\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertFormExists(function (AssertForm $form) {\n        $form-\u003edoesntContain('label', [\n            'for' =\u003e 'username',\n        ]);\n    });\n```\nTesting for selects is also easy and works a bit like the `assertFormExists()`. It takes a selector as the first argument, and closure as the second argument. The second argument returns an instance of `\\Sinnbeck\\DomAssertions\\Asserts\\AssertSelect`. This can be used to assert that the select has certain attributes.\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertFormExists(function (AssertForm $form) {\n        $form-\u003efindSelect('select:nth-of-type(2)', function (AssertSelect $select) {\n            $select-\u003ehas('name', 'country');\n        });\n    });\n```\nYou can also assert that it has certain options. You can either check for one specific or an array of options\n```php\n$this-\u003eget('/some-route')\n    -\u003eassertFormExists(function (AssertForm $form) {\n        $form-\u003efindSelect('select:nth-of-type(2)', function (AssertSelect $select) {\n            $select-\u003econtainsOption([\n                [\n                    'x-data' =\u003e 'none',\n                    'value'  =\u003e 'none',\n                    'text'   =\u003e 'None',\n                ]\n            ])\n            -\u003econtainsOptions(\n                [\n                    'value' =\u003e 'dk',\n                    'text'  =\u003e 'Denmark',\n                ],\n                [\n                    'value' =\u003e 'us',\n                    'text'  =\u003e 'USA',\n                ],\n            );\n        });\n    });\n```\nYou can check if a select has a value.\n```php\n$this-\u003eget('/some-route')\n        -\u003eassertFormExists('#form1', function (AssertForm $form) {\n            $form-\u003efindSelect('select', function (AssertSelect $select) {\n                $select-\u003ehasValue('da');\n            });\n        });\n```\n\n\nYou can also check selects with multiple values\n```php\n$this-\u003eget('/some-route')\n        -\u003eassertFormExists('#form1', function (AssertForm $form) {\n            $form-\u003efindSelect('select', function (AssertSelect $select) {\n                $select-\u003ehasValues(['da', 'en']);\n            });\n        });\n```\nTesting for datalists works mostly the same as selects. Only difference is that the selector needs to be either `datalist` or an id (eg. `#my-list`).\nThe assertion uses the `\\Sinnbeck\\DomAssertions\\Asserts\\AssertDatalist` class.\n```php\n$this-\u003eget('/some-route')\n        -\u003eassertFormExists('#form1', function (AssertForm $form) {\n            $form-\u003efindDatalist('#skills', function (AssertDatalist $list) {\n                $list-\u003econtainsOptions(\n                    [\n                        'value' =\u003e 'PHP',\n                    ],\n                    [\n                        'value' =\u003e 'Javascript',\n                    ],\n                );\n            });\n        });\n```\n\n### Usage with Livewire\nAs livewire uses the `TestResponse` class from laravel, you can easily use this package with Livewire without any changes\n```php\nLivewire::test(UserForm::class)\n    -\u003eassertElementExists('form', function (AssertElement $form) {\n        $form-\u003efind('#submit', function (AssertElement $assert) {\n            $assert-\u003eis('button');\n            $assert-\u003ehas('text', 'Submit');\n        })-\u003econtains('[wire\\:model=\"name\"]', 1);\n    });\n```\n\n### Usage with Blade views\nYou can also use this package to test blade views. \n```php\n$this-\u003eview('navigation')\n    -\u003eassertElementExists('nav \u003e ul', function(AssertElement $ul) {\n        $ul-\u003econtains('li', [\n            'class' =\u003e 'active',\n        ]);\n    });\n```\n\n## Overview of methods\n| Base methods                                   | Description                                                                          |\n|------------------------------------------------|--------------------------------------------------------------------------------------|\n| `-\u003ehas($attribute, $value)`                    | Checks if element has a certain attribute with a certain value. Value is optional    |\n| `-\u003ehasXdata('foo')`                            | Magic method. Same as `-\u003ehas('x-data', 'foo')`                                       |\n| `-\u003edoesntHave($attribute, $value)`             | Checks if element doesnt a certain attribute with a certain value. Value is optional |\n| `-\u003eis($type)`                                  | Checks if the element is of a specific type (div, span etc)                          |\n| `-\u003eisDiv()`                                    | Magic method. Same as `-\u003eis('div')`                                                  |\n| `-\u003econtains($selector, $attributes, $count)`   | Checks for any children of the current element                                       |\n| `-\u003econtainsDiv, ['class' =\u003e 'foo'], 3)`        | Magic method. Same as `-\u003econtains('div', ['class' =\u003e 'foo'], 3)`                     |\n| `-\u003econtainsText($needle, $ignoreCase)`         | Checks if the element's text content contains a specified string                     |\n| `-\u003edoesntContain($selector, $attributes)`      | Ensures that there are no matching children                                          |\n| `-\u003edoesntContainDiv, ['class' =\u003e 'foo'])`      | Magic method. Same as `-\u003edoesntContain('div', ['class' =\u003e 'foo'])`                   |\n| `-\u003edoesntContainText($needle, $ignoreCase)`    | Checks if the element's text content doesn't contain a specified string              |\n| `-\u003efind($selector, $callback)`                 | Find a specific child element and get a new AssertElement. Returns the first match.  |\n| `-\u003efindDiv(fn (AssertElement $element) =\u003e {})` | Magic method. Same as `-\u003efind('div', fn (AssertElement $element) =\u003e {})`             |\n\n| Form specific methods                   | Description                            |\n|-----------------------------------------|----------------------------------------|\n| `-\u003ehasAction($url)`                       | Ensures the form has a specific action |\n| `-\u003ehasMethod($method)`                    | Ensures a form has a specific method   |\n| `-\u003ehasSpoofMethod($method)`               | Ensures form has a spoofed method      |\n| `-\u003ehasCSRF()`                             | Ensures form has a csrf token          |\n| `-\u003efindSelect($selector, $callback)`      | Finds a select to run assertions on    |\n\n| Select specific methods        | Description                                                        |\n|--------------------------------|--------------------------------------------------------------------|\n| `-\u003ehasValue($value)`             | Ensures a select has a specific value                              |\n| `-\u003ehasValues($values)`           | Ensures a select has an array of values (multiple select)          |\n| `-\u003econtainsOption($attributes)`  | Checks for an option with the given attributes                     |\n| `-\u003econtainsOptions($attributes)` | Checks for any options with the given attributes (array of arrays) |\n\n## Testing this package\n\n```bash\nvendor/bin/pest\n```\n\n## Changelog\n\nPlease see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.\n\n## Contributing\n\nPlease see [CONTRIBUTING](CONTRIBUTING.md) for details.\n\n## Credits\n\n- [René Sinnbeck](https://github.com/sinnbeck)\n- [All Contributors](../../contributors)\n\n## License\n\nThe MIT License (MIT). Please see [License File](LICENSE.md) for more information.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsinnbeck%2Flaravel-dom-assertions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsinnbeck%2Flaravel-dom-assertions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsinnbeck%2Flaravel-dom-assertions/lists"}