chromedriver headless alerts

风格不统一 提交于 2019-11-29 02:49:59

问题


I have this issue with selenium webdriver tests with chromedriver. Although I can run tests succesfully when using Chrome browser I can't run the same tests in headless mode.

I cannot handle the Js alerts. Actually when taking a screenshot it seems that the alert won't even pop-up.

Alert screenshot

I have tried several workarounds:

1) driver.window_handles --> No other window seems to be present

2) driver.execute_script("window.confirm = function(){return true;}") --> Nothing changed with that script

3) element = WebDriverWait(driver, 20).until(EC.alert_is_present()) and of course an explicit wait

In browser mode I use a plain:

try:
    print driver.switch_to.alert.text
    driver.switch_to.alert.accept()
except NoAlertPresentException as e: 
    print("no alert")

Anyone else having this issue with alerts in headless mode?

  • chromedriver v.2.30.477691
  • Chrome Version 59.0.3071.115

回答1:


Still having this problem as of Chrome 61, so I spent a while looking for a different solution. My favorite because of it's simplicity is injecting javascript before the alert is shown in order to automatically accept the alert.

Just put the following line of code before the line that causes the alert to be shown:

driver.ExecuteJavaScript("window.confirm = function(){return true;}");

Works with both headless chrome and PhantomJS.




回答2:


It seems that I have the same issue when running headless chrome. The alert window does not pop up base on the screen shots. It works fine on chrome but not headless chrome.

I am running on chrome 60.0.3112.72 and chrome driver 2.30

Because the headless chrome automatically discards alerts. check this: https://bugs.chromium.org/p/chromium/issues/detail?id=718235


BTW, how come you can screen shot in chrome 59 in headless mode? chrome 59 has a bug that makes every screen shot a 1x1 pixel image in headless mode, so I upgraded to chrome 60.




回答3:


Since Chrome headless doesn't (currently) support alerts, you have to monkeypatch the alert() and confirm() methods. This is the approach I've used (in C#):

    /// <summary>
    /// The Chrome Headless driver doesn't support alerts, so we need to override the window.alert method to get the expected behavior.
    /// </summary>
    /// <param name="driver">The active IWebDriver instance</param>
    /// <param name="result">The result that the alert should return, i.e., true if we want it "accepted", false if we don't</param>
    public static void SetupAlert(this IWebDriver driver, bool result)
    {
        // ks 7/27/17 - The Chrome Headless driver doesn't support alerts, so override the various window.alert methods to just set 
        const string scriptTemplate = @"
window.alertHandlerCalled = false;
window.alertMessage = null;
window.alert = window.confirm = function(str) {
    window.alertHandlerCalled = true;
    window.alertMessage = str;
    return {{result}};
};";

        var script = scriptTemplate.Replace("{{result}}", result.ToString().ToLower());
        var js = (IJavaScriptExecutor)driver;
        js.ExecuteScript(script);
    }

    /// <summary>
    /// This is an optional accompaniment to the <see cref="SetupAlert"/> method, which checks to see
    /// if the alert was, in fact, called. If you don't want to bother to check, don't worry about calling it.
    /// Note that this doesn't reset anything, so you need to call <see cref="SetupAlert"/> each time before calling
    /// this method.
    /// </summary>
    public static void WaitForAlert(this IWebDriver driver, TimeSpan? timeout = null)
    {
        const string script = @"return window.alertHandlerCalled";
        var js = (IJavaScriptExecutor)driver;
        var timeToBail = DateTime.Now.Add(timeout ?? TimeSpan.FromMilliseconds(500));
        while (DateTime.Now < timeToBail)
        {
            var result = (bool)js.ExecuteScript(script);
            if (result) return;
            Thread.Sleep(100);
        }
        throw new InvalidOperationException("The alert was not called.");
    }

I use it like this:

        Driver.SetupAlert(true);
        this.ClickElement(ResetButton);
        Driver.WaitForAlert();



回答4:


Just wanted to add this in case someone comes across this issue using NightwatchJS.

The above accepted solution worked for me, but using JS it needed a slight modification from

driver.ExecuteJavaScript("window.confirm = function(){return true;}");

I needed to change it to

// this.api.perform() in my case is the same as browser.perform() 
this.api.perform(function () { this.confirm = function () { return true; }})


来源:https://stackoverflow.com/questions/45242264/chromedriver-headless-alerts

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!