In this tutorial we're going to build a test class that will run through all guest URLs defined in our web.php
routes
and check that they all return a HTTP status of 200
. This is allow us to quickly check all open URLs and make sure
that there aren't any errors on these page.
Defining Your Routes
When you define your routes in Laravel you'll add them to the routes/web.php
. Using the guest middleware will make
sure that anybody can access these URLs without having to be logged in. When the URLs are wrapped in the guest
middleware we can make sure we only check these URLs.
<?php
// Guest middleware
Route::group(['middleware' => ['guest']], function(){
// Home page
Route::get('/', 'HomeController@index');
// Tutorials
Route::get('/tutorials', 'TutorialController@index');
Route::get('/tutorials/{tutorialSlug}', 'TagsController@show');
// Blog Post
Route::get('/{postSlug}', 'PostController@show');
});
Create Smoke Test Class
Laravel allows use to make HTTP request tests to where we can make a GET
request to all the URLs in our web.php
file and assert the status of the response. To build this test class we'll need
to do the following.
- Get all guest routes
- Loop through each route and check if the URL is dynamic
- If the URL is dynamic then create a test URL
- Make a HTTP request to this URL
- Check if URL returns 200 HTTP status
Get All Guest Routes
To get all routes that are defined in Laravel you can use Illuminate\Routing\Router
with the method getRoutes
method. This will return all routes defined in your application. We need to then loop through all of these, check the
middleware is set to guest, remove any dusk added routes and return these routes.
<?php
private function getGuestRoutes()
{
return array_filter(app(Router::class)->getRoutes()->getRoutes(), function ($route) {
$middleware = $route->middleware();
return in_array('guest', $middleware) &&
strpos($route->uri(), '_dusk') === false ? $route : false;
});
}
Convert Dynamic Routes
After we have all the routes we need to then loop through the routes, check if they're dynamic and check a test model to match the dynamic route. First we need to map our dynamic routes to a model to create the route.
<?php
protected $dynamicMappings = [
'tutorialSlug' => Tutorial::class,
'postSlug' => Post::class
];
Then we can pass in the route into this function, check to see if we need to change the dynamic route, create a new model and return the new route for the model.
<?php
/**
* @param $url
*
* @return mixed
*/
private function convertMapping($url)
{
foreach($this->dynamicMappings as $mapping => $modelClass)
{
$stringMapping = '{'.$mapping.'}';
if(strpos($url, $stringMapping) !== false) {
factory($modelClass)->create();
return str_replace($stringMapping, app($modelClass)->first()->slug, $url);
}
}
return $url;
}
The return of dynamic URL mapping function can be used to make a HTTP request then we can check to see if the HTTP status is a 200.
Full Test Class
Below is the full test class to use in your application.
<?php
namespace Tests\Feature\SmokeTests;
use App\Models\Post;
use App\Models\Tutorial;
use Illuminate\Routing\Router;
use Tests\TestCase;
class SmokeGuestTest extends TestCase
{
protected $dynamicMappings = [
'tutorialSlug' => Tag::class,
'postSlug' => Post::class
];
public function testCheckGuestRoutes()
{
foreach($this->getGuestRoutes() ?? [] as $route) {
$url = $this->convertMapping( $route->uri );
$response = $this->get($url);
$response->assertStatus(200);
}
}
/**
* Get all the urls that can be accessed by a guest user
*/
private function getGuestRoutes()
{
return array_filter(app(Router::class)->getRoutes()->getRoutes(), function ($route) {
$middleware = $route->middleware();
return in_array('guest', $middleware) &&
strpos($route->uri(), '_dusk') === false ? $route : false;
});
}
/**
* @param $url
*
* @return mixed
*/
private function convertMapping($url)
{
foreach($this->dynamicMappings as $mapping => $modelClass)
{
$stringMapping = '{'.$mapping.'}';
if(strpos($url, $stringMapping) !== false) {
factory($modelClass)->create();
return str_replace($stringMapping, app($modelClass)->first()->slug, $url);
}
}
return $url;
}
}