Jest: mock object used inside tested function - javascript

I would like to mock an object used inside called tested function. All I have found I another tickets was calling function in tested function, but I need to replace certain object that is used there. Is something like that possible in Jest?
util.test.js
describe('testname', function () {
it('import test', function () {
Utils.generateRandomPoints(10); // inside this function, I'd like to mock used object
});
});
utils.js
export function generateRandomPoints(arrayLength) {
const result = [];
for (let i = 0; i < 100; i++) {
// instead of "new Point" I'd like to use "new MockedPoint" for testing.
result.push(new Point(i));
}
return result;
};

const MockPoint = jest.fn();
jest.mock('path/to/Point', () => ({
Point: jest.fn().mockImplementation(MockPoint),
}));
and you can add whatever functionality to MockPoint, e.g.
const MockPoint = jest.fn((props) => console.log(props));

Related

Javascript Functions as constants

I have inheritted some code and I've very rarely used JS. In the code, athere are losts of functions which are defined into contstants. I'm trying to debug an issue using a browser, and I am struggling to call any of the functions from the commandline
can anyone let me know how I would do this please. Example below (not actual code)
const updateDisplay = function () {
if (0x0 === seq[hl_0b('0x8', '3D61')]) {
return;
}
if (0x1 === seq[hl_0b('0x16', 'Sg%G')]) {
get('display')['innerText'] = '';
}
const a = 0x32 * (seq[hl_0b('0x7', '7U46')] - 0x1 - get(hl_0b('0x22', 'uOD4'))[hl_0b('0x24', 'Mu]C')]['length']);
setTimeout(function (b) {
get(hl_0b('0x2b', 'Q0y5'))[hl_0b('0x10', 'Zu59')] += seq[b];
buttonFlash(null, hl_0b('0x5', 'lRst') + seq[b]);
}, a, seq[hl_0b('0x1e', '2f%K')] - 0x1);
};
Updated to include actual code
to create a constant function you need to call it with const instead of constant. After that you can create your function as
const toto = function(){
/*DO SOMETHING*/
}
This function can be write as an arrow function to as
const toto = () => {/*DO SOMETHING*/}
Anyway, this is links for documentations if you want
https://developer.mozilla.org/en-US/docs/Glossary/Function
https://www.w3schools.com/js/js_const.asp

Implement unregister after registration of callback

