Published on

Browser Testing Experiment Using Laravel Dusk

In the previous crud feature testing tutorial we discussed how to test using PHPUnit and Laravel BrowserKit Testing. Based on the tutorial, I tried to explore further in the real project and testing can run well. However, there are sides that we cannot test when using these two tools. One of them is testing the functionality of applications that have javascript on the client side. Therefore, I try to use different tools to do browser testing, namely Laravel Dusk.

What is Laravel Dusk?

According to the official laravel documentation, Laravel Dusk is a tool that provides an easy-to-use browser automation and testing API.By default, Dusk does not require us to install the JDK on the local computer.Instead, Dusk uses a standalone ChromeDriver installation.Alternatively, we are also free to use other drivers.

By using Laravel Dusk, we can simulate what the user will do. For example, when registering in our project, the user will enter the register page, then the user fills in the register form, after that the user clicks the Register button and if successful the browser will display the home page or dashboard. By using laravel dusk, we write down the scenario of what the user will do when registering and then we run laravel dusk to start browser testing.

Overview

In this tutorial we will try to use Laravel Dusk for browser testing.

As a case study, in this tutorial we will try testing the register feature and the login feature.

Because our focus in this tutorial is browser testing using Laravel Dusk, so we will not code the register and login features.Instead, we use Laravel Breeze to generate the register feature and login feature in our project.The ultimate goal of this tutorial is to see if we can test the register and login features according to the testing scenario.

Preparation

In addition to the requirements for the Laravel installation process, there are preparations that friends must prepare before following this tutorial, namely installing node js and NPM.

We will use this NPM to build assets from Laravel Breeze. If you haven't installed it, you can try following the tutorial install multiple node js versions using NVM

Now I first check the node js version that I am using in this tutorial.

node -v

Output at the terminal

v18.18.2

NPM is installed when we install Nodejs. Now I check the version of NPM that I am using.

npm -v

Output in the terminal:

9.8.1

Step 1 - Create New Project

Open the terminal and run the following command to create a new project using composer.

composer create-project --prefer-dist laravel/laravel laravel-dusk-testing-example

Wait until the create project process is complete.

Step 2 - Install Laravel Dusk

Now we try to install Laravel dusk in our project. To install Laravel dusk, we first move to the project directory.

cd laravel-dusk-testing-example

Then we install the laravel dusk package using composer.

composer require laravel/dusk --dev

After the package is installed, run the following command.

php artisan dusk:install

Output:

Dusk scaffolding installed successfully.
Downloading ChromeDriver binaries...
ChromeDriver binary successfully installed for version 122.0.6261.69

As written in the output above, the above command generates Dusk scaffolding which includes creating a tests/Browser directory, testing examples using laravel Dusk and installing chrome drivers to our OS.

Next we set the APP_URL configuration and also the database in the .env file.

APP_URL=http://127.0.0.1:8000

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=db_testing
DB_USERNAME=root
DB_PASSWORD=password

Notes:

  1. APP_URL must be the same as the URL to access our project in the browser. Since we will use php artisan serve, so we customize the URL as above.
  2. As an experiment, we use a database with the name db_testing (make sure you have created a database with the name db_testing) and for database credentials adjust it to your database credentials.

Next, we try to run testing examples that are already available when we run the php artisan dusk: install command.

To run laravel dusk, we first run our project.

php artisan serve

Because we have used terminal to run the above command, we open a new terminal tab to run laravel dusk.

Now we try to run browser testing using the following command.

php artisan dusk

Output in the terminal:


   PASS  Tests\Browser\ExampleTest
  ✓ basic example                                                        0.56s  

  Tests:    1 passed (1 assertions)
  Duration: 0.65s

Step 3 - Install and Setup Laravel Breeze

At this stage we will use the laravel breeze starter kit for our project. Now open the terminal again and install the laravel breeze package.

composer require laravel/breeze --dev

Next we run breeze:install to select the stack to use.

php artisan breeze:install

After we run the above command, a prompt appears. Here you can choose freely, for example:

Which Breeze stack would you like to install? ───────────────┐
Blade with Alpine └──────────────────────────────────────────────────────────────┘

Would you like dark mode support? ───────────────────────────┐
No └──────────────────────────────────────────────────────────────┘

Which testing framework do you prefer? ──────────────────────┐
PHPUnit └──────────────────────────────────────────────────────────────┘

Wait for the install process to complete.

   INFO  Installing and building Node dependencies.  


added 144 packages, and audited 145 packages in 10s

35 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

> build
> vite build

vite v5.1.4 building for production...
48 modules transformed.
public/build/manifest.json             0.26 kB │ gzip:  0.13 kB
public/build/assets/app-CB8Dc99X.css  31.65 kB │ gzip:  6.05 kB
public/build/assets/app-9mbrzSRH.js   73.42 kB │ gzip: 27.22 kB
✓ built in 935ms


   INFO  Breeze scaffolding installed successfully.  

After the install process is complete, we run the migrate command.

php artisan migrate

