Как я могу получить мои тесты на жасминовые тесты для загрузки до того, как javascript считает документ "готовым"?

Я достаточно уверен, что проблема заключается в том, что привязки jquery, установленные для запуска на $(document).ready, не имеют доступного для них файла html. Поэтому, когда происходят мои события, которые предназначены для внесения изменений в DOM с помощью функции jquery, ничего не происходит, и мои тесты терпят неудачу. Я видел "решение" этой проблемы здесь, но это решение, которое действительно работало для меня, потребовало изменения моей рабочей функции jquery для связывания с методом .live вместо .click метод. У меня есть две проблемы. Сначала я не хочу менять свой рабочий код, чтобы тесты прошли правильно. Структура тестирования должна проверять, будет ли код работать в приложении, где DOM-загрузка и привязки javascript происходят в правильном порядке. Вторая проблема, с которой я сталкиваюсь, заключается в том, что .on и .delegate оба не работали по какой-то причине, и единственное, что в конечном итоге работало, это использовать метод .live, который в настоящее время находится в процессе устаревания. В заключение я хотел бы выяснить, как изменить либо мои тесты, либо сами рамки тестирования, так что приборы загружаются перед функциями, которые работают в $(document).ready.

Я работаю с рельсами 3.2.8, и у меня есть две разные ветки, созданные для эксперимента с тестированием жасмина. Одна из ветвей использует жемчужину jasminerice, а другая - драгоценный камень жасминовых рельсов. Javascript и jQuery (при использовании метода .live) все тесты проходят правильно в обеих этих настройках.

Вот описание ветки с помощью jasminerice:

Вот строки из моего файла Gemfile.lock, описывающие настройку жасмина и jQuery:

jasminerice (0.0.9)
  coffee-rails
  haml
jquery-rails (2.1.3)
  railties (>= 3.1.0, < 5.0)
  thor (~> 0.14)

Jasminerice по умолчанию включает расширение jasmine-jquery. Расширение jasmine-jQuery предоставляет метод toHaveText, который я использую в тестах.

Тестовый файл jasmine_jquery_test.js, который находится непосредственно в каталоге spec/javascripts, содержит это содержимое:

#= require application

describe ("my basic jasmine jquery test", function(){

    beforeEach(function(){
        $('<a id="test_link" href="somewhere.html">My test link</a>').appendTo('body');
    });

    afterEach(function(){
        $('a#test_link').remove();
    });

    it ("does some basic jQuery thing", function () {
        $('a#test_link').click();
        expect($("a#test_link")).toHaveText('My test link is now longer');
    });

    it ("does some the same basic jQuery thing with a different trigger type", function () {
        $('a#test_link').trigger('click');
        expect($("a#test_link")).toHaveText('My test link is now longer');
    });

});
describe ('subtraction', function(){

    var a = 1;
    var b = 2;

    it("returns the correct answer", function(){
        expect(subtraction(a,b)).toBe(-1);
    });

});

Мой файл javascript tests.js, который находится в каталоге app/assets/javascripts, имеет этот контент:

function subtraction(a,b){
    return a - b;
}

jQuery (function($) {
/* 
    The function I would rather use - 
    $("a#test_link").click(changeTheTextOfTheLink)
    function changeTheTextOfTheLink(e) {
        e.preventDefault()
        $("a#test_link").append(' is now longer');
    }
*/

    $("a#test_link").live('click', function(e) {
        e.preventDefault();
        $("a#test_link").append(' is now longer');
    });

});

Мой файл application.js, расположенный в том же каталоге app/assets/javascripts, имеет следующее содержание:

//= require jquery
//= require jquery_ujs
//= require bootstrap
//= require vendor
//= require_tree . 

И описание ветки жасмин-рельсов можно найти в содержании моего первого вопроса о стеке-потоке, связанного с жасмином.

Итак, если кто-нибудь имеет представление о том, как манипулировать тестами, чтобы функции $(document).ready запускались после загрузки приборов, я бы очень хотел услышать ваши мысли?

Ответы

Ответ 1

Добавление jQuery непосредственно в html-устройство работало для меня, чтобы получить желаемое поведение. Это не совсем ответ на этот вопрос, но я начинаю считать это лучшим решением в настоящее время. Мои изменения, внесенные в настройку драгоценных камней жасминовых рельсов, и я еще не пробовал ее в ветке jasminerice.

Вот мой тестовый файл:

describe ("my basic jasmine jquery test", function(){

    beforeEach(function(){
        loadFixtures('myfixture.html');
    });

    it ("does some basic jQuery thing", function () {
        $('a#test_link').click();
        expect($("a#test_link")).toHaveText('My test link is now longer');
    });

    it ("does the same basic jQuery thing with a different event initiation method", function () {
        $('a#test_link').trigger('click');
        expect($("a#test_link")).toHaveText('My test link is now longer');
    });

});
describe ('substraction', function(){

    var a = 1;
    var b = 2;

    it("returns the correct answer", function(){
        expect(substraction(a,b)).toBe(-1);
    });

});

