PHPUnit comes out of the box with features like AssertSee and AssertSeeText in both cases we can assert against a specific text, to assert HTML tags we are going to rely on these features with some custom work to polish these a little bit more.
I need to test that some forms generate a CSRF token.
Laravel CSRF token directive generates an input like this:
<input type="hidden" name="_token" value="random_generated_token" ...>
As the generated token changes between requests we are not going to test the generated token value, instead we are going to assert that the input exists with some of the attributes required, PHPUnit assertSee has second param to escape a value so we can do something like this:
$this ->get("contact-us") ->assertSee([ '<input name="some_database_column"' ], false);
It would solve our solution, but probably there is a better way to use this for more cases, so writing using a "wishful thinking" approach my desired code would be something like this:
$this->get("contact-us") ->assertHtml('input', [ "type" => "hidden", "name" => "_token", ])
This would be useful as it adds an assertion that would work in multiple cases by only passing the tag name and an array of attributes
We can add something like this in Laravel by adding a custom macro to the TestResponse class in the AppServiceProvider or any other custom Provider:
TestResponse::macro('assertHtml', function ($tag, $attributes) { $attributes = collect($attributes) ->map(function ($attributeValue, $attributeKey) { return "$attributeKey=\"$attributeValue\" "; }) ->values() ->implode("", ""); $htmlElement = "<$tag $attributes"; $this->assertSee([$htmlElement], false); });
Now we can test our DOM by testing the presence of a tag and an attribute.
We can go a little bit forward in this case, I would need to assert that a form as CSRF tokens in multiple forms in the app, so we can rely on our macro to create more assertions, in this case as the expected HTML tag and attributes would not change I can add something like this:
TestResponse::macro('assertCSRFTokenExists', function () { $this->assertHtml('input', [ "type" => "hidden", "name" => "_token", ]); });
This assertion is short, reusable, easy to read and use:
$this->get("contact-us")->assertCSRFTokenExists();
For more powerful assertions you should consider an excellent package like:
sinnbeck/laravel-dom-assertions
Hopefully, this helps to add basic DOM assertions in your tests
The above is the detailed content of Test Your DOM in Laravel with PHPUnit. For more information, please follow other related articles on the PHP Chinese website!