Recently I decided I wanted to learn more about end-to-end testing. In the interest of getting hands-on quickly, I chose to add TestCafe to one of my pre-existing projects so I had a featureful app ready to be tested. This project was already using Jest for unit and integration tests. This redundancy was intentional, as I wanted to write TestCafe tests that cover the same cases as my Jest tests for learning purposes.
Since this project already utilizes Jest as a test framework as well as Typescript, I ran into some interesting challenges. Therefore, I thought it might be useful to document how I set up my environment.
This article is written for others who are looking to get set up with TestCafe in a pre-existing React + Typescript + Jest project. This article mainly covers installation, and won’t cover some of the interesting things you can do with TestCafe. That article will come later, now that my environment is ready to go!
1. Install TestCafe
The first step is to of course install TestCafe! This needs to be done both within the project, and globally on your local environment so we can run
testcafe commands in the console.
Run the following command in the terminal to install TestCafe globally:
npm i -g testcafe
Next, we’ll install TestCafe as a dependency for this project. Run the following command within your project’s directory:
npm i testcafe
Great! We’ve installed everything we need to get started.
2. Create end-to-end test file structure
This is how I am structuring this project:
I am going to follow the conventions I established previously with this project and add
.e2e.tsx files in all my component directories, but you can set up your test file structure how you see fit. Another common convention is to have a
test directory that includes all your test files in one location.
3. Update TestCafe configuration in
Whether you include your tests in your component directories or put them in a separate
test directory, you’ll have to make some changes to your TestCafe configuration to specify that only
.e2e.tsx files are run by TestCafe and not our pre-existing Jest
.test.tsx files. Let’s do that now.
First, create a
.testcaferc.json on the top-level of your project directory if one does not exist yet.
Inside, specify the default source for
testcafe commands by writing the following JSON:
This glob format indicates that TestCafe will run all files with the extension
.e2e.tsx in all directories within
src. Notice that this means it will NOT run files with the extension
.spec.tsx for that matter). That’s great since those are our Jest files and we don’t want TestCafe to run those!
4. Write a simple test to get started
Alright, we are now ready to write a test to see TestCafe in action!
For this first test, I created the
Header.e2e.tsx file in my
src/Header directory. I chose this as my first test because it’s testing a very simple React component. Therefore, this is a good place to experiment with some basic tests.
src/Header/Header.e2e.tsx I wrote the following:
This will instantiate a simple test that checks that an element with the ID of
mains exists on the development server page.
5. Fix TestCafe/Jest type collisions
We’re almost done setting up TestCafe in this project, but there is one more oddity when working with both TestCafe and Jest within a Typescript project: type collisions! 🙃
Before I even dive into the issue, let’s follow best practices and do some red-green testing to see the error and find out what breaks.
Let’s start up our development server. In the console, run the following command:
Ok, did it work? Well if you’re following this example and you have both Jest and TestCafe packages in the project, you should get this error:
Failed to compile.TypeScript error in <PATH-TO-OUR-PROJECT>/src/Header/Header.e2e.tsx(15,6):
Property 'expect' does not exist on type 'DoneCallback'. TS2339
Uh oh, our development server failed to compile! So what’s happening here? Well both Jest and TestCafe have global declarations for the typing of the function
test. Jest’s declaration expects a
DoneCallback object as the parameter of the function, while TestCafe’s declaration types the parameter as a
As we can see from the error, when Typescript compiles the global variable for
test, it ends up with the Jest declaration instead of the TestCafe declaration. This means our Jest tests still run as expected without any adjustments, but we can’t run our TestCafe tests!
Hopefully, these packages typing incompatibilities will get sorted with future package updates. But for now, we can simply add a line in our TestCafe tests that declares the type of
declare const test: TestFn;
This declares a variable of
test with the type equal to that of
TestFn is the interface defined within the TestCafe package in
node_modules. This is the exact same declaration that is made within the TestCafe package (that which gets overwritten by Jest).
src/Header/Header.e2e.tsx should look like this:
So, does it all work? Let’s find out!
6. Check compatibility
Ok, let’s run our code in all our environments and make sure everything is still working.
First, let’s start up our development server again:
The app should compile as expected and open in the browser. No more type collisions!
Next, let’s run our Jest tests again to make sure they’re still working:
npm run test
We should see any pre-existing Jest tests evaluate in our console. Great, our
test typing hasn’t broken in Jest. Now, all we need to do is run TestCafe!
7. Run TestCafe tests!
To run the test, first we need to make sure our development server is running. In the console, run the following command:
Now that our server is running on
localhost:3000, we’re ready to run
Make sure you run the following command in a separate terminal window to ensure our development server keeps running in the original terminal window.
This will start up TestCafe in the Chrome browser and run any tests in the default source (which we set above to be any
.e2e.tsx files in any directories within
A new Chrome browser should open and run our test using TestCafe!
Awesome, we did it! We’ve successfully added TestCafe to our React + Typescript + Jest project while maintaining all pre-existing functionality.
There are many reasons you might want both Jest and TestCafe in your project. Whether it’s to confidently boost test coverage, or for your own learning like in my case, these two technologies can work alongside each other within a Typescript project. However, there are a few hurdles to get over having to do with incorrect test files being run, and global typing.
Hopefully, this walkthrough can streamline your environmental setup, as well as teach a little something about the general TestCafe installation process, type collisions, and TestCafe configs.
Thanks for reading!