Следите за селектором JQuery в Жасмин
Я тестирую несколько модулей JavaScript с помощью Jasmine и хочу шпионить (смоделировать) элемент DOM, доступ к которому осуществляется с помощью селектора jQuery.
Моя спецификация:
it("should be able to mock DOM call", function() {
spyOn($("#Something"), 'val').andReturn("bar");
result = $("#Something").val();
expect(result).toEqual("bar");
});
В моем specrunner.html у меня есть:
<input type="hidden" id="Something" value="foo" />
К сожалению, спецификация не работает с:
должен быть в состоянии смоделировать вызов DOM Ожидаемый 'foo' равным 'bar'.
6 ответов
Эта строка неверна:
spyOn($("#Something"), 'val').andReturn("bar");
Функция spyOn Жасмина ожидает два параметра. Первый - это существующий объект. Второе - это имя функции в виде строки. Вы правильно передаете имя функции в виде строки ("val"), но не передаете существующий объект в качестве первого параметра.
$("#Something")
... это не существующий объект. Это результат (возвращаемое значение) селектора jQuery. Более конкретно, он вернет объект jQuery, представляющий совпавшие узлы - вроде как массив результатов.
$
... это существующий объект.
$.fn
... это существующий объект.
$("#Something")
... это не существующий объект - это результат селектора jQuery.
Это будет работать:
it("should be able to mock DOM call", function () {
//spyOn($.fn, "val").andReturn("bar"); //pre-jasmine 2.0 syntax
spyOn($.fn, "val").and.returnValue("bar"); //Jasmine 2.0 Syntax
var result = $("#Something").val();
expect(result).toEqual("bar");
});
Похоже, я нашел хорошее решение
it "should open past statuses", ->
# We can't use $('.past') here cause each time $('.past') called it returns different objects
# so we need to store spy in variable
showSpy = spyOn($.fn, 'show')
# do the stuff
$('.show-past').click()
# then check if 'show' action was called
expect($.fn.show).toHaveBeenCalled()
# and if it realy our object
expect(showSpy.mostRecentCall.object.selector).toEqual('.past')
Это не основано на вашем коде, но я надеюсь, что это может кому-то помочь. И, да, пример в CoffeScript.
Проблема в том, что два вызова $ возвращают два разных jQuery-обернутых узла.
Это должно работать:
it("should be able to mock DOM call", function(){
// var node = $("Something");
// spyOn(node, 'val').andReturn('bar');
// expect(node.val()).toEqual('bar');
var node = $("Something");
spyOn(node, 'val').and.returnValue('bar');
expect(node.val()).toEqual('bar');
});
В следующий раз помощь будет более распространена в списке рассылки Jasmine: jasmine-js@googlegroups.com.
Вы можете создать свой собственный поддельный DOM-элемент и затем использовать $('#elementid')[0] как обычно
addFakeElementWithId = function (elementId) {
var fake = document.createElement("div");
fake.setAttribute("id", elementId);
document.body.appendChild(fake);
};
Я написал вспомогательную функцию, которая принимает массив пар id/value.
var jasminTestHelper = {
spyOnValAndFake : function(obj) {
var i, j;
spyOn($.fn, 'val').andCallFake(function() {
for ( i = 0, j = obj.length; i < j; i++) {
if (this.selector === '#' + obj[i][0]) {
return obj[i][1];
}
}
})
}
}
Каждая пара сообщает фейкер-функции, для какого идентификатора, какое значение должно быть возвращено, если функция jQuery-val() вызывается с помощью селектора id. Используется так:
jasminTestHelper.spyOnValAndFake([["id1", "value1"], ["id2", "value2"]]);
Если $('#id1').val()
вызывается в тестируемой функции, фейковая функция возвращает value1
, если $('#id2').val()
называется это возвращает value2
, Таким образом, вам не нужно возиться с DOM, вы просто насмехаетесь над функцией jQuery-val() и моделируете возвращаемые значения. Другие jQuery-функции, вероятно, могли бы издеваться так же.
Я думаю, что в моей версии жасмина (2.0.3) произошли изменения, поэтому решение Алекса Йорка не сработало как есть, но определенно дало мне путь. Итак, вот рабочий код JQuery спецификации, который должен быть протестирован
$('someSelector').data('someAttribute').enable();
вот часть жасминовой спецификации
var mockJqueryObject = { enable:function(){},disable:function(){}};
//this mocks the .data('someAttribute') in above code.
spyOn($.fn, "data").and.returnValue(mockSelectBoxObject);
Более детальная спецификация может использовать другой уровень макета, как
spyOn(mockJqueryObject,"enable")
spyOn(mockJqueryObject,"disable")