Error testing this function - javascript

I want to write a unit test for this function with Jasmine:
getState: function () {
var $selectState = this.$('#selectState:visible');
if ($selectState) {
return $selectState.val();
}
return null;
},
I wrote this test:
describe("function getType", function(){
it("should return value", function() {
var obj = {val: function(){return 'ok';}};
var spy1 = jasmine.createSpy("spy1").and.callFake(
function() {
return obj;
}
);
var dollar = $;
$ = spy1;
expect(view.getType()).toEqual('ok');
$ = dollar;
});
});
In my oppinion it should work, but it does not. This is the error message:
Expected undefined to equal 'ok'.
Does anybody know what the problem could be?

I solved the problem. this.$ seems to be different from $, thus changing the test function like this solved the problem:
describe("function getState", function(){
it("should return value", function() {
var obj = {val: function(){return 'ok';}};
var spy1 = jasmine.createSpy("spy1").and.returnValue(obj);
var dollar = view.$;
view.$ = spy1;
expect(view.getState()).toEqual('ok');
view.$ = dollar;
});
});

Related

Javascript Protractor - Seeing outside functions as undefined

In specs/Test.js is a test definition: "regex2"
In pages/TablePage.js is a page object
in regex2 there is a try to use a function from TablePage.js
it('regex2', function(){
table_page.matchPriceRegex(table_page.workingBalanceField)
});
it is saying table_page.matchPriceRegex is not a function
The function itself from TablePage.js:
var TablePage = (function () {
function TablePage() {
this.workingBalanceField = element(By.xpath('//*[#id="root"]/main/section/div/div/div[5]/div/div[1]'));
}
TablePage.prototype.matchPriceRegex = function (locator) {
this.text = locator.getText();
expect(this.text).toMatch("\d{0,3}?,?\d{0,3}?\.?\d{0,3}?");
};
});
module.exports = TablePage;
The require's are incorporated with the spec file so it should see it
var TablePage = require("./../pages/TablePage");
var table_page = new TablePage();
var protractor = require("protractor");
var jasmine = require("jasmine-node");
var browser = protractor.browser;
var number = 0;
When in my IDE(WebStorm) I hold ctrl and click on the function name it redirects me correctly, as it sees it
The typeof the functions or variables form TablePage is undefined
Do you know where is the problem?
The error comes from TablePage.js, it should be.
var TablePage = (function () {
function TablePage() {
this.workingBalanceField = element(By.xpath('//*[#id="root"]/main/section/div/div/div[5]/div/div[1]'));
}
TablePage.prototype.matchPriceRegex = function (locator) {
this.text = locator.getText();
expect(this.text).toMatch("\d{0,3}?,?\d{0,3}?\.?\d{0,3}?");
};
return TablePage; // return the class as outer function return value
})();
// `(function(...){})` return a function, you should use `()` to execute the
// return function to get the returned class: TablePage.
module.exports = TablePage;

Javascript execution error in Sublime

I am learning JavaScript and this is my 1st week :)
var Module = (function () {
// code
var publicMethod = {};
var privateMethod = function(someStringToBePassed) {
debug("I love USA. "+someStringToBePassed);
}
publicMethod.someFunction = function() {
privateMethod("USA is sexy");
}
return publicMethod;
})();
debug(Module.someFunction());
I am executing this in Sublime. I am seeing the following result.
--> I love USA. USA is sexy
--> undefined
Please explain why I am seeing undefined here.
[Finished in 0.0s]
Please tell me why I am seeing "undefined" in the results
You're not returning anything from someFunction. Try this:
Now someFunction returns the value of privateMethod. privateMethod returns the constructed string.
var Module = (function () {
// code
var publicMethod = {};
var privateMethod = function(someStringToBePassed) {
return "I love USA. "+someStringToBePassed;
}
publicMethod.someFunction = function() {
return privateMethod("USA is sexy");
}
return publicMethod;
})();
debug(Module.someFunction());
var Module = (function () {
//code
var publicMethod = {};
var privateMethod = function(someStringToBePassed) {
return ("I love USA. "+someStringToBePassed);
}
publicMethod.someFunction = function() {
return privateMethod("USA is sexy");
}
return publicMethod;
})();
var sample = Module;
console.log(sample.someFunction())

Idiom for using Jasmine with bare functions and RequireJS

