CI for Laravel

Browser Tests with Laravel Dusk

We take care of as much as possible when running browser tests on Chipper CI, however there are aspects of its setup that are up to you!

Here are the steps and information needed to most reliably get Browser tests working with minimal fuss.

🔴 If your account was created before February 28th, 2023, please use these Dusk docs.

Things to Know

  1. Dusk tests ignore system environment variables and items within phpunit.xml. Dusk only care about what's in your .env file.
  2. Dusk will grab a .env.dusk.{env} file, if it exists, and swap it with your current .env file (again, if it exists). It replaces those files when it's done running tests.

1. Update Build Pipeline

Running Dusk browser tests in your builds requires updating your chipperci.yml file.

There are 2 steps:

1️⃣ Add the dusk service. Since we run Chrome (via Selenium) in a separate VM, you need to define dusk as a separate service.

services:
  - dusk:

2️⃣ Add a pipeline step. To actually run your tests, create a pipeline step similar to the following:

pipeline:
  - name: Browser Tests
    cmd: |
      php -S [::0]:8000 -t public 2>server.log &
      sleep 2
      php artisan dusk:chrome-driver $CHROME_DRIVER
      php artisan dusk --env=ci

⚠️ A few things to note:

  1. IPv6: The web server needs to bind to the VMs IPv6 network - we do so on port 8000 via [::0]:8000
  2. Driver Version: Chipper CI provides a CHROME_DRIVER environment variable with the correct Chrome version
  3. Env: We're assuming --env=ci, which means you'll want to create file .env.dusk.ci

2. Create an Env File

Since we're using --env=ci, we'll need to create file .env.dusk.ci. This can be committed to your Git repository, or generated on the fly in your pipeline.

You don't need to use ci however - you can use whatever environment name you'd like.

At the minimum, you'll need the following:

APP_KEY=base64:<some-valid-key>
APP_URL="http://${BUILD_HOST}:8000"

👉 The .env.dusk.ci file should also contain ALL application-specific environment variables you need to run tests in your application.

You may also need:

APP_DOMAIN=${BUILD_HOST}

The variable $BUILD_HOST is provided by Chipper CI automatically. It's the internal hostname of the build server. We use that hostname so the Chrome VM can reach our web server in the build container.

If you're connecting to a database, you likely want to add configuration for that into your .env.dusk.ci file as well:

DB_CONNECTION=mysql
DB_HOST=${DB_HOST}
DB_USERNAME=chipperci
DB_DATABASE=chipperci
DB_PASSWORD=secret

REDIS_HOST=${REDIS_HOST}

Using Pre-defined Environment Variables

Note that you can use environment variables / secrets set in your project settings. This is helpful if some .env vars are set as secrets and not commited to the .env.dusk.{env} file in your repository.

For example, if you created secret AWS_SECRET_ACCESS_KEY, you can read it into your .env.dusk.ci file like so:

AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}

Notes

Chrome is run in a separate VM from the build server. This has some ramifications:

  1. The Chrome VM needs to be able to send HTTP requests the build server
  2. The build server needs to communicate to the Chrome VM

Setting the APP_URL environment variable correctly covers point 1, and is described above.

For point 2, Chipper CI sets environment variable DUSK_DRIVER_URL for you.

Within file tests/DuskTestCase.php, that environment variable is used:

    /**
     * Create the RemoteWebDriver instance.
     */
    protected function driver(): RemoteWebDriver
    {
        $options = (new ChromeOptions)->addArguments(collect([
            $this->shouldStartMaximized() ? '--start-maximized' : '--window-size=1920,1080',
        ])->unless($this->hasHeadlessDisabled(), function (Collection $items) {
            return $items->merge([
                '--disable-gpu',
                '--headless',
            ]);
        })->all());

        return RemoteWebDriver::create(
            $_ENV['DUSK_DRIVER_URL'] ?? 'http://localhost:9515',
            DesiredCapabilities::chrome()->setCapability(
                ChromeOptions::CAPABILITY, $options
            )
        );
    }

Older DuskTestCase.php versions do not use $_ENV['DUSK_DRIVER_URL']. If yours does not use it, you'll need to update tests/DuskTestCase.php to do so.