Built with Express and Cypress.
This repo is built to demonstrate some DRY approaches to E2E testing with Cypress.
The following approaches are demonstrated with "before and after" examples:
- Text assertions
- Link assertions
- Click events
- Enter text
- Common page assertions
In large applications, cypress E2E tests can become very complex, time consuming and hard to maintain.
Some tests can become repeated - for example with common elements, assertions and user journeys.
A simple example would be the following. To assert that some text equals X, we could do this:
cy.get('[data-cy="main-heading"]').invoke('text').then((text) => {
expect(text.trim()).equal('The landing page');
});
This is quite a lot of methods and lines of code for a simple, strict equality text assertion.
Instead, a command could be created and this could simply become:
cy.assertText(mainHeading(), 'The landing page');
The assertion could even become the following - avoiding the need to import the mainHeading
selector in individual tests.
cy.assertMainHeadingText('The landing page');
It might seem minor at first glance. Such approaches can be adapted to many other areas, which improve the test suite and ultimately reduce development time on E2E tests. By creating such commands, we can ensure that:
- Every assertion asserts the text with strict equality, instead of "should contain".
- Individual E2E tests have only 1 line per assertion instead of 3 lines.
- Tests are DRY and consistent, with improved readability.
- Tests for user journey iterations become easier to update.
- Future E2E refactoring is easier, since we should only need to update in one place.
- Once some patterns are in place, reduce time and effort on E2E tests.
- Unlikely, but if Cypress's
invoke('text')
ortext.trim()
methods change, we only need to update them in one place.
Additionally, as an application grows, we could otherwise be repeating the same assertions throughout multiple tests. With text assertions, the only differences between tests are the selector and/or expected text.
For example, 1x test spec could contain 4x lines of code to assert a single piece of text. If we have 200 tests, this means 800 lines of code. Instead, this could be 200 lines of code; 1 line for each spec.
It is best to introduce such approaches as early as possible. As a real world example - in a "medium sized, historical project", I recently introduced a generic assertText
command which removed just over 2,000 lines of code.
This repo aims to demonstrate such approaches with simple "before and after" examples.
- Node version 22.8.0 or higher with corresponding npm.
- Run
npm install
in the root directory. Yarn should also work.
- Spin up the UI
npm run dev
- In a separate terminal, open up the Cypress GUI
npx cypress open .