Search code examples
javaseleniumfirefoxselenium-webdriverjunit

Selenium Close File Picker Dialog


We are using Selenium-Webdriver on Jenkins box (running linux), to drive Firefox for testing a fairly complex web app. The web app requires the uploading of a photo for testing, and we have achieved that by using sendkeys to the input file dialog. Unfortunately (perhaps due to the way the uploader works, it is plupload and uploads through XHR and not a FORM post) the File Picker Dialog never closes. While this was slightly annoying, in the past the tests still passed fine. Switching from selenium-2.45.0 to selenium-2.53.1 and upgrading FireFox to 45 we discovered that our tests now failed because element is no longer visible due to the File Picker Dialog (at least we assume that is reason that the elements no longer react to clicks is because they are behind the file dialog).

I realize that there is no way to click on the close dialog button, and I have tried sending the escape key various ways to browser to close the dialog but nothing I have tried works:

((RemoteWebDriver)driver).getKeyboard().pressKey(Keys.ESCAPE);

Since the Jenkins server running on the tests is on a different server than the Firefox being driven by Selenium, Roboto and AutoIt aren't an option. Is there some way to trigger closing of dialog that doesn't involve interacting with the dialog box. My thought was injecting some javascript into the page to create a form around the file input, and then submit the form (to nowhere), and then reloading the page but that has proven unsuccessful.

File Upload Dialog


Solution

  • There's probably a click event transmitted to the <input type="file"> element, which opens the file dialog.

    One way to overcome this issue is to disable the internal click by overriding the method. This piece of JavaScript will disable the internal click for each <input type="file"> element:

    ((JavascriptExecutor)driver).executeScript(
        "HTMLInputElement.prototype.click = function() {                     " +
        "  if(this.type !== 'file') HTMLElement.prototype.click.call(this);  " +
        "};                                                                  " );
    

    Then upload the file by calling .sendKeys("full file path") on the <input type="file"> element.

    In some cases, the <input type="file"> only resides in memory. If that's the case, you'll have to insert it in the page:

    ((JavascriptExecutor)driver).executeScript(
        "HTMLInputElement.prototype.click = function () {" +
        "    if (this.type !== 'file') {" +
        "        HTMLElement.prototype.click.call(this);" +
        "    }" +
        "    else if (!this.parentNode) {" +
        "        this.style.display = 'none';" +
        "        this.ownerDocument.documentElement.appendChild(this);" +
        "        this.addEventListener('change', () => this.remove());" +
        "    }" +
        "}");
    

    See https://gist.github.com/florentbr/d7bee068932bdf6e00af3b9f01af9af6