In cypress how do I intercept the same url but with a different payload

439 Views Asked by At

My application is making it's calls to backend from the same url, but with different payloads. How can I test that those requests (that differ only in payload) are made with cypress when url is always the same? Here is what Ido

const requests = ProductList.initialRequestList;
const aliases = [];

requests.forEach((request, index) => {
  cy.intercept('POST', `${baseUrl}${request.endpoint}`, (req) => {
    if (req.body.query && req.body.query === request.payload.query) {
      aliases.push(`@${request.payload.query}`);
    }
  }).as(request.payload.query);
});

cy.visit('/someurl');

cy.wait(aliases)
  .then(() => {
    aliases.forEach((alias, index) => {
      // aliases ok/different here
      console.log(alias);

      cy.get(alias)
        .then((interception: cy.intercept.Interception) => {
          // here not ok all the same
          console.log(interception.response.body.message);
        });
    });
  });
1

There are 1 best solutions below

13
TesterDick On BEST ANSWER

Initially I posted the Cypress docs on dynamic alias, but it turns out they are not very dynamic.


A reproducible test

Here's a Cypress test to replicate the problem, based on the code you added above.

  • using a fireFetches() function to send the requests instead of cy.visit()

  • stubbing the cy.intercept() response since I have no API endpoint to hit

  • added middleware: true to allow all intercepts (a, b & c) to check the interception against the request data.

  • only the request that matches body.query === request.payload.query will respond

const baseUrl = 'domain/api/'     
const requests = [
  {endpoint: '1', payload: {query: 'a'}},
  {endpoint: '1', payload: {query: 'b'}},
  {endpoint: '1', payload: {query: 'c'}}
]

function  fireFetches() {      // for testing only, since I don't have app
  cy.window().then(win => {
    requests.forEach(request => {
      const url = `${baseUrl}${request.endpoint}`
      win.fetch(url, {
        method: 'POST',
        body: JSON.stringify({ query: request.payload.query })
      })
    })
  })
}

requests.forEach(request => {
  cy.intercept({
    method: 'POST', 
    url: `**/${baseUrl}${request.endpoint}`, 
    middleware: true
  }, (req) => {
    const body = JSON.parse(req.body)
    if (body.query === request.payload.query) {
      req.reply({message: `response for "${request.payload.query}"`})
    }
  })
  .as('endpoint')
})

fireFetches()

requests.forEach(() => {

  cy.wait('@endpoint').then(interception => {
    const body = JSON.parse(interception.request.body)

    if (body.query === 'a') {
      expect(interception.response.body.message).to.eq('response for "a"')
    }
    if (body.query === 'b') {
      expect(interception.response.body.message).to.eq('response for "b"')
    }
    if (body.query === 'c') {
      expect(interception.response.body.message).to.eq('response for "c"')
    }
  })
})

enter image description here


Your test - one intercept, checking at the cy.wait() end

For you the API server will provide the response, you don't need to mock the response and therefore you only need one `cy.intercept'

const requests = ProductList.initialRequestList;

const url =  `**/${baseUrl}${requests[0].endpoint}` // endpoint is common
cy.intercept('POST', url).as('endpoint')

cy.visit('/someurl')

// differentiate requests at cy.wait()
requests.forEach(() => {
  cy.wait('@endpoint').then(interception => {
    const body = JSON.parse(interception.request.body)
    if (body.query === request.payload.query) {
      expect(...)
    }
  })
})

Waiting only once and expecting `cy.get(${request}.all)` to work

Summarizing the comments below, Artoo proposes to use

cy.wait(${request}).then(() => cy.get(${request}.all)...

but the problem is cy.get(${request}.all) doesn't actually wait for all responses, it only gets whatever has responded so far in the test.

Since you are relying on actual responses from the API server (not mocking), the results will be asynchronous and not predicatble.

So, you must cy.wait(${request}) n-times as shown by Filip Hiric in his video Intercepting multiple requests