Use constants or no for expectations in tests? - javascript

For example, we have some big page that we testing, and for test we have big mock.
And one of our expectations - check value of product price.
It can be done like:
expect(price).toBe(20);
Or, we can use value directly from mock:
expect(price).toBe(orderMock.data.user.order.price);
Or define additional variable like:
const expectedPrice = orderMock.data.user.order.price;
expect(price).toBe(expectedPrice);
Which way will be preferrable?

I believe both ways are ok in your scenario, however I would declare const mostly when I have multiple attributes, in order to avoid repeat orderMock.data.user.order too many.
Sometimes you can use object destructuring as well, when you have more attributes:
const { price:expectedPrice, otherAttribute } = orderMock.data.user.order;
expect(price).toBe(expectedPrice);
expect(otherValue).toBe(otherAttribute);
Just keep in mind if you do something similar with methods you may lose your bind.

I appreciate second way a lot more, cause its re-useable and it's says about it self - variable names are like descriptions
PS: In my opinion you should use var instead of const cause many older browsers dont fully support const https://caniuse.com/?search=const
If im right const is full supported since ECMA 6

Related

Whats up with eval()?

I've seen a lot about how the eval() function is evil; not a wise choice for HTML/JavaScript programming. I would like to use a function where I can pass in a string to have it read as a variable name, and eval() seems to do just that, but I don't want to use a destructive function.
From what I understand, the issue with eval() is that it can read third-party input as actual code, which opens a door for malicious activity. I have a map element that keeps track of location using strings for the location names. I also have large blocks of text assigned to variables so I can pull up a description of the current location easily. This seems like an acceptable time to use eval, as the strings that I would be passing in would be provided by other parts of the code. Is this a fair judgement, or is there some other function that I should be using?
(Moving my comment as an answer)
An easy way to get around that is to save whatever variable you're interested in accessing in a javascript Object (i.e. key-value pairs), and access them via indexing. This simple use case doesn't need eval.
From what I understand, the issue with eval() is that it can read third-party input as actual code, which opens a door for malicious activity.
This is not the only reason. One could argue that by today's standards the performance of JavaScript code is negligible.
However, one has to take into account that eval() actually invokes the JavaScript interpreter which is significantly slower than writing the code upfront. ¹
I would like to use a function where I can pass in a string to have it read as a variable name, and eval() seems to do just that, but I don't want to use a destructive function.
This does not warrant the use of eval(). As mentioned in the comments, you can achieve this with keeping track of variables in an object:
let vars = {}
vars["some_variable_name"] = "test"
const var_name = "some_variable_name"
console.log(vars[var_name]) // "test"
as the strings that I would be passing in would be provided by other parts of the code
Might be, but what if in the future some piece of that code actually does process some user input?
Not worth the performance penality and obvious security risk in my opinion.
For a simple way to use a variable name as a string is to use an Object (called a dictionary or map in some languages)
const stringToGrade = {
"freshman": 9,
"sophomore": 10,
"junior": 11,
"senior": 12,
};
document.querySelector("#btn").addEventListener("click", () => {
const asString = document.querySelector("#inp").value.toLowerCase();
const grade = stringToGrade[asString];
console.log(`Your grade number is ${grade}`);
});
<input id="inp" placeholder="Enter your grade level (freshman, sophomore, etc.)" />
<button id="btn">Submit</button>

Getting deformation object in spark ar environment

