Getting started with Cypress
Tags: sqa, automation, cypress
Published: 2024-02-09 12:10:19

Cypress is a popular automation framework and unlike selenium cypress does not require a web driver. It is built on top of node.js and compatible with both JavaScript and TypeScript.

**_Prerequisites_**: 
 
-  As mentioned earlier it is built on top of node.js so it requires node.js as a Javascript run time environment. Having the latest version is recommended.

-  Any IDE of our choice is fine as long as it supports javaScripts or typeScripts. Visual Studio Code is a popular one. I personally like WebStorm, you can also try out Atom and Intelij Idea.

**_Installation Process:_**
Cypress can be installed with the node package manager(npm). we can install Cypress with this simple command
```bash
npm cypress install 
```
However, it is recommended to use the command below since we want to add this as a dev dependency.

```bash
npm install cypress --save-dev
```
Specifying Cypress as a dev dependency allows us to specify the exact version of Cypress we are using. This also ensures consistency across different development environments and makes it easier to reproduce issues or run tests on different machines.

**_Know Your Files_**:

Now that we are done with the installation we can start writing tests using cypress but first, let's get familiar with the files and folders.

- Cypress/Fixtures: Fixtures are used to store commonly used test data in JSON format

- Support/CustomCommand.js: This file helps in creating custom commands or global overrides that will be

- package.json: It holds information about the project, dependencies, etc. This file also holds "scripts" metadata. These scripts can be called using "npm run ". These are various commands that can be run via terminals.

- cypress.config.js: This holds various cypress-related configurations like URL, admin username, password, timeouts, etc where behavior cypress can be modified.

- Screenshots: This folder stores the screenshots that were generated while the automation script was running.
- Videos: This folder stores the video of the runtime so it is easier to trace defects.

These files and folders automatically generate when we install Cypress along with some other files.

Additionally, you would like to create some other folders and files as well.

- Cypress/TestSuites: The TestSuites folder includes all the test files. The test files are written as ".js" or ".ts".

- Cypress/Reusables: this folder contains methods that can be commonly used throughout our tests

- Cypress/Support/API: The API folder contains some commonly used API-related methods, API methods related to specific modules, and a file containing methods for API calls in general

- CustomCommand.js: This file helps in creating custom commands or global overrides that will be available for all other classes and functions

- Cypress/PageObjects: The PageObjects folder contains classes that help separate page-specific functions.

- Cypress/Wiring: The wiring folder contains locators and getter functions of the locators that are used in PageObjects helper functions.

_**Project Layout:**_

```
cypress/
├── fixtures/
│   └── data.json
├── support/
│   ├── commands/
│   │   ├─ API 
│   ├── pageObjects/
│   │   ├── Page1/
│   │   │   └── Page1Objects.js
│   │   ├── Page2/
│   │   │   └── Page2Objects.js
│   ├── wiring/
│   │   ├── Reusables/
│   │   │   └── Reusable.js
│   │   ├── Page1/
│   │   │   └── Page1Functions.js
│   │   ├── Page2/
│   │   │   └── Page2Functions.js
├── tests/
│   ├── verifyWorkflow.js
├── support/
│   ├── customCommands.js
└── screenshots/
└── videos/

```
**_Test Case_**:

Now inside the testSuites folder, we can create a new file with .js or .ts extension this file will be considered a test file. Inside a test file, we need to have at least a "describe" block and a "it" block. The "describe" block is used for grouping related test cases whereas the "it" block represents a single end-to-end test. There are also some hooks available in Cypress such as "before", "beforeEach", "after", and "afterEach" These hooks can be utilized for setting up and cleaning up the test data as well as for prerequisites for the test cases. 

Cypress utilizes Mocha, a popular testing framework, for structuring tests. Mocha provides a flexible and intuitive syntax for organizing test suites and cases, enhancing test readability. Additionally, Cypress utilizes Chai, an assertion library, for writing clear and expressive assertions within tests. Chai offers a wide range of assertion styles, including should, expect, and assert, enabling developers to choose the syntax that best fits their testing preferences. Together, Mocha and Chai help in creating comprehensive and readable test suites, which helps a great deal in terms of facilitating effective testing and ensuring the robustness of web applications built with Cypress. This is what a typical test file would look like:

```js
// login.spec.js

// Describe block to group related test cases
describe('Login Page', () => {
  // before block to run once before any test cases
  before(() => {
    // Perform any setup tasks before any test cases
    // This can include starting the application server or preparing test data
  });

  // beforeEach block to run before each test case
  beforeEach(() => {
    // Visit the login page
    cy.visit('/login');
  });

  // Test case to verify successful login
  it('should allow user to log in with valid credentials', () => {
    // Enter username and password
    cy.get('input[name="username"]').type('your_username');
    cy.get('input[name="password"]').type('your_password');

    // Click the login button
    cy.get('button[type="submit"]').click();

    // Assertion to verify successful login
    cy.url().should('include', '/dashboard');
    cy.contains('Welcome').should('be.visible');
  });

  // Test case to verify error message with invalid credentials
  it('should display error message with invalid credentials', () => {
    // Enter invalid username and password
    cy.get('input[name="username"]').type('invalid_username');
    cy.get('input[name="password"]').type('invalid_password');

    // Click the login button
    cy.get('button[type="submit"]').click();

    // Assertion to verify error message
    cy.contains('Invalid username or password').should('be.visible');
  });
  // afterEach block to run after each test case
  afterEach(() => {
    // Clear any logged-in state or cookies
    // This ensures a clean state before each test case
    cy.clearCookies();
    cy.clearLocalStorage();
  });

  // after block to run after all test cases
  after(() => {
    // Perform any cleanup tasks after all test cases
    // This can be useful for resetting the application or cleaning up resources
  });
});

```
Thank you for taking the time to read this. I hope you found it informative and enjoyable. If you have any questions, comments, or feedback, please don't hesitate to reach out.