Skip to main content
Version: 3.1.0

Cypress integration

Preface

Using the Cypress commands provided by the package @mocks-server/cypress-commands you'll be able to change the current mock of Mocks Server simply using a Cypress command. This means that you can develop solid tests, without the dependency of the real API, because you can control in every moment the responses that the API will return to your web page.

You'll be able to develop Cypress tests for error cases, slow requests and many other cases that are very hard to reproduce with a real api, with the advantage that you could reuse the same mocks while you are developing the application.

Installation

npm i --save-dev @mocks-server/cypress-commands

Add this line to your project's cypress/support/commands.js file:

import "@mocks-server/cypress-commands"

Cypress Commands

Set current mock:

cy.mocksSetMock("admin-user");

Use specific route variant:

cy.mocksUseRouteVariant("get-users:error");

Restore routes variants to those defined in current mock:

cy.mocksRestoreRoutesVariants();

Set delay time:

cy.mocksSetDelay(2000);

Set any setting:

cy.mocksSetSettings({
watch: false,
delay: 0,
mock: "get-users-error"
});

Configures the Mocks Server administration API client, used under the hood:

cy.mocksConfig({
adminApiPath: "/foo",
baseUrl: "http://localhost:3000"
})

Example

describe("books page", () => {
describe("when there are two books", () => {
before(() => {
cy.mocksSetMock("two-books"); // Use "two-books" mock
cy.visit("/");
});

it("should display two books", () => {
cy.get("#books li").should("have.length", 2);
});
});

describe("when there is an error loading data", () => {
before(() => {
cy.mocksUseRouteVariant("get-books:error"); // Use "get-books:error" route variant
cy.visit("/");
});

after(() => {
cy.mocksRestoreRoutesVariants(); // Restore mock route variants after the test
});

it("should display error message", () => {
cy.get("#books .error").should("exist");
});
});

describe("when the API is slow", () => {
before(() => {
cy.mocksSetDelay(3000); // Set a delay of 3 seconds in API responses
cy.visit("/");
});

after(() => {
cy.mocksSetDelay(0); // Restore the delay to 0
});

it("should display loading", () => {
cy.get("#books .loading").should("exist");
});

it("should display two books", () => {
cy.get("#books li").should("have.length", 2);
});
});
});

Start the application, Mocks Server and Cypress

For running tests, you'll need to start your application configured to make requests to the Mocks Server url, start Mocks server, and only then, start the execution of Cypress.

We recommend the usage of the start-server-and-test package to start all needed dependencies before running tests.

The next example is based on a create-react-app application which is using the REACT_APP_BASE_API environment variable to set the api url:

{
"scripts": {
"mocks:ci": "mocks-server --no-plugins.inquirerCli.enabled",
"start:mocked": "REACT_APP_BASE_API=http://localhost:3100 react-scripts start",
"mocks:ci-and-start:mocked": "start-server-and-test mocks:ci tcp:3100 start:mocked",
"cypress:run": "cypress run",
"test:mocked": "start-server-and-test mocks:ci-and-start:mocked http-get://localhost:3000 cypress:run",
}
}

Now, when running npm run test:mocked, Mocks Server will be started without the interactive CLI, then the application will be started configured to make requests to the Mocks Server url, and then the Cypress tests will be executed.

Configuration

By default, the API client is configured to request to http://localhost:3100/admin, based in the default Mocks Server options

You can change both the base url of Mocks Server, and the api path of the administration API using the cy.mocksConfig command mentioned above, or the plugin environment variables:

  • MOCKS_SERVER_BASE_URL: Modifies the base url of Mocks Server. Default is http://localhost:3100.
  • MOCKS_SERVER_ADMIN_API_PATH: Modifies the path of the Mocks Server administration API. Default is /admin.
  • MOCKS_SERVER_ENABLED: Disables requests to Mocks Server, so the commands will not fail even when Mocks Server is not running. This is useful to reuse same tests with mocks and a real API, because commands to change Mocks Server settings will be ignored.

Reusing tests for real and mocked APIs

Running tests only using a mock server is not enough, probably you may want to run your tests also using the real API, but only a subgroup of them, as not every tests will be valid for the real API (error cases, etc.).

Here you have a proposal about how to reuse your tests and run them in two different ways:

Use an environment variable to skip tests

We will use the MOCKS_SERVER_ENABLED environment variable to know if Mocks Server is enabled, and skip tests that can be executed only when the api is mocked.

Create an onlyMocks method in the cypress/support/utils.js file:

export const onlyMocks = fn => {
if (!!Cypress.env("MOCKS_SERVER_ENABLED")) {
fn();
}
};

Now, wrap your Mocks Server dependent tests definitions using the onlyMocks method:

import { onlyMocks } from "../support/utils";

onlyMocks(() => {
describe("This tests will only be executed when mocks are enabled", () => {
// ...
});
});

Start the application with the real API and Cypress

Based on the previous example, now we can add a command to start the application configured to make requests to the real API and run Cypress at a time:

{
"scripts": {
"mocks:ci": "mocks-server --no-plugins.inquirerCli.enabled",
"start:mocked": "REACT_APP_BASE_API=http://localhost:3100 react-scripts start",
"start:api": "REACT_APP_BASE_API=http://foo-api.com react-scripts start",
"mocks:ci-and-start:mocked": "start-server-and-test mocks:ci tcp:3100 start:mocked",
"cypress:run": "cypress run",
"cypress:run:no-mocks": "MOCKS_SERVER_ENABLED=false cypress run",
"test:mocked": "start-server-and-test mocks:ci-and-start:mocked http-get://localhost:3000 cypress:run",
"test:api": "start-server-and-test start:api http-get://localhost:3000 cypress:run:no-mocks"
}
}

Now, when running npm run test:api the application will be started configured to make requests to the real API, and then the Cypress tests will be executed skipping mock-dependent tests. You could also use npm run test:mocked to run Mocks Server, start the application configured to make requests to it, and run Cypress without skipping any test.