How to run Drupal’s Nightwatch tests in Lando

This post follows on from "How to run Drupal’s PHPUnit tests in Lando" post but covers running (not writing) NightwatchJS tests instead of PHPUnit tests. NightwatchJS tests in Drupal run quickly and are fairly easy to write. As a module maintainer they are my preferred type of test over functional PHP unit tests. This post doesn't cover writing tests and is only focussed on running them within Lando containers.

We won't cover the initial set up of Lando in this blog post so please refer to the previous post in particular the sections titled "Lando set up" and "Drupal 8 installation". Once you have a working Drupal 8 installation we can continue.

Configure Lando to run Nightwatch tests

To run NightwatchJS tests we need to use Yarn or NPM to do so. In this example we'll use Yarn.

To have an environment to run the tests we need to install two new services (containers) in Lando. The first is the Chromedriver that DrupalCI uses which will be used to run the tests in a real browser. The second image (node) is a node image which also includes PHP and associated modules.

The node container also needs access to PHP as when the tests are run a full Drupal install needs to happen so PHP is required. As a node container can't run PHP commands we need this combination container.

Add the following to your services section in your existing .lando.yml file:

  chrome:
    type: compose  
    app_mount: false
    services:    
      image: drupalci/webdriver-chromedriver:production    
      command: chromedriver --log-path=/tmp/chromedriver.log --verbose --whitelisted-ips=
  node:
    type: compose
    build_as_root:
      - chown www-data:www-data /var/www
      - ln -s /etc/php/7.3/mods-available/gd.ini /etc/php/7.3/cli/conf.d/20-gd.ini
      - ln -s /etc/php/7.3/mods-available/pdo_sqlite.ini /etc/php/7.3/cli/conf.d/20-pdo_sqlite.ini
      - ln -s /etc/php/7.3/mods-available/sqlite3.ini /etc/php/7.3/cli/conf.d/20-sqlite3.ini
    services:
      image: thecodingmachine/php:7.3-v3-cli-node12
      command: 'tail -f /dev/null'
      environment:
        SIMPLETEST_BASE_URL: "http://appserver"
        SIMPLETEST_DB: "sqlite://localhost/tmp/db.sqlite"
        DRUPAL_TEST_DB_URL: "sqlite://localhost/tmp/db.sqlite"
        PHP_EXTENSIONS: "bcmath bz2 gd mbstring mcrypt pdo pdo_sqlite sqlite3 simplexml tokenizer xml yaml"

We also need a way of telling Lando to run yarn within the node/php container so add this tooling section:

tooling:
  yarn:
    service: node
    cmd: yarn

Install the needed node modules

To run the Nightwatch tests we need to install some node modules in our node container. Change directory to your Drupal core directory:

cd web/core

Note if you have a different webroot specified you'll need to modify the above command.

Now install the modules:

lando yarn install

This will use the node service (container) to install the correct node modules that Drupal core requires to run tests.

Add environment variables

When you run the tests in the next step some environment variables need to be passed to node via a .env file. This needs to be created in Drupal's core directory and should contain the following:

DRUPAL_TEST_BASE_URL=http://mysite.lndo.site
DRUPAL_TEST_DB_URL=sqlite://localhost/sites/default/files/db.sqlite
DRUPAL_TEST_WEBDRIVER_HOSTNAME=chrome
DRUPAL_TEST_WEBDRIVER_PORT=9515
DRUPAL_TEST_CHROMEDRIVER_AUTOSTART=false
DRUPAL_TEST_WEBDRIVER_CHROME_ARGS="--disable-gpu --headless --no-sandbox"
DRUPAL_NIGHTWATCH_OUTPUT=reports/nightwatch
DRUPAL_NIGHTWATCH_IGNORE_DIRECTORIES=node_modules,vendor,.*,sites/*/files,sites/*/private,sites/simpletest

Important! Edit the first line so it matches your Lando site's address (change mysite to match whatever your site is called in Lando).

Run Nightwatch tests

Now we're ready to run the tests. Make sure you're currently in the core directory. The following command runs the Drupal core test to check the login page works correctly:

lando yarn test:nightwatch tests/Drupal/Nightwatch/Tests/loginTest.js

