How to write Cypress.io end-to-end tests in TypeScript is a question that comes up again and again. Here is what you need to do step by step if you are using WebPack already. If you don't want to follow steps, just use bahmutov/add-typescript-to-cypress module.
You can find the source code for this post in bahmutov/use-typescript-with-cypress repo.
Install Cypress
If you haven't already, install Cypress
1 | npm install --save-dev cypress |
Open Cypress for the first time - it will scaffold cypress
folder with examples. We don't need it and can delete it. I will replace it with a single JavaScript spec file.
1 | it('loads examples', () => { |
Cypress runs the test and it passes
There is no IntelliSense yet. The global variable cy
has type any
according to VSCode.
If we add @ts-check
comment, VSCode is complaining about unknown variable cy
.
1 | // @ts-check |
Fix IntelliSense and ts-check
Ok, if you want IntelliSense and ts-check
to work - just add a single comment with reference types at the top of the JavaScript spec file, see Cypress docs.
1 | /// <reference types="cypress" /> |
That's it. Nothing else is necessary. You now have IntelliSense and ts-check
working.
TypeScript Spec
Let's switch from JavaScript to TypeScript. Rename spec.js
to spec.ts
and start using types. We don't need the reference comment or @ts-check
directive.
1 | type Url = string |
Hmm, Cypress cannot bundle the spec file.
VSCode cannot find global variable cy
anymore.
Let's fix this. We will need Webpack and Cypress Webpack preprocessor.
Transpile TypeScript using Webpack
To transpile TS code I will use Webpack. I am following the Webpack TypeScript guide exactly as written.
1. install tools
1 | npm install --save-dev webpack typescript ts-loader |
2. copy tsconfig.json
example
I will copy the tsconfig.json
exactly as is from the Webpack TypeScript guide and save it locally.
1 | { |
Then I will add a single types
entry to load global cypress
variables.
1 | { |
I have IntelliSense and types working in VSCode again.
3. copy webpack.config.js
example
We need webpack.config.js
too - and again I am copying the example from the Webpack TypeScript guide as is.
1 | const path = require('path') |
For Cypress transpile, the entry
and the output
fields do not matter, since each spec file will have its own. But the ts-loader
and resolve
rules are important. Now we need to configure Cypress to transpile spec files using Webpack, and not its built-in Browserify.
Cypress Webpack preprocessor
We need to install cypress-webpack-preprocessor and point it at webpack.config.js
. I am copying everything exactly as its README shows.
1 | npm install --save-dev @cypress/webpack-preprocessor |
Because we have already configured Webpack and ts-loader
, no other dependencies are necessary.
Now copy the options snippet from the README to cypress/plugins/index.js
to configure Webpack as a preprocessor
1 | const webpack = require('@cypress/webpack-preprocessor') |
Start Cypress again and the TypeScript specs will be transpiled.
Additional features
If we try to use ES6 features in our specs, VSCode will show an error, and Cypress test will not be transpiled.
1 | it('handles ES6 features', () => { |
Go to tsconfig.json
and change target
property from "es5" to "es6".
1 | { |
Now everything will work again and we can test how an ES6 proxy can intercept and redirect calls.
1 | it('handles ES6 features', () => { |
IntelliSense with custom commands or assertions
If you extend the cy
global object with custom commands, you also need to add their type definitions. See section Cypress IntelliSense in cypress-example-todomvc
for example.
If you write custom assertions to extend should(...)
chainers, you can also provide type definitions for them, see recipe Adding Chai Assertions.