Execute tests on changing files using cypress.io

I'm currently experimenting with using Cypress to test a large Angular application that I've developed. What I want to achieve is to load an expectation file into my test and then run the test based on this expectation file.

Despite trying different combinations of cy.readFile(), cy.fixture(), and even using axios to load the file via HTTP, I haven't been successful so far.

The main problem seems to be that I can't utilize these methods outside of the it() function, which prevents me from looping through the data to create the individual tests. I am attempting something similar to the following... Is this feasible in Cypress? Am I overlooking something obvious?

Assume my expectation file looks like this:

{
    "mainPage": [1, 2, 3],
    "otherPage": [4, 5, 6]
}

I aim for my code to load it and navigate through the various pages:

describe(`Testing the application`, 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]);
            })
        })
    })
})

To me, this seems like quite a common scenario, so I'm puzzled as to why it's proving to be challenging :)

Answer №1

My situation is quite similar, as I need to access an application configuration file located in the app assets folder.

I retrieve the file using a require statement like this:

const runtimeConfig = require('../../../src/data/my-config');

This method works effectively, allowing me to set expectations based on the file contents for testing purposes.

Therefore, your code implementation may resemble the following:

const expectation = require('path/to/expectation.json');

describe(`Testing the application`, function() {
  Object.keys(expectation).forEach(function(pageName) {
    it(`for page ${pageName}`, function() {
      gotoPage(pageName);
      var pageData = getDataFrompage();
      expect(pageData).to.equal(expectation[pageName]);
    })
  })
})

readFile()

When attempting to use cy.readFile(), an error message is displayed:

Uncaught Error: Cannot call "cy.readFile()" outside a running test.

To prevent this error, you can enclose the read operation within a before block:

let runtimeConfig;
before(function(){
  cy.readFile('./src/data/my-config.json').then( fileContents => {
    runtimeConfig = fileContents;
  })
})

Unfortunately, Cypress does not wait for the file read operation to finish before proceeding with the tests.


fixture()

Another approach attempted was using the fixture pattern demonstrated 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')

However, incorporating this method for my config file by moving it to the /cypress/fixtures directory did not yield the desired results.

This process also seems somewhat convoluted – in essence, transforming a file read into a simulated route navigation to enable Cypress to pause for its completion.

Overall, this approach appears intricate and does not align well with the dynamic testing scenario outlined.

Answer №2

  1. Assume that you are working with data stored in an expectation.json file.
    {
      "homePage": [5, 6, 7],
      "aboutPage": [8, 9, 10]
    }
    

In order to generate test cases dynamically based on this data, your code could look something like the following:

const data = require("path/to/expectation.json");

describe('Testing the application', function() {
   Object.keys(data).forEach(function(page, i){
      it(`Test Case For: ${page}`, function() {
        cy.log(data[page])
      })
   })
})

https://i.stack.imgur.com/QQGLp.png

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Transferring data using AJAX between an AngularJS frontend and a Node.js backend

Just a heads up: The main question is at the bottom in case you find this post too lengthy ;) I'm currently working on developing my first angularjs app and I've hit a roadblock when it comes to fetching data via ajax from my nodejs (express) se ...

Can you explain the variance in these code snippets when implementing React's setState() function?

