How do these nested JavaScript functions work? - javascript

I have a question related to this code:
const somaHorasExtras = (salario, valorHorasExtras) => salario + valorHorasExtras;
const calculaDescontos = (salario, descontos) => salario - descontos;
const verifiqueSe = (valor) => {
const assercoes = {
ehExatamenteIgualA(esperado) {
if (valor !== esperado) {
// eslint-disable-next-line no-throw-literal
throw {};
}
},
};
return assercoes;
};
const teste = (titulo, funcaoDeTeste) => {
try {
funcaoDeTeste();
console.log(`${titulo} passou!`);
} catch {
console.error(`${titulo} não passou!!!`);
}
};
teste('somaHorasExtras', () => {
const esperado = 2500;
const retornado = somaHorasExtras(2000, 500);
verifiqueSe(retornado).ehExatamenteIgualA(esperado);
});
teste('calculaDesconto', () => {
const esperado = 2300;
const retornado = calculaDescontos(2500, 200);
verifiqueSe(retornado).ehExatamenteIgualA(esperado);
});
My question is related to the verifiqueSe function specifically. How does this function work? Does someone can explain how this function work in conjunction with the inner function ehExatamenteIgualA? What is the assercoes which is returned?
Thank you.

Your verifiqueSe(valor) function returns an object. You may find it a little confusing, since this syntax:
const foo = {
bar() {
//
}
};
is just a short syntax for object method:
const foo = {
bar: function () {
//
}
};
So in order to call the bar() function, you'd need to reach it through foo:
foo.bar();

Related

Mock a function and used it as UUT with Jest in JS

I want to test one function from exported object in one describe and mock it in another function from the same exported object since the second function is using the first function.
// funcs.js
const func1 = () => {
return true;
};
const func2 = () => {
const bool = func1();
if (bool) {
// do something
} else {
// do else
}
};
export const funcs = {func1, func2};
// funcs.spec.js
const {funcs as uut} from './funcs';
describe('unit', () => {
describe('func 1', () => {
test('', () => {
const bool = uut.func1();
expect(bool).toBeTruthy();
});
});
describe('func 2', () => {
test('', () => {
jest.mock(uut.func1).mockReturnValue(false);
uut.func2();
// rest of test
});
});
});
I tried using jest.requireActual but did not work. What is the best approach for this if even possible?

JavaScript - Map of Objects applies function only on last object (possible hoisting issue)

I have created a WebPage function that should act as a class.
I have a map of url keys and WebPage object values and I want to call a method on each object. The method, called startMonitoring should set an interval to a variable scoped to each object.
However, the interval is set only on the last object and every other object will get the same output when printed afterwards.
Here is my code:
export const startMonitoring = (websitesMap) => {
websitesMap.forEach((website) => {
website.startMonitoring();
});
};
export function WebPage(url, checkTime) {
// other variables
this.scheduledTask;
...
WebPage.prototype.startMonitoring = () => {
this.scheduledTask = setInterval(async () => {
// asynchronous work
}, checkTime * 1000);
};
}
This happens because you are setting the prototype each time your create a new object. So all instances will access the last one you define.
And you will, now, have to use regular functions to have access to the correct this.
export const startMonitoring = (websitesMap) => {
websitesMap.forEach((website) => {
website.startMonitoring();
});
};
export function WebPage(url, checkTime) {
// other variables
this.scheduledTask;
this.checkTime = checkTime;
...
}
WebPage.prototype.startMonitoring = function() {
this.scheduledTask = setInterval(async function() {
// asynchronous work
}, this.checkTime * 1000);
};
As Pointy said, using the prototype, this would work:
const startMonitoring = (websitesMap) => {
websitesMap.forEach((website) => {
website.startMonitoring();
});
};
function WebPage(url, checkTime) {
// other variables
this.scheduledTask;
this.url = url;
WebPage.prototype.startMonitoring = function() {
this.scheduledTask = setInterval(async () => {
console.log('hello', this.url);
}, checkTime * 1000);
};
}
const websites = [new WebPage('#', 1), new WebPage('#test', 1)]
startMonitoring(websites);
Also, changing the prototype function should also work:
const startMonitoring = (websitesMap) => {
websitesMap.forEach((website) => {
website.startMonitoring();
});
};
function WebPage(url, checkTime) {
// other variables
this.scheduledTask;
this.url = url;
this.startMonitoring = () => {
this.scheduledTask = setInterval(async () => {
console.log('hello', this.url);
}, checkTime * 1000);
};
}
const websites = [new WebPage('#', 1), new WebPage('#test', 1)]
startMonitoring(websites);