You should see the following test output:

yarn run v1.22.4
$ cross-env BABEL_ENV=development node -r dotenv-safe/config -r babel-register ./node_modules/.bin/nightwatch --config ./tests/Drupal/Nightwatch/nightwatch.conf.js tests/Drupal/Nightwatch/Tests/loginTest.js

[Tests/Login Test] Test Suite
=============================
ℹ Connected to chrome on port 9515 (131ms).
  Using: chrome (74.0.3729.157) on Linux platform.

Running:  Test login

✔ Expected element <.user-role-form .machine-name-value> to be visible in 2000ms (534ms)
✔ User "user" was created successfully (29ms)
✔ Passed [equal]: The user "user" was logged in.
✔ Element <body> was visible after 23 milliseconds.
✔ Testing if element <h1> contains text 'Reports' (23ms)
✔ Ensuring no deprecation errors have been triggered (6ms)

OK. 6 assertions passed. (15.09s)
Done in 25.59s.

Complete .lando.yml file example

A more complete .lando.yml might look like:

name: projectname
recipe: drupal9
config:
  xdebug: true
  webroot: docroot
  php: '7.2'
proxy:
  mailhog:
    - mail.projectname.lndo.site # Change projectname to the same as the name key above.
  adminer:
    - adminer.projectname.lndo.site # Change projectname to the same as the name key above.
services:
  appserver:
    build:
      - 'if [ ! -z ${GITHUB_TOKEN} ]; then cd $LANDO_MOUNT && composer config
        --global --auth --unset github-oauth.github.com && composer config
        --global github-oauth.github.com $GITHUB_TOKEN; fi'
    overrides:
      environment:
        SIMPLETEST_BASE_URL: "http://appserver"
        SIMPLETEST_DB: "sqlite://localhost/tmp/db.sqlite"
        MINK_DRIVER_ARGS_WEBDRIVER: '["chrome", {"browserName":"chrome","chromeOptions":{"args":["--disable-gpu","--headless", "--no-sandbox"]}}, "http://chrome:9515"]'
        DRUSH_OPTIONS_ROOT: '/app/web'
        DRUSH_OPTIONS_URI: 'http://projectname.lndo.site'
  database:
    creds:
      user: database
      password: database
      database: database
  mailhog:
    type: mailhog
    hogfrom:
      - appserver
    portforward: true
  adminer:
    type: compose
    services:
      image: dehy/adminer
      command: '/bin/s6-svscan /etc/services.d'
    portforward: true
  chrome:
    type: compose
    app_mount: false
    services:
      image: drupalci/webdriver-chromedriver:production
      command: chromedriver --log-path=/tmp/chromedriver.log --verbose --whitelisted-ips=
  node:
    type: compose
    build_as_root:
      - chown www-data:www-data /var/www
      - ln -s /etc/php/7.3/mods-available/gd.ini /etc/php/7.3/cli/conf.d/20-gd.ini
      - ln -s /etc/php/7.3/mods-available/pdo_sqlite.ini /etc/php/7.3/cli/conf.d/20-pdo_sqlite.ini
      - ln -s /etc/php/7.3/mods-available/sqlite3.ini /etc/php/7.3/cli/conf.d/20-sqlite3.ini
    services:
      image: thecodingmachine/php:7.3-v3-cli-node12
      command: 'tail -f /dev/null'
      environment:
        SIMPLETEST_BASE_URL: "http://appserver"
        SIMPLETEST_DB: "sqlite://localhost/tmp/db.sqlite"
        DRUPAL_TEST_DB_URL: "sqlite://localhost/tmp/db.sqlite"
        PHP_EXTENSIONS: "bcmath bz2 gd mbstring mcrypt pdo pdo_sqlite sqlite3 simplexml tokenizer xml yaml"
tooling:
  drupal-check:
    service: appserver
    cmd: vendor/bin/drupal-check
  yarn:
    service: node
    cmd: yarn
  test:
    service: appserver
    cmd: "php /app/vendor/bin/phpunit -c /app/phpunit.xml"

This includes the ability to run PHPUnit tests (see the last blog post) as well as Nightwatch tests.

Back to blog