Can you explain the variance between these two blocks of code? this.setState((state)=>({ posts: state.posts.filter(post=> post.id !==postRemoved.id) })) versus this.setState((state)=>{ posts: state.post ...

AngularJS has encountered an issue with a route resolve promise that has not been completely resolved

I'm currently working on a simple task to manage user roles within routes. The goal is straightforward: Verify the role of the logged-in user on each route (using a resolve function to authenticate the user based on token or login credentials) Direc ...

Does the Angular templateCache get shared across different applications? And does it stay persistent?

Is it possible for two Angular applications that operate on the same domain to exchange data within the templateCache? Or does each main application module have its own unique cache? I am curious about the circumstances under which a new templateCache is g ...

View an image in advance of uploading it and concealing any broken images

The foundational code for previewing an image before it is uploaded can be found at this link. Here are the codes: <script type="text/javascript"> function readURL(input) { if (input.files && input.files[0]) { var ...

Issue with handling keypress event and click event in Internet Explorer

Below is the HTML code for an input text box and a button: <div id="sender" onKeyUp="keypressed(event);"> Your message: <input type="text" name="msg" size="70" id="msg" /> <button onClick="doWork();">Send</button> </di ...

Get the large data file in sections

I ran a test script that looks like this: async function testDownload() { try{ var urls = ['https://localhost:54373/analyzer/test1','https://localhost:54373/analyzer/test2'] var fullFile = new Blob(); for (le ...

AngularJS can be used to display a webpage

After facing the need to print a given page using AngularJS, I came up with a simple solution as shown below: <div class="modal fade" id="extrait" aria-hidden="true" data-backdrop="false"> <table class="table table-hover table-bordered" i ...

Displaying country-specific API details (such as capital and currency) in a card container when selecting a country from a dropdown menu

My objective is to display the card information for South Africa as the default value, even before entering any country's name into the search bar input field or selecting a specific country from the provided list. I am utilizing the restcountries API ...

GraphQL Shield throws an 'Unauthorized' error for a permitted mutation

I've been working on setting up a GraphQL API with apollo-server-express, and I'm trying to handle permissions using graphql-shield middleware. However, I'm running into some issues when it comes to allowing mutations to be executed. My aim ...

top margin is functioning properly in Internet Explorer, but not in Google Chrome

margin-top is behaving differently in IE compared to Google Chrome. Two menus are supposed to be displayed one above the other in my design. The issue lies in the line margin-top:30%; within .anothermenu ul. In Chrome, the second menu appears above the f ...

What impact does the spread operator have on the efficiency of code execution

Exploring two techniques for constructing an array of objects: Technique 1 (including all properties, even if duplicates exist): const employees = [ { company: 'ABC', country: 'IN', zip: 123, employeeId: 123, emp ...

Store data in LocalStorage according to the selected value in the dropdown menu

Can you help me understand how to update the value of a localstorage item based on the selection made in a dropdown menu? <select id="theme" onchange=""> <option value="simple">Simple</option> <option valu ...

React Context Matters: Troubles Unleashed

I've been facing some difficulties with passing a value from one file to another. The problem seems to be related to implementing context, but I can't seem to figure out where I went wrong! import React from 'react' const Mycontext = ...

Could the issue with jQuery selector potentially be connected to AngularJS?

Integrating a third-party web page into an Android webview in our app presents the challenge of automating the login process. Since the app has access to the login credentials for the third-party site, I'd like to execute some Javascript for this purp ...

Restrict the PHP generated Json response to display only the top 5 results

I need to modify my search bar so that it only displays the top 5 related products after a search. public function getProducts() { if (request()->ajax()) { $search_term = request()->input('term', ''); $locatio ...

A guide to sending props to a CSS class in Vue 3

I need to develop a custom toast component that includes a personalized message and class. While I have successfully passed the message as props, I am encountering difficulties in applying the bootstrap class. Component File: Toast.vue <script ...

Angular-indexedDB: Crafting personalized queries

I've integrated the bramski/angular-indexedDB library into my application. The basic CRUD operations are running smoothly, but I'm encountering some issues with custom queries not functioning as intended. I have set up the code below: angular.m ...

Sharing an array with a child component using the @Input decorator

I am attempting to send an array to a child component. The array is created within the subscribe method of the onInit lifecycle hook in the parent component. Parent component: import { Component, OnInit } from '@angular/core'; @Component({ s ...

What steps should be taken to enable the "You and moderator can reply" feature in a bot when sending proactive messages to channels?

A project I am currently working on involves creating a bot that sends proactive messages to channels. The client has requested that I include options like No reply or You and moderator can reply with the messages posted by the bot proactively. Here is wh ...