DRY combine two functions in one [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
I am trying to refactor my code and have noticed I am repeating myself. Was wondering if there is a way to combine these two functions in one?
export const fn1 = article => article.categoryValueDtoSet.reduce((res, item) => {
const result = { ...res };
if (item.language) {
const language = item.language.languageValue;
const category = item.categoryValue;
result[language] = category;
}
return result;
}, { it: undefined, de: undefined, en: undefined );
export const fn2 = article => article.titleDtoSet.reduce((res, item) => {
const result = { ...res };
if (item.language) {
const language = item.language.languageValue;
const category = item.titleValue;
result[language] = title;
}
return result;
}, { it: undefined, de: undefined, en: undefined );
First you would need function which you will pass to the reduce function as a callback. For this you can use a higher-order function which is basically a function that returns a function. We can call this function dry
const dry = (fieldName) => (res, item) => {
const result = { ...res };
if (item.language) {
const language = item.language.languageValue;
result[language] = item[fieldName];
}
return result;
}
then we can extract the initial object that is being passed to the reduce callback:
const intialValueObject = { it: undefined, de: undefined, en: undefined };
and then pass the dry function to the reduce function as an argument:
export const fn1 = article => article.categoryValueDtoSet.reduce(dry('categoryValue'), { ...initialValueObject });
export const fn2 = article => article.titleDtoSet.reduce(dry('titleValue'), { ...intialValueObject });
There is pretty much always a way. Could you be more specific with your constraints?
If nothing else, you can share the reduce logic
let reducer = (res, item) => {
const result = { ...res };
if (item.language) {
const language = item.language.languageValue;
const category = item.categoryValue;
result[language] = category;
}
return result;
}
export const fn1 = article => article.categoryValueDtoSet.reduce(reducer, { it: undefined, de: undefined, en: undefined });
export const fn2 = article => article.titleDtoSet.reduce(reducer, { it: undefined, de: undefined, en: undefined });
Most straightforward and simple, albeit with bad naming because I don't know what all this represents:
function reduceIt(it) {
return it.reduce((res, item) => {
const result = { ...res };
if (item.language) {
const language = item.language.languageValue;
const category = item.categoryValue;
result[language] = category;
}
return result;
}, { it: undefined, de: undefined, en: undefined });
}
export const fn1 = article => reduceIt(article.categoryValueDtoSet);
export const fn2 = article => reduceIt(article.titleDtoSet);

Mocking chained methods

(I use Jest for testing)
For example, I have this function:
const find = () => {
return {
where: () => {
in: () => {}
}
};
};
and I call that in different place:
find('me').where('id').in(['123']);
How to mock and test calls in find(), where() and in()?
Here's a dirt simple mock interface:
const find = (findData) => {
const data = {
find: findData
};
const self = {
where: (whereData) => {
data.where = whereData;
return self;
},
in: (inData) => {
data.in = inData;
return self;
},
data
};
return self;
};
const res = find('me').where('id').in(['123']);
console.log(res.data);

How to make Object.assign work?

Background
I am trying to extend the functionality of an old object via Object.assign, by passing in a new object with an additional feature.
const oldObj = () => {
const printLog = () => console.log("hello");
return {printLog};
};
const newObj = () => {
const test = () => {
printLog(); //fails here!
console.log("world");
};
return {test};
};
const mix = Object.assign(oldObj(), newObj());
mix.printLog();
mix.test();
Problem
My mix object fails execution, even though it has bot printLog and test methods:
Object {printLog: function, test: function}
Question
How can I fix my code so that the test function will work as expected?
In order to access printLog, you have to access it through this. However, your function test cannot be an arrow function because arrow functions use the this context of the context they're defined in, so to get the result you want, change printLog() into this.printLog() and switch test from an arrow function to a regular function:
const oldObj = () => {
const printLog = () => console.log("hello");
return {printLog};
};
const newObj = () => {
const test = function() {
this.printLog(); //fails here!
console.log("world");
};
return {test};
};
const mix = Object.assign(oldObj(), newObj());
mix.printLog();
mix.test();
edit: Change your code to this:
const oldObj = () => {
const printLog = () => console.log("hello");
return {printLog};
};
const newObj = () => {
function test() {
this.printLog();
console.log("world");
};
return {test};
};
const mix = Object.assign(oldObj(), newObj());
mix.printLog();
mix.test();

Categories