Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capture a variable in a stubbed function

Tags:

cypress

I have a test case which opens a secondary window. From what I read online, you should prevent this second window opening and visit the url that should have been opened. However, in all the test example I saw, the second url is static. In my case, I need it to be dynamic. This is why I'm using a cy.stub() to a window opening and trying to get the url from it.

cy.visit('https://myUrl.com');

cy.window().then(win => {
  cy.stub(win, 'open', newUrl => {
    cy.wrap(newUrl).as('newUrl');
  });
});

cy.get('#myButton').click(); // opens new window at new url with generated keys

cy.get('@newUrl').then(newUrl => {
  cy.visit(newUrl);
});

However, the cy.wrap() inside the cy.stub() triggers this error:

Error:        CypressError: Cypress detected that you returned a promise from a command while also invoking one or more cy commands in that promise.

The command that returned the promise was:

  > `cy.click()`

The cy command you invoked inside the promise was:

  > `cy.wrap()`

Because Cypress commands are already promise-like, you don't need to wrap them or return your own promise.

Basically my question is how to capture the url in a stub for later use. Thanks in advance.

like image 715
Xavier DF Avatar asked Jun 06 '26 20:06

Xavier DF


1 Answers

The problem is using cy.wrap() or any cy commands inside an event listener. The code you have is valid, and the error should actually be a warning IMO.

One way to handle it is with a plain JS variable.

You may also need a cy.origin() wrapper for this test.

In a recent similar question How to access new tab by clicking on "href" it was found that the cy.visit(newUrl) was causing a reload of the test window, which looses all the data (variables and aliases) previously obtained.

cy.visit('https://myUrl.com');

let nextUrl;

cy.window().then(win => {
  cy.stub(win, 'open', newUrl => {
    nextUrl = newUrl
  });
});

cy.get('#myButton').click(); // opens new window at new url with generated keys

cy.then(() => {

  const newOrigin = nextUrl.split('?')[0]  // remove query params 
      .replace('http://', 'https://')      // correct for secure protocol

  cy.origin(newOrigin, { args: { nextUrl } }, ({ nextUrl }) => {
    cy.visit(nextUrl) 
  })
})

Alternative way to alias

Looking again at your code, you may be able to apply the alias this way

cy.window().then(win => {
  cy.stub(win, 'open').as('newUrl');
})

cy.get('#myButton').click(); 

cy.get('@newUrl').then(newUrl => {
  cy.visit(newUrl);
})
like image 58
Fody Avatar answered Jun 10 '26 04:06

Fody



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!