5 Answers
5

Jasmine's spyOn function expects two parameters. The first is an existing object. The second is a function name as a string. You are correctly passing in the function name as a string ("val") but you are not passing in an existing object as the first parameter.

$("#Something")

...is not an existing object. It is the result (the return value) of a jQuery selector. More specifically, it will return a jQuery object representing the matched nodes - kind of like an array of results.

I'm similarly confused. var $foo = $('#foo'). Now $foo IS an existing object: it is a jQuery object. It has a val() method; it just happens to get it by looking up its prototype chain to jQuery.fn. So why can't I do spyOn($foo, "val")? Why does Jasmine's spy require me to specify where the method is defined? My use case is that I want to check that, say, hide() has been called, not just in general, but on $foo. So spyOn(jQuery.fn, "hide") doesn't give me the information I want, but spyOn($foo, "hide") would - if it worked.
–
Nathan LongOct 27 '11 at 21:15

@NathanLong is right - this is the wrong answer. I'm not sure why its been upvoted so high..
–
badunkJul 6 '12 at 10:11

8

@NathanLong The problem is that every time you execute a jquery selector, you get a brand new object, so the one you set up to spy upon is going to be different than the one you get inside the code under test. Hence Alex is telling you to spy the prototype ($.fn) for all the jquery objects.
–
Leonardo Garcia CrespoAug 29 '12 at 19:51

@badunk it's upvoted so high because it answers the question: "what is actually called when I use jQuery('foo')" ;)
–
metaOct 16 '13 at 8:50

Hi , Can you please help me on the BLOCK method of jQuery ,I am not able to check its called count in Jasmine/Sinon test case ...
–
N.KJun 2 at 7:31

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')

This is not based on your code but i hope this can help someone. And, yes, example in CoffeScript.

This is your answer, jQuery returns a different object for each query, even if its the same selector. You need to reference the same object in order to properly spy on it. Otherwise, you're spying on one, and executing on another.
–
badunkJul 6 '12 at 10:10

If $('#id1').val() is called in your function under test, the fake-function returns value1, if $('#id2').val() is called it returns value2. So you don't need to fiddle with the DOM, you just mock the jQuery-val()-function and simulate return-values. Other jQuery-functions could probably mocked the same way.