JavaScript testing using Nightwatch
This documentation needs review. See "Help improve this page" in the sidebar.
Setup
How to set up Nightwatch is explained in the core README file for tests, core/tests/README.md
.
Alternatively, if you use DDEV, you can use DDEV Selenium Standalone Chrome.
Creating a test
To create your own test, add a file in your module: your_module/tests/src/Nightwatch/Tests/exampleTest.js
.
In that file, write some JS:
module.exports = {
'@tags': ['your_module'],
before: function(browser) {
browser
.drupalInstall();
},
after: function(browser) {
browser
.drupalUninstall();
},
'Visit a test page and create some test page': (browser) => {
browser
.drupalRelativeURL('/test-page')
.waitForElementVisible('body', 1000)
.assert.containsText('body', 'Test page text')
.drupalRelativeURL('/node/add/page')
.setValue('input[name=title]', 'A new node')
.setValue('input[name="body[0][value]"]', 'The main body')
.click('#edit-submit')
.end();
},
};
Remember to use @tags to tag your test with your modules' machine name so it gets picked up by the test runner on drupal.org.
Nightwatch Command Reference
- Nightwatch methods: https://nightwatchjs.org/api/
- Drupal Nightwatch methods (in core): https://git.drupalcode.org/project/drupal/-/tree/11.x/core/tests/Drupal/...
- If you want to learn how to add custom commands/assertions, have a read at https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-comman...
- Nightwatch includes accessibility testing with axe-core: https://nightwatchjs.org/guide/using-nightwatch/accessibility-testing.html
Writing Unit tests in Nightwatch
It is possible to use Nightwatch for unit testing JavaScript. In order to unit test your JavaScript, it is important that the JavaScript is written in a way that is testable. Writing unit-testable JavaScript is not specific to Drupal, and you should look around the Internet for examples of how to do it.
You can mark your test as a unit test by setting:
'@unitTest' : true
Here is an example test
const assert = require('assert');
const testScript = require('../../Scripts/unitTestScript');
const dataProvider = [
{input: 'value_1', expected: 'value_1Test'},
{input: 'value_2', expected: 'value_2Test'},
{input: 'value_3', expected: 'value_3Test'},
];
module.exports = {
'@tags': ['unit_test'],
'@unitTest' : true,
'example unit test' : function (done) {
dataProvider.forEach(function (values) {
assert.strictEqual(testScript.testMethod(values.input), values.expected);
});
setTimeout(function() {
done();
}, 10);
}
};
Writing Accessibility tests in Nightwatch
Here is the core accessibility test that tests multiple URLs for accessibility issues (taken from a11yTestAdmin.js). Drupal's Nightwatch implementation now also leverages Deque's axe accessibility engine to evaluate for known accessibility errors. This sample list of URLs should cover most basic elements from the Drupal UI.
const argv = require('minimist')(process.argv.slice(2));
const adminTest = {
'@tags': ['core', 'a11y', 'a11y:admin'],
before(browser) {
browser.drupalInstall({ installProfile: 'nightwatch_a11y_testing' });
// If an admin theme other than Claro is being used for testing, install it.
if (argv.adminTheme && argv.adminTheme !== browser.globals.adminTheme) {
browser.drupalEnableTheme(argv.adminTheme, true);
}
},
after(browser) {
browser.drupalUninstall();
},
};
const testCases = [
{ name: 'User Edit', path: '/user/1/edit' },
{ name: 'Create Article', path: '/user/1/edit' },
{ name: 'Create Page', path: '/node/add/page?destination=/admin/content' },
{ name: 'Content Page', path: '/admin/content' },
{ name: 'Structure Page', path: '/admin/structure' },
{ name: 'Add content type', path: '/admin/structure/types/add' },
{ name: 'Add vocabulary', path: '/admin/structure/taxonomy/add' },
// @todo remove the skipped rules below in https://drupal.org/i/3318394.
{
name: 'Structure | Block',
path: '/admin/structure/block',
options: {
rules: {
'color-contrast': { enabled: false },
'duplicate-id-active': { enabled: false },
region: { enabled: false },
},
},
},
];
testCases.forEach((testCase) => {
adminTest[`Accessibility - Admin Theme: ${testCase.name}`] = (browser) => {
browser.drupalLoginAsAdmin(() => {
browser
.drupalRelativeURL(testCase.path)
.axeInject()
.axeRun('body', testCase.options || {});
});
};
});
module.exports = adminTest;
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion