Mocking multiple calls - javascript

I'm using ts-mock-imports and I want to mock multiple return values of a function call, then check that a function was called a given number of times. The following works:
const getUserSpy = dataServiceMock.mock('getUserFromDB')
.returns({...USER_1})
.returns({...USER_2});
In my test case, I have two calls to getUserFromDB() and with the above, getUserSpy.callCount is equal to 2. But this is order-dependent, so I'd rather be able to do the following:
const getUser1Spy = dataServiceMock.mock('getUserFromDB')
.withArgs(USER_1_ID).returns({...USER_1});
const getUser2Spy = dataServiceMock.mock('getUserFromDB')
.withArgs(USER_2_ID).returns({...USER_2});
What I would expect is that getUser1Spy is called once, and getUser2Spy is called once. However, it looks like the second call to withArgs() removes the previous instance of mocking.

This worked:
const getUserSpy = dataServiceMock.mock('getUserFromDB');
getUserSpy.withArgs(USER_1_ID).returns({...USER_1});
getUserSpy.withArgs(USER_2_ID).returns({...USER_2});
// ... then ...
assert(getUserSpy.callCount).equals(2);

Related

Calling function within a Function

I have a situation where I generate code from within a Blockly component. The resulting code will have a function that I want to call. According to the Blockly "Generating and Running JavaScript" documentation, I should use eval().
When I look up eval() on MSDN, I get a section that I should "never use eval" and use Function instead.
Here is some example code from what the output of the code could be:
let blocklyResult = `function onExecute() {
console.log('Function has been called!');
}`;
let code = new Function(blocklyResult);
I want to call the onExecute function from within the code variable, but I cannot figure out how I can do that?
What is the best way to accomplish my desired result.
the Function constructor will generate a function with the string code inside. if the string code come in format of function, the function will generate this function, but you also need to call it. So ether (if you can) pass as a string the code to execute (not function) or add execute the function yourself. like this:
var a = `function onExecute(){console.log('Function has been called')}`
var b = new Function(`(${a})()`);
b();
Following Function document link, you should define function just from code lines, not include something like function XXXXX() {}
So, it should be
let blocklyResult = `console.log('Function has been called!')`;
let code = new Function(blocklyResult);
code()
let blocklyResult = `function onExecute() {
console.log('Function has been called!');
}`;
// v1
let code1 = new Function(`${blocklyResult};onExecute();`);
code1();
// v2
let code2 = (new Function(`return ${blocklyResult}`))();
code2();
v1 creates a new function every time it's called
v2 returns the function so it can be called multiple times without recreating the blockly function
v2 is preferable IMO

JavaScript: Access variables created by an Click-Event outside the Scope of .addEventlistener()

I want to update Variables outside an Click-Eventlistener.
The following is just demo-code, its not intended to work or anything, just to demonstrate my problem.
Class
class test {
constructor() {
// SOMETHING
}
get a() {//DOSTH};
get b() {//DOSTH};
Button - Part
applyBtn.addEventListener('click', () {
const a1 = testArr.a;
const b1 = testArr.b;
});
console.log(a1);
console.log(b1);
Of course, the console.log(a1) e.G. is executed immediately which leads to nothing being logged. This makes completely sense, since I get a1 and b1 after the button is clicked.
My Question
How do I create code (e.g. a function or a class) that works after the Button is clicked with the condition that it should not be inside of the addEventlistener() functionality?
I have something like the Promise-Technique in my mind by using a then().
*Edit
Background-Information
My goal is to create a new class that uses a1 and a2
and sends these variables to another file (a python file, I am using ChildProcesses of NodeJS for doing so).
I would like to keep a clean code structure which implements the OOP principle as most as possible, which is why I do not want to add this functionality inside of the addEventListener().
You can try closures. With a function closure you can store data in a separate scope, and share it only where necessary.
const click = () => {
let count = 1
return () => count++
}
const incrementCount = click()
const anotherIncrementCount = click()
console.log(incrementCount()) // 1
console.log(incrementCount()) // 2
console.log(incrementCount()) // 3
console.log(anotherIncrementCount()) // 1

Test code inside an rxjs subscription when using jasmine marbles

I want to be able to test the code that runs inside an observable subscription:
function foo(someStream$: Observable<number>) {
someStream$.pipe(
map((x) => x + 3),
).subscribe((result) => {
SomeService.someFunc(result)
})
}
For example, I want to make sure someFunc() gets called with result. I would think that I should be able to do something like
const someStream$ = cold('-a--', { a: 5 })
const someFuncSpy = spyOn(SomeService, 'someFunc')
foo(someStream$)
expect(someFuncSpy).toHaveBeenCalledWith(8)
Problem is that I will be told that someFunc was never called. I do not want to separate the stream and the subscribe into separate functions.
you could use Rx.Observable.of(5) instead of cold() to pass a number through the observable

Exporting Objects and Promises in NodeJS

I am trying to export a function that will let you put in a parameter (trading pair) and it will return the data for that trading pair. This is the code that creates a function that:
Accepts a parameter (trading pair).
Returns the data for that trading pair in the form of a Promise.
Then calls another function which processes that data.
// This function is exported and let's you feed in pairs you want data for - feeling proud.
function pullData(coinPair) {
kc.getTicker({
pair: coinPair
}).then(returnData).catch(console.error)
}
// This function is the callback, which I believe means this function is called and fed the results of the Promise returned from 'kc.getTicker'.
// At first it just logs the data, but now I'll need to find a way to return the data as a usable array. Maybe use the 'return()' function?
function returnData(pairData) {
// Nae Nae
//return pairData;
console.log(pairData);
}
// Finally we export our hard work
exports.pullData = pullData;
I now want to simply have the exported function return the data (and for this data to be usable by a callback function.
// Including important sub modules & config files
const tradeData = require('./example');
var config = require('./config');
// Log the config pairs (Method 1):
function logArrayElements(element, array) {
console.log(element);
}
config.pairs.forEach(logArrayElements);
// Was going to cycle through config pairs. However, I will instead have a base strategy that will be replicated for each pair and run side by side.
//console.log(tradeData.pullData('ETH-USDT'));
tradeData.pullData('ETH-USDT', calculations);
function calculations() {
console.log(pairData);
}
The relevant lines here are the including of the file ('./example') and the pitiful attempt at using the function with a callback down lower.
My goal is to be able to pass something like this:
tradeData.pullData('ETH-USDT', calculations);
function calculations() {
// Calculations and logic here
}
That may involve having '.then' simply return the data. I believe this would allow for a 'calculations' function to use the data after the asynchronous function finishes...
Any answers are greatly appreciated as I haven't been able to find guidance as to what I should do here.
I'm not sure what it is you like pullData to return. you would like it to return only the data? So something like this:
function pullData(coinPair) {
return kc.getTicker({
pair: coinPair
})
.catch(console.error) //.then(returnData)
}
And then you'd like it to receive a calculations function that is performed on the data like this:
function pullData(coinPair,calculations) {
return kc.getTicker({
pair: coinPair
}).then(calculations).catch(console.error)
}
Now the caller can do:
pullData(pair,calculations);
But the caller may ass well do:
pullData(par).then(calculations)
I'm not sure what the benefit here is.
My question may have confused others, as I was genuinely lost as to the proper structure to follow.
Upon review the following day, what I was trying to do was:
Create a function that would request data from an API.
Export this function and allow it to be called in other files.
Allow those other files to pass in their own callbacks in order to perform their desired calculations and use the data appropriately.
In my original question, I did not define a callback as a parameter for the data collecting function. As a result, the function would only ever expect one parameter, namely the 'pair'. I believe it would then call '.then()' once the asynchronous process was finished. However, the function it calls would have to be within the original file.
To remedy this I had to add a function, in this case, named 'calculations', as a parameter in the function and then have '.then()' call that function. This told '.then()' to look for the function that would be passed as the second parameter and then call it once the data had been received from the API.
This now means I can export the function to multiple other files and if I want other functions to use the data I just have to pass those functions in with the call.

Why does it work correct with an array but not with an object?

I am developing an AngularJS application and found the following behavior.
I have two functions in my service. The first function returns all the categories stored in the database and the second returns one category by its id.
Here is my service:
angular.module('categoriesRepository', [])
.service('categoriesRepository', ['$cordovaSQLite', 'sqliteHelper',
function ($cordovaSQLite, sqliteHelper) {
//this works - returns an array with all categories
this.getAll = function () {
var categories = [];
$cordovaSQLite.execute(sqliteHelper.getDb(),
"SELECT * FROM categories;")
.then(function (res) {
for (var i = 0; i < res.rows.length; i++) {
categories.push(res.rows[i]);
}
});
return categories;
}
//this works not - returns undefined
this.getById = function (id) {
var category;
$cordovaSQLite.execute(sqliteHelper.getDb(),
"SELECT * FROM categories WHERE id = ?;", [id])
.then(function (res) {
category = res.rows[0];
});
return category;
}
}]);
I know that I can use Angulars $q to run functions asynchronously, and use their values when they are done processing.
Why does the getById function return the category directly and the getAll wait until the array is filled?
EDIT
I had the getAll function posted wrong. There is no return statement before $cordovaSQLite.execute
UPDATE:-
After your question is updated.
In the first example your are creating an array first by doing var categories = [];and then returning this array before finishing your async call. When your async call completes it just pushes certain elements into the array thus not destroying the reference to the array (categories ) variable. When it is returned back if you will debug it you will find the function returning an empty array and later when the async call succeeds only then the array will be filled.
In the second example you are creating just a variable and then returning it before the async call finishes. But then the async call is finished you assign the variable to a new value. thus destroying the earlier reference.
Solution:-
Though not a preffered approach to make it work. you will have to maintain the category variable reference. for this you can use angular.copy OR angular extend
So the second part of your code should be like
this.getById = function (id) {
var category;
$cordovaSQLite.execute(sqliteHelper.getDb(),
"SELECT * FROM categories WHERE id = ?;", [id])
.then(function (res) {
angular.copy(res.rows[0], category);
//now the reference to the category variable
//will not be lost
});
return category;
}
Better Practice:-
The way you have been developing this application is wrong. Async calls should not be handled this way. I earlier asked a question just to clarify the way to handle the async calls and state inside the angular app, factories and controllers please have a look here. It provides two ways to handle the state and async calls. There might be many more practices out there but these two suit me best.
It is unfortunate that this approach appears to 'work' because it is caused by the modification of the returned array object "at some unspecified time" after it is returned.
In the usage the array is accessed/observed after1 it has been modified by the asynchronous call. This makes it appear to function correctly only because of the (accidental) asynchronous-later-than observation.
If the observation was prior to the actual completion of the SQLite operation - such as immediately after the getAll function call - it would reveal an empty array.
Both functions are incorrectly written and the first accidently releases Zalgo (or perhaps his sibling).
See How do I return the response from an asynchronous call? for more details.
1 Chrome's console.log can be confusing as it works like console.dir and thus may be showing the current value and not the value when it was invoked.
As stated already, this is a bad approach. You can't use result of your function immediately after it returns.
However I didn't see the answer to your exact question: why do they behave differently?
It happens because with an array you return a reference to an object (type Array). Later on you use same reference to modify contents of the object, i.e. push new items into the array.
However in second function you modify the reference itself. You make you local variable categories point to a new object. Thus old object (reference to which was returned to outer scope) remains untouched. To make it work the same way you should have written
category.row = res.rows[0];
You return the result of the execute in the first case, whereas you return the variable in the second case, which has most likely not been populated yet.

Categories

Resources