Testing views in isolation with Laravel Mojito
- 3 Min. Read.
With Laravel Mojito you can test your views in isolation with ease.
Install the package
In your Laravel project root, run the following composer command:
1 |
composer require nunomaduro/laravel-mojito --dev |
Create your first test
With artisan, create a new test:
1 |
php artisan make:test WelcomeTest |
Add the InteractsWithViews
trait, which adds the assertView
method to your test
1 2 3 4 5 6 7 8 9 10 |
trait InteractsWithViews { /** * Create a new view test case. */ protected function assertView(string $view, array $data = [], array $mergeData = []): ViewAssertion { return new ViewAssertion(view($view, $data, $mergeData)->render()); } } |
Next up, you can make an assertion on your view, for example assert that the word ‘Mojito’ is present:
1 |
$this->assertView('welcome')->contains('Mojito'); |
Asserting a view contains a word within a specific selector
With Laravel Mojito you can use query selectors like in CSS to make more specific assertions. In the welcome template there is a div with a class ‘links’, and the last link is the one to GitHub:
1 2 3 4 |
<div class="links"> ... <a href="https://github.com/laravel/laravel">GitHub</a> </div> |
Let’s say we want to add an assertion that in the welcome template there is a link to GitHub, we would use the following code:
1 |
$this->assertView('welcome')->in('.links')->contains('GitHub'); |
And if we want to make sure the link is correct, we can do it with the hasLink
method:
1 |
$this->assertView('welcome')->in('.links')->hasLink('https://github.com/laravel/laravel'); |
Passing $data to your view
Create a new blade template called title.blade.php
and add a variable $title
in it:
1 |
<h1>{{ $title }}</h1> |
We want to test our new title.blade.php
view, and to do so we have to pass in $data, so the view gets rendered as expected:
1 2 3 |
$this->assertView('title', [ 'title' => 'Hello!' ])->contains('Hello!'); |
Making complex assertions
You can make complex assertions, for example to make sure the first meta
tag in the head has an attribute charset
with the value of utf-8
:
1 |
$this->assertView('welcome')->in('head')->first('meta')->hasAttribute('charset','utf-8'); |
Testing views with HTTP tests
Sometimes testing a view in isolation is not sufficient because of all the logic that gets executed before rendering a view. Assume we have a NameController
like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// app/Http/Controllers/NameController.php namespace App\Http\Controllers; class NameController extends Controller { public function show($name) { $name = ucfirst($name); return view('name', [ 'name' => $name ]); } } // routes/web.php Route::get('/name/{name}', 'NameController@show'); // resourcies/views/name.blade.php <h1>Hello {{ $name }}!</h1> |
When we visit our application at /name/codecaptain
, a view would be rendered with the following HTML:
1 |
<h1>Hello Codecaptain!</h1> |
To make an assertion on the view rendered by the controller, we can use HTTP Tests:
1 2 3 |
$response = $this->get('/name/codecaptain'); $response->assertStatus(200); $response->assertView()->contains('Codecaptain'); |
The unit test will make an HTTP request to your application, and on the returned response we can run our assertions as if it were an isolated blade template.