Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic alias for cy.intercept() #16321

Closed
baeharam opened this issue May 4, 2021 · 12 comments
Closed

Dynamic alias for cy.intercept() #16321

baeharam opened this issue May 4, 2021 · 12 comments
Labels
stage: awaiting response Potential fix was proposed; awaiting response topic: cy.intercept()

Comments

@baeharam
Copy link

baeharam commented May 4, 2021

What would you like?

By #3083, I have to distinguish each graphql request because, cypress groups requests which has same endpoint very often. To handle independently each request, we can use operationName for alias like below.

cy.intercept('POST', '/graphql', req => {
  req.alias = req.body.operationName;
});

cy.wait('@someAlias');

However, if same request is sent multiple time with different variables, it is grouped again. Therefore, I cannot distinguish these queries. To do this, I thought random string will work as a suffix to operationName like below.

cy.intercept('POST', '/graphql', req => {
  const randomString = generateRandom();
  req.alias = `${req.body.operationName}${randomString}`;
});

From above, each request differentiated even if it is same request. But, how can I wait? how can I store that dynamic alias? I mean this ${req.operationName}${randomString} alias. When I store this alias to outer variable, I cannot use that variable with wait syntax.

Is there other way?

Below solution is not working

let alias = '';
cy.intercept('POST', '/graphql', req => {
  const randomString = generateRandom();
  alias = `${req.body.operationName}${randomString}`
  req.alias = alias;
});
cy.wait(`@${alias}`);

Why is this needed?

I have to wait all graphql requests when I load or visit specific page.

Thanks for your reading.

@jennifer-shehane
Copy link
Member

@baeharam What is we had a feature like shown in #8531? Would that help for your use case?

@jennifer-shehane jennifer-shehane added stage: awaiting response Potential fix was proposed; awaiting response topic: cy.intercept() labels May 4, 2021
@Renato66
Copy link

Renato66 commented May 4, 2021

in that example:
alias = 'operation-string'
cy.wait( 'operation-string'); // this wont work
cy.wait( '@operation-string'); // this will work
fixing:

let alias = '';
cy.intercept('POST', '/graphql', req => {
  const randomString = generateRandom();
  alias = `${req.operationName}${randomString}`
  req.alias = alias;
});
cy.wait(`@${alias}`);

@baeharam
Copy link
Author

baeharam commented May 6, 2021

@jennifer-shehane I checked that issue, but it is not related to my problem because I have to use dynamic alias out of cy.intercept. That issue handles k inside of cy.intercept.

@Renato66 It was typo so I updated my description. Also, it doesn't work for your suggestion too. Anyway thanks.

@Renato66
Copy link

Renato66 commented May 6, 2021

still missing body:
req.body.operationName
@baeharam

@baeharam
Copy link
Author

baeharam commented May 6, 2021

@Renato66 Thanks. I fixed typo

@flotwig
Copy link
Contributor

flotwig commented May 6, 2021

@baeharam this is a JS problem, not a Cy problem. In JS, only objects are passed by reference, primitives like strings are passed by value. So in your example, you're actually doing cy.wait('@').

This will work because putting the .wait in the .then uses the updated value of alias:

let alias = '';
cy.intercept('POST', '/graphql', req => {
  const randomString = generateRandom();
  alias = `${req.body.operationName}${randomString}`
  req.alias = alias;
})
.then(() => {
  cy.wait(`@${alias}`);
})

@baeharam
Copy link
Author

baeharam commented May 7, 2021

@flotwig Thanks for your suggestion, but I already tried your code. It didn't work and result was cy.wait('@').

@bahmutov
Copy link
Contributor

bahmutov commented May 7, 2021

@baeharam the problem here is that by the time .then() => cy.wait(@{alias}) runs the alias variable is still undefined. We first need to make sure the alias is set. Here is how you could do that

it('creates random alias', () => {
  let alias = ''
  cy.intercept('GET', '/todos', (req) => {
    alias = 'get-todos-' + Cypress._.random(1e6)
    req.alias = alias
  })

  cy.visit('/?delay=2400')

  // first, wait for the alias string to become define
  cy.wrap('the alias string')
    .should(() => {
      expect(alias, 'alias string').to.not.be.empty
    })
    .then(() => {
      cy.wait(`@${alias}`)
    })
})

First, we retry using .should(() => ...) until the alias is set. Then we have the .then callback - by the time it executes, the alias has been set and all is good. Here is this test in action

alias.mp4

@baeharam
Copy link
Author

baeharam commented May 7, 2021

@bahmutov Your solution nearly works! Thanks!

My solution from your suggestion.

it('creates random alias', () => {
  const aliasList = [];
  cy.intercept('GET', '/todos', (req) => {
    const alias = 'get-todos-' + Cypress._.random(1e6)
    req.alias = alias
    aliasList.push(alias);
  })

  cy.visit('/?delay=2400')

  // first, wait for the alias string to become define
  cy.wrap('the alias string')
    .should(() => {
      expect(alias, 'alias string').have.length(??)
    })
    .then(() => {
      aliasList.forEach(alias => cy.wait(`@${alias}`));
    })
})

But, I have this conditions in my situation.

(1) There are multiple graphql request
(2) If I cannot know number of request, how can I ensure to wait every requests?

@bahmutov
Copy link
Contributor

bahmutov commented May 7, 2021

So at this point I would ask myself - do you know what to expect? Maybe you want to check if the number of requests is > 10 and write that as an assertion? Maybe use something like network idle by looking at the timestamp of the last intercept? I have such example at https://glebbahmutov.com/blog/cypress-tips-and-tricks/#wait-for-network-idle

@baeharam
Copy link
Author

@bahmutov Great solution! Thanks!

@baeharam
Copy link
Author

For someone to solve this problem: see #16321 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stage: awaiting response Potential fix was proposed; awaiting response topic: cy.intercept()
Projects
None yet
Development

No branches or pull requests

5 participants