Как протестировать jQuery с Jasmine для $("#element-id"), если используется как $(this)
Я не знаю, как запустить этот тест Жасмин для моего JS, и, конечно, другие люди имеют эту проблему. Может, я делаю что-то не так или, может быть, это невозможно - я не нашел намека на это. Проблема связана с тем, что - в jQuery - $(this) не совпадает с элементом, выбранным, например, $ ("# this-id"):
Javascript:
[..]
$("#button-id").on("click", function(e) { callSomeFunctionWith( $(this) ); } );
Жасмин-тест (CoffeeScript):
[..]
spyOn some.object, "callSomeFunctionWith"
spyOnEvent( $("#button-id"), 'click' )
$("#button-id").trigger( "click" )
expect( some.object.callSomeFunctionWith ).toHaveBeenCalledWith( $("#button-id") )
К сожалению, этот тест не пройден (с любым изменением, таким как сохранение ссылки на переменную сначала в моем тесте Жасмин), потому что функция НЕ вызывается с помощью $("#button-id"), а вместо этого вызывается с помощью $(this), и $(this)!= $("#button-id").
Кто-нибудь может сказать мне, как выполнить этот тест? Я совсем потерян. Даже отличная статья Реми Шарпа о jQuery и $ (this) не получила меня дальше.
1 ответ
Хорошо, теперь у меня есть решение моей проблемы. Решение простое, объяснения нет. Я объясню решение с нуля.
Это мой код Javascript с jQuery, который я хочу протестировать с помощью jasmine-jquery:
$( "input.toggler" ).on( "click", function( e ) {
[...]
doSomethingWith( $(this) );
} );
А теперь, используя Jasmine-jQuery, я хочу убедиться, что функция JS "doSomethingWith" вызывается с правильным значением "$(this)".
Сначала можно подумать, что $(this) === $( "input.toggler"), но это не так. Внутри функции обратного вызова обработчика щелчков используемый jQuery $ (this) не является ни объектом jQuery $ ("input.toggler"), ни элементом DOM, на который ссылается этот объект. Как объясняет Реми Шарп в своей действительно хорошей статье " jQuery's this: demystified", "this" внутри функции обратного вызова является элементом DOM, но $ (this) создает объект jQuery из этого элемента DOM. И это не идентично объекту jQuery $( "input.toggler").
Поэтому, если вы хотите проверить это с помощью Jasmine, используя функцию "toHaveBeenCalledWith", вы должны сначала извлечь элемент DOM, используя document.getElementById(...) или же document.getElementsByTagName(...)[INDEX] (где INDEX это индекс элемента, который вы хотите, так как последняя функция дает вам массив элементов DOM), что является простым старым Javascript. Затем, когда вы извлекли требуемый элемент DOM, вы должны создать из него jQuery-объект, заключив его в $ (и).
Мой проходящий Jasmine-jQuery-тест наконец-то выглядит примерно так (с использованием Coffeescript):
it "does something with my input element", ->
DOM_input_element = document.getElementsByTagName( "input" )[0] # Choose the correct DOM element here
spyOn myobject.functions, "doSomethingWith"
spyOnEvent( $( 'input.toggler' ), 'click' )
[...]
$( 'input.toggler' ).trigger( 'click' )
# Check for changes after click:
expect( myobject.functions.doSomethingWith ).toHaveBeenCalledWith( $( DOM_input_element ) )
Таким образом, "$ (this)" из моего кода Javascript переводится в "$(DOM_input_element)" в моем тесте Jasmine-jQuery.
Надеюсь, это поможет вам в ваших проектах! Мне понадобилось много времени, чтобы понять это.