Как ждать выполнения запросов jQuery Ajax от WatiN? - PullRequest
8 голосов
/ 04 марта 2010

Я пишу WatiN тесты для тестирования Ajax веб-приложения и столкнулись с проблемой синхронизации запросов Ajax.

После того, как Ajax-запрос вызван действием на странице, я бы хотел, чтобы WatiN дождался завершения запроса, прежде чем проверять, что страница была обновлена ​​правильно.что решение будет включать в себя eval-ing JavaScript для регистрации обработчиков для $.ajaxStart и $.ajaxComplete для отслеживания того, выполняются ли запросы.Я скоро вникну в это, но хотел посмотреть, решил ли кто-нибудь еще это.Похоже, что это обычная проблема с тестированием Ajax.

Ответы [ 3 ]

18 голосов
/ 04 марта 2010

Я создал несколько методов расширения WatiN Browser для решения этой проблемы, но все еще заинтересован в других решениях.

Метод InjectAjaxMonitor создает глобальную переменную javascript, которая присоединяется к событиям ajaxStart и ajaxComplete для отслеживания количества выполняющихся запросов.

Всякий раз, когда вам нужно дождаться завершения запросов AJAX, прежде чем двигаться дальше, вы можете позвонить browserInstance.WaitForAjaxRequest();.


public static class BrowserExtensions
{
    public static void WaitForAjaxRequest( this Browser browser )
    {
        int timeWaitedInMilliseconds = 0;
        var maxWaitTimeInMilliseconds = Settings.WaitForCompleteTimeOut*1000;

        while ( browser.IsAjaxRequestInProgress()
                && timeWaitedInMilliseconds < maxWaitTimeInMilliseconds )
        {
            Thread.Sleep( Settings.SleepTime );
            timeWaitedInMilliseconds += Settings.SleepTime;
        }
    }

    public static bool IsAjaxRequestInProgress( this Browser browser )
    {
        var evalResult = browser.Eval( "watinAjaxMonitor.isRequestInProgress()" );
        return evalResult == "true";
    }

    public static void InjectAjaxMonitor( this Browser browser )
    {
        const string monitorScript =
            @"function AjaxMonitor(){"
            + "var ajaxRequestCount = 0;"

            + "$(document).ajaxSend(function(){"
            + "    ajaxRequestCount++;"
            + "});"

            + "$(document).ajaxComplete(function(){"
            + "    ajaxRequestCount--;"
            + "});"

            + "this.isRequestInProgress = function(){"
            + "    return (ajaxRequestCount > 0);"
            + "};"
            + "}"

            + "var watinAjaxMonitor = new AjaxMonitor();";

        browser.Eval( monitorScript );
    }
}
6 голосов
/ 14 декабря 2010

Это решение работает не очень хорошо, потому что .ajaxStart вызывается только для первого Ajax-запроса, тогда как .ajaxComplete вызывается каждый раз, когда Ajax-запрос завершается. если вы запустите в своей консоли этот простой код:

$.ajax({url:"/"}); $.ajax({url:"/"})

и добавив некоторые записи в методы обработчика .ajaxStart и .ajaxComplete, вы увидите, что обработчик .ajaxStart будет вызываться только один раз, а обработчик .ajaxComplete - дважды. Так что ajaxRequestCount станет отрицательным, и весь ваш дизайн облажался.

Я предлагаю вам использовать .ajaxSend вместо .ajaxStart, если вы хотите сохранить свой дизайн.

Другим решением будет использование .ajaxStop вместо .ajaxComplete, но при этом вам не нужен ajaxRequestCount, вам нужен только логический параметр, который говорит, что за сценой выполняются запросы ajax.

Очень полезную информацию можно найти: http://api.jquery.com/category/ajax/global-ajax-event-handlers/

Надеюсь, это поможет.

3 голосов
/ 05 января 2011

Я сам столкнулся с этой проблемой, работая над некоторыми тестами с использованием WatiN. Я обнаружил, что в версии 1.1.0.4000 WatiN (выпущенной 2 мая 2007 г. (последняя версия 2.0 RC2 от 20 декабря 2009 г.)) утверждается, что улучшена поддержка обработки Ajax в тесты добавлено:

Для лучшей поддержки тестирования AJAX включенные сайты, этот релиз добавляет еще несколько опций для вашей панели инструментов.

Добавлен новый метод, который будет ждать пока какой-то атрибут не имеет определенного значение. Это может быть удобно в ситуации, когда вам нужно ждать пока значение элемента не получит обновлен.

Пример:

// Wait until some textfield is enabled
textfield.WaitUntil("disable", false.ToSting, 10);
// Wait until some textfield is visible and enabled
textfield.WaitUntil(new Attribute("visibile", new BoolComparer(true)) && new Attribute("disabled", new BoolComparer(false)));

Для получения дополнительной информации см. Ссылку на примечания к выпуску .

Я еще не изучал это подробно, поэтому не могу сказать, в каких случаях это может быть полезно или нет. Но подумал, что стоит упомянуть, если кто-нибудь еще столкнется с этим вопросом.

...