Chat with us, powered by LiveChat

This website uses cookies

Our website, platform and/or any sub domains use cookies to understand how you use our services, and to improve both your experience and our marketing relevance.

Introduction to Laravel Dusk: Testing Todo App

April 6, 2017

7 Min Read
Reading Time: 7 minutes

In the previous part of this series, I completed the ToDo app. Today, I am going to test this app using Laravel Dusk. I will start this article with a brief introduction of Laravel Dusk, how you can setup Laravel Dusk and then go into the process of testing the ToDo application.

Laravel Dusk Test ToDo App

What is Laravel Dusk?

Laravel Dusk is a browser automation testing tool introduced in Laravel 5.4. It is the perfect tool for browser testing applications and API. It uses ChromeDriver by default but you can use any Selenium compatible drivers.

Install Laravel Dusk

Laravel Dusk can be installed by running the following command:

composer require laravel/dusk

Once the installation finishes, I will register it inside the `register()` method in `AppServiceProvider`. For this, go to app/Providers folder and open AppServiceProvider.php file. Add the following line right before the start of the class:

use Laravel\Dusk\DuskServiceProvider;

Next, in the `register()` method, paste the following code:

public function register()
{
    if ($this->app->environment('local', 'testing')) {
        $this->app->register(DuskServiceProvider::class);
    }
}

At this point, `AppServiceProvider` class will look like this:

<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Schema;
use Laravel\Dusk\DuskServiceProvider;
class AppServiceProvider extends ServiceProvider
{
    /**
* Bootstrap any application services.
*
* @return void
*/
    public function boot()
    {
        //
        Schema::defaultStringLength(191);
    }
    /**
* Register any application services.
*
* @return void
*/
    public function register()
    {
        if ($this->app->environment('local', 'testing')) {
            $this->app->register(DuskServiceProvider::class);
        }
    }
}

Now, run the following command to install Laravel Dusk:

php artisan dusk:install

Once the command is completed, the Browser directory will be created inside the tests directory (this will contain an Example Test file). In this directory, I will create all the tests for browser automation.

Next, I will describe the testing process of the ToDo app.

You might also like: Automate Code Testing With PHP Continuous Integration

Creating Browser Test Cases for the ToDo App

I will use the default browser (Chrome) for the tests.

First of all, run the following command to create a new Test file:

php artisan dusk:make TodoTest

Once the command finishes, it will create a new test file with the name TodoTest inside the Browser directory. This file will contain an example test case method `testExample()`. Remove this method from the file.

Before I start adding the methods for test cases, open .env file and add the full app URL in the  APP_URL constant.

APP_URL=http://localhost/todoapplaravel/public

Now, I could start writing the test cases.

User Registration Test

I will begin by creating a new test function which will test user registration process and check whether the user is redirected to the dashboard.

Inside the `TodoTest` class, create a new function with the name `testRegister()`. Paste the following code in it:

public function testRegister()
{
    $this->browse(function ($browser) {
        $browser->visit('register')
            ->type('name', 'Tayor Otwell')
            ->type('email', 'taylor@laravel.com')
            ->type('password', 'ahmedkhan')
            ->type('password_confirmation', 'ahmedkhan')
            ->attach('userimage', 'C:\images\taylor.jpg')
            ->press('Register')
            ->assertPathIs('/todoapplaravel/public/todo');
    });
}

In the above code, I called the `browse` method along with the `$browser` instance, which is automatically passed by Dusk and used to make assertion for the application. First, I used the  `visit()` method to direct browser to the register page. Then, in the `type` method, I first defined the name of the input field and after the comma, I assigned its value. Since I am using a file input type in the registration form, I have used the `attach` method to attach the file to the input. I entered the name of the type file input field and then defined the path where the image is saved at the local machine. Next, I used `press` (used to press the button on the web page). Inside this, I defined the button to press (in this case, it is Register). Finally, I checked the assert that the user is redirected to dashboard i.e. ‘/todo/’ by using the `assertPathIs` method. I need to add the full URL, as shown in the browser after the ‘localhost’, i.e. ‘/todoapplaravel/public/todo’.

Create a New ToDo Test

Now, create a new method with the name `testCreateTodo()`. Add the following code in it.

public function testCreateTodo()
{
    $this->browse(function ($browser) {
        $browser->visit('todo')
            ->clickLink('Add Todo')
            ->type('todo', 'Testing it With Dusk')
            ->type('category', 'dusk')
            ->type('description', 'This is created with dusk')
            ->press('Add')
            ->assertPathIs('/todoapplaravel/public/todo');
    });
}

After redirecting to the ‘todo’, I have used `clickLink` method to click on the add todo, since it is a link, not a button. Next, I added todo input values. Once done, I pressed the Add button. Next, I am asserting that it is redirected to the dashboard. The todo item has been added successfully. If not, then assert would fail.