I wrote a simple piece of software that allows users to "register" a function when a state is set.
This was easily achieved by adding functions to an array.
I want to return a function that is able to "unregister" that particular function.
Note that a user might register the same function twice. This means that the "unregistering" function cannot be based on the function as a key in a map
The only thing that springs to mind is making the "register" function way more complex, where each item in the "callbacks" array is not just a function, but an object like this:
{
id: someId
fn: [the function]
}
And that the unregister function will filter the someId value. But I just can't like this.
Ideas?
const state = {}
const callbacks = []
const register = (fn) => {
callbacks.push(fn)
return () => {
console.log('Unregister function. HELP!!! How do I do this?')
}
}
const setState = async (key, value) => {
state[key] = value
for (const fn of callbacks) fn(key, value)
}
const getState = (key) => {
return state[key]
}
const f1 = () => {
console.log('f1')
}
const f2 = () => {
console.log('f2')
}
const unregF1a = register(f1)
const unrefF1b = register(f1)
const unregF2 = register(f2)
setState('some', 'a')
unregF1a()
setState('some', 'b')
Loop through your callbacks and remove the desired function (works if the same function is registered twice).
You could do a simple for loop:
function unregister(fn) {
for (let i = callbacks.length - 1; i >= 0; i--) {
if (callbacks[i] === fn) {
callbacks.splice(i, 1)
}
}
}
Or you can use let and replace the whole array:
let callbacks = [];
function unregister(fn) {
callbacks = callbacks.filter(cb => cb !== fn)
}
If you want to be able to register the same function more than once and be able to unregister them independently, then yes, you'll need to track some kind of id.
An id can be something simple, like an increasing integer, and you can store them in a different array, in the same index the function is in the callbacks array (that's hashing).
Something like this:
const state = {}
const callbacks = []
const ids = []
let nextId = 0
const register = (fn) => {
const id = nextId
callbacks.push(fn)
ids.push(nextId)
nextId++
return () => {
// find the function position using the ids array:
const fnIndex = ids.findIndex(cbId => cbId === id)
if (fnIndex === -1) return // or throw something
// Now remove the element from both arrays:
callbacks.splice(fnIndex, 1)
ids.splice(fnIndex, 1)
}
}
This way, the unregister function always looks for the exact index where the id/fn resides.

Can't access inner function properly

Not sure if this is the right title but should be quick help.
Pretty much I keep on getting errors on testing a function because "TypeError: ParseThis.changeIt is not a function". Here's my code. What am I missing that causing this type error? Thanks!
const ParseThis = () => {
const changeIt = string => string;
return { changeIt: changeIt() }
}
Edit: More details!
Thanks for the help again
When you return your object, maybe you wanted to return the function and not the result of the call:
return { changeIt: changeIt };
or this which is more concise:
return { changeIt };
According to how you are using the translate function, I think you should export it this way:
const Translator = {
const translate = string => string;
};
if (module.exports) {
module.exports = Translator;
}
or this way:
const Translator = () => {
const translate = string => string;
return { translate };
}
if (module.exports) {
module.exports = Translator();
}
Return the function instead of calling it.
const ParseThis = () => {
const changeIt = string => string;
return { changeIt };
}
In the original post, changeIt() is a call to changeIt with no first parameter. It returns the value undefined. To return a function instead of calling it, omit the parenthesis.
Let's analyze your code.
Let's start from this:
const changeIt = string => string;
At this point, changeIt is a function that, given a parameter, it returns that a parameter.
Without an arrow function, if we should use the old classic named function, it would be like this:
function changeIt(parameter) {
return parameter;
}
What happens if you call changeIt() with no parameter? In javascript, when you pass no parameters ot a function, it's like you are passing undefined. So the function will return undefined.
Then you have this line:
return { changeIt: changeIt() }
But as we have seen, changeIt() is equal to undefined. So your code is equivalent to:
return { changeIt: undefined }
Which is clearly not a function!
What you probably meant to do, is not returning the result of function invokation, but return the function itself. So, instead that assigning changeIt(), just assign changeIt:
return { changeIt: changeIt }
Notice that you repeated twice the word changeIt, so you can get rid of this repetition and just write:
return { changeIt }
Your function is returning an object, so instead of
ParseThis.changeIt()
You should be doing something like
const a = ParseThis();
a.changeIt('some string');
But, note that even in your example, changeIt in the returning object is not a function.
Probably you are trying this
const ParseThis = () => {
const changeIt = string => string;
return { changeIt: changeIt};
}
Note that I've used { changeIt: changeIt}, setting changeIt to a reference of the inner function changeIt. And you are using { changeIt: changeIt()} setting changeIt to the value returned of the inner function changeIt. Those are two different operations.
The problem is that you are exporting a function, and not the object containing the nop function. You need to add parenthesis to your dummy:
const Translator = () => {
const translate = string => string;
return { translate };
};
if (module.exports) {
module.exports = Translator(); // add parenthesis here
}
Alternatively you could run the function you import, but I suspect that would be different from your real Translator api.

is there a good way to call methods dynamically in js?

I have 2 js functions:
function onRegionMouseOver()
{
}
function onRegionMouseOut()
{
}
Is it possible to call these js functions dynamically doing something like this?:
var type = 'Out'
//the following line would exec onRegionMouseOut() above:
call(onRegionMouse[type]())
You can use this:
var onRegionMouseHandlers = {
out: function () {},
in: function () {}
}
// and using like this
var whatToUse = 'in';
// use
onRegionMouseHandlers[whatToUse]()
Also, you can remove your which choose what function have to be called. You can just add two handlers to two different events.
You can define the functions as properties of an object, use bracket notation to call the function.
const methods = {
onRegionMouseOver() {console.log("Over")},
onRegionMouseOut() {console.log("Out")}
}
let fn = "onRegionMouse";
let type = "Out";
methods[`${fn}${type}`]();
type = "Over";
methods[`${fn}${type}`]();
without template literal or let
var methods = {
onRegionMouseOver: function onRegionMouseOver() {console.log("Over")},
onRegionMouseOut: function onRegionMouseOu() {console.log("Out")}
}
var fn = "onRegionMouse";
var type = "Out";
methods[fn + type]();
type = "Over";
methods[fn + type]();
You can do something like that, provided you declare an object that contains the functions.
var onRegionMouse = {
Out: onRegionMouseOut,
Over: onRegionMouseOver
};
Now you can just do
var type = 'Out';
onRegionMouse[type]();
what about:
var myFunctions = {
out: function onMouseOut()...,
enter: function onMouseEnter()...
}
You can call it now with myFunctions[ "out" ] ()

Is `eval` the only way to create functions with dynamically determined arity in JavaScript?

I'm using a JavaScript spy library,
simple-spy.
I've found out that when spying on a given function,
the resulting spy always has an arity of 0.
This creates a problem with my use of
this currying function.
So I've submitted a pull-request
that adds arity transparency to
the spy library.
The code looks like this:
function spy(fn) {
const inner = (...args) => {
stub.callCount++;
stub.args.push(args);
return fn(...args);
};
// ends up a string like
// 'a,b,c,d'
// depending on the `fn.length`
const stubArgs = Array(fn.length)
.fill(null)
.map((m, i) => String.fromCodePoint(97 + i))
.join();
const stubBody = 'return inner(...arguments);';
// this seems to be the only way
// to create a function with
// programmatically specified arity
const stub = eval(
// the wrapping parens is to
// prevent it from evaluating as
// a function declaration
`(function (${stubArgs}) { ${stubBody} })`
);
stub.reset = () => {
stub.callCount = 0;
stub.args = [];
};
stub.reset();
return stub;
}
exports.spy = spy;
This seems to work.
Is it possible to do this
without the use of eval?
Is it possible to
reduce the use of eval
to even less that this?
I'm aware that there are other issues
with this spy implementation.
It is simplistic and it works
for my use case so far.
Like Benjamin wrote, I used a simple:
function spy(fn) {
const stub = (...args) => {
stub.callCount++;
stub.args.push(args);
return fn(...args);
};
stub.reset = () => {
stub.callCount = 0;
stub.args = [];
};
stub.reset();
Object.defineProperty(stub, 'length', {value: fn.length});
return stub;
}
exports.spy = spy;
Much, much better looking.

Categories

Resources