Mock an internal variable inside a function [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 15 days ago.
Improve this question
I want to check the result of a function with sum of two numbers without having a return statement:
function sum(a,b){
var res = a+b;
return true;
}
test('sum of numbers', () => {
expect(sum(1,2)).toBe(res)
});
How to get the value of the res variable in my test?

The test should be testing the result of the function. You can not access variables inside of a function since the varaibles scope is to the function block and it is not global.
You function should be returning the result from the function and your test should be testing what you expect the output to be.
function sum(a,b){
var res = a + b;
return res;
// return a + b;
}
test('sum of numbers', () => {
expect(sum(1,2)).toBe(3)
});

Testing implementation details like this is an anti-pattern in regards to frontend testing. You should be testing the user interaction that calls this function (eg. a button click). Then, check whether the rendered text on the screen is your desired result (ex. 1+1=2).
Project requirements that dictate a function is tested directly, are quite simply wrong.

Basic test case for your sum function
test('sum of numbers', () => {
expect(sum(1,2)).toBe(3)
});
or you can use toEqual at the place of toBe.
Even you can check this post https://jestjs.io/docs/getting-started.

I have a few suggestions for you. To get the res value, you can try using a reference type like a JavaScript object.
function sum(a,b, obj){
var res = a+b;
obj.res = res;
return true;
}
test('sum of numbers', () => {
let obj = {};
expect(sum(1, 2, obj)).toBe(true)
expect(obj.res).toBe(5);
});
OR
Another option is to return an object from the function, which would include the boolean value you need to test, along with the internal variable.
function sum(a,b){
var res = a+b;
return {
res,
val: true
};
}
test('sum of numbers', () => {
const {res, val} = sum(2, 3);
expect(val).toBe(true)
expect(res).toBe(5);
});
I noticed in one of your comments on a post that you mentioned
Its a requirement in my project. I have to test an internal variable value inside a function
Just double checking, is it possible that the requirement is actually asking you to return the local variable and compare it, instead of a boolean? If so, you can follow the method outlined in #epascarello's answer. Hope that helps!

Related

Pass variable into function to be defined [duplicate]

This question already has answers here:
What's the difference between passing by reference vs. passing by value?
(18 answers)
Closed last year.
EDIT 2: Why has this very specific question been marked as a duplicate of this very conceptual one: What's the difference between passing by reference vs. passing by value?. If someone else had the same question as me, they wouldn't end up with this one on Google by searching for it and - even if they did - it wouldn't answer their question.
EDIT: Thanks everyone for your help so far. Pretty difficult stuff to understand from my point of view. The reason I'm doing this is that I've set up a function which I'm calling multiple times and in which I define a variable (a unique one with each call). I need to be able to refer back to each unique variable afterwards. Here is my actual attempted code below. What would the right way to do this be?
let newSeq1
let newSeq2
function sequenceClip(sample, length, sequenceVariable) {
let currentPosition = Tone.Transport.position
let whenToStart
if (currentPosition === '0:0:0') {
whenToStart = '0:0:0'
} else {
const barToStartOn = +currentPosition.slice(0, currentPosition.indexOf(':'))
whenToStart = `${barToStartOn + 1}:0:0`
}
sequenceVariable = new Tone.Sequence((time, note) => {
sampler.triggerAttackRelease(note, '4m', time)
}, [sample], length).start(whenToStart);
}
loop1.addEventListener('mousedown', () => {
sequenceClip("C3", '1m', newSeq1)
})
loop2.addEventListener('mousedown', () => {
sequenceClip("C#3", '4m', newSeq2)
})
How do I pass a variable into a function in Javascript to be assigned a value. E.g.:
Why does the variable not get assigned the value 5? And what's the way around this?
let a
function defineVariable(var2beDefined) {
var2beDefined = 5
}
defineVariable(a)
console.log(a === 5)
You would typically write an initializer function that returns a value and assign that return value to the relevant global variable. For example:
let newSeq1
let newSeq2
function sequenceClip(sample, length, sequenceVariable) {
let currentPosition = Tone.Transport.position
let whenToStart
if (currentPosition === '0:0:0') {
whenToStart = '0:0:0'
} else {
const barToStartOn = +currentPosition.slice(0, currentPosition.indexOf(':'))
whenToStart = `${barToStartOn + 1}:0:0`
}
return new Tone.Sequence((time, note) => {
sampler.triggerAttackRelease(note, '4m', time)
}, [sample], length).start(whenToStart);
}
loop1.addEventListener('mousedown', () => {
newSeq1 = sequenceClip("C3", '1m')
})
loop2.addEventListener('mousedown', () => {
newSeq2 = sequenceClip("C#3", '4m')
})
Note that both newSeq1 and newSeq2 will be undefined until the first mousedown/mouseup events.
Reassigning an identifier, by itself, never has any side-effects (in most circumstances) - the only change resulting from someIdentifier = someNewValue will be when other parts of the code reference that same someIdentifier.
If you want to pass in something to be assigned to, pass in a function which, when called, assigns to the outer variable.
let a;
function defineVariable(callback) {
callback(5);
}
defineVariable(newVal => a = newVal);
console.log(a === 5)
The only time that assigning to an identifier will have side effects is if:
Inside a function with a simple argument list, you reassign one of the parameters (in which case the arguments object will be changed as well)
You're using ES6 modules, and you reassign an identifier that's being exported, in which case other modules that import it will see the change as well

Clean way to acces nested variable properties from the $scope [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
I want to access same variable properties in a java script file but because are too many properties the code looks a bit to ugly. I have the next code:
$scope.invoice = new Invoice();
$scope.operations = {
editingLine: {},
isNewLine: false,
isEditOpen: false
};
$scope.modify = function (invoiceLine) {
if ($scope.operations.isEditOpen) return;
let originalLine = $scope.invoice.invoiceLines.find(line => line.id = invoiceLine.id);
tempLine = angular.copy(originalLine);
$scope.operations.editingLine[invoiceLine.id] = true;
$scope.operations.isEditOpen = true;
};
Is there any way to access the the property invoiceLine which is set on the object invoice, or the property isEditOpen which is set on the object operations in cleaner way? I have a lot of repetition of this code in my file and I want to find a clener way to access properties like this.
I know that I can to define a variable var operations = $scope.operations and to access the property operations.isEditOpen when I need this value but still, I want something more simpler because I don't want to create variable for all objects from the scope.
Is there any way to create a function with two params (objectFromScope, neededProperty) that can return the requiered property value from a variable which is set on the scope? Or is there any better way to do not have such much code when I want to access an object property from the scope?
PS: I can also do something like this:
let editingLine = $scope.operations.editingLine;
let isNewLine = $scope.operations.isNewLine;
let isEditOpen = $scope.operations.isEditOpen;
$scope.modify = function (invoiceLine) {
if (isEditOpen) return;
let originalLine = invoiceLines.find(line => line.id = invoiceLine.id);
tempLine = angular.copy(originalLine);
editingLine[invoiceLine.id] = true;
isEditOpen = true;
};
But is this a good approach?
Is there any way to create a function with two params ( objectFromScope, neededProperty ) that can return the required property value from a variable which is set on the scope? Or is there any better way to do not have such much code when I want to access an object property from the scope?
Yes, but I don't see how it saves you any trouble. It will also make it harder to switch to TypeScript (though you can make it work with keyof if you don't want to dereference an entire property path).
But this is that function:
function getPropertyValue( objectFromScope, neededProperty ) {
const pathComponents = neededProperty.split( '.' );
let obj = objectFromScope;
for( const component of pathComponents ) {
obj = obj[ component ];
}
return obj;
}
Usage:
$scope.invoice = new Invoice();
$scope.operations = {
editingLine: {},
isNewLine: false,
isEditOpen: false
};
$scope.modify = function( invoiceLine ) {
if ($scope.operations.isEditOpen) return;
const lines = getPropertyValue( $scope, 'invoice.invoiceLines' );
let originalLine = lines.find(line => line.id = invoiceLine.id);
tempLine = angular.copy(originalLine);
$scope.operations.editingLine[invoiceLine.id] = true;
$scope.operations.isEditOpen = true;
};
...but this really doesn't make your code any easier to read or maintain. Instead it makes it worse because doing things this way is very non-idiomatic for JavaScript and AngularJS: anyone else who works on this project will stare at the code for a few minutes and scratch their head before wondering out loud why you're doing this in the first place.

How to Call function as a variable in TypeScript [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Example :
Creating function
const isElementLoaded = () => {
//Logic
return true;
}
Calling function using this.isElementLoaded :
if (this.isElementLoaded)
{
//output true
}
If you don't want to use (), you need to make it an accessor property. (The only other way to call it without () is to use it as a tag function on a tagged template literal, which doesn't seem relevant to what you're doing. :-) )
In a class, you'd do that like this:
class Example {
get isElementLoaded() {
return /*...appropriate value...*/;
}
}
In an object literal, it's basically the same:
const obj = {
get isElementLoaded() {
return /*...appropriate value...*/;
}
};
In either case, TypeScript should be able to infer the return type from your return statement, but if necessary add the annotation, e.g.:
class Example {
get isElementLoaded(): boolean {
return /*...appropriate value...*/;
}
}
If you want to add an accessor to an object after it's created, you use defineProperty:
Object.defineProperty(obj, "isElementLoaded", {
get() {
return /*...appropriate value...*/;
},
// flags here if appropriate; they default to `false` if omitted
});
You'll need to be sure the type information for the object includes the accessor (perhaps as an optional property).
Either you use a function and then you need to use () to call the function (that's the TypeScript / JavaScript syntax):
const isElementLoaded = () => {
//Logic
return true;
}
// in a function:
if (this.isElementLoaded()) {
//output true
}
Or, you can use a property on your class with a getter:
get isElementLoaded() {
//Logic
return true;
}
// in a function
if (this.isElementLoaded) {
//output true
}
tl;dr: use this.isElementLoaded()
You are actually not calling the function you created there. You are using arrow notation to create a function, you could do the same with
function isElementLoaded(...){...}
which would it make more clear maybe that you have to call it to actually do something. By just calling the name of the function you reference to the function body - but that is not progressed in any way.
Here's a quick try-out example: https://jsbin.com/kekifugoqe/edit?js,console
Hit 'run' and you see the difference in the output.

How to return an object to the controller from a factory that uses PouchDB

I have a angularJS factory created to insert and get some values from IndexedDB. I can successfully insert the values to the IndexedDB. But when i try to get the values out of the DB and pass it to the controller i face problems.
factory.getAllProgressData = function() {
var dbOptions = {};
dbOptions.include_docs = true;
var output = {};
var result = {};
pouchDb.allDocs(dbOptions, function(err, res) {
if (err)
console.log(err);
if(res) {
output.weight = getWeightValues(res.rows);
console.log(output); // <== This console line prints the object
}
});
console.log(output); // <== This console line does NOT print the object
return output;
};
var getWeightValues = function(rows) {
var weightValues = [];
for (var i = 0; i < rows.length; i++) {
weightValues.push(rows[i].doc.Weight);
};
return weightValues;
};
As you can see in the comments of the code, when i print the object to the console at the first place it prints. But when i try to do it bellow it doesn't print. And the return value is also empty. I'm very new to javascript and this behavior is not clear to me. I want the result object to be returned to the Controller. Please help. Thanks in advance.
Just guessing but maybe the answer is because pouchDb.allDocs is an asynchronous function. This might be a good opportunity for you to learn about writing asynchronous JavaScript (aka AJAX). AJAX is a difficult concept for those new to JavaScript.
For example, you should be able to clearly understand what gets printed to the console and in what order in the following code:
function printB() { console.log('B'); }
console.log('A');
setTimeout(printB, 10);
console.log('C');
The answer is ACB, not ABC, and not BAC. If you understand why, you are well on your way to answering your own question.
A slightly more relevant example:
var a = 'A';
function changeAtoB() { a = 'B'; console.log(a); }
console.log(a);
setTimeout(changeAtoB, 10);
console.log(a);
The answer is AAB, not ABA, for the same reasons as the previous example. In addition, note that setTimeout does a specific thing, but it is a good general introductory example of the concept of an asynchronous function.
To address your question more directly, the second example corresponds to why your output variable is probably defined for one call to console.log but not the other.

Using eval to run a set of closures in JavaScript [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I want to store into an array, a set of closures to be run when it been called.
Is eval the best thing to do it?
"Eval is evil" ;-)
but here's a possible solution
Array.prototype.execute = function() {
for ( var i in this ) {
if ( i && 'execute' != i && Function == this[ i ].constructor ) {
this[ i ].apply( this );
}
}
};
var arr = [];
arr.push( ( function() {alert('A'); } ) );
arr.push( ( function() {alert('B'); } ) );
arr.push( ( function() {alert('C'); } ) );
arr.execute();
please keep in mind: it's not recommended to extend basical Javascript types in the way I did.
I’m not sure what you mean by "run when it been called", but since Arrays are Objects, you can store static information as object keys in the array:
var arr = ['foo','bar'];
arr.methods = {
foo: function() { alert(this[0]); },
bar: function() { alert(this[1]); },
};
arr.run = function() {
for (var fn in this.methods) {
this.methods[fn].call(this);
}
};
​arr.run();​
You could also make this into a reusable function using prototypal inheritance, but you would need to embed the array inside it, since Arrays are not "subclassable" in javascript.
Ok, since everybody keeps guessing at what it is you're actually looking for, here's my .02:
var closures = (function(Global,undefined)
{
var that = [];//return value
that[0] = (function(some,vars, forClosure1)
{
return function()
{
console.log(some, vars,forClosure1);
};
})(values,of,closureArguments);//create all closures you need
that.execAll = function (context,args)//the method to call them all (with arguments)
{
context = (context === undefined || context === Global ? that : context);
args = args.length ? args : [];//make sure arguments has length property
for (var i=0;i<that.length;i++)
{
if (typeof that[i] === 'function')
{
that[i].apply(context,args);
}
}
};
return that;//return closure array (with execAll method)
})(window);
Now, I've created an array of closures, that has its own method execAll, you can pass 2 arguments to this method: the first determines the context in which the closre functions of the array will be called, the second expects an array or arguments object to pass to each of these closure functions.As it currently stands, the closures cannot be called in a global context using execAll. That's just for safety, but you never know, maybe you might want to call them in the global object's context.
All in all, I think this is what you're looking for, though I must admit: I'm struggeling to see how this code could be of any use, but maybe that's just me.Anyway: good luck
You can create a function on the fly and store the reference in a variable:
var something = function() { alert("hello world"); };
And by extension in an array:
var something = [function() { alert("hello world"); },
function() { alert("hello world"); },
function() { alert("hello world"); }];
Which you may later call by using something(); in the first example or something[1](); in the second for instance. Eval is absolutely not needed here, unless the actual body of the function comes from user input (god forbid :-) )
What and how to call it is left to the implementation, but it should be fairly trivial once you are aware of this.

Categories

Resources