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

Cypress test hangs forever when system throws an unexpected alert during the test #27896

Open
tausif29 opened this issue Sep 25, 2023 · 16 comments
Labels
stage: needs investigating Someone from Cypress needs to look at this type: bug

Comments

@tausif29
Copy link

tausif29 commented Sep 25, 2023

Current behavior

When Web application unexpectedly throws an error by alert box
Cypress test hangs/stuck forever and test never gets completed or failed until user manually closes the browser.

image

I have a below sample HTML page to reproduce the issue, Here I am explicitly throwing the alert box after 5 seconds of the page load.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Button Alert Example</title>
</head>
<body>

  <button onclick="changeLabel()">Click me for a label</button>
  <p id="label"></p>

  <iframe id="myFrame" style="display:none;"></iframe>

  <script>
    // Show alert after 5 seconds of page load within the frame
    setTimeout(function() {
      var frame = document.getElementById('myFrame');
      frame.style.display = 'block';
      frame.contentWindow.alert("Error While Processing Request");
    }, 5000);

    function changeLabel() {
      document.getElementById('label').innerText = "You clicked the button!";
    }
  </script>

</body>
</html>

Below is the Cypress test to reproduce the issue:

describe('Reproduce Alert Test', () => {
  it('Handle alert in a Frame', () => {
    cy.visit('/alert-test.html');
    cy.wait(6000)

    // Verify page title
    cy.title().should('eq', 'Alert Example');

    // Click the button and verify the label
    cy.get('button').contains('Click me for a label').click();
    cy.get('#label').should('have.text', 'You clicked the button!');
  });
});

NOTE: Issue gets reproduced when the webpage contains the the iFrame, Without iFrame Cypress automatically accepts the alert message.

Desired behavior

Either Cypress test should automatically accept the alert message and test should be continued further or Cypress test should gets failed immediately.

Test code to reproduce

Sample HTML Page to Reproduce the Issue:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Button Alert Example</title>
</head>
<body>

  <button onclick="changeLabel()">Click me for a label</button>
  <p id="label"></p>

  <iframe id="myFrame" style="display:none;"></iframe>

  <script>
    // Show alert after 5 seconds of page load within the frame
    setTimeout(function() {
      var frame = document.getElementById('myFrame');
      frame.style.display = 'block';
      frame.contentWindow.alert("Error While Processing Request");
    }, 5000);

    function changeLabel() {
      document.getElementById('label').innerText = "You clicked the button!";
    }
  </script>

</body>
</html>

Sample Cypress Code:

describe('Reproduce Alert Test', () => {
  it('Handle alert in a Frame', () => {
    cy.visit('/alert-test.html');
    cy.wait(6000)

    // Verify page title
    cy.title().should('eq', 'Alert Example');

    // Click the button and verify the label
    cy.get('button').contains('Click me for a label').click();
    cy.get('#label').should('have.text', 'You clicked the button!');
  });
});

Cypress Version

All

Node version

All

Operating System

All

Debug Logs

No response

Other

No response

@nagash77
Copy link
Contributor

@tausif29 can you please specify the version(s) of Cypress, Node and what OS(es) you are running and seeing this behavior? Please also include debug logs which will assist in helping us debug this issue. Are you using Test replay as well?

@nagash77 nagash77 self-assigned this Sep 25, 2023
@tausif29
Copy link
Author

@nagash77 Issue is not version specific, It replicates on the all the versions, I have checked on version 10 , 12 & 13

I have shared the sample HTML & Cypress Code to reproduce the issue.

@kmieshkov1
Copy link

Have the same issue. I was trying to handle that with cypress events like cy.on('window:alert', () => true) but it doesn't work either

@ojemuyiwa
Copy link

Just a thought @tausif29 in your e2e.ts or index.js in support do you have:

Cypress.on('uncaught:exception', (err, runnable) => {
    return false;
});

@tausif29
Copy link
Author

Just a thought @tausif29 in your e2e.ts or index.js in support do you have:

