My test function reverseAdd call another function add that is defined in same module.
I need to test, if test function call another.
Module
function add(a, b) {
return a + b;
}
function reverseAdd(a, b) {
add(b, a);
}
module.exports = {
add,
reverseAdd
}
Test
const exp = require('./add');
describe('add', () => {
it('should add two numbers', () => {
expect(exp.add(1, 2)).toBe(3);
});
it('should add two numbers', () => {
exp.add = jest.fn();
exp.reverseAdd();
expect(exp.add).toHaveBeenCalledTimes(1);
});
});
Result
Expected mock function to have been called one time, but it was called zero
As I understand wraped function is another function, and it is not called in test function.
How can I wrap/spy the function add?
playground: https://repl.it/repls/WoodenElectricInstances
Thanks #ltamajs, I found solution.
Need to rewrite module to
function add(a, b) {
return a + b;
}
function reverseAdd(a, b) {
module.exports.add(b, a); <----- here changes
}
module.exports = {
add,
reverseAdd
}
Related
I have dozens of functions with try catch block to handle and log any error occurred.
function add(a, b) {
try {
return a + b;
} catch (error) {
log.error(error.message + ' in add');
}
}
As this try catch statements have same kind of code for each function mentioning error message and the function name in each log, I want some way to avoid writing try catch for each function and want it to be added automatically. My function should be like below one but should work like above one.
function add(a, b) {
return a + b;
}
How could it be possible?
You can wrap your functions up using closures.
For logging, you can try using Function.name, but for meaningful information this rules out arrow functions and otherwise anonymous functions. This could be solved by explicitly passing a name string to the wrap function, but...
There is of course no guarantee the returned function is used via an identifier related to the original name (whatever vs anError below).
const wrap = func => (...args) => {
try {
return func.apply(this, args);
} catch (e) {
console.error(`${e} in ${func.name}`);
}
};
const add = wrap((a, b) => a + b);
const fail = wrap(t => {
if (t)
throw new Error('foo');
});
const whatever = wrap(function anError () {
throw 'an error';
});
console.log(add(1, 2));
fail(false);
fail(true);
whatever();
Combined output:
3
Error: foo in
an error in anError
can you try with callback...
function add(a, b){
return a + b;
}
function substract(a, b){
return a - b;
}
function calc(a){
try{
const f = Array.prototype.shift.apply(arguments);
return f(...arguments);
}catch(e){
console.log(e.stack);
}
}
calc(substract, 1, 2);
Pulling my hair out here trying to understand the infuriating nuances of Javascript. Hopefully some JS guru can take a gander, point and go, "well, there's yer problem...".
Here's a slimmed down sample of the problem:
var Parent = (function () {
var func1 = function () {
func2(function (res) {
console.log(res);
});
};
var func2 = function (callback) {
callback('abc');
};
return {
init: function () {
func1();
func2();
}
};
})();
Call with Parent.init();
This fails with the error:
Uncaught TypeError: callback is not a function
at check2 (<anonymous>:9:9)
at Object.init (<anonymous>:15:13)
at <anonymous>:1:8
What's getting me, is that if I comment out the enclosing code, like so, then it works as expected:
// var Parent = (function () {
var func1 = function () {
func2(function (res) {
console.log(res);
});
};
var func2 = function (callback) {
callback('abc');
};
// return {
// init: function () {
// func1();
// func2();
// }
// };
// })();
...and call with func1();
Result:
abc
What am I missing?
Thanks
In your version, you're calling func2() without specifying the callback function, which is a required argument. In your second example (with init commented out), you're correctly specifying the callback function in func2(function (res) { ... });.
Is the below snippet something you're looking for?
const Parent = (function () {
const func1 = function () {
func2(function (res) {
console.log(res);
});
}
const func2 = function (callback) {
callback('abc'); // this is passing 'abc' to line 3 of this snippet
}
return {
init: function () {
func1();
// func2(); // you don't want to call "func2" here, as "func1" calls it
// Or you could run:
func2(function (res) {
console.log(res);
});
// But this makes "func1" redundant
}
};
});
Parent().init();
// Output
abc
You have to pass callback parameter into func2 inside init. something like this.
init: function () {
func1();
func2(function (res) {
console.log(res);
});
}
From a comment on the question:
I just want to know why it works in the one sample, but not the other.
Because in one example you pass an argument to func2 and in the other you don't. Look at the working version:
func2(function (res) {
console.log(res);
});
vs. the non-working version:
func2();
The difference is that the first one passes a function which gets invoked as callback('abc'); whereas the second one passes nothing, so the attempt to invoke the non-existant callback function fails.
As an aside, in your non-working example you call func2 twice, once with the callback and once without. So it both "works" and "fails" in that case.
I've seen a few answers but its still a little unclear to me how to go about this.
I have a retry function, whose parameter of fn I'd like to call with the original parameters supplied to it:
function retry(fn, retries=3, err=null) {
if (!retries) {
return Promise.reject(err);
}
return fn().catch(err => {
return retry(fn, (retries - 1), err);
});
}
Is there a clean way to do this in JS?
In short, I'd like to do something like:
function a(b,c,d) { return Promise.resolve(b + c + d) }
retry(a, ...originalParams)
Besides what you've covered yourself, another way would be to wrap your function and it's arguments into a thunk. However, it's not exactly what you would like it to be.
function retry(fn, retries=3, err=null) {
if (!retries) {
return Promise.reject(err);
}
return fn().catch(err => {
return retry(fn, (retries - 1), err);
});
}
function toThunk(fn, ...args) {
// note that we return a new function which closes over
// the function and arguments here (e. g. creating closures)
return () => fn(...args);
}
function sumP(a, b, c) {
return Promise.resolve(a + b + c);
}
// ---
retry(toThunk(sumP, 1, 2, 3)).then(result => {
console.log(result);
});
I have been trying to learn about callBack hell, and was trying to replicate and then change it into promises. Here is my code, its saying on execution cb is not a function
What i am missing here.
var t = addTwo(function(a, b) {
console.log(a * b);
divideTwo(function() {
console.log("arshita");
})
})
function addTwo(cb) {
cb(3, 4);
}
function divideTwo(cb1) {
}
addTwo();
You have an error in your code
var t = addTwo(function(a, b) {
console.log(a * b);
divideTwo(function() {
console.log("arshita");
})
})
function addTwo(cb) {
cb(3, 4);
}
function divideTwo(cb1) {
}
addTwo((a, b) => a + b); // <----- Here you passed nothing, though `addTwo`
// expected a callback. I wrote an example callback that sums `a` and `b`
Update
If you want to see what callback hell looks like, then have a look at this (a simple, only 3-level callback hell):
function init(msg, cb) {
alert(msg)
cb()
}
function running(msg, cb) {
alert(msg)
cb()
}
function finish(msg) {
alert(msg)
}
// The below code may not be considered as "callback hell" yet, but add few more iterations and it definitely will become a hell
init('program started!', function() {
running('program is running', function() {
finish('program shut downs')
})
})
I'd like to create a logging decorator around jQuery function but it is called only once (in initialization time). How to fix it? Please look at the code.
function makeLogging(f) {
function wrapper(...rest) {
console.log(f.name);
console.log(rest);
return f.apply(this, rest);
}
return wrapper;
}
const task = $('.task');
task.on = makeLogging(task.on);
task.on('click', () => console.log('hi'));
The click event does not display messages about the called function.
You are doing it a little bit wrong, if I caught the idea what you want to achieve. For functionality, you described, please try following:
task.on('click', makeLogging(() => console.log('hi')));
In your original code, you wrapped the functionality of on() function, but this on() function is not called as event handler - it only install actual event handler. That's why logging is called only once during installation of the handler.
Code example of answer
function makeLogging(f) {
function auxiliaryWrapper(x, rest) {
return () => {
console.log(f.name);
console.log(rest);
x();
}
}
function mainWrapper(...rest) {
const restWithWrap = rest.map(arg => {
if (typeof arg === 'function') {
return auxiliaryWrapper(arg,rest);
}
return arg;
});
console.log(restWithWrap);
return f.apply(this, restWithWrap);
}
return mainWrapper;
}
const task = $('.task');
task.on = makeLogging(task.on);
task.on('click', () => console.log('hi'));