What approach can I take to mock bare functions when working with Jasmine and RequireJS?
As far as I can tell, I cannot conveniently use spyOn, because that needs the object the function is a method on. Although I can get this object (the RequireJS context.defined object), the assignment to bareFunction in foo.js has already occurred by the time the test is run, making changes to that function impossible at test-time (IIUC).
bare-function.js
define(function() {
return function bareFunction() {
return 'a';
};
});
foo.js
define(function(require){
var bareFunction = require('bare-function');
return {
doSomething: function() {
var v = bareFunction();
return v.toUpperCase();
}
};
}
foo-unit-test.js
define(function(require) {
var bareFunction = require('bare-function');
var target = require('foo');
describe('foo', function(){
describe('doSomething', function(){
it('should uppercase the result of the bare-function', function() {
//arrange
var bareFunctionResult = 'test value';
bareFunction.mockWith(function() { return bareFunctionResult; }); // Pseudocode.
//act
var result = target.doSomething();
//assert
expect(result).toBe(bareFunctionResult.toUpperCase());
});
});
});
});
The best I can come up with is attach a __stub method to the bare function and have the function short-circuit if this is set. e.g.
bare-function.js
define(function() {
var stub;
function bareFunction() {
if(stub) {
return stub();
}
return 'a';
};
bareFunction.__stub = function(v) {
stub = v;
};
bareFunction.__unstub = function() {
stub = null;
};
return bareFunction;
});
In the end I modified my foo.js so that doSomething accepted an optional shadow function for bareFunction, enabling trivial stubbing/mocking.
foo.js
define(function(require){
var bareFunction = require('bare-function');
return {
doSomething: function(bareFunctionShadow) {
var fn, v;
fn = bareFunctionShadow || bareFunction;
v = fn();
return v.toUpperCase();
}
};
}
foo-unit-test.js
define(function(require) {
var bareFunction = require('bare-function');
var target = require('foo');
describe('foo', function(){
describe('doSomething', function(){
it('should uppercase the result of the bare-function', function() {
//arrange
var bareFunctionResult = 'test value';
var bareFunctionMock = function() { return bareFunctionResult; };
//act
var result = target.doSomething(bareFunctionMock);
//assert
expect(result).toBe(bareFunctionResult.toUpperCase());
});
});
});
});

Javascript error - Object has no method

I got the following script shortened :
var HTH = HTH || {};
(function() {
var assetGrouping = function() {
var self = this;
this.options = {
_tmpElement: '',
QuantityAssigned: 0,
qtyInputField: ''
};
this.init = function(options){
// ...
this.options.QuantityAssigned = 0;
jQuery(this.options.qtyInputField).bind('keyup', function(){
self._tmpElement = jQuery(this);
self.CalculateQuantityAssigned();
});
// ...
}
CalculateQuantityAssigned = function(){
// ...
}
}
HTH.assetGrouping = new assetGrouping();
})();
$(document).ready(function(){
HTH.assetGrouping.init({
qtyInputField: 'input[name^="at700_group_qty"]'
});
});
The error happen at the following line : self.CalculateQuantityAssigned(); and the error is Uncaught TypeError: Object [object Object] has no method 'CalculateQuantityAssigned'.
I don't understand. Using this will fail of course and self is working when I want to access self.options but not for self.CalculateQuantityAssigned().
Thanks.
Change:
CalculateQuantityAssigned = function(){
// ...
}
to
this.CalculateQuantityAssigned = function(){
// ...
}
(function () {
}); <-- You have a function, but you never execute it!
You need to add the ();

How to stub require() / expect calls to the "root" function of a module?

Consider the following jasmine spec:
describe("something.act()", function() {
it("calls some function of my module", function() {
var mod = require('my_module');
spyOn(mod, "someFunction");
something.act();
expect(mod.someFunction).toHaveBeenCalled();
});
});
This is working perfectly fine. Something like this makes it green:
something.act = function() { require('my_module').someFunction(); };
Now have a look at this one:
describe("something.act()", function() {
it("calls the 'root' function of my module", function() {
var mod = require('my_module');
spyOn(mod); // jasmine needs a property name
// pointing to a function as param #2
// therefore, this call is not correct.
something.act();
expect(mod).toHaveBeenCalled(); // mod should be a spy
});
});
This is the code I'd like to test with this spec:
something.act = function() { require('my_module')(); };
This has bogged me down several times in the last few months. One theoretical solution would be to replace require() and return a spy created with createSpy(). BUT require() is an unstoppable beast: it is a different "copy" of the function in each and every source file/module. Stubbing it in the spec won't replace the real require() function in the "testee" source file.
An alternative is to add some fake modules to the load path, but it looks too complicated to me.
Any idea?
rewire is awesome for this
var rewire = require('rewire');
describe("something.act()", function() {
it("calls the 'root' function of my module", function() {
var mod = rewire('my_module');
var mockRootFunction = jasmine.createSpy('mockRootFunction');
var requireSpy = {
mockRequire: function() {
return mockRootFunction;
}
};
spyOn(requireSpy, 'mockRequire').andCallThrough();
origRequire = mod.__get__('require');
mod.__set__('require', requireSpy.mockRequire);
something.act();
expect(requireSpy.mockRequire).toHaveBeenCalledWith('my_module');
expect(mockRootFunction).toHaveBeenCalled();
mod.__set__('require', origRequire);
});
});
It looks like I found an acceptable solution.
The spec helper:
var moduleSpies = {};
var originalJsLoader = require.extensions['.js'];
spyOnModule = function spyOnModule(module) {
var path = require.resolve(module);
var spy = createSpy("spy on module \"" + module + "\"");
moduleSpies[path] = spy;
delete require.cache[path];
return spy;
};
require.extensions['.js'] = function (obj, path) {
if (moduleSpies[path])
obj.exports = moduleSpies[path];
else
return originalJsLoader(obj, path);
}
afterEach(function() {
for (var path in moduleSpies) {
delete moduleSpies[path];
}
});
The spec:
describe("something.act()", function() {
it("calls the 'root' function of my module", function() {
var mod = spyOnModule('my_module');
something.act();
expect(mod).toHaveBeenCalled(); // mod is a spy
});
});
This is not perfect but does the job quite well. It does not even mess with the testee source code, which is kind of a criterion for me.
I needed to do this today and came across this post. My solution follows:
In a spec helper:
var originalRequire = require;
var requireOverrides = {};
stubModule = function(name) {
var double = originalRequire(name);
double['double'] = name;
requireOverrides[name] = double;
return double;
}
require = function(name) {
if (requireOverrides[name]) {
return requireOverrides[name];
} else {
return originalRequire(name);
}
}
afterEach(function() {
requireOverrides = {};
});
In a spec:
AWS = stubModule('aws-sdk');
spyOn(AWS.S3, 'Client');
// do something
expect(AWS.S3.Client).toHaveBeenCalled();
This was very helpful, but it doesn't support calling through via .andCallThrough().
I was able to adapt it though, so I thought I'd share:
function clone(obj) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
var key;
var temp = new obj.constructor();
for (key in obj) {
if (obj.hasOwnProperty(key)) {
temp[key] = clone(obj[key]);
}
}
return temp;
};
spyOnModule = function spyOnModule(name) {
var path = require.resolve(name);
var spy = createSpy("spy on module \"" + name + "\"");
moduleSpies[path] = spy;
// Fake calling through
spy.andCallThrough = function() {
// Create a module object
var mod = clone(module);
mod.parent = module;
mod.id = path;
mod.filename = path;
// Load it backdoor
originalJsLoader(mod, path);
// And set it's export as a faked call
return this.andCallFake(mod.exports);
}
delete require.cache[path];
return spy;
};
You can use gently module (https://github.com/felixge/node-gently). Hijacking require is mentioned in examples, and dirty NPM module actively uses it, so I suppose it works.
There is another approach. You can put the module in the global scope by not using var when requiring it:
someModule = require('someModule');
describe('whatever', function() {
it('does something', function() {
spyOn(global, 'someModule');
someFunctionThatShouldCallTheModule();
expect(someModule).toHaveBeenCalled();
}
}
You could also wrap the module in another module:
//someModuleWrapper.js
require('someModule');
function callModule(arg) {
someModule(arg);
}
exports.callModule = callModule;
//In the spec file:
someModuleWrapper = require('someModuleWrapper');
describe('whatever', function() {
it('does something', function() {
spyOn(someModuleWrapper, 'callModule');
someFunctionThatShouldCallTheModule();
expect(someModuleWrapper.callModule).toHaveBeenCalled();
}
}
And then obviously make sure that wherever someFunctionThatShouldCallTheModule is, you're requiring the wrapper rather than the real module.

Categories

Resources