The quality of a product always depends on how alert the developer is. The better this skill is, the fewer bugs and unsatisfied customers there will be.

I, for one, sometimes have problems with this. But fortunately, there is a solution, and this solution is called autotests. Automated testing allows you to arrange continuous checks of the product’s quality and rids you of this task.

Today, I will tell you how to set up automated tests in a Vue project. You’ll be able to test entire pages and individual components, mock server requests, and run it all in Docker.

Link to the Vue Boilerplate.

Let’s imagine that we have a Vue project that has been under development for a thousand years and the only tests it has are unit tests. That is, functional ones that feature out-of-the-box, ill-considered settings.

First, we will open the documentation of the Cypress framework. We will use it to write integration tests. It’s pretty well-developed and has a lot of features, plugins, and other supporting things.

Be sure to read the documentation to understand what it is and how it works.

Now let’s install the necessary packages.

Open the console at the project root and insert the command below:

npm i -D cypress @cypress/vue @vue/cli-plugin-e2e-cypress vue-cli-plugin-cypress-experimental

After successfully installing the packages, let’s add the main settings file cypress.json. You need to create it in the project root and insert the code below:

{
  "baseUrl": "http://localhost:3000",
  "chromeWebSecurity": false,
  "pluginsFile": "tests/e2e/plugins/index.js",
  "supportFile": "tests/e2e/support/index.js",
  "fixturesFolder": "tests/e2e/fixtures",
  "integrationFolder": "tests/e2e/integrations",
  "testFiles": "**/*.spec.js*",
  "experimentalComponentTesting": true,
  "componentFolder": "tests/e2e/components",
  "nodeVersion":"system",
  "video": false,
  "viewportWidth": 1366,
  "viewportHeight": 768
}

A few words about what these parameters mean

  • baseUrl — the URL where cypress browser will start
  • chromeWebSecurity — allows you to open non-secure pages, give access to iframes, etc.
  • pluginsFile — the path where files with plugins for cypress are kept
  • supportFile — the path where support files are kept
  • fixturesFolder — the path where mock files are kept to swap API data
  • integrationFolder — the path where files with integration tests are kept
  • testFiles — the path where all test files are kept
  • componentFolder — the path where files with tests for components are stored
  • experimentalComponentTesting — this flag is required if you want to test components
  • nodeVersion — specify node.js version
  • video — turn on/off video recording of the tests
  • viewportWidth — browser window width
  • viewportHeight — browser window height

In the settings, you can already see a list of files and folders you need to create.
In Vue, the folder for tests is located in the project root and is usually called tests. It should already have a unit folder, next to which we will create another one for our tests.
Let’s call this new folder e2e. In it, we will add some more files and folders. The final result should look like this:

tests
  e2e
    components
      - HelloWorld.spec.js
      - ...
    fixtures
      - example.json
      - ...
    integrations
      - Home.spec.js
      - ...
    plugins
        - index.js
    support
      - commands.js
      - index.js

To save you the hassle, I prepared a repo with the project already set up. So you can copy everything from there and not bother https://github.com/denisoed/setup-cypress-vue.

Next, in the package.json file, in the scripts block, add the command to run the tests

"scripts": {
    "test:e2e": "vue-cli-service test:e2e --mode test"
}

We have completed the basic steps; now, we can start.

npm run test:e2e

If everything was done correctly, the browser will open with a list of our tests.

Cypress Integration & Component Tests.

Cypress Integration & component tests

And the console will show this result

DONE  Compiled successfully in 3572ms

App running at:
  - Local:   http://localhost:8080/ 
  - Network: http://192.168.88.241:8080/

Note that the development build is not optimized.
  To create a production build, run npm run build.

It looks like this is your first time using Cypress: 6.5.0

✔  Verified Cypress! /home/denisoed/.cache/Cypress/6.5.0/Cypress

Opening Cypress...

It can be called a victory, but we shouldn’t relax; we’re not done yet.

Image.

Setting up a server to mock API requests

As a mock server, we will use the JSON server library. It’s based on Express.js, so you shouldn’t have any problems setting it up or extending it.

Let’s install the package

npm i json-server

While you’re at it, add a command to run in package.json, so you can update the command to run tests. Now, the server will start first, and then cypress will launch.

"scripts": {
    "test:e2e": "npm run test:server & vue-cli-service test:e2e --mode test",
    "test:server": "node ./tests/server/server.js"
}

Next, add a new folder in the tests folder for our server. Let’s call it server

Let’s repeat the process that we did with the files and folders for the tests — just copy them from the ready-made project https://github.com/denisoed/setup-cypress-vue.

tests
  server
    data
      - users.js
    config.js
    server.js
  • server.js file —the main file for starting the server
  • config.js file— server options
  • data folder — stores files with test data that will be returned by the json server