Cypress.on('uncaught:exception', (err, runnable) => {
    return false;
});

@ojemuyiwa Yes its there in my test [Refer below screenshot]
image

@ojemuyiwa
Copy link

Just a thought @tausif29 in your e2e.ts or index.js in support do you have:

Cypress.on('uncaught:exception', (err, runnable) => {
    return false;
});

@ojemuyiwa Yes its there in my test [Refer below screenshot] image

Ahh I see, so although I don't see any use case for an iframe showing alerts, your cy.on('window:alert' targets the parent window and not the iframe window. if you get the iframe using cy.get('#myFrame') you may access its window. See examples on the same window https://testersdock.com/cypress-javascript-alert-confirm-prompt/

@kmieshkov1
Copy link

@ojemuyiwa The issue is: if an alert pops up from the main content (top) Cypress handles it correctly and accepts it by default, but when alerts are invoked from the iframe - Cypress hangs, cy.on('window:alert', () => true) doesn't work in this case
The expected behavior is to handle alerts disregarding from where they were invoked since it's blocking the whole application (by the nature of alert windows)

@hatseh
Copy link

hatseh commented Nov 11, 2023

We are facing the same issue. I confirm what @tausif29 said, we can reproduce it on all versions of node/cypress using the code sample they provided.

@kmieshkov1
Copy link

Hey @jennifer-shehane 👋 any updates on this one?

@samelawrence
Copy link

samelawrence commented Mar 22, 2024

+1 for this thread, we are experiencing the same issue and it is disrupting major portions of our test suite. I wonder if this is related to the Chrome team deprecating the unload event? I can only reproduce this issue reliably in Chrome.

@jennifer-shehane jennifer-shehane added type: bug stage: needs investigating Someone from Cypress needs to look at this labels Apr 1, 2024
@jennifer-shehane
Copy link
Member

I'm able to recreate this given the example in Chrome, Firefox, and Electron in Cypress 13.7.1. This doesn't seem browser specific, or related to Chrome's deprecation of the upload event.

We don't have a timeline to share for addressing this issue unfortunately.

@samelawrence
Copy link

@jennifer-shehane Thanks for looking into this! I'll stay subscribed to this issue and hope for an update soon, as this is currently blocking large portions of our test suite. If possible, it would be really helpful to know what version introduced this bug. When I rolled my Cypress installation back to a version when we last had successful runs (13.6.4), I was still able to reproduce the bug, so I haven't been able to pinpoint when this change was introduced. If anyone else seeing this can answer my question, please do - I know Jennifer has a lot on her plate. Thanks!

@RTJakobs
Copy link

Hello, I have been working with Cypress since the beginning of the year and have now also encountered the problem that I cannot automate a window that comes from an IFrame.
Is there already an update or a Cypress version that can solve the problem?

@hatseh
Copy link

hatseh commented May 28, 2024

One solution we found is to use the cy.stub() utility function: https://docs.cypress.io/api/commands/stub.
This way we stub window.alert, window.confirm, window.prompt or window.print

const stubWindow = (win) => {
  if (win.alert.restore) {
    win.alert.restore()
  }
  cy.stub(win, 'alert')
    .callsFake(() => {
      throw new Error('window.alert() called, failing current test!')
    })
    .as('alert')
}

@RTJakobs
Copy link

Would I put this source code e.g. in beforeEach() or does it have to be directly in the test case?
And when I have clicked on my element, do I then use the const together with cy.on()?

@hatseh
Copy link

hatseh commented May 29, 2024

We call it inside a getIframe function that is used to get the body of an iframe to fetch any element inside that iframe.

Cypress.Commands.add('getIframe', (iframeSelector = 'iframe', selector = 'body') => {
  cy.get(iframeSelector)
    .its('0.contentDocument')
    .then((doc) => {
      const win = doc.defaultView
      stubWindow(win)
      return cy.wrap(win.document.body, { log: false })
    })
})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stage: needs investigating Someone from Cypress needs to look at this type: bug
Projects
None yet
Development

No branches or pull requests

8 participants