webdriverio/webdriverio

[🐛 Bug]: `dialog.accept()`/`dialog.dismiss()` Has no Effect in IFrame in Firefox

Open

#14.732 geöffnet am 29. Aug. 2025

Auf GitHub ansehen
 (2 Kommentare) (0 Reaktionen) (0 zugewiesene Personen)JavaScript (6.029 Stars) (1.793 Forks)batch import
Bug 🐛help wanted

Beschreibung

Have you 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

Contributor Guide