Cypress - nested function instead of using while loop - javascript

I spotted that when I'm using while loop, cypress does not work, so instead of while loop I found this kind of solution:
const functionName = () => {
if ( a != b ) {
this.functionName();
} else {
cy.get(".selector").click()
}
};
This block of code (typescript) works really well, but 'this' is highlighted in red and the message appears: "Object is possibly 'undefined'."
Any idea how can I to get rid off this error?

Assuming it's a typescript error, add the Non-null assertion operator
// Compiled with --strictNullChecks
function validateEntity(e?: Entity) {
// Throw exception if e is null or invalid entity
}
function processEntity(e?: Entity) {
validateEntity(e);
let s = e!.name; // Assert that e is non-null and access name
}
For reference, How to suppress "error TS2533: Object is possibly 'null' or 'undefined'" answers the same question.
You probably don't need the this. prefix at all, since the function is defined on the current scope (not a class method).

Related

TypeError: "this is undefined" When using forEach on member array

I have a class marketData:
export class marketData {
id: number;
denomCount: number;
itemCount: number;
conversionRates: Array<number> = [];
conversionRateToLowest: Array<number> = [];
itemPrices: Array<Array<number>> = [];
}
I would like to define a member function for it, validate(), that checks that the values of the class are set properly. I wrote part of this method to check itemPrices:
this.itemPrices.forEach(function(this, prices){
if(prices.length != this.itemCount){
// handle error
});
However, the above gives me a ERROR TypeError: "this is undefined". I got the exact same error trying to check itemPrices in this manner:
this.itemPrices.forEach(function(prices){
if(prices.length != this.itemCount){
// handle error
});
i.e. without the this in the function parameters.
What is the correct way to access the itemCount member variable?
Its because of the the way you are using forEach. Use Arrow Functions instead like below. And its recommended that when using typescript classes always use arrow functions else you will keep running into this problem.
this.itemPrices.forEach((prices) =>{
if(prices.length != this.itemCount){
// handle error
}
});
You can make use of ES6's arrow functions to access this. Anyways, do read this up to udnerstand to context of this when it comes to JavaScript and using them within OOP in JS.
this.itemPrices.forEach((prices: number) => {
if (prices.length != this.itemCount){
// handle error
});
});
The value of this in the function is not the same as it is inside the class. You can either use fat arrow function or use bind(this) to bind the function to the class.
this.itemPrices.forEach(function(prices){
if(prices.length != this.itemCount){
// handle error
}).bind(this);

Coffeelint says I have implicit parens?

Coffeelint is telling me I have implicit parens. I'm trying to find what is causing this error.
#309: Implicit parens are forbidden.
Here's my code:
((factory) ->
if typeof module == 'object' and module.exports
module.exports = factory
else
factory(Highcharts)
return
)(Highcharts) ->
...
if seriesTypes.map
seriesTypes.map::exportKey = 'name'
if seriesTypes.mapbubble
seriesTypes.mapbubble::exportKey = 'name'
if seriesTypes.treemap
seriesTypes.treemap::exportKey = 'name'
return
###The entire block over code is one function.
Anyone give this a shot?
I think there's an issue with your code. Look at JS generated:
(function(factory) {
if (typeof module === 'object' && module.exports) {
module.exports = factory;
} else {
factory(Highcharts);
}
})(Highcharts)(function() {
...
});
As the first function returns undefined there's an error trying to call undefined as a function.
Actually no_implicit_parens is for:
# This rule prohibits implicit parens on function calls.
# Some folks don't like this style of coding.
myFunction a, b, c
# And would rather it always be written like this:
myFunction(a, b, c)
With this option on, you must put brackets around any arguments list of any function call.
To make your code working you may do the following:
((factory) ->
...
)(Highcharts(->
...
))
These brackets around the callback function do the trick. But as I said, I'm sure there's an issue with your code and the fix actually makes no much sense to me :)

Javascript - Check Amazon Objects to see if defined

I get an error if part of the Amazon product is missing. For example, I can do this check:
typeof success.data[i].OfferSummary[0].LowestNewPrice[0].Amount !== "undefined"
but if OfferSummary is not defined this would throw an error. Do I need to check every object under the data? Is there an easier way?
I was thinking of doing a try ... catch and trapping the error, but I'm sure someone has run into this before.
Yes you'll need to check at each step or wrap the check in a try catch block.
At the moment you're trying to access a property on undefined, which does not exist.
if (success.data[i] && success.data[i].OfferSummary[0] &&
success.data[i].OfferSummary[0].LowestNewPrice[0] &&
success.data[i].OfferSummary[0].LowestNewPrice[0].Amount !== undefined) {}
//OR
var amount = null;
try {
amount = success.data[i].OfferSummary[0].LowestNewPrice[0].Amount;
} catch( err ) {}
if (amount !== undefined){}
If you're using lodash you may use function _.get:
var amount = _.get(success, 'data[' + i + '].OfferSummary[0].LowestNewPrice[0].Amount', 0);
The 3rd parameter is default value which will be returned in case of smth in this path is not defined.
Actually, under the hood it's just a set of if-checks but the code looks more elegant.

Anonymous/inline interface implementation in TypeScript

I've just started with TypeScript and I'm trying to understand why the following inline object definition isn't considered valid. I have a collection of objects - their type is irrelevant (to me), but they implement the interface so that when I iterate through them I know that the interface methods will be present in each object in the collection.
I came across a "compiler" error when I tried to create an object with private information required to implement the required method:
interface Doable {
do();
}
function doThatThing (doableThing: Doable) {
doableThing.do();
}
doThatThing({
private message: 'ahoy-hoy!', // compiler error here
do: () => {
alert(this.message);
}
});
The compiler error message is "Argument of type '{ message: string, do: () => void; }' is not assignable to type Doable. Object literal must specify known properties, and 'message' does not exist in type Doable". Note that the same message is given if I define the object outside of the function call, i.e.
var thing: Doable;
thing = {
private message: 'ahoy-hoy!', // error here
do: () => {
alert(this.message);
}
};
doThatThing(thing);
The same error occurs if I add "unexpected" methods as well:
doThatThing({
do: () => {
alert("ahoy hoy");
},
doSecretly: () => { // compiler error here now
alert("hi there");
}
});
I looked at the JavaScript and discovered that this within the inline object definition was being scoped to the global object:
var _this = this; // wait, no, why!?
function doThatThing(doableThing) {
doableThing.do();
}
doThatThing({
message: 'ahoy-hoy!',
do: function () {
alert(_this.message); // uses global
}
});
I tried searching for information on inline implementations of interfaces in TypeScript, but couldn't find anything speaking to this issue specifically.
I can confirm that the "fixed" compiled JS works as intended:
function doThatThing(doableThing) {
doableThing.do();
}
doThatThing({
message: 'ahoy-hoy!',
do: function () {
alert(this.message);
}
});
...and that makes sense to me, because (as far as I understand) this is implicitly calling the Object constructor, so this should be scoped to the new Object instance.
It seems like the only solution is to declare each implementation as a class implementing the interface, but that feels really regressive/heavy-handed since I'm only going to have one instance of each class. If the only contract with the called function is implementing the interface, then why can't the object contain additional members?
Sorry, this turned out longer than I intended ...in summary, I'm asking:
Why is that inline interface implementation ("anonymous class", as would be said in Java) considered invalid in TypeScript? Specifically, what does that compiler error mean, and what does it protect against?
Why is the scope-reassignment to the global object generated in the "compiled" JavaScript?
Assuming it's my error (e.g. that the compiler error is necessary for protecting against some undesirable condition), is the only solution really to explicitly declare a class in advance, like so?
interface Doable {
do() : void;
}
class DoableThingA implements Doable { // would prefer to avoid this ...
private message: string = 'ahoy-hoy';
do() {
alert(this.message);
}
}
class DoableThingB implements Doable { // ... as well as this, since there will be only one instance of each
do() {
document.getElementById("example").innerHTML = 'whatever';
}
}
function doThatThing (doableThing: Doable) {
doableThing.do();
}
var things: Array<Doable>;
things = new Array<Doable>();
things.push(new DoableThingA());
things.push(new DoableThingB());
for (var i = 0; i < things.length; i++) {
doThatThing(things[i]);
}
P.S. The compiler error only appeared when I upgraded to TS 1.6 today, although the faulty scope bug in the compiled JS occurs in both 1.6 and 1.5.
Update: François Cardinaux provided a link to this answer, which recommends using a type assertion, but this only removes the compiler error and actually causes a logic error due to improper scope:
interface Doable {
do();
}
function doThatThing (doableThing: Doable) {
doableThing.do();
}
doThatThing(<Doable>{ // assert that this object is a Doable
private message: 'ahoy-hoy!', // no more compiler error here
do: () => {
alert(this.message);
}
});
Looking at the compiled JS, this is incorrect:
var _this = this; // very wrong, and now hidden
function doThatThing(doableThing) {
doableThing.do();
}
doThatThing({
message: 'ahoy-hoy!',
do: function () {
alert(_this.message); // s/b "this.message", which works in JS (try it)
}
});
OK, I finally discovered the problem to question 2 - I was using the fat arrow => to declare the object's method here:
doThatThing(<Doable>{
private message: 'ahoy-hoy!',
do: () => { // using fat arrow: global scope replaces new object's scope
alert(this.message);
}
});
...which "sucked" the global scope into the method. The problem is fixed using the longer syntax, like so:
doThatThing(<Doable>{
private message: 'ahoy-hoy!',
do: function() { // using "regular" anonymous function syntax, "this" meaning is preserved
alert(this.message);
}
});
So in summary:
unanswered;
There was a typo in my code, and I should have been using "function()" instead of "=>"; and,
Type-asserting the object with the interface removes the compiler error.

Having IE Issues When Passing Object By Ref. and Dynamically Adding Properties

So, I've created a function to do some error checking on an XML file that I recieve from an AJAX call. Part of the validation is that the function then builds out an object for easy access while I process that data into a form. In FF, works like a charm. IE dies with the error:
Object doesn't support this property or method
Here is the function (minus the un-important bits):
function checkReceiveXMLTagString( doc, messageObject, tag ) {
var tag_nodes = doc.getElementsByTagName( tag );
...do some error checking...
messageObject[tag] = tag_str; <-- error occurs on this line
return true;
}
Here is an example of how the function is call:
if ( checkReceiveXMLTagString( messageObject.Name[0], messageObject.Name[0], "First" ) ) {
...process messageObject.Name[0].First...
}
Like I said, FF has no issues. Safari loads the pages as well. IE has issues.
Thanks!
Looks like something is making messageObject be null or undefined
If the error is on this line:
messageObject[tag] = tag_str;
Then, the only two ways I know of that that can cause an error are:
messageObject is not an object that you can set properties on (null or undefined are the most likely ways that would happen)
tag is null or undefined
Since I see that your code calls this function hundreds of times so you can't effectively just break on it, I'd suggest you put in some defensive coding to check for those conditions and output something to the debug console to identify what the state is when the problem occurs. You can even trigger a conditional breakpoint with code like this:
if (!messageObject || !tag) {
debugger;
}
In the toughest cases, you can put an exception handler around it and break when the exception is thrown:
try {
messageObject[tag] = tag_str;
} catch(e) {
debugger;
}
Both of these will allow you to capture the condition in the debugger and examine all your parameters at the time of the error.

Categories