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
- Use custom handling logic
- Change handler settings
- Disable the handler
- Handle a dialog invoked on page load
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');
});