SinonJS 101 error - qunit

I'm try to learn this tech and somehow getting stuck at the opening.
Please tell me why this test isn't working. What obvious thing did I miss?
var myfunc = function() {
alert('hello');
}
test("should spy on myfunc", function() {
var mySpy = sinon.spy(myfunc);
myfunc();
sinon.assert.calledOnce(mySpy);
});

It's the scope of myfunc. This works:
var o = {
myfunc: function() {
alert('hello');
}
};
test("should spy on myfunc", function() {
var mySpy = sinon.spy(o, "myfunc");
o.myfunc();
sinon.assert.calledOnce(mySpy);
ok(true);
});

The reason your test is not working is because you're not invoking the spy, rather the original function.
And the reason #carbontax's example works is because in that case, o.myfunc is replaced by the spy automatically; so when you invoke o.myfunc, you're actually invoking the spy.

As Mrchief said, you are not invoking spy but calling myfunc();, you should invoke spy something like.
test("should spy on myfunc", function() {
var mySpy = sinon.spy(myfunc);
mySpy(); // <= should called instead of myfunc()
sinon.assert.calledOnce(mySpy);
});

Related

Jasmine spyOn function call inside function under test

I am trying to use Jasmine to test the following function:
var Pdba = Class.create();
Pdba.prototype = {
getChangeGroup: function(userId) {
var query = 'active=true^u_change_group=true^u_organization=false^';
var exGroup = new CompanyGroup();
var groups = exGroup.getGroupsByQuery(userId, query); //want to spy/mock this call
if (groups.next()) {
return groups.sys_id.toString();
}
return '';
}
type: 'Pdba'
};
I want to SpyOn the getGroupsByQuery() call, so that it doesn't make the actual call. Below is a collection of various things I have been trying, mostly just to see if I can "spy" and see that it has been called, then work on overriding so that I can replace the call with my own data.
describe('my suite of getChangeGroup tests', function() {
var expPdba;
var validUserId = 'user1';
var expGrp;
var ggbqMoc
beforeEach(function() {
expPdba = new global.Pdba();
coGrp = new CompanyGroup();
spyOn(coGrp, 'getGroupsByQuery');
ggbqMoc = jasmine.createSpy('getGroupsByQuery');
});
it('should return \'\' for empty userId', function() {
coPdba.getChangeGroup('');
expect(coGrp.getGroupsByQuery).toHaveBeenCalled();
expect(ggbqMoc).toHaveBeenCalled();
});
});
Is this possible or do I need to change the function under test to take a 'CompanyGroup' as a parameter?
Thank you
I'm assuming you are using jasmine v3. The syntax for creating a spy is pretty weird now- you have to pass a string that refers to the name of the variable you want to create a spy for, and then you pass an array of function names that should be spied on.
Try this:
describe('my suite of getChangeGroup tests', function() {
var expPdba;
var validUserId = 'user1';
var expGrp;
var spy;
beforeEach(function() {
expPdba = new global.Pdba();
coGrp = new CompanyGroup();
spy = jasmine.createSpyObj('coGrp', ['getGroupsByQuery'])
});
it('should return \'\' for empty userId', function() {
coPdba.getChangeGroup('');
expect(coGrp.getGroupsByQuery).toHaveBeenCalled();
expect(spy).toHaveBeenCalled();
});
});

Jasmine testing, using a constructor in the beforeEach

