This module integrates the Drupal content management system with Cypress E2E testing. It will help you to:
- Use Cypress for testing whole Drupal projects, including configuration.
- Include Cypress tests in custom Drupal modules.
- Ship custom Cypress commands and predefined cucumber step definitions with Drupal modules.
It also includes some handy Cypress plugins out of the box:
- The Cucumber preprocessor to write specifications in Gherkin.
- Cypress testing library to add some good-practice commands.
- An extension to test Shadow DOM in web components.
- And another one to upload files during tests.
Apart from standard system requirements, you will need Composer and npm available on your system first. From there, this is shortest path to get it up and running:
-
Download and extract Drupal
curl -O https://ftp.drupal.org/files/projects/drupal-8.8.5.tar.gz tar -xvzf drupal-8.8.5.tar.gz cd drupal-8.8.5
-
Install the Cypress Module and upgrade PHPUnit
composer require drupal/cypress composer require phpunit/phpunit:^7 symfony/phpunit-bridge phpspec/prophecy sebastian/global-state:^2 sebastian/environment:^3.1 phpunit/php-code-coverage:^6
-
Install the minimal profile and the Cypress module
php core/scripts/drupal install minimal drush en cypress -y
-
In case of doubt, loosen the directory permissions so the module can copy settings files for you. If you don't, it might ask you to do that yourself.
chmod 755 sites/default
-
Start a test server and run tests
vendor/bin/drush serve & vendor/bin/drush cypress:run
The test suite for the Cypress module itself, located in the tests\Cypress
,
should have been executed. They also serve as examples on how to write Cypress
tests yourself.
How meta!
You are good to go, now draw the rest of the drowsy the owl!
Back to serious. What happened now? A new directory called
drupal-cypress-environment
was created, which you can safely add to
.gitignore
. All dependencies have been downloaded there and the Drupal
installation was scanned for modules with a tests/Cypress
directory which
where added as new test suites. Additionally a testing.services.yml
file
should have been created in your sites/default
directory. This one can be
added to your git repository, since it allows you to adapt configuration:
cypress.enabled
: This one is important! It is disabled by default and should be enabled only intesting.services.yml
. It opens up backdoors for Cypress to speed up tests, which are huge security threats for a publicly accessible website.cypress.executable.drush
: A path to thedrush
executable that will be used by cypress. Relative to the Drupal root directory. It defaults tovendor/bin/drush
, which is where it will be if you simply download Drupal as shown above. But if you use a different directory layout (like the [composer template]), you might have to adapt this.cypress.test_suites
: The module will register a test suite for each module containing atests/Cypress
directory with the modules machine name. This parameter allows to add other directories as well.
The cypress:run
command will just run all scoped tests, while cypress:open
starts the Cypress user interface for interactive debugging.
A test suite can hook into the test framework in different ways by simply containing certain files or directories.
package.json
: If a test suite contains apackage.json
file, its dependencies and additional settings will be merged into the global package that is automatically maintained indrupal-cypress-environment
.integration
: The actual tests and implementations. The modules uses the Cucumber preprocessor for Cypress innonGlobalStepDefinitions
mode. This means that test specifications are written in*.feature
files and implementations in arbitrary*.js
files stored in a directory with the same name as the*.feature
file. Please refer to the Cucumber preprocessor documentation for a lot more details on test organisation.steps
: This directory will be scanned for*.js
files that contain global step definitions. These are available to all scenarios. Not just within the current suitesintegration
folder, but also to other test suites. This can be used to share common steps defined by a Drupal module.plugins/index.js
: This file will be automatically added to Cypress plugin system and allows to add additional extensions that are not covered out of the box by this module.support/index.js
: That's the entry point for anything that would go into Cypress notion ofsupport
files. Here, for example, test suites can share reusable commands.
The module comes with list of simple drush commands.
Simply lists all discovered test suites. Nothing fancy.
Will run all or a specific set of test suites. Also accepts an option to define [tags] that should be run. [tags]: https://github.com/TheBrainFamily/cypress-cucumber-preprocessor#running-tagged-tests
Examples:
# Run all test suites
drush cypress:run
# Run all tests of a specific suite
drush cypress:run mytestsuite
# Run all tests within a folder in a specific suite
drush cypress:run mytestsuite:sub/folder
# Run a specific spec file
drush cypress:run mytestsuite:sub/folder/Fancy.feature
# Run all tests matching a certain tags expression
drush cypress:run --tags "@Completed and @Issue-123"
# Both options can be combined
drush cypress:run mytestsuite:sub/folder --tags "@Completed and @Issue-123"
Starts the Cypress user interface for running tests interactively.
Rebuilds the Cypress environment. This is automatically invoked when running
drush cypress:run
or drush cypress:open
, but can be used if you need to run
cypress directly from within drupal-cypress-environment
.
The Cypress module comes with a set of predefined commands that can be used by other test suites to easily interact with Drupal.
Install Drupal at the beginning of your test case. This command reuses the test setup behind Drupals Browsertests. If the tests are run against a SQLite database, it also automatically caches the install process and reuses it across test runs to speed things. It takes a set of options as arguments:
The profile
option defines the installation profile to use. It defaults to
testing
.
cy.drupalInstall({profile: 'umami_demo'});
The value of config
can be the path to a configuration sync directory,
relative to the Drupal root. This can be used to run tests against a fully
configured project. The chosen profile
has to match the one in configuration
in this case.
cy.drupalInstall({config: '../config/sync'});
setup
allows to define a custom setup script (identical to nightwatch test
setups). The path should be prefixed with the test suites name.
cy.drupalInstall({setup: 'cypress:integration/CypressTestSiteInstallScript.php'});
The cache
property allows to define a persistent cache file that can be placed
anywhere relative to the Drupal root directory. It can be used to maintain a
cached version of the installation to speed up exection on build servers as
well as testing update procedures properly.
After a site has been recreated from cache, the setup process will automatically
run drush updb -y
and drush cim -y
.
cy.drupalInstall({cache: '../install-cache.zip'});
Using the strictConfigCheck
flag, Drupal config checking can be disabled. This
only makes sense in combination with a config
directory.
cy.drupalInstall({strictConfigCheck: false});
This should be called at the end of each test case (preferrably in afterEach
),
to clean up test site installs created by cy.drupalInstall
.
cy.drupalUninstall();
Execute arbitrary drush commands against the current test site.
cy.drush('cron');
Execute a simple PHP script in the test suite. Can be used for test content
setup or other tasks that don't have to be run through the user interface. The
script is executed in context of a fully booted Drupal environment and has
access to the container much like drush scr
.
The first argument is the script path, relative to your test suite. The second
an arbitrary context object that will be passed to the script as an $args
variable.
cy.drupalScript('cypress:integration/Scripts/testPage.php', {title: "Test page"});
Control the user session a test case operates in. The settings will persist across subsequent requests within this test case.
user
to automatically log in a specific account:
cy.drupalSession({user: 'admin'});
language
to select the language the system is accessed in:
cy.drupalSession({language: 'de'});
workspace
to make the system automatically switch to a specific workspace:
cy.drupalSession({workspace: 'stage'});
... and a boolean flag to show or hide the toolbar during the test run. By default the toolbar is turned of to avoid problems with Cypress not being able to click elements because they are hidden behind it.
cy.drupalSession({toolbar: true});
Search for a Drupal entity by properties and visit one of the registered link
patterns. This allows to easily access entity pages without relying on internal
entity id's. This example would bring you to the edit page of a node with title
Testpage
.
cy.drupalVisitEntity('node', {title: "Testpage"}, 'edit-form');