webdriverio/webdriverio
Auf GitHub ansehen[🐛 Bug]: `dialog.accept()`/`dialog.dismiss()` Has no Effect in IFrame in Firefox
Open
#14.732 geöffnet am 29. Aug. 2025
Bug 🐛help wanted
Beschreibung
Have you read the Contributing Guidelines on issues?
- I have read the Contributing Guidelines on issues.
WebdriverIO Version
9.19.2
Node.js Version
v22.13.1
Mode
WDIO Testrunner
Which capabilities are you using?
[
{
browserName: 'chrome',
},
{
browserName: 'firefox',
},
],
What happened?
I created a repository where I reproduce some bugs in wdio: https://github.com/htho/wdio-repro-collection
I test an application that has an iframe that displays a dialog at some point.
In chrome i can call dialog.accept() (as long as I am in the frame that opened the dialog), in firefox it has no effect.
What is your expected behavior?
I should be able to call dialog.accept()/dialog.dismiss() regardless of the current context.
How to reproduce the bug.
git clone https://github.com/htho/wdio-repro-collection.git
cd wdio-repro-collection
npm ci
npm run test:alertInIframe
For completeness sake this is the relevant code:
let _dialog: PromiseWithResolvers<WebdriverIO.Dialog> | undefined;
before(async () => {
browser.on("dialog", (dialog) => {
if(_dialog === undefined) throw new Error("Received a dialog event but no resolver is set up!");
_dialog.resolve(dialog);
});
});
beforeEach(async () => {
_dialog = Promise.withResolvers<WebdriverIO.Dialog>();
await browser.switchFrame(null);
await browser.url(`https://htho.github.io/wdio-repro-collection/alertInIframeParent.html`);
});
describe('dialog', () => {
it("is triggered and handled in parent (works in chrome & firefox)", async () => {
if(_dialog === undefined) throw new Error("Dialog resolver must be setup at this point!");
await $(`#alert`).click();
await expect(_dialog.promise).resolves.toBeDefined();
const dialog = await _dialog.promise;
await expect(dialog.message()).toBe("my alert (parent)");
console.log("####################################################### A")
await dialog.accept();
console.log("####################################################### B")
await browser.switchFrame(null);
console.log("####################################################### C")
});
it("is triggered and accepted in child (works in chrome but not in firefox)", async () => {
if(_dialog === undefined) throw new Error("Dialog resolver must be setup at this point!");
await browser.switchFrame($(`iframe`));
await $(`#alert`).click();
await expect(_dialog.promise).resolves.toBeDefined();
const dialog = await _dialog.promise;
await expect(dialog.message()).toBe("my alert (iframe)");
console.log("####################################################### A")
await dialog.accept(); // no effect in firefox
console.log("####################################################### B")
await browser.switchFrame(null); // fails here - we can not switch the frame while a dialog is open.
console.log("####################################################### C")
});
it("is triggered in child but accepted in top-level (works neither in chrome nor in firefox)", async () => {
if(_dialog === undefined) throw new Error("Dialog resolver must be setup at this point!");
await browser.switchFrame($(`iframe`));
await $(`#alert`).click();
await expect(_dialog.promise).resolves.toBeDefined();
const dialog = await _dialog.promise;
await expect(dialog.message()).toBe("my alert (iframe)");
console.log("####################################################### A")
await browser.switchFrame(null);
console.log("####################################################### B")
await dialog.accept();
console.log("####################################################### C")
});
it("is triggered in child but appears when we are in the top-level (works neither in chrome nor in firefox)", async () => {
if(_dialog === undefined) throw new Error("Dialog resolver must be setup at this point!");
await browser.switchFrame($(`iframe`));
await $(`#delayedAlert`).click();
await browser.switchFrame(null);
await expect(_dialog.promise).resolves.toBeDefined();
const dialog = await _dialog.promise;
await expect(dialog.message()).toBe("my delayed alert (iframe)");
console.log("####################################################### A")
await dialog.accept(); // no effect in chrome and firefox
console.log("####################################################### B")
await browser.switchFrame(null); // fails here - we can not switch the frame while a dialog is open.
console.log("####################################################### C")
});
});
<!-- alertInIframeParent.html -->
<h1>Alert Iframe</h1>
<h2>Parent</h2>
<button id="alert" onclick="alert('my alert (parent)')">Show Alert</button>
<button id="delayedAlert" onclick="setTimeout(() => alert('my delayed alert (parent)'), 1000)">Show Delayed Alert</button>
<h2>Iframe</h2>
<iframe id="myIframe" src="alertInIframe.html"></iframe>
<!-- alertInIframeParent.html -->
<button id="alert" onclick="alert('my alert (iframe)')">Show Alert</button>
<button id="delayedAlert" onclick="setTimeout(() => alert('my delayed alert (iframe)'), 1000)">Show Delayed Alert</button>
Relevant log output
*Please reproduce the bug to generate the relevant logs - I think they would be too hard to read in this context.*
Code of Conduct
- I agree to follow this project's Code of Conduct
Is there an existing issue for this?
- I have searched the existing issues