t.setNativeDialogHandler Method

Important

Read the authentication guide for information on how to handle native authentication prompts.

The t.setNativeDialogHandler method allows users to define a set of rules for native dialog interaction.

TestCafe cannot interact with native dialogs before you initialize your first native dialog handler. If a native dialog appears before you call t.setNativeDialogHandler, the test fails with an error.

  • To dismiss all native dialogs, do not specify any arguments.
  • If you want to interact with dialogs in a different way, pass a function with dialog handling logic to the method.

TestCafe can interact with the following native dialog types:

Note

The browser does not display native dialogs when you use the TestCafe Native Dialog Handler. Call the t.getNativeDialogHistory method to view dialog contents.

t.setNativeDialogHandler(fn(type, text, url) [, options]) → this | Promise<any>
Parameter Type Description
fn Function / ClientFunction The handler function. Runs on the client when a page invokes a native dialog.
options (optional) Object See Client Function Options.

Table of Contents

Dismiss every dialog

Do not specify any arguments to dismiss all native dialogs:

await t.setNativeDialogHandler();
await t.eval(() => alert('TestCafe will dismiss this dialog!'));

Use custom handling logic

Create a handler function to interact with native dialogs:

  await t
    .setNativeDialogHandler((type, text, url) => 
        {
            // place the logic here
        }
    );

Note

TestCafe executes handler functions on the client. Do not reference Node.js API in handler functions.

The handler function can access the following dialog data:

Argument Type Description
type String Dialog type (alert, confirm, beforeunload, prompt, print, geolocation)
text String Dialog message
url String The URL of the page that invoked the dialog. Allows users to distinguish between main window dialogs and <iframe> dialogs.

TestCafe passes the function’s return value to the dialog. Different dialogs accept different data types:

Dialog type Expected return value Default action
alert None ‘OK’
beforeunload None ‘Leave’. It is impossible to emulate a click of the ‘Stay’ button.
print None ‘Cancel’
confirm true for ‘OK’, false or null for ‘Cancel’ ‘Cancel’
prompt String ‘Cancel’
geolocation Error object for ‘Block’, any other value for ‘Allow’. The success callback of the getCurrentPosition method usually expects a GeolocationPosition object. ‘Allow’ (TestCafe passes undefined to the success callback).

Examples

Accept All Native Dialogs

The following handler clicks the OK button for every native dialog:

fixture`TestController.setNativeDialogHandler`
    .page`https://devexpress.github.io/testcafe/example/`;

test('Should populate input', async t => {
    await t
        .setNativeDialogHandler(() => true)
        .click('#populate');
});

Distinguish between different dialog types

The following handler responds to geolocation dialogs, and dismisses the rest:

  await t
    .setNativeDialogHandler((type) => {
        if (type === 'geolocation')
            return { timestamp: 12356, accuracy: 20, coords: {latitude: '34.15321262322903', longitude: '-118.25543996370723'} };
        return null;
    });

The following handler gives different responses to different dialogs:

fixture`TestController.setNativeDialogHandler`
    .page`./pages/index.html`;

test('Handle Multiple Dialogs', async t => {
    await t
        .setNativeDialogHandler((type, text) => {
            switch (type) {
            case 'confirm':
                switch (text) {
                case 'Do you want to subscribe?':
                    return false;
                case 'Do you want to delete your account?':
                    return true;
                default:
                    throw 'Unexpected confirm dialog!';
                }
            case 'prompt':
                return 'Hi there';
            default:
                throw 'An alert was invoked!';
            }
        })
        .click('#confirm-subscription')
        .click('#show-prompt')
        .click('#confirm-account-deletion');
});

Pass custom data to the dialog handler

The app in the example below requires the user to enter the name of an item that they want to delete. Use the options.dependencies parameter to pass this data to the handler function:

class Page {
    constructor () {
        /* ... */
        this.deleteBtn = Selector('.item__delete');
        this.name      = Selector('.item__name').textContent;
    }

    async delete () {
        const name = await this.name;

        await t
            .setNativeDialogHandler(() => name, { dependencies: { name } })
            .click(this.deleteBtn);
    }
}

Change handler settings

To specify a new set of handler settings, call the t.setNativeDialogHandler method again:

// Test
test('Switch from "allow" to "block"', async t => {
  await t
    .setNativeDialogHandler((type) => {
        if (type === 'geolocation')
            return { timestamp: 12356, accuracy: 20, coords: {latitude: '34.15321262322903', longitude: '-118.25543996370723'}; // Passes this data to geolocation requests
        return null;
    });
    .click('#buttonGeo')
    .setNativeDialogHandler((type) => {
        if (type !== 'geolocation')
            return null;

        const err = new Error('Some error');

        err.code = 1;

        return err; // Blocks geolocation requests
    })
    .click('#buttonGeo');

Disable the handler

To disable the dialog handler, pass null to the t.setNativeDialogHandler method:

    t.setNativeDialogHandler(myHandlingFunction); // enables the handler
    await t.eval(() => alert('TestCafe will dismiss this dialog!'));
    t.setNativeDialogHandler(null) // disables the handler
    await t.eval(() => alert('TestCafe cannot handle this dialog.'));

Handle a dialog invoked on page load

TestCafe cannot interact with native dialogs before you initialize your first native dialog handler.

If your website invokes a native dialog on startup, start the test from a different page (for example: about:blank). Initialize a handler and use the t.navigateTo method to open your website.

Important

Use an absolute path/URL to navigate away from the about:blank page.

<body>
    <button id='btn'>Click me</button>
    <script>
        alert()
    </script>
</body>
fixture`TestController.setNativeDialogHandler`
    .page`about:blank`;

test('Handle a Dialog Invoked on Page Load', async t => {

    await t
        .setNativeDialogHandler(() => true)
        .navigateTo(`file:///${path.join(__dirname, './pages/dialog-on-load.html')}`)
        .click('#btn');
});