DEV Community

Cover image for Guide to Integrating Cypress and Cucumber with Angular
Alimur Razi Rana
Alimur Razi Rana

Posted on

Guide to Integrating Cypress and Cucumber with Angular

In software engineering, despite developers' confidence in their code, comprehensive testing is indispensable for determining its efficacy. Developers and QA engineers must navigate through diverse testing phases to ascertain the comprehensive functionality of their applications. Two widely embraced methodologies for this purpose, are End-to-End (E2E) testing and Behavior-Driven Development (BDD) testing.

While Cypress and Cucumber are favored tools for such testing, integrating them poses challenges due to their differing configurations. If developers try to work with typescript, it creates one extra configuration layer. Cypress’s configuration changed a lot from their pre-10 version. So maybe this blog can help others when they need to work later.

Numerous tutorials and blogs cover the importance and procedures of E2E testing or BDD testing. However, This article focuses specifically on integration procedures for these testing methodologies.

Now it's time to make our hands dirty. Cypress and cucumber will be integrated into an angular project which by default maintains typescript. So ensure that you have already installed Node.js, npm, and ng package in your work environment.

  • Create a new angular project. ng new angular-cypress-cucumber
  • E2E testing needs your project running, so you need to run this angular project by npm start
  • Install @cypress/schematic package, this will help the angular project to run with Cypress. ng add @cypress/schematic

During installation, @cypress/schematic automatically includes necessary npm packages. Additionally, it generates a Cypress configuration file, "cypress.config.ts" and adjusts the "angular.json" configuration file accordingly. Furthermore, it establishes a dedicated "cypress" sub-directory, including sample test files to help the developer get started.

We will execute test cases on a user list page. On this basic listing page, we can envision below scenarios:

  • Initially, the page will display no users.
  • Following the click of the "Get Users" button, an API call will be triggered. If the API returns a valid response, the list will appear.
  • In case of an error returned by the API, the page will remain unchanged.

Now it is time for BDD
npm i @badeball/cypress-cucumber-preprocessor @cypress/webpack-preprocessor -d

Replace the whole cypress.config.ts with below configuration content

import { defineConfig } from 'cypress';
const webpack = require("@cypress/webpack-preprocessor");
const preprocessor = require("@badeball/cypress-cucumber-preprocessor");

async function setupNodeEvents(on, config) {
  await preprocessor.addCucumberPreprocessorPlugin(on, config);
  on(
    "file:preprocessor",
    webpack({
      webpackOptions: {
        resolve: {
          extensions: [".ts", ".js"],
        },
        module: {
          rules: [
            {
              test: /\.feature$/,
              use: [
                {
                  loader: "@badeball/cypress-cucumber-preprocessor/webpack",
                  options: config,
                },
              ],
            },
          ],
        },
      },
    })
  );
  return config;
}

export default defineConfig({
  e2e: {
    'baseUrl': 'http://localhost:4200', // this will be the default page for e2e testing
    specPattern: ["**/e2e/**/*.feature"], // all e2e test file’s name should be in this pattern
    setupNodeEvents
  },
  component: {
    devServer: {
      framework: 'angular',
      bundler: 'webpack',
    },
    specPattern: '**/*.cy.ts'
  }
})
Enter fullscreen mode Exit fullscreen mode

The configuration file facilitates the preprocessing of Cucumber-generated test cases, preparing them for execution by Cypress. Furthermore, it adjusts the spec locations, allowing Cypress to discover .feature files for test execution. These feature files encapsulate BDD test cases written in the Gherkin syntax.

In the package.json file add this new property too

"cypress-cucumber-preprocessor": {
    "stepDefinitions": "cypress/e2e/bdd-cucumber/step-defination/*.step.cy.ts"
},
Enter fullscreen mode Exit fullscreen mode

Within the existing cypress/e2e directory, create a new folder named bdd-cucumber and create another folder inside bdd-cucumber named features. Navigate to the cypress\e2e\bdd-cucumber\features directory and create a new file named user-page.feature. As previously noted, Cucumber or BDD operates with the Gherkin language. The features within this folder will adhere to its syntax.

user-page.feature

Feature: User List functionality
  Background: Prepare user page
    Given I am on the user page

  Scenario: Users appear in UI when API call succeeds
    When I click the "Get Users" button
    Then A api call will be requested with valid response
    And user list will be appear on successful api request

  Scenario: Users do not appear in UI when API call fails
    When I click the "Get Users" button to check failed response
    Then A api call will be requested with failed response
    And User list will not appear on failed api request
Enter fullscreen mode Exit fullscreen mode

You can also install highlight-cucumber vscode extension to colorize those features.

In the bdd-cucumber folder create another folder named step-defination . Cypress test files will be added to this folder.

user-page.step.cy.ts

import {
  Given,
  When,
  Then,
} from '@badeball/cypress-cucumber-preprocessor';

const apiUrl = 'https://jsonplaceholder.typicode.com/users';

Given('I am on the user page', () => {
  cy.visit('/');
});

When('I click the "Get Users" button', () => {
  cy.intercept('GET', apiUrl).as('getUserList');
  cy.contains('Get User').click();
});

Then('A api call will be requested with valid response', () => {
  cy.wait('@getUserList').then((interception) => {
    expect(interception.request.url).to.eq(apiUrl);
    expect(interception.response?.statusCode).to.eq(200);
  });
});

Then('user list will be appear on successful api request', () => {
  cy.get('span.user-name').its('length').should('be.greaterThan', 0);
});

When('I click the "Get Users" button to check failed response', () => {
  cy.intercept('GET', apiUrl, { forceNetworkError: true }).as('getUserList');
  cy.contains('Get User').click();
});

Then('A api call will be requested with failed response', () => {
  cy.wait('@getUserList').then((interception) => {
    expect(interception.request.url).to.eq(apiUrl);
    expect(interception.error).to.exist;
    expect(interception.error?.message).to.eq('forceNetworkError called');
  });
});

Then('User list will not appear on failed api request', () => {
  cy.get('span.user-name').should('not.exist');
});
Enter fullscreen mode Exit fullscreen mode

As we have already written our test cases, the next step is to implement a user list page. For simplicity, the Angular project comprises solely html and typescript code to retrieve user data via API.

app.component.ts

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

type User = {
  name: string;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})

 export class AppComponent {
  title = 'angular-cypress-cucumber';
  url = "https://jsonplaceholder.typicode.com/users";
  users: User[] = [];
  constructor(private httpClient: HttpClient) {}

  getUsers() {
    this.httpClient.get<User[]>(this.url).subscribe(
      {
        next: (res) => {
          this.users = res;
        },
        error: (err: any) => {
          alert("Something went wrong!");
         },
        complete: () => { }
      }
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

app.component.html

<div>
  <button (click)="getUsers()">Get User</button>
  <ul>
    <li *ngFor="let user of users">
      <span class="user-name">{{user.name}}</span>
    </li>
  </ul>
</div>
Enter fullscreen mode Exit fullscreen mode

Now navigate to the project's directory, and run the command npm run cypress:open. Before that, ensure that the angular project is running in http://localhost:4200 which is declared as the base URL in the cypress configuration.

Github Link

Top comments (0)