chromedriver无头警报

时间:2017-07-21 16:10:20

标签: selenium-webdriver selenium-chromedriver google-chrome-headless

我用chromedriver进行了selenium webdriver测试。虽然我可以在使用Chrome浏览器时成功运行测试,但我无法在无头模式下运行相同的测试。

我无法处理Js警报。实际上,当拍摄截图时,警报似乎甚至不会弹出。

Alert screenshot

我尝试了几种解决方法:

1)driver.window_handles - >似乎没有其他窗口存在

2)driver.execute_script("window.confirm = function(){return true;}") - >该脚本没有任何改变

3)element = WebDriverWait(driver, 20).until(EC.alert_is_present())当然还有明确的等待

在浏览器模式下,我使用普通的:

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

其他人在无头模式下遇到此问题的警告?

  • chromedriver v.2.30.477691
  • Chrome版本59.0.3071.115

4 个答案:

答案 0 :(得分:15)

Chrome 61还有这个问题,所以我花了一些时间寻找不同的解决方案。我最喜欢的是因为它的简单性是在显示警报之前注入javascript以便自动接受警报。

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

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

适用于无头镀铬和PhantomJS。

答案 1 :(得分:3)

在运行无头镀铬时,我似乎遇到了同样的问题。 警报窗口不会根据屏幕截图弹出。它适用于镀铬而不是无头镀铬。

我在chrome 60.0.3112.72上运行 和镀铬驱动程序2.30

因为无头镀铬会自动丢弃警报。 检查一下: https://bugs.chromium.org/p/chromium/issues/detail?id=718235

顺便说一句,你怎么能在无头模式下用chrome 59屏幕截图? chrome 59有一个错误,使每个屏幕在无头模式下拍摄1x1像素图像,因此我升级到了chrome 60。

答案 2 :(得分:0)

由于Chrome headless(当前)不支持警报,因此您必须对alert()confirm()方法进行单一操作。这是我使用的方法(在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();

答案 3 :(得分:0)

只是想添加此内容,以防有人使用NightwatchJS遇到此问题。

上面接受的解决方案对我有用,但是使用JS时需要对它进行一些修改

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

我需要将其更改为

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