I am trying to get deformation object to change it properties by JS, but I cannot even get it by any Spark module.
Spark AR have sample project with face distortion deformation.
https://developers.facebook.com/docs/ar-studio/tutorials-and-samples/samples/face-distortion/
You can even see in tutorial, that there is some morph object attached, which called faceDistortionPack. This object is located in assets, and I tried to get it by different ways in script, but couldn't make it. I want to write some js logic to manipulate deformations.
const Scene = require('Scene');
const Diagnostics = require('Diagnostics');
const faceMesh = Scene.root.find('facemesh_distortion');
Diagnostics.log(faceMesh); // FaceMesh: https://sparkar.facebook.com/ar-studio/learn/documentation/reference/classes/scenemodule.facemesh
Diagnostics.log(faceMesh.deformation); // null
Diagnostics.log(faceMesh.find('faceDistortionPack')); // Exception...
// ....
I want to get 'faceDistortionPack' object to access it properties, like 'nose_z', so I can change them by JS.
Although this is a pretty old question I thought I'd answer anyway if anyone struggles with this and comes across this thread.
First of all: There's an amazing collection of helpful tips, tutorials, snippets etc. called Spark AR Community. There you can find a GitBook with an alternative, better indexed and better working version of the official script object reference. I recommend using it if you're lost in the official reference or it's not working which happens quite often. There you can see, that the BlendShapesMesh, mentioned in the previous answer is deprecated as of Spark AR v85+, so that won't help anyone. ()
So, what you are trying to achieve, if I understand it correctly, is to access the faceMesh's Blendshapes and change their value through script. What you need to do is this:
Follow the instructions in this Tutorial: https://sparkar.facebook.com/ar-studio/learn/tutorials/face-distortion-retouching/
After you applied the Blendshapes, mess around a bit with adjusting the Blendshapes, so you understand what's happening.
Add a script to your assets. You're gonna want to access the faceMesh-Object's Blendshapes' weight Property through script. That can be done by using the getBlendshapes()-Method of the Mesh-Class.
Here's a code example:
//Require Modules
const Scene = require('Scene');
const Diagnostics = require('Diagnostics');
const Reactive = require('Reactive');
//Enable async/await [part 1]
(async function () {
//Load Assets as Promise
const loadAssets = await Promise.all(
[
Scene.root.findFirst("faceMesh0"), //Put name of your facemesh here, default is faceMesh0
]
).then(function(assets){
const faceMesh = assets[0]; //Assign the facemesh from the assets-Array of the promise to a variable you can work with better
const faceMeshShapes = faceMesh.getBlendShapes(); //Access all Blendshapes of the faceMesh-Object and store them in an Array
What you have now is a variable called faceMeshShapes, that's an object with an array of Blenshapes in it. You can console log it with Diagnostics.log(faceMeshShapes) and see that there's an array called "_value" in it, that's filled with all Blendshapes as objects, that have a weight-Property, which specifies the weight of the Blendshape with a scalarValue. You can consolelog this Value by converting it with the pinLastValue()-Method of the scalarValue-Class and you can assign different values by binding it to a custom value, that you convert to a scalarValue by using the val()-Method from the Reactive-Module.
Here's an example:
Diagnostics.log(faceMeshShapes._value[0].weight.pinLastValue()); //console log the Value of the weight property's scalarValue of the Blendshape that's stored at the index 0 of the _value-Array
faceMeshShapes._value[0].weight = Reactive.val(0.5) //set the weight to 0.5
Diagnostics.log(faceMeshShapes._value[0].weight.pinLastValue()); //console log the changed value of the weight property
So basically, that's how you can access every Blendshape's weight. The index should be according to the order in which they are listed in spar AR studio, beginning with 0 for the first BlendShape. Now you can do lots of things with this value, like binding it to an animation that animates it from 0-1 or to the mouth-openess using the face-tracking module and so on.
Last but not least, don't forget any semicolons and close all brackets.
});
})(); // Enable async/await [part 2]
P.S.: It can really help sometimes to understand what's happening and how to access stuff, by console logging a list of all properties of an object. Especially since the spark AR documentation is pretty weak on that part (and pretty weak in general). You can use the following function from MDN to do that. It's nothing fancy, but it does the job and has saved me a couple of times already :)
function listAllProperties(o) {
var objectToInspect;
var result = [];
for(objectToInspect = o; objectToInspect !== null;
objectToInspect = Object.getPrototypeOf(objectToInspect)) {
result = result.concat(
Object.getOwnPropertyNames(objectToInspect)
);
}
return result;
}
The link you posted isn't live any more.
I'm guessing the below links are more relevant now for others looking into this. I animated a series of blendShapes, and these links were useful. Basically cycling through the weights of each blendShape.
https://sparkar.facebook.com/ar-studio/learn/documentation/reference/classes/scenemodule.blendshapesmesh
https://sparkar.facebook.com/ar-studio/learn/documentation/reference/classes/scenemodule.blendshape

Conditional data structure (object) access