И вот мой файл fixture:

<a id="test_link" href="somewhere.html">My test link</a>

<script>
    $("a#test_link").click(changeTheTextOfTheLink)
    function changeTheTextOfTheLink(e) {
        e.preventDefault()
        $("a#test_link").append(' is now longer');
    }
</script>

Ответ 2

Лично я считаю, что это ошибка jasmine-jquery. Я "решил" это, сделав мои светильники частью SpecRunner.html. Не идеально, но он работает в простых случаях.

Ответ 3

Вы пробовали jasmine-jquery?

https://github.com/velesin/jasmine-jquery

С его страницы github,

jasmine-jquery предоставляет два расширения для Jasmine JavaScript Testing Framework:

набор пользовательских совпадений для рамки jQuery     API для обработки HTML, CSS и JSON-светильников в ваших спецификациях

Ответ 4

Я использовал dom_munger, чтобы автоматически сгенерировать инструмент для меня, поэтому добавление кода jquery вручную внутри инструмента не является для меня вариантом. Я искал тот же ответ, и лучшим решением, о котором я могу думать сейчас, является использование делегата события в jQuery.

Например, вместо того, чтобы писать это:

$('#target').click(function(){
    // Do work
});

Сделайте это:

$(document).on('click', '#target', function(){
    // Do work
});

Таким образом, слушатель прикрепляется к документу, который присутствует перед загрузкой прибора. Поэтому, когда событие click происходит на #target, оно пузырится до документа. Документ проверяет, соответствует ли исходный код второму аргументу - '#target'. Если он совпадает, будет вызываться функция обработчика.

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

Ответ 5

Я принял несколько иной подход к описанным здесь для решения этого ограничения.

Отказ от ответственности: я работаю в Microsoft, поэтому я не могу публиковать свой исходный код здесь без юридического одобрения, поэтому вместо этого я просто опишу подход, который хорошо работает.

Вместо того, чтобы пытаться изменить способ работы document.ready, я изменил источник jasmine-jquery для поддержки функции с именем fixturesReady, которая выполняет обратный вызов.

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

Затем на этом фрагменте вы можете установить триггер:

jasmine.Fixtures.prototype.load = function() {
  this.cleanUp()
  this.createContainer_(this.read.apply(this, arguments))

  fixturesReady.trigger("loaded", arguments); // <----- ADD THIS

}

Итак, в ваших тестах теперь вы можете указать код:

fixturesReady(yourCallback)

И вы знаете, что при вызове yourCallback вы можете безопасно запросить DOM для ваших элементов крепления.

Кроме того, если вы используете плагин async.beforeEach jasmine, вы можете сделать это:

async.beforeEach(function(done){

    fixturesReady(done);

    ...

    loadFixtures("....");

});

Надеюсь, что это поможет, и даст вам некоторые идеи по решению этой проблемы.

ПРИМЕЧАНИЕ. Помните, что в вашем плагине устраняются любые обратные вызовы в блоке afterEach, если необходимо:)

Ответ 6

Прошло некоторое время с тех пор, как этот вопрос был задан (и принят ответ).

Вот лучший подход для структурирования вашего теста и загрузки script для тестирования с жасмином.

Шаблоны/link.tmpl.html

<a id="test_link" href="somewhere.html">My test link</a>

JS/тест-link.js

$("a#test_link").click(changeTheTextOfTheLink)
function changeTheTextOfTheLink(e) {
    e.preventDefault()
    $("a#test_link").append(' is now longer');
}

данные/ссылка-test.spec.js

describe ("my basic jasmine jquery test", function(){

    jasmine.getFixtures().fixturesPath = ''

    var loadScript = function(path) {
      appendSetFixtures('<script src="' + path + '"></script>');
    };

    beforeEach(function(){
        loadFixtures('templates/link.tmpl.html');
        loadScript('js/test-link.js');
    });

    it ("does some basic jQuery thing", function () {
        $('a#test_link').click();
        expect($("a#test_link")).toHaveText('My test link is now longer');
    });

    it ("does the same basic jQuery thing with a different event initiation method", function () {
        $('a#test_link').trigger('click');
        expect($("a#test_link")).toHaveText('My test link is now longer');
    });

});

Spec Runner

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
  <title>Spec Runner</title>

  <link rel="stylesheet" type="text/css" href="lib/jasmine-2.0.3/jasmine.css">
  <script type="text/javascript" src="lib/jasmine-2.0.3/jasmine.js"></script>
  <script type="text/javascript" src="lib/jasmine-2.0.3/jasmine-html.js"></script>
  <script src="lib/jasmine-2.2/boot.js"></script>

  <script type="text/javascript" src="lib/jquery-2.1.3.min.js"></script>
  <script type="text/javascript" src="lib/jasmine-jquery.js"></script>

  <script type="text/javascript" src="specs/link-test.spec.js"></script>
</head>

<body>
</body>
</html>