Ошибка Qunit: утверждение вне контекста тестирования

Я искал все, и эта ошибка возникает из-за неправильного использования asyncTest. Однако, по документации, похоже, что я делаю это правильно. Я предполагаю, что мне где-то не хватает маленькой детали, и мне нужна дополнительная пара глаз...

Я пытаюсь проверить код, который делает запрос ajax для получения страницы, а затем загружает ее в лайтбокс. lightbox-content не отображается в DOM до тех пор, пока вызов ajax не завершится и не будет отображаться. Поэтому я могу проверить это только в моем обратном вызове onComplete, где у меня есть мой тест, чтобы проверить, правильно ли он загружен.

Вот мой код:

asyncTest('mytest', 1, function() {
    utils.lightbox.show('/login', {
        onComplete: function() {
            ok($('#lighbox-content').is(':visible'), 'Lightbox loaded the /login page.');
            start();
        }
    });
});

Я получаю сообщение об ошибке:

Uncaught Error: assertion outside test context, was at HTMLDivElement.window.utils

Кто-нибудь может увидеть, где я ошибаюсь?

Ответ 1

Я согласен с тем, что ваш код соответствует документации, насколько я могу судить.

Обновление

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

asyncTest('mytest', 1, function() {
    stop();
    ...
});

Я использую Sinon.JS, чтобы избежать вызовов AJAX в первую очередь. Это имеет три преимущества:

  • Я не зависеть от сервера для ответа на запросы.
  • Я могу указать разные результаты для каждого теста.
  • Тесты выполняются намного быстрее.

Мытье может быть сделано на уровне XMLHttpRequest или в методе jQuery, и это довольно просто. Вот пример из одного из моих тестов:

module("geo", {
    setup: function () {
        this.server = sinon.fakeServer.create();
    },

    teardown: function () {
        this.server.restore();
    }
}

test("returns detected ZIP code", function () {
    this.server.respondWith("/geo/detect-zip-from-ip",
                            [ 200, { "Content-Type": "text/html" }, '90210' ]);
    geo.detectZip(function (zip) {
        assertThat(zip, is('90210'));
    });
    this.server.respond();
});

Ответ 2

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

Объяснение словами:

  • У меня сложный асинхронный тест
  • У меня есть задержки событий, и есть ok и equal утверждения внутри
  • Конечно, все это завернуто внутри asyncTest
  • Но, когда тест "завершен", и я вызываю start(), обработчики событий остаются там
  • После вызова start() все дальнейшие вызовы ok внутри asyncTest становятся незаконными
  • И выбросить исключения
  • Интересно, что произойдет, если превышено число в expect (в вашем примере это второй параметр). Такое же исключение?

Объяснение в коде:

    asyncTest('mytest', /*1,*/ function() {

          function imgLoadedOrFailed (result) {
              clearTimeout(imageTimeToLive);
              img.off();
              ok(result, 'Image in carousel pane has been loaded');
          }

          var imageTimeToLive = setTimeout(
                  imgLoadedOrFailed.bind(this, false), 
                  5000),
              img = panes[index].find('img:first');

          if (img) {
              img.on('load', imgLoadedOrFailed.bind(this, true));
              img.on('error', imgLoadedOrFailed.bind(this, false));
          }
      });


      // at some point I call: start();

В этом примере, когда я "закончу" вызов вызова start(), события onload и onerror все равно могут произойти.