View the Todo Test

Before creating this test, I need to edit the dashboard.php file. I will add an id to all the icons so that I can click them using the automation testing. For this, go to the resources/views/todo directory and open the dashboard.php file. Now, replace the code in this file with the following:

@extends('layouts.app')
@section('title', 'Home ')
@section('content')
 <div class="row">
      <div class="col-md-9">
    <ul class="list-group">
    @if($todos != false)
          @foreach ($todos as $todo)

    <li class="list-group-item"><a id="view{{$todo->id}}" class="secondary-content" href="{{url('/todo/'.$todo->id)}}"><span class="glyphicon glyphicon-triangle-right"></span></a><a id="edit{{$todo->id}}" class="secondary-content" href="{{url('/todo/'.$todo->id).'/edit'}}"><span class="glyphicon glyphicon-pencil"></span></a><a id="delete{{$todo->id}}" href="#" class="secondary-content" onclick="event.preventDefault();
                                            document.getElementById('delete-form').submit();"><span class="glyphicon glyphicon-trash"></span></a><form id="delete-form" action="{{url('/todo/'.$todo->id)}}" method="POST" style="display: none;">
                         {{ method_field('DELETE') }}{{ csrf_field() }}
                            </form> {{$todo->todo}} 
                                            </li>

@endforeach
@else
<li class="list-group-item"> No Todo added yet <a href="{{ url('/todo/create') }}"> click here</a> to add new todo. </li>
@endif
    </ul>
    </div>

      <div class="col-md-3">
          <img class="img-responsive img-circle" src="{{asset('storage/'.$image)}}">
      </div>
    </div>
@endsection

In the above code, I gave an id to the view,edit & delete. This is a  concatenation of the view and the id of a todo i.e. `id=”view{{$todo->id}}”` for view, `id=”edit{{$todo->id}}”` for edit and `id=”delete{{$todo->id}}”` for delete.

Now, I will create the todo test for viewing todo. For this, go to the TodoTest.php file and add a new method `testViewTodo()` with the following code:

public function testViewTodo()
{
    $this->browse(function ($browser) {
        $browser->visit('todo')
            ->assertVisible('#view1')
            ->visit(
            $browser->attribute('#view1', 'href')
        )
            ->assertPathIs('/todoapplaravel/public/todo/1')
            ->clickLink('Edit')
            ->type('description', 'Testing it with dusk again')
            ->press('Update')
            ->assertPathIs('/todoapplaravel/public/todo/1');
    });
}

In the above code, I first visited ‘todo’ and then asserted that id #view1 exists in the dashboard. Then, I visited this link using the `visit` method. Inside this method, I defined which attribute to click using the `attribute` method. Next, I asserted its path. If it is valid, I called the clickLink method to click on the Edit link, which is visible on that page. Next, I have edited its description using the `type` method and then pressed the Update button using the press method. Next, I  checked the path again to see that it redirect back to the same todo or not using `assertPathis` method.

Edit the Todo Test

Now, create a new function with name the `testEditTodo`. Add the following code to it:

public function testEditTodo()
{
    $this->browse(function ($browser) {
        $browser->visit('todo')
            ->assertVisible('#edit1')
            ->visit(
            $browser->attribute('#edit1', 'href')
        )
            ->type('description', 'Testing it with dusk again')
            ->press('Update')
            ->assertPathIs('/todoapplaravel/public/todo/1');
    });
}

In The above code, I first redirected to the dashboard and then clicked the edit icon, updated the todo description and then asserted that the path is same or not.

Delete a Todo Test

Now, create a new function with the name `testDeleteTodo`. Add the following code to it:

public function testDeleteTodo()
{
    $this->browse(function ($browser) {
        $browser->visit('todo')
            ->assertVisible('#delete1')
            ->visit(
            $browser->attribute('#delete1', 'href')
        )
            ->assertPathIs('/todoapplaravel/public/todo');
    });
}

Logout Test

Now, create a new function with the name `testLogout()` and add the following code to it:

public function testLogout()
{
    $this->browse(function ($browser) {
        $browser->visit('todo')
            ->clickLink('Logout')
            ->assertPathIs('/todoapplaravel/public/login');
    });
}

Login Test

After registration, the user is automatically redirected to Login page. That’s why, I have not created the login test before. Now, create a new function with the name `testLogin` and paste the following code in it:

public function testLogin()
{
    $this->browse(function ($browser) {
        $browser->visit('login')
            ->type('email', 'tessa@cloudways.com')
            ->type('password', 'ahmedkhan')
            ->press('Login')
            ->assertPathIs('/todoapplaravel/public/todo');
    });
}

