Cypress - Functional testing

Features

  • Developer friendly.
  • Open source (MIT).
  • It can records snapshots and videos of your tests.
  • It has a test runner console.
  • It only currently supports Chrome variants and Firefox.
  • It doesn’t have native iframe support, though there are workarounds.
  • It has its own promise-based system that you have to use (it can’t use ES6 promises).

Functional E2E Testing

Set up

  • As dev dependency.

    1
    npm install cypress --save-dev
  • Just use it for execution.

    1
    2
    # launches the modal helper
    npx cypress open

Write tests

  1. Create configuration.
  • Add it to cypress.json file.

    1
    2
    3
    {
    "baseUrl": "http://localhost:8000/"
    }
  1. Create the runner.
  • Starts the dev server, runs all tests fro my_module, via scripts/cypress.js.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    return devServer.listen(port, HOST, err => {
    if (err) {
    return console.log(err);
    }
    if (isInteractive) {
    clearConsole();
    }
    console.log(chalk.cyan('Starting the development server...\n'));
    return cypress
    .run({
    spec: './cypress/integration/my_module/*.js',
    })
    .then(results => {
    devServer.close();
    });
    });
  1. Create the test file.
  • cypress/integration/my_module/sidebar.js.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    /* globals context cy */
    /// <reference types="Cypress" />
    context('Sidebar', () => {
    beforeEach(() => {
    cy.visit('/');
    // example: review progress bar
    cy.contains('Progress').should('exist');
    });

    // dummy example
    it('does something', () => {
    cy.contains('My_module Exercises');
    });

    it('closes when X is clicked and reopens when hamburger is clicked', () => {
    cy.get('[data-testid=closeSidebar]').click();
    cy.contains('Progress').should('not.exist');
    cy.get('[data-testid=openSidebar]').click();
    cy.contains('Progress').should('exist');
    });

    it('navigates to /up-going when Up & Going is picked', () => {
    cy.contains(/Up & Going \(/).click({ force: true });
    cy.url().should('include', '/up-going');
    cy.contains('Chapter 1: Into Programming').should('exist');
    cy.contains('Chapter 2: Into JavaScript').should('exist');
    });
    });
  1. Trigger tests.
  • Add command on scripts as via package.json.

    1
    2
    3
    "scripts": {
    "cypress": "node scripts/cypress.js"
    },

Code snippets

Visit a page

1
2
3
4
5
describe('My First Test', () => {
it('Visits the Kitchen Sink', () => {
cy.visit('https://example.cypress.io')
})
})

Query for an element

1
2
3
4
5
6
7
describe('My First Test', () => {
it('finds the content "type"', () => {
cy.visit('https://example.cypress.io')

cy.contains('type')
})
})

Click on an element

1
2
3
4
5
6
7
describe('My First Test', () => {
it('clicks the link "type"', () => {
cy.visit('https://example.cypress.io')

cy.contains('type').click()
})
})

Make an assertion

1
2
3
4
5
6
7
8
9
10
describe('My First Test', () => {
it('clicking "type" navigates to a new url', () => {
cy.visit('https://example.cypress.io')

cy.contains('type').click()

// Should be on a new URL which includes '/commands/actions'
cy.url().should('include', '/commands/actions')
})
})

Multi-command/multi-assertion

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
describe('My First Test', () => {
it('Gets, types and asserts', () => {
cy.visit('https://example.cypress.io')

cy.contains('type').click()

// Should be on a new URL which includes '/commands/actions'
cy.url().should('include', '/commands/actions')

// Get an input, type into it and verify that the value has been updated
cy.get('.action-email')
.type('fake@email.com')
.should('have.value', 'fake@email.com')
})
})