Reputation: 3183
I am trying to use cypress to test a large angular app that I have built. My requirement is that I load an expectation file into my test and then drive the test off this expectation file.
I have so far been unable to get this to work using various combinations of cy.readFile()
, cy.fixture()
, and even axios
to load the file via http.
The issue seems to be that I can't use these methods outside of it()
and if I can't do that it means I can't loop through the data to create the its. I am trying to do something like the below... is this even possible in cypress? Am I missing something obvious?
Lets say my expectation looks like this:
{
"mainPage": [1, 2, 3],
"otherPage": [4, 5, 6]
}
I want my code to load it and go through the various pages:
describe(`Test the app `, function() {
cy.readFile("path/to/expectation.json").then(function(expectation) {
Object.keys(expectation).forEach(function(pageName) {
it(`for page ${pageName}`, function() {
gotoPage(pageName);
var pageData = getDataFrompage();
expect(pageData).to.equal(expectation[pageName]);
})
})
})
})
This seems to me like a pretty obvious use-case so I'm confused why it appears to be so difficult :)
Upvotes: 6
Views: 7676
Reputation: 71
{ "mainPage": [1, 2, 3], "otherPage": [4, 5, 6] }
Then your code would be something like this to create Test cases dynamically
const data = require("path/to/expectation.json");
describe('Test the app', function() {
Object.keys(data).forEach(function(page, i){
it(`Test Case For: ${page}`, function() {
cy.log(data[page])
})
})
})
Upvotes: 0
Reputation: 23483
I have a similar requirement, except I'm reading an application config file (which lives within the app assets folder).
I read it with a require
like so,
const runtimeConfig = require('../../../src/data/my-config');
This works well, I can then proceed to test with expectations based on the file contents.
So, your code would be something like this
const expectation = require('path/to/expectation.json');
describe(`Test the app `, function() {
Object.keys(expectation).forEach(function(pageName) {
it(`for page ${pageName}`, function() {
gotoPage(pageName);
var pageData = getDataFrompage();
expect(pageData).to.equal(expectation[pageName]);
})
})
})
readFile()
Trying cy.readFile()
, you get get this error message
Uncaught Error: Cannot call "cy.readFile()" outside a running test.
You can stop this error by wrapping the read in a before
like so
let runtimeConfig;
before(function(){
cy.readFile('./src/data/my-config.json').then( fileContents => {
runtimeConfig = fileContents;
})
})
but unfortunately Cypress does not wait for the read to complete before proceeding to test.
fixture()
I also tried the fixture pattern shown in example.spec.js
context('Files', function(){
beforeEach(function(){
cy.visit('https://example.cypress.io/commands/files')
})
it('cy.fixture() - load a fixture', function(){
// Instead of writing a response inline you can
// connect a response with a fixture file
// located in fixtures folder.
cy.server()
// https://on.cypress.io/fixture
cy.fixture('example.json').as('comment')
cy.route(/comments/, '@comment').as('getComment')
// we have code that gets a comment when
// the button is clicked in scripts.js
cy.get('.fixture-btn').click()
cy.wait('@getComment').its('responseBody')
.should('have.property', 'name')
.and('include', 'Using fixtures to represent data')
but could not get it to work with my config file even when copying it to the /cypress/fixtures
folder.
Also, this feels a quite hacky - if I understand this code correctly, it is turning the file read into a pseudo route navigation so that Cypress can wait on it.
This pattern is complicated and certainly does not lend itself to the dynamic testing scenario you describe.
Upvotes: 7