cypress-example-recipes icon indicating copy to clipboard operation
cypress-example-recipes copied to clipboard

Add example of testing confirms and alerts triggered from within an iframe

Open jennifer-shehane opened this issue 5 years ago • 6 comments

The iframes have to be of the same origin and the alert/confirm triggered by something other than onload of the iframe for the examples to work.

Confirm

index.html

<html>
<body>
  <iframe id="iframe" width="300" height="200" src="iframe.html"></iframe>
</body>
</html>

iframe.html

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>Stubbing Iframe Window Confirm</title>
</head>
<body>
  <h1>My Iframe</h1>
  <input type="button" onclick="return confirmSubmit(this);">
  <script>
    function confirmSubmit() {
      if (confirm('Are you sure you want to submit your application?')) {
        console.log('CONFIRMED')
      }
    }
  </script>
</body>
</html>

spec.js

it('confirms in iframe', () => {
  cy.visit('index.html')
  cy.get('iframe').then(($iframe) => {
    const $body = $iframe.contents().find('body')
    const $win = $iframe[0].contentWindow

    cy.stub($win, 'confirm').as('windowConfirm')

    cy.wrap($body)
      .find('input').click().should(function () {
        expect(this.windowConfirm).to.be.calledWith('Are you sure you want to submit your application?')
      })
  })
})
Screen Shot 2020-01-29 at 1 59 15 PM

Alert

index.html

<!DOCTYPE html>
<html lang="en">
<body>
<iframe id="iframe" width="300" height="200"
  src="iframe.html">
</iframe>
</body>
</html>

iframe.html

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>Stubbing Iframe Window Alert</title>
</head>
<body>
  <h1>My Iframe</h1>
  <button id="alert">Alert</button>
  <script>
    var btn = document.getElementById('alert')
    btn.addEventListener('click', function (event) {
      window.alert("Hello world!")
    })
  </script>
</body>
</html>
it('alerts in iframe', () => {
  cy.visit('index.html')
  cy.get('iframe').then(($iframe) => {
    const $body = $iframe.contents().find('body')
    const $win = $iframe[0].contentWindow

    cy.stub($win, 'alert').as('windowAlert')

    cy.wrap($body)
      .find('#alert').click().should(function () {
        expect(this.windowAlert).to.be.calledWith('Hello world!')
      })
  })
})
Screen Shot 2020-01-16 at 11 35 04 AM

jennifer-shehane avatar Jan 29 '20 07:01 jennifer-shehane

Thanks! Do you know of a way to dismiss the confirm within the iframe, as if OK or Cancel was clicked?

isaacsobczak avatar Feb 28 '20 22:02 isaacsobczak

That is what the code above should do. This only works for iframe of the same origin of the main application under test though.

jennifer-shehane avatar Mar 02 '20 06:03 jennifer-shehane

Thank you very much. It looks like I'm able to stub the javascript function that calls confirm, but not the confirm itself. In my example, things are a little complicated, as I have an application with many nested iframes, and, I am using these instructions to open the application in a child window: https://glebbahmutov.com/blog/cypress-using-child-window/

Thanks!

isaacsobczak avatar Mar 17 '20 16:03 isaacsobczak

@jennifer-shehane I came across a situation where the code block you have mentioned above not working. I suspect the issue in my case is that the alert() was invoked inside a document ready again inside an internal same origin iframe which is not the top,

$(document).ready(function() { if(${!empty no_valid_licence}){ alert('Warning: some warning here'); } }

what my test has is,

cy.get('iframe#adminBody').then(($iframe) => {
      const $body = $iframe.contents().find('body')
      const $win = $iframe[0].contentWindow

      cy.stub($win, 'alert').as('windowAlert')
      cy.wrap($body).find('a:contains(\'cypress-client-23\')').click()
})
cy.get('@windowAlert').should('have.been.calledOnce')

Wonder if I missed anything but the only way I could pass this point in my test was to change the app side to fire the alert on the top iframe of the application using something like, parent.window.alert('Warning: some warning here'); which then automatically handle by cypress.

And the above test block works smoothly when I stub a alert happen inside the same iframe but not inside document.ready, which is thee main reason I was inclined that this perhaps need a work out to correctly add the stub to the window instance.

Any input on this would be highly appreciated.

supun-hettigoda avatar Mar 11 '21 03:03 supun-hettigoda

Are there any workarounds to handle these dialogs if the iframes are from different origins?

mmitchell3590 avatar Mar 31 '21 13:03 mmitchell3590

How to handle alerts if it is triggered from nested iframe. Any example would be much appreciated.

kavitha24 avatar Apr 13 '22 11:04 kavitha24