Dhamo
Dhamo

Reputation: 1251

Cypress intercept identical request based on request body

In my app, I have a flow that triggers two POST requests to the same endpoints but with a slightly changed request body. How can we achieve this with cypress?

Request 1: Request URL: http://localhost:8000/weather/F20210908060000/spot

Request Method: POST

Request body:

{
  "locations": [
    {
      "timestamp": "2021-09-18T06:00:00.000Z",
      "coordinates": [
        106.41364531249987,
        -15.435157996299878
      ]
    },
    {
      "timestamp": "2021-09-18T07:00:00.000Z",
      "coordinates": [
        106.41364531249987,
        -15.435157996299878
      ]
    }
  ],
  "elements": [
    2
  ]
}

Request 2: Request URL:

http://localhost:8000/weather/F20210908060000/spot

Request Method: POST

Request body:

{
  "locations": [
        {
      "timestamp": "2021-09-18T04:00:00.000Z",
      "coordinates": [
        106.41364531249987,
        -15.435157996299878
      ]
    },
    {
      "timestamp": "2021-09-18T05:00:00.000Z",
      "coordinates": [
        106.41364531249987,
        -15.435157996299878
      ]
    },
{
      "timestamp": "2021-09-18T06:00:00.000Z",
      "coordinates": [
        106.41364531249987,
        -15.435157996299878
      ]
    },
    {
      "timestamp": "2021-09-18T07:00:00.000Z",
      "coordinates": [
        106.41364531249987,
        -15.435157996299878
      ]
    }
  ],
  "elements": [
    2
  ]
}

Note: Request 2 has more data in its request.

My code so far:

 cy.intercept("POST", "**/spot", (req) => {
        expect(req.locations).to.have.length.above(3);
    }).as('postSPOT1');
    Weather.activateSPOTWeather()
 });
 cy.wait('@postSPOT1').its('response.statusCode').should("eq", 200);

enter image description here

Upvotes: 7

Views: 5768

Answers (1)

Visal
Visal

Reputation: 737

There's a pattern for checking the response here How to match intercept on response

I changed the matcher to a function, as you want to evaluate an expression not match part of the response.

cy.intercept("POST", "**/spot").as('postSPOT1')

function waitFor(alias, checkFn, maxRequests, level = 0) {
  if (level === maxRequests) {
    throw `${maxRequests} requests exceeded`        
  }
  cy.wait(alias).then(interception => {
    if (!checkFn(interception)) {
      waitFor(alias, checkFn, maxRequests, level+1)
    }
  })
}

const maxRequests = 10
const checkFn = (interception) => interception.request.locations > 3
waitFor('@postSPOT1', checkFn, maxRequests) 

cy.get('@postSPOT1.last')
  .then(lastInterception => {
    ...     
  })

Or with cypress-recurse add-on

cy.intercept("POST", "**/spot").as('postSPOT1')

recurse(
  () => cy.wait('@postSPOT1'),
  (interception) => interception.request.locations > 3,
  {
    log: true,
    limit: 10, // max number of iterations
    timeout: 30000, // time limit in ms
  },
)

cy.get('@postSPOT1.last')
  .then(lastInterception => {
    ...     
  })

If there are exactly two requests and you only want the second, it might be simpler to just wait twice

cy.intercept("POST", "**/spot").as('postSPOT1')
cy.wait('@postSPOT1')  // discard
cy.wait('@postSPOT1')
  .then(lastInterception => {
    ...     
  })

Upvotes: 2

Related Questions