jest: how to test multiple functions in one file? - javascript

is there a way to test multiple functions in one file with jest?
in ch03.js:
var min = function(a, b) {
if(a < b)
return a
else
return b
}
// even/odd number checker
var isEven = function(number) {
n = Math.abs(number);
if (n==0)
return true;
else if (n==1)
return false;
else {
return isEven(n-2);
}
}
module.exports = isEven;
and my test file:
in test/ch03-test.js
jest.dontMock('../ch03');
describe('min', function() {
it('returns the minimum of two numbers', function() {
var min = require('../ch03');
expect(min(2, 3)).toBe(2);
expect(min(22, 3)).toBe(3);
expect(min(2, -3)).toBe(-3);
});
});
describe('isEven', function() {
it('checks if given number is even', function() {
var isEven = require('../ch03');
expect(isEven(0)).toBe(true);
expect(isEven(-2)).toBe(true);
expect(isEven(0)).toBe(true);
expect(isEven(3)).toBe(false);
});
});
I don't want separate files for every small javascript function.
Is there a way to test multiple functions in one file?

You should try rewire
When "requiring" a module with rewire, it exposes getter and setter for variables in the module, including private ones.
Something like this should work:
jest.dontMock('../ch03');
var rewire = require('rewire');
var min = rewire('../ch03').__get__("min");
describe('min', function() {
it('returns the minimum of two numbers', function() {
expect(min(2, 3)).toBe(2);
expect(min(22, 3)).toBe(3);
expect(min(2, -3)).toBe(-3);
});
});

Related

module.exports multiple functions in Jest testing

