Как я могу получить мои тесты на жасминовые тесты для загрузки до того, как 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>