to navigateEnterto select Escto close

    Organizing and maintaining Cypress tests

    1. Avoid adding empty line after each statement

    Avoid adding empty line after each command. There should be logical separation between the code statements.

    2. Avoid writing comments

    Avoid writing comments in the code unless it is really needed. The code should be self explanatory.

    3. Importing external files before internal files

    Always keep import statements for external libraries before importing internal files.


    1import faker from "faker";
    3import {
    4  navSelectors,
    5  headerSelectors,
    6} from "../../constants/selectors/common";
    7import { groupsSelectors } from "../../constants/selectors/groups";
    8import { groupIndexTexts } from "../../constants/texts/groups";

    4. Avoiding Repetitive Code

    There are different ways we can avoid repetitive code. Consider using following ways to avoid repetitive code:

    • Custom commands

    e.g. cy.login() for most of the application's functionalities login is first step

    • Utility functions
    • Loops (If same assertion logic is used for multiple elements)

    5. Maintaining paths

    We can create a separate file for storing all the routes and import them whenever required. For storing them, we can create routes.js file under constants folder. Remember these will be variables or functions and not an object. Please refer the below example:

    3export const newSignupPath = "/signups/new";
    4export const signupOtpPath = "/api/v1/signups/otp_generation";
    5export const loginPath = "/login";

    6. Add files which we don't want to commit or track in .gitignore

    We would want to ignore some files that are created along with time or during the installation of cypress like node_modules, videos, screenshots etc. These files are important but can be ignored while committing our changes into the repository. Such files can be added in .gitignore.

    7. Use webpack aliases

    webpack.config.js file, which describes how the cypress files and assets should be transformed and what kind of output should be generated.

    1// Incorrect
    2import { agentsSelectors } from "../../constants/selectors/agents.js"
    3import { agentsTexts } from "../../constants/texts/agents.js"
    6import { agentsSelectors } from "Selectors/agents.js"
    7import { agentsTexts } from "Texts/agents.js"

    8. Importing fakers from fixtures

    Often we need to use some random data to perform integration testing. And there comes a npm package,faker which helps us to generate random data very easily. Instead of directly importing faker into the test file, we can create a fake.js file in fixtures folder and import the fake data in our tests.

    2import faker from "faker";
    3const fake = {};
    5const streetAddress = () => faker.address.streetAddress();
    6const url = () => faker.internet.url;
    7const city = () =>;
    9Object.defineProperty(fake, "streetAddress", { get: streetAddress });
    10Object.defineProperty(fake, "url", { get: url });
    11Object.defineProperty(fake, "city", { get: city });
    13export default fake;
    1// integration/test.spec.js
    2import fake from "Fixtures/fake"
    4describe("Create new tags", ()=>{
    5  it("should be able to create new tags", () => {
    6    const url = fake.url;
    7    const streetAddress = fake.streetAddress;
    8    const city =;
    10    cy.contains("tagSelectors.cityName", city).should("exist");
    11    cy.contains("tagSelectors.streetName", streetAddress).should("exist");
    12    cy.contains("tagSelectors.urlInputField", url).should("exist");
    13  });

    9. Use within() for narrowing the scope of cypress

    Whenever multiple elements with same selector is present, we can select the desired element using within() to narrow the scope. e.g. Let's say, there is table of canned responses list. Each row has an edit, and delete button. So, to select one of them, we first need to get the element with name and then use within() to narrow down the scope. Each row contains only one edit button, so the correct edit button is selected.

    ![] (

    1cy.contains(cannedResponseSelectors.tableRow, cannedResponseName)
    2  .within(() => {
    3    cy.get(cannedResponseSelectors.editButton).click();
    4  });