I have a set of JavaScript functions that handle certain objects. All these objects have the following flexibility:
Fields can be accessed like this: data[prop][sub-prop][etc.], OR
Like this (with a type sub-structure): data[TYPE][prop][sub-prop][etc.].
The object is accessed in many places, and the condition (let's call it is_mixed) is relevant everywhere.
I thought of the following alternatives:
Always access data like this: (is_mixed ? data[TYPE] : data)[prop][sub-prop][etc.]
Have a function called getData and always access data like this: getData()[prop][sub-prop][etc.].
The function code would be:
function getData() { return is_mixed ? data[TYPE] : data; }
Run the following on every new input: if (is_mixed) { data = data[TYPE]; }
It seems to me that options 2 and 3 might be copying the object data (which might be big) and performance is important here (I didn't find the literature to support this guess), but option 1 will make the code big and ugly.
Is there a better option? What's the best way to acheive this in terms of performance, code quality and basically best practices?
It seems to me that options 2 and 3 might be copying the JSON content
No, they won't. They both just copy an object reference, which is quick and cheap (like copying a boolean). #2 is of course slightly slower, since it's a function call, but if it's used a lot, any decent JavaScript engine will inline the function anyway, giving you the benefit of modularity at the source level. (It can take thousands of calls to the function in a shortish period of time to make that kick in, though; e.g., a modern engine only bothers with optimization when it looks likely to matter.)

Bluebird promisifyAll doesn't work in a vanilla case

I'm trying to promisify a Pusher.js function and I am a bit confused why the last technique works and the first two don't, since the first two seem to be following the documentation example.
The errors I get are: triggerAsync not defined.
Sample
var Pusher = require('pusher');
var pusher = new Pusher(params);
Promise.promisifyAll(Pusher); //this doesn't work for some reason
var triggerAsync = Promise.promisify(pusher.trigger); //this also doesn't work
Promise.promisifyAll(Object.getPrototypeOf(pusher)); //this works
...since the first two seem to be following the documentation example.
So is the last! If we take a look at the documentation for Promise#promisifyAll over at bluebirdjs.com (at the bottom of the document) you will find this, which gives a short explanation for why you need to employ this behaviour:
In all of the above cases the library made its classes available in one way or another. If this is not the case, you can still promisify by creating a throwaway instance:
var ParanoidLib = require("...");
var throwAwayInstance = ParanoidLib.createInstance();
Promise.promisifyAll(Object.getPrototypeOf(throwAwayInstance));
// Like before, from this point on, all new instances + even the throwAwayInstance suddenly support promises
So although it doesn't give us a definitive answer for why we need to do this with Pusher, we can at least be sure that it is because it doesn't "[make] its classes available in one way or another". You can also rest assured that you aren't necessarily doing it wrong (you shouldn't use this method unless you have to).

Why shouldn't I access elements more "directly" (elemId.innerHTML)

I've seen some JavaScript code to access HTML elements like this: elementID.innerHTML, and it works, though practically every tutorial I searched for uses document.getElementById(). I don't even know if there's a term for the short addressing.
At first I thought simplistically that each id'ed HTML element was directly under window but using getParent() shows the tree structure is there, so it didn't matter that elements I wanted were nested. I wrote a short test case:
http://jsfiddle.net/hYzLu/
<div id="fruit">Mango<div id="color">red</div></div>
<div id="car">Chevy</div>
<div id="result" style="color: #A33"></div>
result.innerHTML = "I like my " + color.innerHTML + " " + car.innerHTML;
The "short" method looks like a nice shortcut, but I feel there is something wrong with it for it practically not appearing in tutorials.
Why is document.getElementById() preferred, or may be even required in some cases?
Why shouldn't I access elements more “directly” (elemId.innerHTML)
Because, according to the others in this thread, referencing arbitrarily by id name is not fully supported.
So, what I think you should be doing instead is store their selections into a var, and then reference the var.
Try instead
var color = document.getElementById('color');
color.innerHTML = 'something';
The reason why this would be a good thing to do is that performing a lookup in the DOM is an expensive process, memory wise. And so if you store the element's reference into a variable, it becomes static. Thus you're not performing a lookup each time you want to .doSomething() to it.
Please note that javascript libraries tend to add shim functions to increase general function support across browsers. which would be a benefit to using, for example, jquery's selectors over pure javascript. Though, if you are in fact worried about memory / performance, native JS usually wins speed tests. (jsperf.com is a good tool for measuring speed and doing comparisons.)
It's safer I guess. If you had a variable named result in the same context that you are doing result.HTML I'm pretty sure the browser will throw a wobbler. Doing it in the way of document.getElementById() in this instance would obviously provide you with the associated DOM element.
Also, if you are dynamically adding HTML to the page I may be wrong, but you could also encounter unexpected behaviour in terms of what result is :)
Also I will add that not all ID's can have values that will not work as variable names. For instance if your ID is "nav-menu".
Although I suppose you could write window["nav-menu"].innerHTML
Which makes me think, what happens if you create a window level variable with the same name as an ID?
Checkout this jsfiddle (tested in chrome): http://jsfiddle.net/8yH5y/
This really seems like a bad idea altogether. Just use document.getElementById("id") and store the result to a variable if you will be using the reference more than once.

Categories

Resources