Migrate a Cypress Cucumber Project To Use TypeScript

Migrate a Cypress Cucumber Project To Use TypeScript

Sunny Sun Lv4

A step-by-step guide to migrate a Cypress Cucumber project from JavaScript to TypeScript

I started my first Cypress and Cucumber project around two years ago. At that time, Cypress version 3 didn’t have built-in support for TypeScript, so the project was coded with JavaScript instead. That was a costly decision. As the project grew, more tests were added, and more developers worked on it. Code quality deteriorated quickly without the compile-time type checking.

Recently, we successfully migrated the project to TypeScript. I’m happy that Cypress version 8 has good support for TypeScript. (Cypress starts supporting TypeScript from version 4.4.0).

The migration was not difficult, but I did learn a few tricks. I will share what I’ve learned in this article.

Overview

The migration process includes the following four steps:

  • Setup TypeScript
  • Update Cypress Cucumber preprocessor configuration to support TypeScript
  • Add type definition file for custom command and Convert the Cypress command.js to TypeScript
  • Change the js file to ts files

Completing the above steps isn’t the end of the story. To fully utilize the benefits of TypeScript, we need to write the commands and tests with types in mind.

Let’s go through the steps one by one. We will also discuss how to “think in types.”

Setup TypeScript

Firstly, we need to install TypeScript into the project:

1
npm install --save-dev typescript

The next step is to add the tsconfig.json file with the following settings:

Since Cypress version 4.4.0, it’s shipped with TypeScript types. In the above configuration, the "types" will tell the TypeScript compiler to include type definitions from Cypress.

Update Cypress Cucumber Processor Configuration to Support TypeScript

In the project, we use Cypress with Cucumber , a Behavior Driven Development (BDD) tool. It allows us to write more readable tests with Gherkin syntax.

To integrate them, a Cypress plugin [cypress-cucumber-processor](https://github.com/TheBrainFamily/cypress-cucumber-preprocessor) is installed. The plugin provides support for converting feature files to Cypress tests.

Before the migration, the plugin is wired with Cypress as a file preprocessor.

1
2
3
const cucumber = require('cypress-cucumber-preprocessor').defaultmodule.exports = (on, config) => {  
on('file:preprocessor', cucumber())
}

To migrate to TypeScript, we need to make some changes in the cypress/plugins/index.js file:

The above changes allow the preprocessor to transpile cucumber feature files to TypeScript. The default Cypress preprocessor is webpack preprocessor . We chose to use browserify preprocessor here, as I found it’s easier to configure than webpack.

Add Custom Command Type Definition File

We need to add a type definition file for custom commands. The definition file can be added at _support/index.d.ts_ . Then, we can declare custom commands in the file.

1
2
3
4
5
6
declare namespace Cypress {  
interface Chainable<Subject> {
validateUser(userName: string): Chainable<boolean>;
// Other commands
}
}

Please note that we add custom commands to the global Chainable interface. The command returns an Chainable object as well. Chainable to Cypress is like Promise to JavaScript.

If you already have the command at _support/commands.js_ , rename it to _support/commands.ts._ You should update the types of arguments and return the types of the commands.

1
2
3
4
5
6
Cypress.Commands.add(  
"validateUser",
(userName: string): Cypress.Chainable<boolean> => {
....
}
);

Change the JavaScript test files to the TypeScript file

This step renames the file extension from js to ts.

Due to our project’s many test files, I wrote a batch file to do a recursive renaming within the integration folder. The gist of the script is the following:

1
2
3
4
for f in integration/**/*.js  
do
mv "$f" "${f%.js}.ts"
done

Thinking in Types

TypeScript is all about types. The main benefit of TypeScript is type safety. During the migration, the most time-consuming part is correcting the errors popping up everywhere after TypeScript is enabled. Those errors aren’t detected in JavaScript, leading to incorrect or false-positive test behavior. Fixing them is the immediate reward for migration.

Migration to TypeScript doesn’t mean we gain the benefits automatically. The old issues will remain if we still write the test like we used to. A common mistake is using any everywhere. Using any may give you a quick fix, but it hides the potential error at compile time.

Another simple “using type” example is to define the type for test environments. In our project, we have three test environments: dev, test and uat. The environment variable was hardcoded and spread through many test files.

We can use the union type below:

1
2
3
export type Environment: 'dev' | 'test' | 'uat';  
// apply the type to function
export function setServiceEnv(env: Environment) {...}

With the simple Environment type, any invalid parameter usage will be caught at compile time. We also got nice IntelliSense support in VSCode.

It will take some practice to utilize strong typing properly. But once you get it, you will love it and never want to return to the old ways again!

To learn more about tips for TypeScript types, please read this article.

Summary

The TypeScript migration for our Cypress project is a success. Not only does the type checking improve code quality, but it also makes coding easier, as developers can take advantage of auto-completion in VS Code.

If you are still coding Cypress tests with JavaScript, it is time to move to TypeScript!

  • Title: Migrate a Cypress Cucumber Project To Use TypeScript
  • Author: Sunny Sun
  • Created at : 2021-11-09 00:00:00
  • Updated at : 2024-08-16 19:46:17
  • Link: http://coffeethinkcode.com/2021/11/09/migrate-cypress-cucumber-project-to-thypescirpt/
  • License: This work is licensed under CC BY-NC-SA 4.0.