Is it possible to get sinon to resolve an argument, when the argument is a defered object?
Consider this:
function needToTest() {
var isInitialized = q.defer();
var importantResult;
var publicStuff;
publicStuff.isInitialized = isInitialized.promise.then(function(res) {
importantResult = res;
});
var someClass = new SomeClass(isInitialized);
publicStuff.getResult = function() {
return importantResult;
};
return publicStuff;
}
I use q as promise library, but it's not important.
SomeClass looks something like this:
function SomeClass(promise) {
this.foo = function() {
//
};
//after some initializing:
var result = true; //or false
promise.resolve(result);
}
It might be that this mock should have some sort of function to resolve a promise, but this is what I have so far:
var someClassMock = sinon.stub().withArgs(q.defer());
someClass.prototype.foo = sinon.stub().returns('foo');
return someClassMock;
and ultimately I try to create a testcase using sinon and Squire like this:
describe('test', function() {
var needToTestInstance;
beforeEach(function(done) {
new Squire()
.mock('someClassMock', someClassMock)
.require(['needToTest'], function(module) {
needToTest = module;
//Need to get the needToTest().isInitialized to resolve with a value!
done();
});
});
describe('importantResult', function() {
expect(needToTestInstance.getResult()).to.be(true);
});
});
Is it possible to get isInitialized to resolve at any point in the test?
Related
I have a Javascript modular application not using Angular/Backbone.
I am trying to write test case for my startup module but facing issue.
Startup.js:
window.claimStartup = function (options) {
this.options = $.extend({}, this.options, options);
this.cmds = new this.serviceModule(this);
}
getClaimsCategories: function (claimTypeCode) {
var self = this;
// Refresh claim categories
return $.when(self.cmds.getClaimsCategories(claimTypeCode))
.then(function (response) {
return response;
});
},
Service.js:
claimStartup.prototype.serviceModule = function (cfg) {
this.cfg = cfg;
this.init();
}
StartUp.spec.js:
var claimStartUp;
beforeEach(function () {
spyOn(window.claimStartup.prototype, 'serviceModule');
claimStartUp = new window.claimStartup();
});
it("should be able to get categories", function () {
jasmine.spyOn(claimStartUp.cmds, 'getClaimsCategories').andReturn('XYZ');
var categories= claimStartup.getClaimsCategories('ABC');
expect(categories).toEqual('XYZ');
});
I am getting error when populating this.cmds it says serviceModule constructor not defined, actually I need to mock serviceModule when claimStartup is initialised.
Please let me know how can i write test case in this scenario.
I am able to fix this, this might be useful for others.
var claimStartUp;
beforeEach(function () {
var spyService = jasmine.createSpy('serviceModule');
var methodService = window.claimStartup.prototype.serviceModule;
window.claimStartup.prototype.serviceModule = spyService;
var spyUI = jasmine.createSpy('uiModule');
var methodUI = window.claimStartup.prototype.uiModule;
window.claimStartup.prototype.uiModule = spyUI;
claimStartUp = new window.claimStartup();
});
I am trying to mock out every instance that is created with the new keyword for an object.
Here is the Object I am trying to mock out:
var SharedWhiteboardView = function(moduleEl, domService) {
'use strict';
var self;
var sharedWhiteboardProblemImage;
var whiteboardController;
var caller = false;
var toolbarController;
return {
initWhiteboard : function()
{
self = this;
sharedWhiteboardProblemImage = domService.find(moduleEl, '#sharedWhiteboardModule-sharedWhiteboardProblemImage');
var toolbarEL = $('#sharedWhiteboard-toolbar');
toolbarController = new ToolbarController(WhiteboardConstants.SHARED_WHITEBOARD_ID, toolbarEL, null);
toolbarController.init(false);
whiteboardController = toolbarController.getWhiteboardController();
},
enableWhiteboardEdition : function(enabled)
{
if(self.getWhiteboardObject() && self.getWhiteboardObject.hasOwnProperty('enableEdition')) self.getWhiteboardObject().enableEdition(enabled);
whiteboardController.setEnabled(enabled);
}
};
}
This is the file which I am trying to test and it creates a new instance of the above object
Box.Application.addModule('SharedWhiteboardModule', function(context) {
'use strict';
var self;
var moduleEl;
var domService;
var sharedWhiteboardView;
var modal;
var assignmentTimer = 3000;
var sharing = false;
var assignmentImageData = '';
return {
/**
* Initializes the module and caches the module element
* #returns {void}
*/
init: function() {
self = this;
domService = context.getService('DomService');
moduleEl = context.getElement();
sharedWhiteboardView = new SharedWhiteboardView(moduleEl, domService);
sharedWhiteboardView.initWhiteboard();
sharedWhiteboardView.enableWhiteboardEdition(false);
};
}
I am trying to write a unit test to test that the sharedWhiteboardView.enableWhiteboardEdition method is called with 'false'
However I am failing to attach a spy or stub that method out. I have tried these solutions and they did not work
//First Attempt
sinon.stub(SharedWhiteboardView, "enableWhiteboardEdition", function() {return 0})
// Second Attempt
sinon.stub(SharedWhiteboardView.prototype, "enableWhiteboardEdition").returns(0);
//Third Attempt
sandbox.stub(SharedWhiteboardView.prototype, 'enableWhiteboardEdition', checkEnableWhiteboardEdition());
//Fourth Attempt Trying the answer provided by chrmod
it.only('when type is "SharedWhiteboardModule-setEditable" should call sharedWhiteboardView.enableWhiteboardEdition', function (done) {
const view = SharedWhiteboardView();
sinon.stub(view, "enableWhiteboardEdition", function() {
console.log('Hit');
});
module.onmessage('SharedWhiteboardModule-setEditable', true);
done();
});
No error but it does not hit the console.log, I removed the 'new' keyword as suggested
Errors that I got:
-Attempted to wrap undefined property enableWhiteboardEdition as function
-Cannot stub non-existent own property enableWhiteboardEdition
Please any help would be great. I have reached a dead end here.
Here is a codepen: http://codepen.io/anon/pen/bgmNxx?editors=0011
All I am trying to do is to have the Fake method get hit when my module calls enableEdition
SharedWhiteboardView is not a constructor, it is rather a factory function. Once called (without new) it returns new object that has enableWhiteboardEdition as own property.
Thus a stub has to be set on that object:
const view = SharedWhiteboardView();
sinon.stub(view, "enableWhiteboardEdition", function() {return 0});
This did it.
it('when type is "SharedWhiteboardModule-setEditable" should call setEditable with appropriate callback', function (done) {
var mockSharedWhiteboardView = {
enableWhiteboardEdition: function() {},
initWhiteboard: function() {},
initScrollBar: function() {},
refreshScrollBar: function() {},
isMainWhiteboardAvailable: function() {}
};
sandbox.spy(mockSharedWhiteboardView, 'enableWhiteboardEdition');
var tempGlobals = {
SharedWhiteboardView: global.SharedWhiteboardView
};
global.SharedWhiteboardView = function() {
return mockSharedWhiteboardView;
};
module = Box.Application.getModuleForTest('SharedWhiteboardModule', contextFake);
module.init();
var shouldEnable = true;
module.onmessage('SharedWhiteboardModule-setEditable', shouldEnable);
assert(mockSharedWhiteboardView.enableWhiteboardEdition.calledWithExactly(shouldEnable),
'should enable the whiteboard');
shouldEnable = false;
module.onmessage('SharedWhiteboardModule-setEditable', shouldEnable);
assert(mockSharedWhiteboardView.enableWhiteboardEdition.calledWithExactly(shouldEnable),
'should not enable the whiteboard');
// cleanup
global.SharedWhiteboardView = tempGlobals.SharedWhiteboardView;
done();
});
Simpleish react question that is evading me for a second:
readData: function(){
var readFromCpDev1 = firebase.database().ref('environments/' + 'cp-dev1');
var envUsersArray = [];
readFromCpDev1.on('value', function(snapshot) {
envUsersArray.push(snapshot.val())
return envUsersArray;
});
console.log(envUsersArray, 'hey');
},
anotherfunc: function(){
}
I have this function and I want to return envUsersArray and use it wherever. Obviously at the moment it is returning a blank array as the readData function is not in the scope of the snapshot function.
How can I pass it down to the readData function and then use it inside another function such as anotherfunc
I know I probably need to call this. somewhere but the logic isn't quite coming to me at the mo
I'd suggest using Promises.
readData: function(){
return new Promise(function(resolve) {
var readFromCpDev1 = firebase.database().ref('environments/' + 'cp-dev1');
var envUsersArray = [];
readFromCpDev1.on('value', function(snapshot) {
envUsersArray.push(snapshot.val())
resolve(envUsersArray);
});
});
},
anotherfunc: function(){
this.readData().then(function(arr) {
//do stuff here
});
}
You may return a promise that will resolve with value that is retrieved asynchronously:
readData: function() {
var readFromCpDev1 = firebase.database().ref('environments/' + 'cp-dev1');
var envUsersArray = [];
return new Promise(function(success) {
readFromCpDev1.on('value', function(snapshot) {
envUsersArray.push(snapshot.val())
success(envUsersArray);
}
});
},
anotherfunc: function(){
this.readData().then(function(result) {
console.log(result);
});
}
I'm having problems testing a Store in flux, wanting to stub out the dispatcher. I've seen how it's done with jest, but I Want to achieve the same with sinon.
Here's what I have
Source
lib/Dispatcher. Full code here
var invariant = require('./invariant');
//...
function Dispatcher() {
this.$Dispatcher_callbacks = {};
}
Dispatcher.prototype.register=function(callback) {
var id = _prefix + _lastID++;
this.$Dispatcher_callbacks[id] = callback;
return id;
};
// ...
module.exports = Dispatcher;
Dispatcher:
module.exports.Dispatcher = require('./lib/Dispatcher')
AppDispatcher:
var Dispatcher = require('flux').Dispatcher;
var copyProperties = require('react/lib/copyProperties');
var AppDispatcher = copyProperties(new Dispatcher(), {
handleViewAction: function(action) {
this.dispatch({
source: 'VIEW_ACTION',
action: action
});
}
});
module.exports = AppDispatcher;
ItemStore, the one I want to test
var AppDispatcher = require('../dispatcher/AppDispatcher');
var EventEmitter = require('events').EventEmitter;
var ItemConstants = require('../constants/ItemConstants');
var merge = require('react/lib/merge');
var CHANGE_EVENT = 'change';
var _items = [];
var ItemStore = merge(EventEmitter.prototype, {
getSoekeresultat: function() {
return _items;
},
emitChange: function() {
this.emit(CHANGE_EVENT);
}
});
AppDispatcher.register(function(payload) {
var action = payload.action;
switch(action.actionType) {
case ItemConstants.ITEMS_FETCHED:
_items = action.payload;
ItemStore.emitChange();
break;
default:
}
return true; // No errors. Needed by promise in Dispatcher.
});
module.exports = ItemStore;
So what I want to stub is AppDispatcher.register. How do I do that?
I've tried doing it several ways, the last I tried was this:
var sinon = require("sinon");
require("jasmine-sinon");
describe("ItemStore", function(){
var AppDispatcher = require('js/dispatcher/AppDispatcher.js');
sinon.stub(AppDispatcher, 'register', function () {
console.log("stub");
});
it("should use stub when called directly", function(){
AppDispatcher.register(function (payload) {
});
//outputs "stub"
});
it("should use stub when requiring itemstore", function(){
var ItemStore = require('js/stores/ItemStore.js');
// doesn't output "stub"
});
});
Can someone tell me how to stub it?
Although it's not strictly answering your question, you can achieve what you're trying to using proxyquire. It'll allow you to stub the AppDispatcher that is required inside ItemStore. e.g.
var proxyquire = require('proxyquire');
var AppDispatcher = require('js/dispatcher/AppDispatcher.js');
var StubbedAppDispatcher = sinon.stub(AppDispatcher)
/*
* This will load the `ItemStore` module, satisfying it's `AppDispatcher`
* dependency (the `require('../dispatcher/AppDispatcher')` statement)
* with our stubbed version.
*/
var ItemStore = proxyquire('js/stores/ItemStore.js', {
'../dispatcher/AppDispatcher': StubbedAppDispatcher
});
I have a function like:
function Aoeu($xhr) {
$xhr('GET', '/url', function(code, response) {});
};
How do I create with Jack a $xhr mock that's to be passed into Aoeu()?
The following says that the mock is an object, not a function (which makes sense):
AoeuTest.prototype.testAoeu = function() {
jack(function() {
var xhrStub = jack.create('$xhr', ['']);
// jack.expect('$xhr');
var aoeu = new Aoeu(xhrStub);
});
};