On this page
- Requirements
- Install Cypress in your project
- Install using NPX
- Install using Yarn
- Setting up Cypress
- Configure Cypress
- Run tests from the command line
- Run with NPX
- Run with Yarn
- Run all tests with NPX
- Run all tests with Yarn
- Run tests in the background via crontab
- .gitignore file for Git repositories
- Cypress, Drush, and Faker.js
- General testing logic
- Example scenario
- Creating random data with Faker.js and Drush in Cypress tests
- Testing the example scenario
- Setting up a system with Drush
- Custom Drush Commands
- Custom Cypress commands for custom Drush commands
- How to Integrate Cypress Tests into DevOps Pipelines
- Resources
Browser testing using Cypress
This documentation needs work. See "Help improve this page" in the sidebar.
With Cypress, you can easily create tests for Drupal, debug them visually, and automatically run them in your continuous integration builds. Cypress's simple, yet powerful API runs as fast as your browser can render content.
It's very easy to set up compared to most other test software, and you might run your first test already after a few minutes.
Requirements
Make sure you have Node.js installed on your system.
Install Cypress in your project
It is recommended to install Cypress in a sub-folder in the root of your Drupal project, since a lot of files and folders will be generated. In this example the folder is called "test", but you can call it anything. It is assumed that all commands are run after creating and entering the test folder:
$ mkdir test
$ cd test
... for a structure like this:
├── composer.json
├── composer.lock
├── test
├── vendor
└── web
Run the following commands in your newly created "test" folder to initialize a Node project package.json file with default values, install Cypress as a dependency, and open Cypress.
Install using NPX
$ npm init -y
$ npm install cypress --save-dev
$ npx cypress open
Install using Yarn
$ npm init -y
$ yarn add cypress
$ yarn run cypress open
Tip: You can add parameters to bypass selecting e2e and browser:
$ npx cypress open --e2e --browser firefox
Setting up Cypress
Cypress should now be open.
- Click "E2E testing"
- Select your preferred browser, and click the "Start E2E testing ..." button
A browser instance of Cypress will now open, but you need to do a few more steps, to finalize the set up.
Configure Cypress
Open the file test/cypress.config.js and add baseUrl: "https://example.org",
substituting example.org
with your local URL, so it looks like this:
const { defineConfig } = require("cypress");
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
baseUrl: "https://example.org",
},
});
Create a folder called "e2e" here: /test/cypress/e2e
Create a file called succesful-login.cy.js here: /test/cypress/e2e/succesful-login.cy.js
Edit succesful-login.cy.js to look like this:
describe('Loads the front page', () => {
it('Loads the front page', () => {
cy.visit('/')
cy.get('.site-branding__name')
.should('exist')
});
});
describe('Tests logging in using a correct password', () => {
it('Succeeds authentication using correct login credentials', () => {
cy.visit('/user/login')
cy.get('#edit-name')
.type('cypress')
cy.get('#edit-pass')
.type('cypress')
cy.get('input#edit-submit')
.contains('Log in')
.click()
cy.contains('Member for')
});
});
The first bit checks if the class site-branding__name
is present in the source on the front page, and then continues to attempt logging in at /user/login, and checks if eventually the text string "Member for" is present.
After creating the file succesful-login.cy.js in the /test/cypress/e2e folder, the browser instance of Cypress should now have a clickable succesful-login.cy.js test.
Run it and see that it fails.
Create a user with user name "cypress" and password "cypress". Click the "Specs" icon in the left side, run the test again, and (if all goes well) see that it succeeds.
Congratulations, you have just run your first Cypress test!
Run tests from the command line
Before deploying new configuration or code to your web site, you can test it locally with a copy of the target database with the code to be deployed, to ensure the functionality is working correctly.
If the tests pass, the code can be pushed to the server, following the standard deployment procedures - updating the database, and importing the new configuration.
Luckily, running Cypress tests from the command line is super easy. Just enter the "test" folder, and run this command to run a single test:
Run with NPX
$ npx cypress run --spec "cypress/e2e/succesful-login.cy.js"
Run with Yarn
$ yarn run cypress run --spec "cypress/e2e/succesful-login.cy.js"
The result will be printed to the screen, giving feedback whether the test failed or passed, and will even record a video to the "videos" folder.
To run all tests, simply run this command from the "test" folder:
Run all tests with NPX
$ npx cypress run
Run all tests with Yarn
$ yarn run cypress run
All tests found in the "e2e" folder are run, and the result is shown on the screen.
Run tests in the background via crontab
you can run Cypress automatically in the background, by adding a line like this in crontab:
*/15 * * * * cd /home/user/drupal10/test && /usr/bin/npx cypress run --spec "cypress/e2e/**/*" >>/tmp/crontab.log 2>&1
The >>/tmp/crontab.log 2>&1
bit at the end allows you to see errors with tail -f /tmp/crontab.log
in another terminal. In Ubuntu, you might see "Error: spawn Xvfb ENOENT". Install it with sudo apt install xvfb
and you may see the tests finally work.
You can find npx location on your machine with whereis npx
.
For more, see Not able to use Node.js and Crontab for more info.
.gitignore file for Git repositories
Cypress generates a lot of files, and many files will be committed to Git. To only commit the relevant files, download cypress.gitignore.txt (original from
cypress-io/cypress-example-todomvc), rename it to .gitignore and place in the "test" folder.
Cypress, Drush, and Faker.js
General testing logic
The idea behind a Cypress test is as follows:
- Set up the (Drupal) system to a state in which it can be tested
- Run the Cypress tests, and confirm the tests have passed
Good tests use randomized data every time they are run, thereby testing a wide range of possible data possibilities over time. Setting up a Drupal system in a state ready to be tested can be accomplished using a combination of Drush and Faker.js.
Example scenario
Consider a scenario where a system has a custom login form, separate to the default Drupal login form. In this case, to test the form functionality, the following things must be tested/ensured:
- Unblocked users are able to log in using the form
- When a user logs in, they are redirected to the correct page
- Non-existent users cannot log in using the form
- Blocked users cannot log in using the form
- Valid users cannot log in with an invalid password
Creating random data with Faker.js and Drush in Cypress tests
Cypress tests can execute commands from the command line, which means Cypress can execute Drush commands. As Cypress tests require setting up the system to be in a state that is ready to be tested, a Cypress test can use Drush to set up the system before running the test on that system.
When using Drush to set up data, it is always preferable to use some kind of randomized data, to try to bring out bugs that you may not have considered. For the example scenario outlined above, a user needs to be created to test that the login form works correctly. Rather than hard-coding the name and password of the user into the test, which would test the same name every time, instead Faker.js can be used to generate a random username and password each time the test is run, then Drush can be used to create an account with the generated username and password. This ensures the system is tested by a wide range of data, rather than hard-coding a value.
Testing the example scenario
The following explains how to bring together Cypress, Drush, and Faker.js to test the example scenario given above.
- Create a new user in the system. Use Faker.js to create a random username, and then have Cypress use Drush to create an unblocked user with that username.
- Have Cypress access the custom login form
- Cypress test: Does the page form at the expected path, and have the login form on it?
- Have Cypress try logging in with the new user
- Cypress test: Was the user logged in? Were they redirected to the correct path?
- Have Cypress block the user with Drush. Have Cypress try logging in with the blocked user
- Cypress test: Was the user correctly blocked?
- Have Cypress try logging in with a non-existent account
- Cypress test: Was the non-existent account correctly blocked from logging in?
- Have Cypress try logging in with the user that was created, but an invalid password
- Cypress test: Was the valid account blocked from logging in with an invalid password?
Setting up a system with Drush
Consider a site using the Groups module. A new group will be required every time a test is run that tests group functionality. Using Cypress, there are two ways to create a group:
- Have Cypress log in with an admin user, visit the group creation page in the browser, and create the group, still in the browser, or:
- Have Cypress execute a Drush command to create the group
With option number one, Cypress, though a browser, will have to load a log-in page, login the user, load the page redirected to after login, load the group create page, create the group, and load the page the group creation form redirects to. This is a lot of page loads, making for a slow/inefficient test. Drush on the other hand can create entities/data in PHP using the Drupal API. With this method no pages are ever loaded, and therefore is significantly faster than running this process through a browser. Over time, as tests are added to a system, a few seconds different in a given test can add up to hours of cumulative execution time, so the more efficient the test, faster the tests will run, and the happier a developer you will be. As such, it is preferable to have the test create a group through the CLI using Drush, over doing so through a browser.
Custom Drush Commands
Often, there will not be an existing Drush command to provide the required functionality. For example, the Groups module does not provide a Drush command to create a group. As such, it is best to create a custom Drush command, and in that command, use the Drupal API to create a group. For example a Drush command, group:create
, could be created allowing for Cypress to create a group with drush group:create "GroupName"
, with GroupName
being generated by Faker.js to ensure it's random.
Custom Cypress commands for custom Drush commands
After creating a custom Drush command, it is advisable to create a custom Cypress command that matches the Drush command, so that tests can use the new functionality provided by the custom Drush command. For the above example of the custom Drush command group:create
, a custom Cypress command cy.createGroup()
can be created, by adding the following to cypress/commands/e2e.js:
Cypress.Commands.add('createGroup', function(groupName) {
cy.log('Create the group');
cy.exec(Cypress.env('drushCommand') + ' group:create "' + groupName + '"')
.its('stderr')
.should('match', /^\[success\]/);
});
This now allows for setting up a new Group from any Cypress test as follows:
// User Faker.js to create a random string for the group name.
// Note that depending on the system, something like company
// name (https://fakerjs.dev/api/company.html#name) that provides
// data appropriate to the real-world data type that the group
// represents.
const groupName = faker.random.alphaNumeric(10) + '-' + faker.random.alphaNumeric(5);
cy.createGroup(groupName);
How to Integrate Cypress Tests into DevOps Pipelines
[NEEDS WORK]
Resources
There is much more to learn about Cypress, please check out these resources. Thanks to Aten Design Group for inspiration for this documentation.
- How to Use Cypress for Testing Drupal / video
- Videos by Gleb Bahmutov, PhD (Cypress Ambassador) / web site
- Drupal Experience Builder initiative is using Cypress: Experience Builder week 3: shape matching, see also #3453097: Meeting of the Experience Builder Initiative 2024-06-06.
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