I'm writing Cypress tests to validate iframe security policies around sandbox & CSP permissions. I have disabled allow-modals
and calls to alert and others fail as expected the following Chrome generated error message: VM271 about:srcdoc:1 Ignored call to 'alert()'. The document is sandboxed, and the 'allow-modals' keyword is not set.
Great, as expected.
Now I need to build a Cypress test to prove that the behavior on the iframe is correct. I was initially going to do this by spying on the iframe/window's console.error and checking for a call with the above error message. This did not work. I have wrapped the window, iframe, and cypress environment error handlers and console.error
functions with a spy and none of them are called when Chrome logs the above 'ignore alert' error message. I also wrapped the iframe window.alert()
in a spy and it is still called (as expected) but the browser's alert modal doesn't show (as expected because it's being ignored by chrome).
Is there a way to catch the browser's 'special' error log here? If it's not being logged through the browser window or iframe window elements, how is it being logged?
Iframe:<iframe><script>alert('test');</script></iframe>
Cypress:
let iframeWindow;let spyErrorIframe;cy.get('iframe').then(($iframe) => { iframeWindow = $iframe[0].contentWindow; function errorHandler(...args) { console.log('~~~ iframe'); return iframeWindow.console.error(...args); } spyErrorIframe = cy.spy(errorHandler); iframeWindow.addEventListener('error', spyErrorIframe); iframeWindow.onerror = spyErrorIframe; cy.spy(iframeWindow.console, 'log'); cy.spy(iframeWindow.console, 'error'); cy.spy(iframeWindow, 'alert');});let mainWindow;let spyErrorWindow;cy.window().then((win) => { mainWindow = win; function errorHandler(...args) { console.log('~~~ window'); return iframeWindow.console.error(...args); } spyErrorWindow = cy.spy(errorHandler); mainWindow.addEventListener('error', spyErrorWindow); mainWindow.onerror = spyErrorWindow; cy.spy(win, 'alert'); cy.spy(win.console, 'log'); cy.spy(win.console, 'error');});cy.wait(GENERIC_TIMEOUT + 1000).then(() => { console.log('~~~ iframe console.error', iframeWindow.console.error.getCalls()); // no calls console.log('~~~ window console.error', mainWindow.console.error.getCalls()); // no calls console.log('~~~ cypress console.error', console.error.getCalls()); // no calls console.log('~~~ iframe error event', spyErrorIframe.getCalls()); // no calls console.log('~~~ window error event', spyErrorWindow.getCalls()); // no calls console.log('~~~ iframe alert', iframeWindow.alert.getCalls()); // one call as expected console.log('~~~ window alert', mainWindow.alert.getCalls()); // no calls});