How to setup Cypress environment with Typescript
Tags: cypress, testing, react, typescript
Published: 2022-02-09 16:31:16

Testing is always the best way to make sure that everything in your application is working as it should (even after fixes or new features). 

_Unit_ tests are so useful, but when it comes to testing a whole flow or bigger functionalities, _end-to-end_ tests are most suitable. In this tutorial, I will help you to setup a Cypress environment with Typescript, create custom commands and use Cypress Testing Library.

### Install

First, you should add cypress to the application you want.

```
yarn add cypress --dev
```
_(or with npm, if you prefer)_

Now, we still need open it for the first time to config. You need to add a new script in your `package.json` and **run** in your terminal. It's very important to run, because it will generate a lot of files in your app.

_root/package.json_
```
"cy:open": "cypress open"
```

This will open the cypress interface and create a _cypress folder_ and _cypress.json file_. As you can see, there are some example tests (_in cypress/integration_) and a lot of default configs. _cypress/integration_ is the folder you can create your tests.  

### Config

#### Typescript

The first thing we need to do is creating a `tsconfig.json` file **inside** the cypress folder and paste this

_cypress/tsconfig.json_
```
{
    "compilerOptions": {
        "target": "ES5",
        "lib": ["es5", "dom"],
        "types": ["cypress"]
    },
    "include": ["**/*.ts"]
}
```

At this time, you should restart your Typescript server. If you're in VSCode just type:
1. ctrl + shift + P
2. restart TS server.

In cypress/support folder, you see _commands.js file_ and _index.js file_. Rename to typescript extension. 

_cypress/support_
```
commands.js -> commands.ts
index.js -> index.ts
```

Create an _index.d.ts file_ in this same folder (cypress/support). This will be important to create custom commands - very useful!. Add this to index.d.ts file:

_cypress/support/index.d.ts_
```
/// <reference types="cypress" />

declare namespace Cypress {
    interface Chainable {

    }
}
```

Now, we have to update root/tsconfig.json by adding "cypress" to exclude.

_root/tsconfig.json_

```
"exclude": ["cypress", "node_modules"]
```

The config is almost done, now, we just have to this to the root/cypress.json

_cypress.json_

```
{
    "video": false,
    "baseUrl": "http://localhost:3000"
}
```

#### Testing Library

Once we configured Typescript, now it's time to add improve our environment. First, we need to add the Cypress Testing Library. It allows us to use commands from testing library.

Just run in your terminal

```
yarn add @testing-library/cypress @types/cypress jest @types/jest -D 
```

After this, is necessary to add these commands to our environment. Add this to the commands.ts file.

_cypress/support/commands.ts_

```
import "@testing-library/cypress/add-commands";
```
 
And add this line to the cypress/tsconfig.json file, so it can identify the library.

cypress/tsconfig.json

```
"types": ["cypress", "@testing-library/cypress"]
```

#### Creating custom commands

This is actually the most cool thing, in my opinion, about Cypress. We can create custom commands like: 

_cy.google() - and then the test visit the google page_
_cy.login() - and then you login in your application_

Literally anything you want. What we always need to do is:
1. Create the command in _cypress/support/commands.ts_
2. Type the command in _cypress/support/index.d.ts_

Sometimes, error may be generated, just restart TS server and everything is ok again.

Let's create our first command: cy.google() will visit google.

_cypress/support/commands.ts_
```
import "@testing-library/cypress/add-commands";

Cypress.Commands.add("google", () => cy.visit("https://www.google.com"));
```

Typing our new command
_cypress/support/index.d.ts_

```
/// <reference types="cypress" />

declare namespace Cypress {
    interface Chainable {
        /**
         * Custom command to visit google page
         * @example cy.google()
         */
        google (): Chainable<Window>
    }
}
```

Now you can use cy.google() in any test you want :)

**Let's create an example test.**

Create an _example.ts_ file in _cypress/integration_ folder.

Since we're using custom commands, we need to reference in **every test file!**

This is my example.ts file:

```
/// <reference path="../support/index.d.ts" />

describe('Cypress TS', () => {
    it('should visit Google', () => {
        cy.google();
    })
}) 
```

You can also add the `cypress run` command to your scripts, this is a way to run cypress tests without open the default item.

#### Extra
**Creating getByDataCy() command**

This command is very useful, since we have to get by data-cy a lot of times in cypress.

_commands.ts_

```
Cypress.Commands.add("getByDataCy", (selector, ...args) => {
  return cy.get(`[data-cy="${selector}"]`, ...args);
});
```

_index.d.ts_

```
/**
* Custom command to get element by data-cy value
* @example cy.getByDataCy('selector')
*/
getByDataCy (selector: string): Chainable<Window>
```

### Conclusion

My goal was helping you to setup your cypress environment, you can search and learn about cypress and all its features later. There are a lot of things to see. 

Thanks for reading :)