Search code examples
testinggraphqlcypress

How to Intercept GraphQL Response and Use the Data in Cypress Test


I'm writing a Cypress test to verify the login functionality of my application. I need to intercept a GraphQL request, extract a value from the response, and use it in subsequent steps of the test. However, I'm encountering issues with promises and Cypress commands.

Here is my current test code:

describe('Login functionality', () => {
it('should login successfully', () => {
    const email = 'admin@email.com';
    const password = 'password';

    cy.visit('/');
    cy.get('input[type="email"]').type(email).should('have.value', email);
    cy.get('input[type="password"]').type(password);
    cy.get('[data-cy="submit-btn"]').click();

    // Intercept the GraphQL login request
    cy.intercept('POST', 'http://localhost:3000/graphql', (req) => {
        if (req.body.operationName === 'LoginVerify') {
            req.alias = 'loginVerify';
            // Continue with the request as is
            req.continue((res) => {
                // Log the response for debugging
                cy.log('Response:', res);
                // Set an alias for the response to use later
                req.reply((res) => {
                    // Assuming the OTP is in the response data
                    const testOtp = res.body.data.getTestOtp;
                    // Save the OTP value for later use
                    req.otp = testOtp;
                });
            });
        }
    });

    // Wait for the login request to complete
    cy.wait('@loginVerify').then((interception) => {
        // Extract the OTP from the intercepted response
        const testOtp = interception.request.otp;

        // Use the OTP value to complete the login process
        
    cy.get('input[type="number"]').type(testOtp).should('have.value', testOtp);
        cy.get('[data-cy="submit-btn"]').click();
        cy.wait(100);
        cy.contains('Welcome Admin');
    });
  });
});

I get the error below:

Timed out retrying after 5000ms: cy.wait() timed out waiting 5000ms for the 1st request to the route: loginVerify. No request ever occurred.

I've tried ensuring the intercept is set up before the actions that trigger the request and increasing the timeout, but I still encounter issues. How can I properly intercept the response, extract the OTP value, and use it in my Cypress test without running into these promise issues?

Any help or guidance would be greatly appreciated!


Solution

  • The click should be between the intercept and the wait. You said you did this, but the code says otherwise.

    So first of all, use this sequence

    cy.intercept('POST', 'http://localhost:3000/graphql', (req) => {
      ...
    })
    
    cy.get('[data-cy="submit-btn"]').click();
    
    cy.wait('@loginVerify').then((interception) => {
     ...
    })
    

    If you still see Timed out retrying after 5000ms it means that http://localhost:3000/graphql is not the correct URL.

    In this case, add some wildcard characters - see url (String, Glob, RegExp). Above you used String URL pattern.

    The following uses Glob URL pattern:

    cy.intercept('POST', 'http://localhost:3000/graphql/**', (req) =>
    

    If still not succeeding, switch to RegExp pattern (which is easier to match correctly):

    cy.intercept('POST', /graphql/, (req) =>
    

    Please note, regex for URL does not have any string delimiters around the regex expression - the / chars are the delimiters. If you add string delimiters, it will not work as a regex.