After reading the Jest documentation, when it's mentioned that to export a single function from a tested file they show the following example:
function sum(a, b) {
return a + b;
}
module.exports = sum;
Now, if I have multiple specific functions I want to export on my tested file, like this:
function sum(a, b) {
return a + b;
}
function multiply(a, b) {
return a * b;
}
function subtract(a, b) {
return a - b;
}
module.exports = sum;
module.exports = multiply;
The multiply function is the only one being exported. How can I make these function be exported? Or only part of my file?
You can do something like this :
module.exports = {};
module.exports.sum = function sum(a, b) {
return a + b;
}
module.exports.multiply = function multiply(a, b) {
return a * b;
}
module.exports.subtract = function subtract(a, b) {
return a - b;
}
End you use it like this:
var MyMathModule = require('./my_math_module');
MyMathModule.sum(a, b);
MyMathModule.multiply(a, b);
MyMathModule.subtract(a, b);
First, in your example, all you are doing there is overriding the exports object with a function ( which is totally fine )
The exports and module.exports are an object and are actually the same object ( i.e. module.exports === exports // true )
To do what you want you can do this a couple ways:
exports.sum = sum
exports.multiply = multiply
or
module.exports = { sum: sum, multiply: multiply } // etc
or
module.exports.sum = sum
module.exports.multiply = multiply
Having in mind the answer to this question, i'll paste here 2 ways to do the same thing.
For example, you have the JS file called exercise5, like this:
//You can create an object with functions, as follows:
const wordAnalysis = {
type: (word) => typeof (word),
whiteSpaces: (word) => {
let wordAnalysis = word.includes(' ')
if (wordAnalysis) {
return 'It has spaces'
} else {
return "It doesn't has spaces"
}
}
}
//Or you can create several single functions, like the following:
function numberAnalysis(word) {
let isANumber = typeof (word) === 'number' ? true : false
return isANumber
}
// în order to avoid overwriting the module.exports, it is needed to do one of the following (I chose the first one):
// 1)
module.exports.firstPlace = wordAnalysis
module.exports.secondPlace = numberAnalysis
// 2)
// module.exports = {
// functions: functions,
// isANumber: isANumber
// }
// 3)
// exports.functions = functions
// exports.isANumber = isANumber
// 4)
// exports = {
// functions: functions,
// isANumber: isANumber
// }
Now the file test named exercise5.test.js:
const wordAnalysis = require('./exercise5')
const numberAnalysis = require('./exercise5')
test('It should give me the type of what was typed', () => {
expect(wordAnalysis.firstPlace.type('teste')).toEqual('string')
})
test('It should give me the type of what was typed', () => {
expect(wordAnalysis.firstPlace.type(22)).toEqual('number')
})
test("It should give true if what is typed has at least a space or false if it doesn't", () => {
expect(wordAnalysis.firstPlace.whiteSpaces('Jon is cool')).toEqual('It has spaces');
})
test("It should give true if what is typed has at least a space or false if it doesn't", () => {
expect(wordAnalysis.firstPlace.whiteSpaces('AllTogetherNow')).toBe("It doesn't has spaces");
})
test('it should analyse if the given expression is a number or not', () => {
expect(numberAnalysis.secondPlace(2)).toBeTruthy()
})
test('it should analyse if the given expression is a number or not', () => {
expect(numberAnalysis.secondPlace('jon')).toBeFalsy()
})
The only thing you need to be aware is to export/import the correct object/function, and of course call it when your are developing the test.

What is the difference between returning a function and returning an object in a Durandal viewmodel?

I'm looking at implementing a wizard type system in my application and looking at the first wizard example on the dfiddle-2.0 project on GitHub. The step viewmodels are all functions though and I'm trying to understand why.
Here is what the dfiddle is using for the index.js of the wizard:
define(['durandal/activator', './step1', './step2', './step3', 'knockout'], function( activator, Step1, Step2, Step3, ko ) {
var steps = [new Step1(), new Step2(), new Step3()];
var step = ko.observable(0);
var activeStep = activator.create();
var stepsLength = steps.length;
var hasPrevious = ko.computed(function() {
return step() > 0;
});
var hasNext = ko.computed(function() {
return (step() < stepsLength - 1);
});
// Start with first step
activeStep(steps[step()]);
return {
showCodeUrl: true,
steps: steps,
step: step,
activeStep: activeStep,
next: next,
previous: previous,
hasPrevious: hasPrevious,
hasNext: hasNext
};
function next () {
if ( step() < stepsLength ) {
step(step() + 1);
activeStep(steps[step()]);
}
}
function previous () {
if ( step() > 0 ) {
step(step() - 1);
activeStep(steps[step()]);
}
}
});
And here is what it's using for step1.js
define(function() {
return function() {
this.name = 'Step 1';
this.s1one = 'Unique to' + this.name;
this.s1two = 'Another property unique to' + this.name;
};
});
Here is what I'm currently using for index.js.
define(['knockout'],
function (ko) {
var rootPath = "viewmodels/wizards/steps/";
var steps = ["step1", "step2", "step3"];
var step = ko.observable(0);
var activeStep = ko.observable();
var stepLength = steps.length;
var hasPrevious = ko.computed(function () { return step() > 0 });
var hasNext = ko.computed(function () { return step() < stepLength - 1 });
var activate = function () {
return activeStep(rootPath + steps[step()]);
};
return {
steps: steps,
step: step,
activeStep: activeStep,
next: next,
previous: previous,
hasPrevious: hasPrevious,
hasNext: hasNext,
activate: activate
}
function next() {
if (hasNext()) {
step(step() + 1);
activeStep(rootPath + steps[step()]);
}
}
function previous() {
if (hasPrevious()) {
step(step() - 1);
activeStep(rootPath + steps[step()]);
}
}
});
And my step1.js
define(function () {
var name = ko.observable("Step 1");
var s1one = ko.observable("Unique to " + name());
var s1two = ko.observable("Another property unique to " + name());
var returnVm = {
name: name,
s1one: s1one,
s1two: s1two
};
return returnVm;
});
The bindings are the same so how are these two approaches different? What am I losing by just returning an object instead of using functions?
The difference is subtle, but important. Modules that return an object are singletons. The same object will be shared among all other modules that depend on it. Modules that return a function are termed constructor functions. Dependant modules will instantiate this constructor function with the new keyword. Therefore, each instance is unique.
Here's some more information gleaned from the Durandal documentation:
A module's define is only exeucted once, at the time the module is first required. As a result, if you return an object instance, you have created a singleton which will stay in memory for the lifetime of your application. If this is not desired, return a constructor function to retain greater control of the lifetime of your objects by allowing consumers to create/release them as needed.
In your example, you aren't losing anything. Either approach works. Which is more correct depends on a number of things. If you do not require unique instances of your module each time it is required, then a singleton is the best choice. However, if say you need multiple instances of the same dialog module, but each with their own data, a constructor function is the way to go.
I hope this helps.

break large public javascript functions into smaller private functions

I have JavaScript class which have huge functions which are very difficult to maintain.
The 2 public functions are called at start and then on click. I want to create private functions inside these public functions say break into into some private functions scope to these public methods.
var searchResultView;
var SearchResultView = function () {
me = this;
this.init = function () {
// huge code
}
this.Search = function () {
// huge code
}
}
jQuery(function () {
searchResultView = new SearchResultView();
searchResultView.init();
searchResultView.Search();
}
What will best way to achieve this. I tried to use below approach but i think this nested function will not work well.
var searchResultView;
function searchResultView() {
me = this;
this.init = function () {
var declareControls = function () {}
var addEvents = function () {}
var fillControls = function () {}
declareControls();
addEvents();
fillControls();
}
this.Search = function () {
var validateAndCreateCriteria = function () {
if (!validateAandGetLocation()) {
alert("invalid location");
return false;
}
if (!validateAandGetCategory()) {
alert("choose search type");
return false;
}
var validateAandGetLocation = function () {}
var validateAandGetCategory = function () {}
}
validateAndCreateCriteria();
}
}
jQuery(function () {
searchResultView = new searchResultView();
searchResultView.init();
});
If I understood correctly, you should have the functions something like this:
var foo = (function() {
var privateBar = function() { // private function
},
privatefooBar = function() { // private function
};
return {
publicFoo : function() { //public function
/* use privateBar and privatefooBar functions here */
}
};
})();
Later you can access publicFoo function by using
foo.publicFoo();
But you can't access the inside functions which are privateBar() and privatefooBar() directly because they are private functions.
Updated Fiddle
Breaking up the function is easy:
function f(..) {
// many lines here
return ret_f;
}
if equivalent to
function f {
function f1(..) {
// not so many lines here
}
function f2(..) {
// not so many lines here
}
var ret_f1 = f1(..);
var ret_f2 = f2(..);
// calculate ret_f from ret_f1 and ret_f2
return ret_f;
}
or if you prefer this style using anonymous functions
function f {
var f1 = function(..) {
// not so many lines here
};
var f2 = function(..) {
// not so many lines here
};
var ret_f1 = f1(..);
var ret_f2 = f2(..);
// calculate ret_f from ret_f1 and ret_f2
return ret_f;
}
I fear however your real question is specific to your existing code and is about what useful smaller functions to extract there and how to combine them.
For this one would need to have your full code and understand it. That might be a bit much for this QA format.

javascript const in javascript library

I am trying to write a small javascript library as shown below. What I really want is when I call
console.log(tnd().pv);
it should output same number and not generate new number everytime. I know the issue is it calls Math.random everytime I console log. But how can I do so that it outputs same number?
(function () {
var tnd = function() {
return new tnlib();
};
var tnlib = function() {
this.version = function(){
console.log('1.0');
};
this.pv = Math.random()*10000000000000000;
};
if(!window.tnd) {
window.tnd = tnd;
}
})();
Don't execute Math.random() on each invocation of tnlib, but as a static variable:
(function () {
function tnd() {
return new tnlib();
}
function tnlib() {
}
tnlib.prototype.version = function(){
console.log('1.0');
};
tnlib.prototype.pv = Math.random()*10000000000000000;
if (!window.tnd) {
window.tnd = tnd;
}
}());
(or, if you really need to make pv an instance property):
var staticPv = Math.random()*10000000000000000;
function tnlib() {
this.pv = staticPv;
…
}

Create anonymous function dynamically?

I'm working on simple evolutionary AI. I need to generate an anonymous function dynamically. For it I have a list of conditions and actions:
var conditions = [
function () { return enemyNear(), },
function () { return mySpeed() > 5; },
function () { return 1 === 1; }];
var actions = [
function () { return alert('walk'); },
function () { return alert('jump'); }
function () { return alert('attack'); } ]
The code chooses one of each to generate a new function:
condition = conditions [Math.floor(Math.random()*conditions .length)];
actions = conditions [Math.floor(Math.random()*actions .length)];
Provided it the chosen condition is enemyNear() and the chosen action is walk(), how can I generate the simple anonymous function?
behavior = function() {
if(enemyNear()) {
walk();
}
}
I can change the way the arrays are saved if needed. How can this be done?
All characters behaviors are called inside a loop like this:
for(i=0,i<chars.length,i++) {
chars[i].behavior.call();
}
The simplest way would be to only put functions inside the arrays:
var conditions = [
enemyNear,
function () { return mySpeed() > 5; },
function () { return 1 === 1;
}];
var actions = [walk, attack, jump];
Then you could define behave as something like:
var behave = function(condition, action) {
if(condition()) {
action();
}
}
And use it like for example:
behave(conditions[2], actions[1]);
Here, 2 and 1 could be a randomly generated number like this:
var getRandomInt = function (min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var actRandomly = function (conditions, actions) {
behave(
conditions[getRandomInt(0, conditions.length -1)],
actions[getRandomInt(0, actions.length -1)]
);
};
Call it like:
actRandomly(conditions, actions);
Of course this only presents the idea, and is not neatly organized.
For the fun of it, I created a Basic jsFiddle Demo Version.
Note: Always use var when you are defining a variable. Don't pollute the global scope.
First, inside of the arrays you will need to have a reference to the condition and action function. Right now, you are calling them, so they basically are the same as a useless array like:
conditions = [true, false, true];
actions = [undefined, undefined, undefined];
I would correct it to something like this:
var conditions = [enemyNear,
function() { return mySpeed() > 5 },
function(){ return true; }];
var actions = [walk, attack, jump];
And then you can create a function that generates a behavior:
function generateBehavior(){
var condition = conditions[Math.floor(Math.random() * conditions.length)];
var action = actions[Math.floor(Math.random() * actions.length)];
return function() {
if(condition()) {
action();
}
}
}
You can see it in action on this JSFiddle demo.
Change your arrays from this:
conditions = [enemyNear(), mySpeed()>5, 1=1];
To this:
conditions = [
function() { return enemyNear() }, // or just enemyNear
function() { return mySpeed() > 5 },
function() { return 1 == 1 } // 1 = 1?
];
With your current code, your functions are being called and conditions becomes an array of the outputs of those functions.
condition = [
enemyNear,
function() { return mySpeed() > 5; },
function() { return 1 == 1; }
];
You need to store your functions in the array, not call them, otherwise you are storing the result of the functions in the array.
function enemyNear() {}
function walk() {}
conditions = [enemyNear]
actions = [walk]
behaviour = function() {
if(conditions[randomNumber]()) {
actions[randomNumber]();
}
}
Simple. Use eval()
var behavior;
eval("behavior = function() { if (enemyNear()) walk(); }");
behavior();

Categories