i am attempting to create a new instance of two classes that i have already written in separate files. when i try to create new instances of them in the beforeEach() section of the test code, the tests return undefined for my newly created objects. however when i create them in each IT section the test run perfectly.
describe("placeStone", function() {
beforeEach(function() {
var go = new Display();
var logic = new Internals(go);
logic.tempBoard = [ array];
});
it("should place a black stone at 0,6", function() {
logic.placeStone(logic.black,0,6);
expect(logic.tempBoard[6][0]).toEqual("B");
});
this returns logic undefined.
describe("placeStone", function() {
it("should place a black stone at 0,6", function() {
var go = new Display();
var logic = new Internals(go);
logic.tempBoard = [ array];
logic.placeStone(logic.black,0,6);
expect(logic.tempBoard[6][0]).toEqual("B");
});
});
this seems to work the way i want. how can i get it to work in the beforeEach() section?
var logic should be defined in the scope of the describe function, then it exists both in the scope of the beforeEach function and the spec (the it function), e.g.
describe('suite', function () {
var myVar;
beforeEach(function(){
myVar = 10;
});
it('checks myVar', function () {
expect(myVar).toEqual(10);
});
});

Javascript: How to spy on superagent with Jasmine?

I'm using the superagent ajax library for an app, and I'm trying to write some unit tests for it. I've got a class which looks like this:
someClass = {
getData: function(){
_this = this;
superagent.get('/some_url').end(function(res){
if(res.body){
_this.data = res.body
}
});
});
}
How do I write a Jasmine test to spy on the _this.data = res.body call? Setting up a spy with and.callThrough() on getData isn't working. I don't want to actually call the URL in question; I'm just trying to test that if it gets data, it does something with it.
Thanks
spyOn(superagent, 'get').and.callFake(function(url) {
return {
end: function(cb) {
//null for no error, and object to mirror how a response would look.
cb(null, {body: data});
}
}
});
Bror's answer works perfectly. To add something to his answer, when we need to add another superagent function (like set) to the spyOn method, you can use as follows.
spyOn(superagent, 'get').and.callFake(function(url) {
return {
set: function() {
return {
end: function(cb) {
//null for no error, and object to mirror how a response would look.
cb(null, {body: data});
}
}
}
});
Here, the set function is used to set headers to the request.
There's another good solution here, which is to abstract out the anonymous function:
someClass = {
getData: function(){
_this = this;
superagent.get('/some_url').end(this.handleAjax);
},
handleAjax: function(res){
if(res.body){
_this.data = res.body
}
}
}
Now you can test the handleAjax function discretely and with simple tests; and also stub superagent as you only need to check a method .end() is called on it with a particular value.
Anonymous functions are problematic for other reasons than just testing so this is a good refactor
Say it's a patch, first make a mock patch return value:
this.mockPatchObject = {
set: () => {
return {
end: (cb: any) => {
cb(null, {body: 'etc'});
},
};
},
};
then return it as the value of patch:
this.superagentSpy = spyOn(request,'patch').and.returnValue(this.mockPatchObject);
then spy on the set function of the "mock" patch object:
this.superagentSetSpy = spyOn(this.mockPatchObject, 'set');

CasperJS code from tutorial does not work

It's my first post here : )
I'm learning CasperJS and I have to write script who search all img's on site and check urls.
I found this tutorial from vgaltes.com
var imagesArray = [];
function getImages() {
var scripts = document.querySelectorAll('img[src]');
return Array.prototype.map.call(scripts, function (e) {
return e.getAttribute('src');
});
};
casper.start('http://fooo.fooo', function () {
imagesArray = this.evaluate(getImages);
var self = this;
imagesArray.forEach(function (item) {
if (self.resourceExists(item)) {
self.echo(item + ' loaded');
} else {
var message = item + ' not loaded';
self.echo(message, 'ERROR');
}
});
});
but when I run this code on CasperJS (with valid url) do not work. Nothing happens.
Casper Version is 1.1
Looks like you did not run the function, try adding the below code in the end
casper.run(function() {this.test.renderResults(true);});
I'm the owner of vgaltes.com. As Pbk1303 said, you have to call to run function. If you read the tutorial, is the last source code posted.
casper.run(function(){
this.echo('finished');
this.test.done(1);
this.test.renderResults(true);
});
Regards,

backbone console log event triggering

I've got a underscore/backbone/require application and I would like to output all events that are triggered through backbone to the console (in other words: pass each event through console.log function). I've tried wrapping it with underscore and manually replacing the function. Neither this:
console.log(Backbone.Events.trigger);
var trigger = Backbone.Events.trigger;
Backbone.Events.trigger = function(name) {
console.log('Event', name, 'triggered.');
trigger.apply(this, arguments);
}
nor this:
Backbone.Events.trigger = _.wrap(Backbone.Events.trigger, function(func) {
console.log('EVENT:', Array.prototype.slice.call(arguments));
func(Array.prototype.slice.call(arguments));
});
console.log(Backbone.Events.trigger);
worked. I'd appreciate a javascript (not coffeescript) solution.
Your wrappings fail because Backbone mixes in Backbone.Events behavior on Backbone.Model, Backbone.Collection, etc. For example, Backbone.Model is defined as
var Model = Backbone.Model = function(attributes, options) {
...
};
_.extend(Model.prototype, Events, {
...
};
This means that when you redefine Backbone.Events.trigger, it is already too late.
But all is not lost! You won't be able to redefine all trigger methods in one go, but you can redefine them on class level:
Backbone.Model.prototype.trigger = function() {
console.log('Event', arguments);
Backbone.Events.trigger.apply(this, arguments);
}
and a demo http://jsfiddle.net/nikoshr/G2Qfn/
For a given class, you can override the trigger method:
var M = Backbone.Model.extend({
trigger: function() {
console.log('Event', arguments);
Backbone.Model.prototype.trigger.apply(this, arguments);
}
});
http://jsfiddle.net/nikoshr/G2Qfn/1/
or for a given instance
var M = Backbone.Model.extend({});
var m = new M();
m.trigger = function() {
console.log('Event', arguments);
M.prototype.trigger.apply(this, arguments);
}
http://jsfiddle.net/nikoshr/G2Qfn/2/

Resources