I will now briefly tell you how to mock API requests.
Suppose your application requests a list of users from the backend.
For example, the URL is https://backend.com/users

First of all, go to the server.js file and turn to the block below

// ---- Сustom routes ---- \\
server.get('/users', (req, res) => {
  res.jsonp(users);
});

In it, you can see that if you request something using the /users URL, it will return the data from the users variable. I think it’s clear. If your application makes requests for some more URLs, just copy the block above and change it as needed.
I have prepared the data in advance, too; you can find them in the data folder. They look like this

module.exports = [
  {
    name: 'Bob',
    age: 32
  },
  {
    name: 'Alice',
    age: 19
  }
];

We’ve changed the URL and prepared the data. This is enough to mock the API. This way, we can mock all requests by describing different cases in tests.

Let’s summarize.
When your application makes a request to the backend, our mock server will intercept it and return the data we need. Simple as that!

“But how will it intercept requests?” you may ask. There’s nothing complicated about that either. 
Usually, projects create an .env file that is to store variables. That’s where they store the link to the API backend server. If you change this link, your application will rely on it. That’s what we will do.

You need to create an .env file in the project root or replace a variable in it if the file already exists. From https://backend.com to localhost:8888

VUE_APP_API_URL=http://localhost:8888

localhost:8888 is the address of our mock server. You can change the port in the config.js file if this one is already taken.

Let’s try to start the server by running the command

npm run test:server

If there are no errors, we will see this result

> node ./tests/server/server.js
JSON Server is running on port: 8888

The mock server for tests has been successfully established.

And to finish this part of the article, I would like to repeat the basic idea.
When we test our application, all requests that were previously routed to the real API server will be intercepted by our mock server. And we won’t have to worry about the backend not working, or no Internet, or anything else.
Your tests will be independent — and that’s very important.

Running tests in Docker

All you need to do is install Docker and Docker Compose.

Let’s start copying the necessary files. Following the same pattern, we will take them from a ready-made project https://github.com/denisoed/setup-cypress-vue.
We need three files: cy-open.yml, docker-compose.e2e.yml, Dockerfile.e2e
They should be placed in the project root.

  • Dockerfile.e2e — will install everything you need for the container to run tests in.
  • docker-compose.e2e.yml— settings for the container.
  • cy-open.yml — this file is to launch the browser from Docker.

Update the package.json file

"scripts": {
    "test:e2e": "npm run test:server & vue-cli-service test:e2e --mode test",
    "test:server": "node ./tests/server/server.js",
    "docker:test:e2e": "docker-compose -f docker-compose.e2e.yml -f cy-open.yml up --exit-code-from cypress"
}

On startup, you may get an error like this

cypress_1  | ----------
cypress_1  | 
cypress_1  | No protocol specified
cypress_1  | [101:0208/050449.746174:ERROR:browser_main_loop.cc(1434)] Unable to open X display.
cypress_1  | The futex facility returned an unexpected error code.
cypress_1  | No protocol specified
cypress_1  | [115:0208/050450.882329:ERROR:browser_main_loop.cc(1434)] Unable to open X display.
cypress_1  | 
cypress_1  | undefined:0
cypress_1  | 
cypress_1  | 
cypress_1  | illegal access
cypress_1  | (Use `Cypress --trace-uncaught ...` to show where the exception was thrown)
cypress_1  | 
cypress_1  | ----------

To solve it, run this command in the console

xhost +si:localuser:root

The result should be

localuser:root being added to access control list

The launch should be successful after this

npm run docker:test:e2e

Docker will start installing and unpacking packages; it will usually take 2 to 5 minutes. After that, it will run a container with tests and a container to launch the browser. It will launch the browser.
That’s it. All you have to do now is to write tests and enjoy the fact that the project is a little more stable, so your sleep is stronger.

Image.

Conclusion

Everything I wrote above is just a setup, preparation for a project. Next, you will spend hours searching for information on how to write tests correctly, mock data, mock plugins, etc. There’s so much out there, it’s crazy.

But what’s still the most important thing in achieving any goal? Of course, it’s continuous progress. Now, you have a manual at your fingertips on where to start to not only stabilize the project but also improve your professional skills.

Stay alert!

Mad Devs IT Services.
A Bit About Event Delegation in React.

A Bit About Event Delegation in React

In this article, we will consider event delegation and what it is for. How it can help you in understanding the mechanisms of the framework, and...

Introduction to the World of Application Design.

Software Architecture 101 – Introduction to the World of Application Design

Hello, everyone!Today, I would like to introduce you to the world of application design.Designing applications can be called a multidisciplinary...

Glitch.com + Node.js App.

Meet Glitch.com 🥳 🤟🏻

My story of interacting with Glitch.com began not so long ago, but in this short time, I really love this coolly invented service. 🥰 So, in this...