DEV Community

Georgi Kurian
Georgi Kurian

Posted on • Updated on

How to set up Laravel Dusk on Laravel Sail or docker.

Yesterday, I was trying to step up Laravel Dusk to test our Laravel web app to make sure that the pages are not crashing for a Vue frontend using Inertia for our releases. But, I ran into many problems, and it took way more time than I expected to set up in Sail. I am posting this so that it could help someone else.

I am using alias sail as alias for ./vendor/bin/sail throughout.

First, install Laravel Dusk.

sail composer require --dev laravel/dusk
sail php artisan dusk:install
Enter fullscreen mode Exit fullscreen mode

We are going to customize the Laravel Sail default docker configuration, so publish the Sail docker file.

sail artisan sail:publish
Enter fullscreen mode Exit fullscreen mode

Sail's default mysql service persists the MySQL data to the local machine so that it is available after restarting the container. This is not needed for a test database, so we are going to create a new MySQL service named mysql.test for testing purposes. Since we have are going to use two both Laravel Test(Phpunit) and Laravel Dusk in our app we need two separate databases for each one. Dusk will use the database dusk_test and Phpunit will take laravel_test.

By default, Dusk will take the database connection specified .env file. Since we don't want Dusk to change our data in the development database, we are going to specify a different database for Dusk. Dusk has a feature that replaces the .env file with .env.dusk.{environment} when we run the tests. We will specify the Laravel Dusk test configuration in the .env.dusk.local file as below.

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:EUzC7XceXTxeQwT+eRMEysZwrs6e/pHjO2xYUNZTggo=
APP_DEBUG=true
APP_URL=http://laravel.test

LOG_CHANNEL=stack
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=mysql.test
DB_DATABASE=dusk_test
DB_USERNAME=sail
DB_PASSWORD=password
Enter fullscreen mode Exit fullscreen mode

The database for Dusk in the above is configured to use a different database port 3307 as the port 3306 is assigned to the mysql service and we changed the database name to dusk_test.

Now, we need the Sail to have the above-configured database service to be up and running for the tests to run. Add new service mysql_test with the configuration below.

mysql.test:
  image: "mysql:8.0"
  ports:
    - "${FORWARD_DB_PORT:-3307}:3306"
  environment:
    MYSQL_ROOT_PASSWORD: "${DB_PASSWORD}"
    MYSQL_DATABASE: "${DB_DATABASE}_test"
    MYSQL_USER: "${DB_USERNAME}"
    MYSQL_PASSWORD: "${DB_PASSWORD}"
    MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
  volumes:
    - "./docker/mysql.test/init:/docker-entrypoint-initdb.d"
  tmpfs:
    - "/var/lib/mysql"
  networks:
    - sail
  healthcheck:
    test: ["CMD", "mysqladmin", "ping", "-p${DB_PASSWORD}"]
    retries: 3
    timeout: 5s
Enter fullscreen mode Exit fullscreen mode

Important things in the above config:

  1. We have configured the default port to be 3307 to not conflict with mysql service.
  2. The database name is ${DB_DATAbase}_test. This database is going to be used by PHPUnit.
  3. Since mysql docker image supports only one database in configuration, but we need two databases for tests, we are going to create a sql script in the path ./.docker/mysql.test/init/01-database.sql to create additional databases. This script will be copied to the container path /docker-entrypoint-initdb.d and will be run during initialization.
  4. For volume, we are using a tmpfs as the data don't have to be persisted.

The file ./docker/mysql.test/init/01-create_dusk_database.sql in the project should have the script:

/* create databases */
CREATE DATABASE IF NOT EXISTS `dusk_test`;

/* give access to database */
GRANT ALL PRIVILEGES ON dusk_test.* TO 'sail'@'%';
Enter fullscreen mode Exit fullscreen mode

Restart the sail by executing sail up command. You can see that mysql.test started and it has two databases *_test and dusk_test databases.

Create a .env.testing config file for specifying the PHPUnit test configuration. The database name will be the database name in your .env file and add _test at the end. No need to give the

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:EUzC7XceXTxeQwT+eRMEysZwrs6e/pHjO2xYUNZTggo=
APP_DEBUG=true
APP_URL=http://localhost

LOG_CHANNEL=stack
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=mysql.test
# Below database name should your database name in .env file and add `_test`
DB_DATABASE=*_test
DB_USERNAME=sail
DB_PASSWORD=password
Enter fullscreen mode Exit fullscreen mode

Now we have completed all the configurations. It's time to test now!
Update the class in file tests/Feature/ExampleTest.php with below:

class ExampleTest extends TestCase
{
    use RefreshDatabase;

    public function test_example()
    {
        User::factory()->create();
        $response = $this->get('/');
        $response->assertStatus(200);
        $this->assertDatabaseCount('users', 1);
    }
}
Enter fullscreen mode Exit fullscreen mode

Replace the function class in file tests/Browser/ExampleTest.php with the below code

class ExampleTest extends DuskTestCase
{
    use DatabaseMigrations;

    public function testBasicExample()
    {
        User::factory()->create();
        $this->browse(function (Browser $browser) {
            $browser->visit('/')
            ->assertSee('Laravel');
        });
    }
}
Enter fullscreen mode Exit fullscreen mode

Run both Phpunit and Dusk tests and see them both passing with database access.

sail test
Enter fullscreen mode Exit fullscreen mode

Debugging Tips

  • Check whether all the required services have started.
  • Check whether our SQL script is copied into the container(sail shell).
  • Check database connections and the databases in it using a database client in your host machine.
  • Check whether you can curl http://laravel.test from inside your container laravel.test.
  • Running php artisan dusk from inside the container won't work by default as Sail is doing some additional things behind the scene (use sail dusk).

Additional information

  • If you add DUSK_DRIVER_URL=http://selenium:4444/wd/hub to your .env.dusk.local file you can run the dusk from inside the container using php artisan dusk.

Discussion (0)