Output:

   INFO  Preparing database.  

  Creating migration table .......................................... 8ms DONE

   INFO  Running migrations.  

  2014_10_12_000000_create_users_table ............................. 14ms DONE
  2014_10_12_100000_create_password_reset_tokens_table .............. 4ms DONE
  2019_08_19_000000_create_failed_jobs_table ....................... 16ms DONE
  2019_12_14_000001_create_personal_access_tokens_table ............ 29ms DONE

At this stage we have prepared our project and the login and register features of laravel breeze are available. So next we try to write tests for these two features.

Step 4 - Testing for Register Feature

We will test for the register feature. Here is the scenario to test the register feature:

  1. User opens the register page.
  2. User fills in name, email, password and confirm password.
  3. User clicks the REGISTER button.
  4. Web opens the user dashboard page.

Now we create a new class to test the register feature. Open the terminal again and run the following dusk command.

php artisan dusk:make RegisterTest

Output di terminal:

   INFO  Test [tests/Browser/RegisterTest.php] created successfully.  

As seen in the terminal output, tests/Browser/RegisterTest.php was successfully generated after the dusk command was successfully run.

Next we open the tests/Browser/RegisterTest.php file, then we remove the default testExample() method and add the user_can_register() method.

<?php

namespace Tests\Browser;

use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;

class RegisterTest extends DuskTestCase
{
    use DatabaseMigrations;

    /** @test */
    public function user_can_register(): void
    {
        $this->browse(function (Browser $browser) {
	        // 1. User membuka halaman register.
            $browser->visit('/register')
            // 2. User mengisi `name`, `email` , `password` dan `konfirmasi password`.
                    ->type('name', 'User')
                    ->type('email', 'user@example.com')
                    ->type('password', 'password')
                    ->type('password_confirmation', 'password')
            // 3. User klik button `REGISTER`.
                    ->press('REGISTER')
            // 4. Web membuka halaman dashboard user.
                    ->assertPathIs('/dashboard');
        });
    }
}

As seen in the line of code above, the tests we write are based on our testing scenario.

After finishing coding, don't forget to save the tests/Browser/RegisterTest.php file again.

Next we try to test the register feature. Previously I had not stopped php artisan serve which was previously run. So the project condition is still in the run state.

Now we run laravel dusk to test the register feature.

php artisan dusk

Output di terminal:

   PASS  Tests\Browser\ExampleTest
  ✓ basic example                                                        0.47s  

   PASS  Tests\Browser\RegisterTest
  ✓ user can register                                                    1.22s  

  Tests:    2 passed (2 assertions)
  Duration: 1.83s


As seen in the terminal output above, the test performed is incremented by one and there is a caption:

 PASS  Tests\Browser\RegisterTest
  ✓ user can register                                                    1.22s  

The register feature testing went well.

Step 5 - Testing for Login Feature

Next we will test for the login feature. Here is the scenario for testing the login feature:

  1. Generate new user data
  2. User opens the login page.
  3. User fills in email, and password.
  4. User clicks the LOG IN button.
  5. The web opens the user dashboard page.

Next we generate a new test for the login feature.

php artisan dusk:make LoginTest

Output at the terminal;

   INFO  Test [tests/Browser/LoginTest.php] created successfully.

Based on the output above, tests/Browser/LoginTest.php was successfully generated.

Next we open the tests/Browser/LoginTest.php file. Just like before we remove the testExample() method and we add the user_can_login() method.

<?php

namespace Tests\Browser;

use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;

class LoginTest extends DuskTestCase
{
    use DatabaseMigrations;

    /** @test */
    public function user_can_login(): void
    {
	    // 1. Generate data user baru
        $user = User::factory()->create([
            'email' => 'user@example.com'
        ]);

        $this->browse(function (Browser $browser) use ($user) {
	        // 2. User membuka halaman login.
            $browser->visit('/login')
            // 3. User mengisi `email` , dan `password`.
                    ->type('email', $user->email)
                    ->type('password', 'password')
            // 4. User klik button `LOG IN`.
                    ->press('LOG IN')
            // 5. Web membuka halaman dashboard user.
                    ->assertPathIs('/dashboard');
        });
    }
}

Unlike the register feature, here we first generate a user before starting another test scenario.

When finished save the tests/Browser/LoginTest.php file again.

php artisan dusk

Output at the terminal:


   PASS  Tests\Browser\ExampleTest
  ✓ basic example                                                        0.46s  

   PASS  Tests\Browser\LoginTest
  ✓ user can login                                                       1.20s  

   PASS  Tests\Browser\RegisterTest
  ✓ user can register                                                    1.18s  

  Tests:    3 passed (3 assertions)
  Duration: 3.05s



As seen in the output above, there is a caption:

   PASS  Tests\Browser\LoginTest
  ✓ user can login                                                       1.20s  

Sign of testing the login feature is running well.

Closing

In this tutorial, we have tried laravel dusk to do browser testing. The testing we have done is testing the register feature and testing the login feature. When we run laravel dusk, we can see the test results running well.