13

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
4

4 回答 4

16

从 Chrome 61 开始仍然存在这个问题,所以我花了一段时间寻找不同的解决方案。由于它的简单性,我最喜欢的是在显示警报之前注入 javascript,以便自动接受警报。

只需将以下代码行放在导致显示警报的行之前:

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

适用于无头 chrome 和 PhantomJS。

于 2017-09-07T13:20:47.237 回答
3

运行 headless chrome 时,我似乎遇到了同样的问题。警报窗口不会根据屏幕截图弹出。它在 chrome 上运行良好,但在无头 chrome 上运行良好。

我在 chrome 60.0.3112.72 和 chrome driver 2.30 上运行

因为 headless chrome 会自动丢弃警报。检查这个: https ://bugs.chromium.org/p/chromium/issues/detail?id=718235


顺便说一句,你怎么能在无头模式下用 chrome 59 截屏?chrome 59 有一个 bug,在 headless 模式下,每个屏幕截图都是 1x1 像素的图像,所以我升级到了 chrome 60。

于 2017-07-26T06:47:13.123 回答
2

由于 Chrome 无头(当前)不支持警报,因此您必须对alert()andconfirm()方法进行monkeypatch。这是我使用的方法(在 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.");
    }

我这样使用它:

        Driver.SetupAlert(true);
        this.ClickElement(ResetButton);
        Driver.WaitForAlert();
于 2017-07-28T21:13:46.963 回答
0

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; }})
于 2018-06-26T21:24:05.677 回答