Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Run tests on dynamic file in cypress.io

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 :)

like image 374
rex Avatar asked Feb 02 '18 08:02

rex


People also ask

How do I run a cypress test file?

Cypress provides two ways to test cases. Either using the Cypress UI Test Runner or from the CLI using the "cypress run" command. A specific test case can be executed on the CLI using the "--spec" option. We can change the browser for a specific test run on CLI using the "--browser" option.

How do you run test cases sequentially in Cypress?

Using the cypress configuration we can execute cypress tests in a sequence we desire. Simply write test file names under the testFiles property in your cypress. json file, like below. On running npm test, you can see on the test runner UI that all the tests are listed from 1 to 13 in sequence.

Can Cypress Run unit tests?

You can use Cypress for unit and integration testing. All tests are written in JavaScript and run in real browsers.


1 Answers

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.

like image 126
Richard Matsen Avatar answered Nov 07 '22 06:11

Richard Matsen