Slava.In
Slava.In

Reputation: 1059

How to cleanup cypress cy.intercept requests queue?

I'm testing several filters (they are on backend) for a dashboard consecutevely using spy function written in before(() => {...}) block :

function aliasQuery(
  request: CyHttpMessages.IncomingHttpRequest,
  operationName: string,
): void {
  const { body } = request;
  if (body.operationName === operationName) {
    request.alias = operationName;
  }
}

export function spyOnGraphQL(operationName: string): void {
  cy.fixture('hosts').then(({ graphQLHostname }) => {
    cy.intercept(ApiMethods.Post, graphQLHostname, (request) => {
      aliasQuery(request, operationName);
    });
  });
}

Then inside for loop I use

cy.wait(`@${operationName}`).should(({response}) => {...})

to check filters one by one.

There's trouble though, after using every filter and getting results I need to reset all filters by sending another graphql request, this request's query name matches the filter's query name, so when cy.wait is called again it catches reset filters request which breaks everything.It goes like this:

Is there a way to clean up requests caught by cy.intercept before applying a new filter? Or at least distinguish reset request from filter request using request payload for instance?

Upvotes: 1

Views: 7106

Answers (3)

daniel.m.bartle
daniel.m.bartle

Reputation: 9

There is an outstanding feature request for cypress asking for this to be added. https://github.com/cypress-io/cypress/issues/23192

For now I've found a workaround, it's a little clunky but it solves the issue for my use case.

I added this custom command, which will loop over the list of currently intercepted requests and call cy.wait() for any where the request has responseWaited is false.

Cypress.Commands.add('clearInterceptList', (interceptAlias) => {
  // clears the list of intercepted requests by waiting for each one
  // intercept alias should be in the form '@postExample' etc.
  cy.get(interceptAlias + '.all').then((browserRequests) => {
    for (let request of browserRequests) {
      if (request.responseWaited === false) {
        cy.wait(interceptAlias)
      }
    }
  })
})

The important thing is this would need to be called before the request is triggered again. So in your for loop it would be something like this:

1. Reset filters
2. cy.clearInterceptList(`@${operationName}`)
3. Apply new filter
4. cy.wait(`@${operationName}`).should(({response}) => {...})

Upvotes: 0

Pendar
Pendar

Reputation: 89

You can use the times option to make sure your intercept only matches once and redefined it later when you are expecting the request. Example:

cy.intercept({ url: /\/api\/.*\/path\/.*/, times: 1 }).as("fetchingMyData")
cy.wait("@fetchingMyData").then(() => { ... }) // the first wait


cy.intercept({ url: /\/api\/.*\/path\/.*/, times: 1 }).as("fetchingMyData2") // this resets the alias and the intercepted requests so that any request made before this point won't be considered.
cy.wait("@fetchingMyData2").then(() => { ... }) // the second wait

Have a look at the options in the docs for more info: https://docs.cypress.io/api/commands/intercept#routeMatcher-RouteMatcher

Upvotes: 3

Slava.In
Slava.In

Reputation: 1059

I didn't find a way to clean up the request queue, but I was able to use an extra callback to ignore some requests by giving them different alias.

function aliasQuery(
  request: CyHttpMessages.IncomingHttpRequest,
  operationName: string,
  callback?: TypeAliasQueryCallback,
): void {
  const { body } = request;

  if (body.operationName === operationName) {
    request.alias = operationName;

    if (typeof callback === 'function') {
      callback(request);
    }
  }
}

export function spyOnGraphQL(
  operationName: string,
  callback?: TypeAliasQueryCallback,
): void {
  cy.fixture('hosts').then(({ graphQLHostname }) => {
    cy.intercept(ApiMethods.Post, graphQLHostname, (request) => {
      aliasQuery(request, operationName, callback);
    });
  });
}

export function ignoreResetRequest(
  request: CyHttpMessages.IncomingHttpRequest,
): void {
  const { body } = request;

  // Checking if the filters are sent (resetting sends empty array)
  if (!body.variables.filter.and.length) {
    request.alias = 'ignored';
  }
}

spyOnGraphQL('some_operation_name', ignoreResetRequest);

Upvotes: 0

Related Questions