I'm trying to spy on native WebSocket constructor, so I wrote:
it("should spy and call through WebSocket constructor", function (done) {
var WSspy = spyOn(window, "WebSocket").and.callThrough();
var ws = new WebSocket("ws://some/where");
expect(WSspy).to.toHaveBeenCalledWith("ws://some/where");
});
but it results in error:
TypeError: Failed to construct 'WebSocket': Please use the 'new' operator, this DOM object constructor cannot be called as a function.
How should I callThrough such constructor?
I found a workaround with callFake:
it("should spy and callFake WebSocket constructor", function (done) {
var realWS = WebSocket;
var WSSpy = spyOn(window, "WebSocket").and.callFake(function(url,protocols){
return new realWS(url,protocols);
});
var ws = new WebSocket("ws://some/where");
expect(WSSpy).toHaveBeenCalledWith("ws://some/where");
done();
});
It works quite fine, but it overwrites the WebSocket.prototype so make sure you use it or save the reference before creating the spy, like
var realWS = WebSocket;
var messageSpy = spyOn(WebSocket.prototype, "close").and.callThrough();
var WSSpy = spyOn(window, "WebSocket").and.callFake(function(url,protocols){
return new realWS(url,protocols);
});
Related
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();
});
});
I´m having a hard time understanding how to perform this action(as the title says), and maybe someone could help me understand the process, my code is below:
My home-view-model:
var Observable = require("data/observable").Observable;
var ObservableArray = require("data/observable-array").ObservableArray;
var http = require("http");
function createViewModel() {
http.getJSON("http://myJsonfile").then(function (r) {
var arrNoticias = new ObservableArray(r.data);
return arrNoticias;
}, function (e) {
});
}
exports.createViewModel = createViewModel;
I have done a console.log of the arrNoticias before i have putted it inside a callback function and it returns [object object] etc...and then i have done this:
console.log(arrNoticias.getItem(0).titulo);
and it returns the info i need!.
Then in my home.js file i have this:
var observableModule = require("data/observable")
var ObservableArray = require("data/observable-array").ObservableArray;
var arrNoticias = require('./home-view-model.js');
console.log(arrNoticias.getItem(0).titulo);
and the result in the console is:
TypeError: arrNoticias.getItem is not a function. (In 'arrNoticias.getItem(0)', 'arrNoticias.getItem' is undefined)
My question is, how does this action is perform? passing the data from view-model to the .js file?
Thanks for your time
Regards
As that function send a URL request so probably it's an async function, which is on hold while requesting so that's why you get undefined. Normally, you will want your function that sends a URL request to return a promise. Based on that promise, you will the result as expected after the request is done. So:
function createViewModel() {
return new Promise<>((resolve, reject) => {
http.getJSON("http://myJsonfile").then(function (r) {
var arrNoticias = new ObservableArray(r.data);
resolve(arrNoticias);
}, function(e) {
reject(e);
});
}), (e) => {
console.log(e);
})
}
In home.js:
var homeVM= require('./home-view-model.js');
var arrNoticias;
homeVM.createViewModel().then(function(r) {
arrNoticias = r;
});
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);
});
});
If you make a request to sails via supertest, the response hangs if you return an error.
Here, we have already lifted sails, and will run this as an integration test against a live db.
var sails = require('sails').lift();
var request = require('supertest');
var app = sails.hooks.http.app;
describe('The creation of a model',function(){
it('should not create a duplicate',function(done){
var user = request.agent(app);
user
.post('/api/create')
.end(function(err,res){
//never gets here, your test will hang
done();
});
});
});
//controller.js
module.exports = {
// /api/create routes here
create:function(req,res){
var params = {
name:"invalid"
};
SomeAction(params,function(err,results){
if (err) {
//the problem is here.
return err;
}
res.json(results);
});
}
};
If you make a supertest request to sails and the function just returns a value, ie. you don't use res.send() or res.json() it will hang the request for supertest. Here's the right way to do it:
var sails = require('sails').lift();
var request = require('supertest');
var app = sails.hooks.http.app;
describe('The creation of a model',function(){
it('should not create a duplicate',function(done){
var user = request.agent(app);
user
.post('/api/create')
.end(function(err,res){
//never gets here, your test will hang
done();
});
});
});
//controller.js
module.exports = {
// /api/create routes here
create:function(req,res){
var params = {
name:"invalid"
};
SomeAction(params,function(err,results){
if (err) {
//you need to send a response to the
res.json({
error:"an error occured"
});
}
res.json(results);
});
}
};
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);
});