Browser

Answering Browser Dialogs

A native dialog halts everything: the page stops, and so does the automation driving it, until the dialog is answered. WithDialogsAccepted says how to answer them. True is OK, and confirm reads true; false is Cancel, and confirm reads false. WithDialogText is what a prompt hands back, and saying it is enough on its own, since a workflow that says what to answer has said to answer. ClearDialogHandling stops answering, which is not the same as WithDialogsAccepted(false): false still answers, with Cancel. Say nothing and nothing changes, so a dialog opens and blocks the way it would for a person. Arm it before the first GoTo. Selenium reads the answer as a driver capability when the browser starts, so a browser that is already running was built without it, and GPAL says so with a WARNING rather than quietly doing nothing. After that, both answers can be changed as often as the workflow likes, before each step that raises a dialog: accept one confirm and dismiss the next, or type a different answer into each prompt.

NOTE

There are two ways to answer, and GPAL takes the quieter one wherever it can. Answering at the browser leaves the page untouched: Selenium does it through the WebDriver unhandledPromptBehavior capability, Puppeteer by replying to Page.javascriptDialogOpening with Page.handleJavaScriptDialog. The page's own alert, confirm and prompt are the browser's, so there is nothing for a site to notice. Answering in the page means replacing those three functions before the page runs, so no dialog is ever raised. OttoMagic always answers in the page, because an open dialog stops the page thread its extension talks through and there is nothing left to rescue the page with. Puppeteer never does: it answers at the browser and can carry prompt text while doing it. Selenium answers at the browser until a workflow calls WithDialogText, because its capability answers a prompt with the prompt's own default and cannot type; from that point it answers in the page too. So a workflow that only says yes or no keeps Selenium untouchable, and one that types into a prompt trades that for the ability to do it at all. One visible difference follows: answered at the browser the dialog opens and is accepted at the next command, so it can be seen briefly; answered in the page it never opens. Answering in the page rides InjectScript, so on OttoMagic it inherits what InjectScript needs: a real profile with Allow user scripts turned on for the extension. That is a one time click in chrome://extensions and there is no switch, capability or API that can do it for you, by design, since it is the guard that stops an extension granting itself arbitrary page script. A browser on a temporary profile has never had it, so nothing registers and the first dialog stops the workflow. Name a profile you have already turned it on in. Selenium registers the same script over CDP and needs nothing of the sort.

WARNING

Replacing the three functions is the one part of this a page could notice, which is why it is only done on the engine with no other way, and only once you ask. GPAL defines each one wherever the browser keeps the real one, which on Chrome is an own property of window rather than on Window.prototype, and reports them through toString the way the browser would, so ordinary checks for tampered natives find nothing. It is not proof against a determined one: a page that takes a clean Function.prototype.toString from a fresh iframe and calls it on window.alert reads GPAL's source. In practice the two populations barely overlap. A site running serious anti-bot is not raising window.confirm, it is rendering its own HTML modal. Native dialogs live on internal tools, admin panels and old line-of-business apps, which are not the sites fingerprinting natives. The exposure that is real is carrying it somewhere it earns nothing: once armed, the replacement is installed on every document whether a dialog appears or not, and it cannot be installed lazily, because the whole point is being there before page scripts run. So arm the browser that does the dialog work, and do not arm the one that visits the hard site.

Examples

GPAL Fluent: High-level fluent C# API

//WithDialogText on its own is enough to turn answering on, so the first block would work without the WithDialogsAccepted line; it is there because it reads better and because it is the call that has to come before the browser starts on Selenium. Changing either answer between two clicks works because GPAL writes the new one onto the page you are standing on as well as keeping it for the next document, and on Puppeteer because the answer is read at the moment the dialog opens. The unit is the step, not the dialog. One answer is in force at a time, so a single click that raises a confirm and then a prompt gets the same decision for both, and there is no way to vary within one action on any engine. After ClearDialogHandling, Puppeteer stops at once; where the answering was done in the page the three functions stay replaced but hand every call straight to the real one, so the page behaves as it would untouched, and ClearInjectedScripts followed by a navigation takes them off altogether. Selenium's capability cannot be stopped, because the driver was started with it and keeps it until the browser closes.

// one answer for the whole workflow

browser

.WithDialogsAccepted(true)

.WithDialogText("hello")

.GoTo("https://example.com/admin")

.LeftClick(saveButton); // its confirm is answered OK, its prompt reads "hello"


// a different answer before each step that raises one

browser

.WithDialogText("first") .LeftClick(saveButton)

.WithDialogText("second").LeftClick(nextButton);


// yes to one, cancel to the next

browser

.WithDialogsAccepted(true) .LeftClick(saveButton)

.WithDialogsAccepted(false).LeftClick(deleteButton);


// stop answering. dialogs open and block again

browser.ClearDialogHandling();

💬 Ask GPAL