End-to-End testing React & Vue SPAs with TestCafé
Unit tests are a great asset to help ensure the quality of your application. But by nature, they only test small isolated pieces of your application and they mock important parts like API and database calls. This makes the tests very quick to execute, but it doesn’t guarantee that your application works when all the pieces are put together. End-to-End testing (E2E) plugs this gap. It is used to test that your application works when used by a real user, for example, you might have an E2E test for the entire flow of a user logging into your site, adding an item to a shopping cart and then completing the order.
TestCafe makes it easy to test in multiple browsers, run on various CI systems, debug, take screenshots, and even run on a mobile device! I have enjoyed using it for some time now to test React and Vue.js single page applications.
First install it via yarn (or npm if you prefer)
yarn add -D testcafe
Then add it to your scripts section
"test:e2e:all": "testcafe chrome ./fixtures/*.test.ts"
In this example I am telling it to find all the tests in the
fixtures folder and then run them in Chrome. You will notice that I am searching for tests written in TypeScript, change the extension to
Writing a Test
await something and trying to perform actions on
Promise<SomeType> when you thought it was actually
SomeType. TestCafe will automatically compile the TypeScript files without any extra configuration and it also includes the TypeScript declarations so you get full documentation in your IDE.
The above gist contains one test fixture which contains 3 basic tests to check that the home page of a Vue.js site is working correctly. The key part to any test is using the Selector API to find elements on the page. The code
Selector(".home__review-container")finds all elements on a page that match the specified CSS selector and works a lot like the jQuery selector API. Hopefully the tests are self explanatory, if not, then you can read more about the basics on the TestCafe getting started page.
The golden rule: Red, Green, Refactor
The Test Driven Development Red/Green/Refactor cycle equally applies to End-to-End testing in TestCafe.
Create a test and make it fail
Most of the TestCafe API is asynchronous and returns promise objects, so it is important to ensure that these promises actually complete. TestCafe is pretty good at throwing an error if you have missed an
await keyword in your code. But I have had tests pass before when I failed to wait on an asynchronous assertion. So it is very important to make sure that your test initially fails to ensure that you are testing what you think you are.
Make the test pass by any means necessary
Figure out all the selectors you need in your test and get it to pass.
Change the code to remove duplication in your project and to improve the design while ensuring that all tests still pass
After writing a few tests you will see that you are using the same selectors in multiple places as well performing common actions on them e.g. clicking a button or typing some text into a text input. Since selectors commonly rely on IDs or class names, they can be quite brittle as the page develops, so it’s important to encapsulate these. TestCafe recommends using the Page Model pattern to represent items on pages.
The following example shows how the earlier example tests can be refactored into using the Page Model:
Two classes have been created (these would normally be in their own file). The
Page class is used to represent the site’s home page and it includes a function to get all of the reviews on the page. There is also a
ReviewCard class to represent the review card component, it has a function to get the reviews numeric rating as well as another function to perform the click action on the component. You can see that the actual tests have been simplified and are easier to read. If you can build up a good page model then you can get testers with limited programming backgrounds to help write tests.
Relying on CSS
All of your E2E tests rely on being able to reliably find elements on the page using CSS selectors. You shouldn’t run into any issues if you are writing your CSS using a convention such as BEM, but you may struggle to reliably find elements if you are using CSS Modules, Styled Components, inline styles, random legacy system spaghetti, etc. A solution might be for your React/Vue.js components to include custom
data- attributes to help identify them.
Start small and build from there
I would recommend starting small with a couple of tests for your most critical happy day scenarios. This will give you a good chance to familiarise yourself with TestCafe and find out what works well for you. Keep your initial page models small and limited to what you actually require, don’t go down the rabbit hole of adding everything on the actual page into your model.
I have found that even having just a few of these scenarios coded provides a lot of benefit and removes the tedious nature of doing a cross-browser sanity check after each deployment into a test environment.
Once you’re feeling comfortable you can start checking more advanced things like comparing screenshots, checking field validation and other errors. But it’s always important to question if your new E2E tests are providing actual value and not testing things that may already be sufficiently covered in unit tests.