Search code examples
javascriptcypressaliasweb-api-testing

Intercept the same API call multiple times in Cypress


Is it possible to use cy.intercept to intercept the same API call multiple times in the same test? I tried the following:

cy.intercept({ pathname: "/url", method: "POST" }).as("call1")
// ... some logic
cy.wait("@call1")

// ... some logic

cy.intercept({ pathname: "/url", method: "POST" }).as("call2")
// ... some logic
cy.wait("@call2")

I would expect that cy.wait("@call2") would wait for the 2nd time the API gets called. However, the second cy.wait will continue immediately because the first API call is identical to the second one.


Solution

  • Updated for Cypress v7.0.0 Released 04/05/2021

    The change-log shows from this release the intercepts are now called in reverse order

    Response handlers (supplied via event handlers or via req.continue(cb)) supplied to cy.intercept() will be called in reverse order until res.send is called or until there are no more response handlers.

    Also illustrated in this diagram from the documentation

    enter image description here


    When you set up identical intercepts, the first one will grab all the calls. But you can wait on the first alias multiple times.

    Here's a (reasonably) simple illustration

    spec

    Cypress.config('defaultCommandTimeout', 10); // low timeout
                                                 // makes the gets depend on the waits 
                                                 // for success
    
    it('never fires @call2',()=>{
    
      cy.intercept({ pathname: "/posts", method: "POST" }).as("call1")
      cy.intercept({ pathname: "/posts", method: "POST" }).as("call2")
    
      cy.visit('../app/intercept-identical.html')
      
      cy.wait('@call1')                               // call1 fires 
      cy.get('div#1').should('have.text', '201')
    
      cy.wait('@call2')                               // call2 never fires
      cy.wait('@call1')                               // call1 fires a second time
      cy.get('div#2').should('have.text', '201')
    
    })
    

    app

    <body>
      <div id="1"></div>
      <div id="2"></div>
      <script>
    
        setTimeout(() => {
          fetch('https://jsonplaceholder.typicode.com/posts', {
            method: 'POST',
            body: JSON.stringify({ title: 'foo', body: 'bar', userId: 1 }),
            headers: { 'Content-type': 'application/json; charset=UTF-8' },
          }).then(response => {
            document.getElementById('1').innerText = response.status;
          })
        }, 500)
      
        setTimeout(() => {
          fetch('https://jsonplaceholder.typicode.com/posts', {
            method: 'POST',
            body: JSON.stringify({ title: 'foo', body: 'bar', userId: 2 }),
            headers: { 'Content-type': 'application/json; charset=UTF-8' },
          }).then(response => {
            document.getElementById('2').innerText = response.status;
          })
        }, 1000)
    
      </script>
    </body>
    

    You can see it in the Cypress log,

    command call# occurrence (orange tag)
    wait @call1 1
    wait @call2
    wait @call1 2