Reputation: 2853
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
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
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
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
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