javascriptcypressdata-driven-testsparametrized-testing

Solution for parameterized testing in Cypress


I'm trying to merge bunch of tests that have same actions and checks using parametrized testing, but keep getting errors. I'm new to Cypress and JS in general, coming from .net background. Any help would be appreciated.

My fixture looks something like this:

{
  "username": "username",
  "password": "password",
  "inputErrorMessageText": "Invalid username or password.",
  "homePageWelcomeText": "Welcome, bla bla bla",
  "testCases": [
    {
      "description": "blank username and password",
      "username": "",
      "password": ""
    },
    {
      "description": "blank password",
      "username": "username",
      "password": ""
    }
  ]
}

I've tried both Cypress.each and data.testCases.forEach:

describe("Tests for login page", () => {
    let loginPage;
    let homePage;
    let data;

    before(() => {
        cy.fixture("login_data").then((fixtureData) => {
            data = fixtureData;
            cy.wrap(fixtureData).should("have.property", "testCases");
        });
    });

    beforeEach(() => {
        loginPage = new LoginPage();
        homePage = new HomePage();
        cy.visit("/");
    });

    Cypress.each(data.testCases, (testCase) => {
        it(`Invalid username or password error appears when attempting login with ${testCase.description}`, () => {
            loginPage.login(testCase.username, testCase.password);
            loginPage.verifyErrorMessage(data.inputErrorMessageText);
        });
    });

    it("Successful login with valid username and password", () => {
        loginPage.login(data.username, data.password);
        homePage.verifyProfileDropDownExists();
    });

    it("Welcome text is displayed after successful log in", () => {
        loginPage.login(data.username, data.password);
        homePage.verifyWelcomeText(data.homePageWelcomeText);
    });
data.testCases.forEach((testCase) => {
    it(`Invalid username or password error appears when attempting login with ${testCase.description}`, function () {
        loginPage.login(testCase.username, testCase.password);
        loginPage.verifyErrorMessage(data.inputErrorMessageText);
    });
});

Keep getting the following error:

TypeError: The following error originated from your test code, not from Cypress. > Cannot read properties of undefined (reading 'testCases')


Solution

  • Issues

    1. (This is the main culprit) Directly using data.testCases.forEach() is not working, as Cypress (Mocha, but splitting hairs here) needs to know what tests to run before the tests actually start running. In this case, since data.testCases won't have a value when Cypress starts gathering the tests to run (as the data is set in the before() block), it's running into an error when data.testCases is undefined.
    2. I don't think Cypress.each is a function. There is Cypress._.each() (using Cypress Lodash) and cy.each() (which isn't what you want here).

    Solution

    Import the fixture directly, instead of loading it via cy.fixture(), which should grant you access to the data.testCases variable prior to Cypress discovering what tests to run. Then you should be able to have multiple tests run, either via data.testCases.forEach() or Cypress._.each().

    import data from '../path/to/data.json';
    
    describe("Tests for login page", () => {
      ...
      Cypress._.each(data.testCases, (testCase) => {
        it(`Invalid username or password error appears when attempting login with ${testCase.description}`, () => {
                loginPage.login(testCase.username, testCase.password);
                loginPage.verifyErrorMessage(data.inputErrorMessageText);
            });
      });
    });
    

    You can still run your data validation that data has property of testCases, without the cy.fixture().