Stiño
Stiño

Reputation: 2853

How to run the same test with different fixtures in Cypress?

I'm trying to run the exact same Cypress test for a component displayed on two separate pages. To achieve this I thought I'd use a forEach statement so that that same code runs for each "state" (see code below).

The problem is that the code block in the before statement starts running for state #2, before the tests for state #1 have finished. This results in the tests for state #1 failing (because it has state #2 fixtures).

How can I make the before part for state #2 wait for all tests in state #1 to be finished?

const states = [
  { 
    "startPath": "/path1", 
    "fixture": "fixture1"
  },
  { 
    "startPath": "/path2", 
    "fixture": "fixture2"
  }
]

describe('Start test', function() {

  // Loop through both test
  states.forEach((state) => {

    // In this before statement the fixtures are setup
    before(function () {
      cy.flushDB()
      cy.fixture(state.fixture)
        .then(fixtureData => {
          new Cypress.Promise((resolve, reject) => 
            cy.createCollections(fixtureData, resolve, reject)
          )
        })
        .then(() => cy.visit(state.startPath)) 
    })
    
    context('Within this context', function() {
      it(`Can run some test for fixture ${state.fixture}`, function() {
        
      })
    })
  })
})

Upvotes: 5

Views: 9315

Answers (4)

Tripti Mittal
Tripti Mittal

Reputation: 71

Works for me perfectly in single fixture JSON with multiple data and not stub API

before describe('Test Single Input Field Form', function() declare :

const testData = require("../../fixtures/multipleInputFields.json")

and then

testData.forEach((data) => {
  const message = data.message
  it("Test Case", function () {
    cy.log("data is:" + data)
    cy.get("#user-message").type(message).should("have.value", message)
    cy.get("#get-input > button").click()
    cy.wait(200)
    cy.get("span#display").should("have.text", message)
  })
})

Upvotes: 0

Stiño
Stiño

Reputation: 2853

Found a solution: I had to wrap it into another describe code block and then it worked:

const states = [
  { 
    "startPath": "/path1", 
    "fixture": "fixture1",
    "context": "1"
  },
  { 
    "startPath": "/path2", 
    "fixture": "fixture2",
    "context": "2"
  }
]

describe('Start test', function() {

  // Loop through both test
  states.forEach((state) => {

    // SOLUTION HERE
    describe(state.context, () => {
  
      // In this before statement the fixtures are setup
      before(function () {
        cy.flushDB()
        cy.fixture(state.fixture)
          .then(fixtureData => {
            new Cypress.Promise((resolve, reject) => 
              cy.createCollections(fixtureData, resolve, reject)
            )
          })
          .then(() => cy.visit(state.startPath)) 
      })
      
      context('Within this context', function() {
        it(`Can run some test for fixture ${state.fixture}`, function() {
          
        })
      })
    })
  })
})

Upvotes: 6

coltdorsey
coltdorsey

Reputation: 91

A third approach can loop a given fixture's data set against one test. Each data set within the fixture will register as its own test.

integration/example_spec.js

const examples = require('../../fixtures/examples');
// `examples` contains the full contents of the fixture

describe('Using `require`', function () {
    examples.forEach((example) => {
        it('gets its data from a fixture', function () {
            // Do something with each example
        });
    });
});

fixtures/examples.json

[
    {
        "name": "Iteration 1"
    },
    {
        "name": "Iteration 2"
    }
]

See: https://github.com/cypress-io/cypress/issues/3963#issuecomment-483581934

Upvotes: 1

Mr. J.
Mr. J.

Reputation: 3731

May I suggest a slightly different approach? You can put the test in a custom command and reuse it in the test. What you'll end up with is this:

const states = [
  { 
    "startPath": "/path1", 
    "fixture": "fixture1"
  },
  { 
    "startPath": "/path2", 
    "fixture": "fixture2"
  }
]

Cypress.Commands.add('testcase', function() {
  // steps which you want to perform in both scenarios
})

describe('Start test', function() {
  states.forEach((state) => {
    it('first scenario', function() {
      cy.flushDB()
      cy.fixture(state.fixture)
        .then(fixtureData => {
          new Cypress.Promise((resolve, reject) => 
          cy.createCollections(fixtureData, resolve, reject)
          )
        })
        .then(() => cy.visit(state.startPath))
        cy.testcase()
    })
  })
})

Upvotes: -1

Related Questions