Skip to content
Koen Verheyen edited this page Sep 19, 2017 · 7 revisions

LibreCat-Frontend-Tests uses Cypress for integration tests. Cypress is a test framework that allows you to run & debug tests in a user interface, as well as run them on the command line. Cypress is currently available for Chrome related browsers on Linux and Mac. Tests are written in JavaScript, but can also use all ECMAScript 2015 (ES6) features since it integrates with the Babel compiler.

Cypress integrates with all common continuous integration software (including Travis CI) and allows you to review recorded test runs on its Dashboard.

Cypress is very well documented and has a Gitter chatbox where you can ask for support. Also, Cypress is planned to be open sourced at the end of 2017.

Best practice

For convenience, the tests should expect LibreCat to be loaded with the default dummy data that is provided with LibreCat. Also try to avoid making changes this default data set in tests as later tests may depend on that data. If it is necessary to change the default data, it is advised to restore the former state in the teardown fase.

The Cypress ecosystem

Cypress combines its own core features for browsing through a website with the power of other widely used frameworks for writing tests.

  • mocha to structure tests
  • chai to define expectations/assertions
  • jQuery for finding elements in a web page

Cypress enhances interacting with the web, which is mostly asynchronous, with a synchronous API. This makes it easy to understand and maintain Cypress tests. In a Cypress test, the API is exposed via the cy object. Most common Cypress methods are chainable; they produce a result, which is passed on as the subject of the next chained command:

cy.get('.header h1')
    .should('be.visible')
    .should('have.text', 'This is the title')
    .next('a:contains("Edit")')
    .click();

In practice each command executed on cy is scheduled and will execute after the previous command has finished. Most commands will retry their action a number of milliseconds until it succeeds, so a test will not fail when you try to get an element in a page that is still rendering.

If a command times out, the test will fail. These timeouts are configurable and depend on the type of command.

Common Cypress methods

Cypress also delivers a bunch of methods for traversing the DOM you may already know from jQuery: find, closest, filter, not, children, parent, parents, first, next, prev, eq, siblings, each,...

The complete API is documented here.

Authentication

Some LibreCat tests may require you to logon in order to access the feature you want to test. You can of course let your test browse through the login page and submit it, but you can also use the custom Cypress command login(username, password). By default, the login command will login with username test and password secret. You can also provide your own credentials, eg: cy.login('einstein', 'einstein');

In most cases you want to use the login command in a beforeEach block so it is repeated before each test.

The login() command is optimised to store authentication cookies in memory, so the actual login for each user should only be executed once.

Localization

Since LibreCat is currently available in English and German, we provided a manner to execute tests in both locales. For this it is necessary to export the locale configuration from LibreCat and export it to the test project (see README.md for details on how to do this.

We added a custom block function l10n in which you can group a set of tests that need to be tested in both locales. Inside tests within the l10n block, you can access all translations via the object this.t, eg:

l10n(() => {
    it('should display the title', function() {
        cy.get('#banner > h1')
            .should('have.length', 1)
            .should('be.visible')
            .should('have.text', this.t.header.title);
    });
});

This test will be executed twice. Before each run, the language will be changed and the correct translations set will be made available via this.t.

Clone this wiki locally