5

I'm using Cypress as my automation framework for both API and UI tests. I've written multiple API tests that are running and passing but they're only validating that the response.status returns a 200. I want to compare the response json from a GET against a stored "expected" response to confirm that the JSON response data is correct.

I've tried different variations of to.deep.equal and deepEquals in my .then(response => {} code block. But I don't want to validate that just one field is returning the correct value, I want to validate whether a bunch of different fields are returning the correct values. My GET request returns over 100 lines of nested JSON fields/values and I only want to validate 20 or so fields/values nested inside each other.

cy.request({
    method: 'GET',
    log: true,
    url: 'https://dev.api.random.com/calculators/run-calculate/524/ABC',

    headers: {
        'content-type': 'application/json',
        'x-api-key': calcXApiKey
    },
    body: {}
}).then(response => {
    const respGet = response.body
    const tPrice = response.body.data.calculations.t_costs[0].comparison.t_price
    cy.log(respGet, tPrice)
    assert.deepEqual({
        tPrice
    }, {
        t_price: '359701'
    })
       // assert.equal(response.status, 200) -- This works great
})

Error= expected { tPrice: undefined } to deeply equal { t_price: 359701 }

1
  • For any future searchers, there's a thing called deepInclude besides deepEqual Commented Mar 22, 2022 at 16:30

2 Answers 2

4

In your example, you're comparing object { tPrice: tPrice } with { t_price: '359701' }, that's why it's always going to fail because the keys are different (apart from the fact that the tPrice variable value is undefined).

If you're already storing the actual value in a variable, there's no need to make an object out of it and use deepEqual. You can do:

const tPrice = response.body.data.calculations.t_costs[0].comparison.t_price
assert.equal(tPrice, '359701');

As to your other question, if I understand it correctly, your response looks like:

{
  data: {
    calculations: {
      t_costs: [
        { comparison: { t_price: "1111" } },
        { comparison: { t_price: "2222" } },
        { comparison: { t_price: "3333" } },
        { comparison: { t_price: "4444" } },
        /* ... */
      ]
    }
  }
}

And you want to assert just a few of those t_costs objects.

For that it's best to use a chai plugin such as debitoor/chai-subset.

To set it up:

npm install --save-dev chai-subset

In your cypress/support/index.js:

const chai = require('chai');
const chaiSubset = require('chai-subset');
chai.use(chaiSubset);

In your spec:

/* ... */
expect( response.body.data.calculations.t_costs )
    .to.containSubset([
        { comparison: { t_price: "1111" } },
        { comparison: { t_price: "3333" } }
    ]);
Sign up to request clarification or add additional context in comments.

2 Comments

This worked great. Thank you so much for your help. It's so much simpler than I was making it haha.
Keep in mind, chai-subset works but error reporting is terrible. You need to manually analyze why it's failing. There is no explicit error of where field doesn't match.
2

I was working on a very similar problem recently. I often forget that Cypress comes bundled with some decent packages; in this case Lodash which is good at dealing with arrays and objects such as a deeply nested JSON API return. I also had an expected return JSON that I wanted to compare to the full response JSON. After a bit of trial and error I did this:

expect(Cypress._.isMatch(response.body, expectedReturn)).to.be.true;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.