How do you use Jasmine to test a jquery click function to see if it called a custom method?

4,124 views
Skip to first unread message

Kevin

unread,
Jun 28, 2011, 8:03:35 PM6/28/11
to Jasmine
I'm writing a `Jasmine` test to determine that a `function` is called
by the `JQuery` click() method. Where is my logic incorrect? Do I
spy on the jquery function or the custom function?

-error

Expected a spy, but got undefined. in http://localhost:8080/...etc.../jasmine.js
(line 1253)


-code

describe("funtionCalled", function() {
it("calls the click() function", function() {
var cc = new CustomClass();
spyOn($.fn, "click");
$( '#fieldID' ).click();
expect(cc.clickFunction()).toHaveBeenCalled();
});
});

-code being tested

var CustomClass = function(){};

$(document).ready(function(){
var cf = new CustomClass();

$( '#fieldID' ).click(
function() {
cf.clickFunction();
}
);
});

CustomClass.prototype.clickFunction = function() {
//some javascript code
};

Rajan Agaskar

unread,
Jun 28, 2011, 9:03:44 PM6/28/11
to jasmi...@googlegroups.com
spy-ing on $.fn.click will often prevent the click from firing at all. 

It's likely you'll want to spy on something like 

spyOn(CustomClass.prototype, "clickFunction")

I believe the following code should get you close 

   describe("funtionCalled", function() {
       it("calls the click() function", function() {
               spyOn(CustomClass.prototype, "clickFunction");
               $( '#fieldID' ).click();
               expect(CustomClass.prototype.clickFunction()).toHaveBeenCalled();
          });
   });

We have often used a dependency-injection-like pattern when writing our JS so we can simply initialize cc in our test, spy on the method we care about, and then pass it in instead of having to spy on the prototype. 

If you're able to easily verify the *results* of the clickFunction (ie, does it show/hide some DOM? Make an ajax call?), you might test for that instead of testing that it's called (since cc is a separate class, testing that clickFunction is called seems OK, as long as you have another unit test covering its behavior). 

Thanks!

Rajan 



--
You received this message because you are subscribed to the Google Groups "Jasmine" group.
To post to this group, send email to jasmi...@googlegroups.com.
To unsubscribe from this group, send email to jasmine-js+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/jasmine-js?hl=en.


Julien Wajsberg

unread,
Jun 29, 2011, 2:03:51 AM6/29/11
to jasmi...@googlegroups.com
On 29 June 2011 03:03, Rajan Agaskar <ra...@pivotallabs.com> wrote:
> testing that
> clickFunction is called seems OK,

Doing this is really testing jQuery, not his own code.
And jQuery is already thoroughly tested :-)

--
Julien

Rajan Agaskar

unread,
Jun 29, 2011, 7:52:09 AM6/29/11
to jasmi...@googlegroups.com
It's testing that he's bound the correct click function to the correct DOM element. I think this is a reasonable test to make -- it's like making sure that your "edit" button really invokes the "edit" behavior for your object, and doesn't remove it instead. 

If the behavior of clickFunction is complicated to describe, and it's already tested as part of another class, there's probably no need to re-do that testing. 


--

Eric Anderson

unread,
Jul 8, 2011, 4:30:31 PM7/8/11
to jasmi...@googlegroups.com
You need to spy on the click method of the jquery object that is returned from $('#fieldId'). So you need to spy both on window.$ and use a fake to inject a spy for the result of $('#fieldId').

I've always done something like this:

describe("functionCalled", function() {


it("calls the click() function", function() {

var field = jQuery('#fieldId');
spyOn(field, 'click');

$ = spyOn(window, '$').andCallFake(function(selector) {
switch(selector) {
case "#fieldId":
return field;
break;
default:
return jQuery(selector);
break;
}
});

$('#fieldId').click();

expect(field.click).toHaveBeenCalled();

$ = jQuery;

});
});

Eric Anderson
AppNexus

Reply all
Reply to author
Forward
0 new messages