Cypress 🤖
The team prefers using Cypress for end-to-end testing on their front-end applications. It is easy to set up, and it provides some modern features which are convenient while writing end-to-end tests.
Configuration
-
The team uses Typescript when building JavaScript applications. After installing Cypress and Typescript, configure
Cypress
to useTypescript
. A sampletsconfig.json
file looks like below{ "compilerOptions": { "target": "es5", "lib": ["es5", "dom"], "types": ["cypress"], "moduleResolution": "node", "resolveJsonModule": true }, "include": [ "**/*.ts" ], "files": [ "./support/index.d.ts" ] }
-
Some scripts should be added to the
package.json
file for easier usage ofCypress
"scripts": { "cypress:open": "cypress open", "cypress:run": "cypress run" }
-
Base URL must be specified in the
cypress.json
to avoid repetitive definition of base URL in each test.{ "baseUrl": "http://localhost:3000", }
Formatting
-
-
-
-
Do not leave line breaks after
context
ordescribe
blocks.describe('User authentication', () => { context('given valid user credentials', () => { it('redirects to the landing page', () => {}) }) })
describe('User authentication', () => { context('given valid user credentials', () => { it('redirects to the landing page', () => {}) }) })
-
Leave one line return around
context
andit
blocks.describe('User authentication', () => { context('given valid user credentials', () => { it('redirects to the landing page', () => { ... }) it('shows user menu', () => { ... }) }) context('given INVALID user credentials', () => { it('shows login error', () => { ... }) }) })
describe('User authentication', () => { context('given valid user credentials', () => { it('redirects to the landing page', () => { ... }) it('shows user menu', () => { ... }) }) context('given INVALID user credentials', () => { it('shows login error', () => { ... }) }) })
Naming
-
camelCase
for file names. -
Each test file name must have the suffix
.spec
to distinguish test files from source files.integration/ ├── UserAuthentication/ │ ├── login.spec.ts │ ├── signup.spec.ts ├── UserSearch/ │ ├── searchByEmail.spec.ts support/ ├── commands.ts/
To enforce this rule a configuration should be added in the
cypress.json
file{ "testFiles": ["**/*.spec.ts"] }
-
Use
describe
to group tests using the file name for the description.// searchByEmail.spec.json describe('Search by email', () => {})
-
Use
context
to describe testing preconditions.context
block descriptions must always start withwhen
orgiven
, and be in the form of a sentence with proper grammar.it('redirects to landing page if user credentials are valid', () => {})
context('given valid user credentials', () => { it('redirects to the landing page', () => {}) })
-
Do NOT prefix
it
block descriptions withshould
. Use the imperative tone instead.it('should redirect to landing page', () => {})
it('redirects to the landing page', () => {})
Element selector
Avoid using highly brittle HTML selectors that are subject to change with target elements. Use data-test-id
attributes
to provide context to the selectors and insulate them from CSS or JS changes.
<div data-test-id="userProfile"></div>
Functions
Use ES6
arrow function for describe/context/it
block
describe('User authentication', function() {
context('given valid user credentials', function() {
it('redirects to the landing page', function() {})
})
})
describe('User authentication', () => {
context('given valid user credentials', () => {
it('redirects to the landing page', () => {})
})
})
Stub HTTP requests/responses
From Cypress v6.0.0
a new command cy.intercept()
has been added to stub HTTP requests and responses. This command can be used to specify HTTP fixtures as well.
cy.intercept('http://example.com/widgets', { fixture: 'widgets.json' })
All information about this command can be found in the documentation.
Custom commands
Cypress
supports user-defined commands. Custom commands are beneficial for automating a workflow repeated in tests. It
can significantly DRY-up tests.
If an application requires login on each page, then this can be made into a custom command
Cypress.Commands.add('login', () => {
cy.visit('/login')
cy.get('input[name=email]').type('[email protected]')
cy.get('input[name=password]').type(`'password'{enter}`)
})
Then this command can be easily used in tests as cy.login()
. When using typescript adding a custom command
requires a TypeScript
definitions file. More can be found in the documentation.