At this point, all the test cases for the ToDo app have been created. The complete TodoTest file will look like the following:

<?php

namespace Tests\Browser;

use Tests\DuskTestCase;

use Illuminate\Foundation\Testing\DatabaseMigrations;

class TodoTest extends DuskTestCase

{

    /**

    * Register test.

    *

    * @return void

    */

   public function testRegister()

   {

       $this->browse(function ($browser) {

           $browser->visit('register')

                   ->type('name', 'Tayor Otwell')

                   ->type('email', 'taylor@laravel.com')

                   ->type('password', 'ahmedkhan')

                   ->type('password_confirmation', 'ahmedkhan')

                   ->attach('userimage', 'C:\Users\ahmed.khan\Downloads\CreatingToDoApplicationinLaravel5.4CreatingAuthToDoViewsRoutesandModifyingController\images\taylor.jpg')

                   ->press('Register')

                   ->assertPathIs('/todoapplaravel/public/todo');

       });

   }

  /**

    * Create Todo test.

    *

    * @return void

    */

   public function testCreateTodo()

   {

       $this->browse(function ($browser) {

           $browser->visit('todo')

                   ->clickLink('Add Todo')

                   ->type('todo', 'Testing it With Dusk')

                   ->type('category', 'dusk')

                   ->type('description', 'This is created with dusk')

                   ->press('Add')

                   ->assertPathIs('/todoapplaravel/public/todo');

       });

   }

   /**

    * View and Edit Todo Test.

    *

    * @return void

    */

   public function testViewTodo()

   {

       $this->browse(function ($browser) {

           $browser->visit('todo')

                   ->assertVisible('#view1')

                   ->visit(

                       $browser->attribute('#view1', 'href')

                   )

                   ->assertPathIs('/todoapplaravel/public/todo/1')

                   ->clickLink('Edit')

                   ->type('description', 'Testing it with dusk again')

                   ->press('Update')

                   ->assertPathIs('/todoapplaravel/public/todo/1');

       });

   }

   /**

    * Edit todo test.

    *

    * @return void

    */

   public function testEditTodo()

   {

       $this->browse(function ($browser) {

           $browser->visit('todo')

                   ->assertVisible('#edit1')

                   ->visit(

                       $browser->attribute('#edit1', 'href')

                   )

                   ->type('description', 'Testing it with dusk again')

                   ->press('Update')

                   ->assertPathIs('/todoapplaravel/public/todo/1');

       });

   }

   /**

    * Delete Todo test.

    *

    * @return void

    */

   public function testDeleteTodo()

   {

       $this->browse(function ($browser) {

           $browser->visit('todo')

                   ->assertVisible('#delete1')

                   ->visit(

                       $browser->attribute('#delete1', 'href')

                   )

                   ->assertPathIs('/todoapplaravel/public/todo');

       });

   }

   /*

    * Logout test.

    *

    * @return void

    */

   public function testLogout()

   {

       $this->browse(function ($browser) {

           $browser->visit('todo')

                   ->clickLink('Logout')

                   ->assertPathIs('/todoapplaravel/public/login');

       });

   }

   /**

    * Login test.

    *

    * @return void

    */

   public function testLogin()

   {

       $this->browse(function ($browser) {

           $browser->visit('login')

                   ->type('email', 'tessa@cloudways.com')

                   ->type('password', 'ahmedkhan')

                   ->press('Login')

                   ->assertPathIs('/todoapplaravel/public/todo');

       });

   }

}

 

This test case file has been added to the todo app Laravel repo on the GitHub.

One Command To Test Them All

On the command line, run the following command to run the automation tests:

php artisan dusk

Check out the following GIF to see browser testing with Laravel Dusk in action:

Concluding The Series

In this series on the Laravel powered ToDo application, I started with setting up migration tables, controller and models. Then, I created user authentication, views and setup ToDo functionality. In this final part of the series, I carried out browser testing of Laravel applications using Laravel Dusk. Feel free to give your feedback on this series in the comments section below.

Share your opinion in the comment section. COMMENT NOW

Share This Article

Launch Laravel apps with 1-Click Install. Painless Server Management

Deploy your apps on optimized Laravel hosting servers.

Ahmed Khan

Ahmed was a PHP community expert at Cloudways - A Managed PHP Hosting Cloud Platform. He is a software engineer with extensive knowledge in PHP and SEO. He loves watching Game of Thrones is his free time. Follow Ahmed on Twitter to stay updated with his works. You can email him at ahmed.khan@cloudways.com

Get Our Newsletter
Be the first to get the latest updates and tutorials.

Do you like what you read?

Get the Latest Updates

Share Your Feedback

Please insert Content

Thank you for your feedback!