хромированные оповещения без головы

У меня проблема с тестами selenium webdriver с помощью chromedriver. Хотя я могу успешно запускать тесты при использовании браузера Chrome, я не могу запускать те же тесты в безголовом режиме.

Я не могу обрабатывать предупреждения Js. Вообще-то при снятии скриншота кажется, что предупреждение даже не всплывает.

снимок экрана с предупреждением

Я пробовал несколько обходных путей:

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")

У кого-нибудь еще есть эта проблема с предупреждениями в безголовом режиме?

  • хромированная отвертка v.2.30.477691
  • Версия Chrome 59.0.3071.115

person Alex Pas    schedule 21.07.2017    source источник


Ответы (4)


Эта проблема все еще существует с Chrome 61, поэтому я некоторое время искал другое решение. Из-за простоты мне больше всего нравится вставлять javascript перед отображением предупреждения, чтобы автоматически принять предупреждение.

Просто поместите следующую строку кода перед строкой, которая вызывает отображение предупреждения:

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

Работает как с безголовым хромом, так и с PhantomJS.

person Ruben van Kruistum    schedule 07.09.2017
comment
Это ПЕРВОНАЧЕ важно. Итак, ребята, поместите эту строку перед element.click() и просто добавьте для python driver.execute_script("window.confirm = function(){return true;}"); - person Alex Pas; 08.09.2017
comment
Привет, ребята, у меня такая же ситуация, что в безголовом режиме всплывающее окно не распознается. Пытался следовать приведенному выше коду. Но это ошибки при использовании ExecuteJavaScript. Я делаю что-то неправильно? Это функция, определяемая пользователем? если это именно то, что мне нужно кодировать. - person Roja; 30.11.2017
comment
Правильно ли я, если буду следовать так: ((JavascriptExecutor) драйвер) .executeScript (window.confirm = function () {return true;}); - person Roja; 30.11.2017
comment
Он должен работать точно так же, как указано выше (с использованием селена и C #). Код в вашем втором комментарии для меня не имеет никакого смысла. Может быть, вам где-то не хватает ссылки или использования? - person Ruben van Kruistum; 01.12.2017
comment
У меня была эта проблема, и это сработало для меня с небольшой модификацией с использованием NightwatchJS (this.api в данном случае то же самое, что и browser.perform ()): this.api.perform (function () {this.confirm = function ( ) {return true;}}) - person ChaBuku Bakke; 27.06.2018

Похоже, у меня такая же проблема при запуске безголового хрома. Окно предупреждения не появляется на снимках экрана. Он отлично работает с хромом, но не с безголовым хромом.

Я использую Chrome 60.0.3112.72 и хром-драйвер 2.30

Потому что безголовый хром автоматически отбрасывает предупреждения. проверьте это: https://bugs.chromium.org/p/chromium/issues/detail?id=718235


Кстати, как получилось, что вы можете сделать снимок экрана в Chrome 59 в режиме без головы? В Chrome 59 есть ошибка, из-за которой каждый снимок экрана представляет собой изображение размером 1x1 пиксель в режиме без головы, поэтому я обновился до Chrome 60.

person Luyao Zhou    schedule 26.07.2017
comment
Я не знаю, но у меня это работает .. driver.save_screenshot("ss.png"), но давайте продолжим тему - person Alex Pas; 27.07.2017

Поскольку 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();
person Ken Smith    schedule 28.07.2017

Просто хотел добавить это на случай, если кто-то столкнется с этой проблемой при использовании 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; }})
person ChaBuku Bakke    schedule 26.06.2018