Javascript Element Validation within If-Statement - javascript

I'm having issues when adding an element validation within an if-statement.
Basically, irrelevant of the result of the if-statement, Protractor is still trying to find the element specified within the if-statement.
Here is the code that is still running even though the if-statement returned false:
if (thisIsAlwaysFalse == true) {
console.log(':::::::::::::::' + thisIsAlwaysFalse);
it('If-statement test', function(done) {
var elementToFind = element(by.xpath('//td[contains(#class,"hello")]'));
browser.wait(function() {
return browser.isElementPresent(elementToFind);
}, 5000);
elementToFind.click();
done();
});
}
Also, funny thing is that the console.log part is successfully ignored!
Anyone has a solution for this or possibly knows why this is happening?
Thanks in advance :)

Have you debugged the problematic area?
Nevertheless, your always-false statement is probably a promise, which is always a truthy value. In order to solve it, you need to put the whole block to then callback.
For example:
doStuff()
.then(function (result) {
if (yourAlwatsFalsyCondition(result) {
return elementFindYouDid(results)
.moreStuff(doMore);
}
})

Related

Named vs anonymous functions different behavior with a promise

I ran into a bug which I finally solved, but why it happen(ed/s) is still beyond me.
I save a variable foo using browser.storage.local.set for a firefox addon that I'm developing. I know that the variable is set, and the apparent bug was relying on some small piece of code that leads to this:
browser.storage.local.get((val) => {
if (val['foo'] === undefined){
console.log('Undefined');
}
else {
console.log('Defined')
}
});
// Outputs `Defined`, which is correct.
However, if I define the callback first, and then I get wrong output.
function checkStoredSettings(val) {
if (val['foo'] === undefined) {
console.log('Undefined')
}
else {
console.log("Defined")
}
}
browser.storage.local.get().then(checkStoredSettings, console.log);
// Outputs `Undefined`, which is incorrect.
//UPDATE
browser.storage.local.get(checkStoredSettings);
// Outputs `Undefined`, which is also incorrect.
Can someone explain what am I not getting here? I have now run the above two codes sequentially (in both orders) in the same scope.
Did you tried something like that ?
browser.storage.local.get('foo').then(console.log)

how to make wait javascript to finish all functions before return result

output = true;
if($("#password-field").css('display') != 'none') {
if(!($("#verificationCode").val())) {
output = false;
$("#code-error").html("required");
}
var codeverify = function(){
var code = document.getElementById("verificationCode").value;
coderesult
.confirm(code)
.then( function(result) {
if (result.user.uid) {
let phoneNumber = result.user.phoneNumber;
//alert(output);
alert("Verification done");
console.log(phoneNumber);
} else {
alert(output);
$("#code-error").html("no user");
output = false;
}
})
.catch(function(error) {
output = false;
$("#code-error").html("wrong");
alert(error.message);
});
}();
}
return output;
When i run this code everything works fine. but before checking the codeverify function it return the output to true even if the codeverify() function returns false
PS. I am using wizard form.
This comes down to how you write JavaScript code, I found that usually when to get to a point where my procedures are out of sync it means that I have done something wrong in previous steps. This is usually only fixed by refactoring.
Remember JavaScript does not behave the same as other languages.
What I can see from your procedure is that you are trying to do many things in one go.
Although I do not have a solution I have a suggestion, consider each action that you want your procedure to execute. Declare a separate function for each of these steps, even if your function only has one line to execute.
If there are dependencies make sure they can be resolved by parameterization.
And lastly, think pure functions. Try and structure every function to receive something and return something.
Another tip that I can give is, write your procedure to select and hold elements in variables until they are required. Consider what elements are required in execution, which of those are in the dom when execution starts and set them to variables before you start executing, then during execution if elements are added that are maybe required for later select them immediately after they are placed in the dom, this means that as your procedure executes all the ingredients are available to do whatever must be done they don't have to go find what they need on the fly.
Good Luck and happy coding.
Your coderesult.confirm(code) using promise(then & catch) so i assume it is asynchronous. You need to google yourself to learn what is async
One important thing of JS behavior is JS always process the rest of the code if there is a async function in between.
Sample:
console.log(1)
setTimeout(()=>{
console.log(2,"i suppose at position 2 but i'm at the last. This is because setTimeout is async function")
},1000)
console.log(3)
In your case, your codeverify function has async code (.confirm()) in between, so JS will process the code after codeverify (return output)until codeverify is fully completed.
Since your output was set at true since the beginning, it will return true from the last row of code return output before your codeverify completed, this is why you always get true. If you change the first row output = undefined, i believe you will see undefined result.
To solve this, one of the way is you can wrap the entire codeverify as Promise.
function codeverify(){
return new Promise((resolve,reject)=>{
var code = document.getElementById("verificationCode").value;
coderesult.confirm(code).then( function(result) {
if (result.user.uid) {
let phoneNumber = result.user.phoneNumber;
//alert(output);
alert("Verification done");
console.log(phoneNumber);
output = true
resolve(output)
} else {
alert(output);
$("#code-error").html("no user");
output = false;
resolve(output)
}
}).catch(function(error) {
output = false;
$("#code-error").html("wrong");
alert(error.message);
reject(output) //you can reject(error.message) so you can pass error message back.
});
})
}
You can execute the function like this:
codeverify().then(successData=>{
console.log(successData) //from what you resolve
}).catch(failedData=>{
console.log(failedData) //from what you reject
})
Lastly, take some time to study what is Asynchronous and What Promise to do with Async because it is everywhere in JS.

Referring to external function parameter within $timeout

I am listening to websocket events with SockJS and want to insert received objects into my $scope.mails.items which is an array. I have the below code snippet and my problem is that for some reason I am not able to pass the message into my delayed function. I know... I tried to read some explanations about this issue asked repeatedly, but still was not able to figure out why it is not working in this particular case. The reason I need to delay this is that I'd like to make sure it gets applied to my view, it does not otherwise.
MyService.receive().then(null, null, function(message) {
$timeout(function(m) {
if($scope.mails.items.indexOf(m) == -1) {
$scope.mails.items.push(m);
}
}, 0, true, message);
});
When debugging it, I can see that the message variable has proper value but when it comes to stopping in the middle of my delayed function, m is not getting the data, however I would expect $timeout to pass it down.
Can you please help?
Not sure why m is not getting value (explanation welcome), but this works:
MyService.receive().then(null, null, function(message) {
$timeout(function() {
if($scope.mails.items.indexOf(message) == -1) {
$scope.mails.items.push(message);
}
}, 0, true, message);
});
The callback function for $timeout does not take any parameters. That m parameter is always going to be null, just use the message parameter from the outer function.

call function using if statement

I want to be able to call a function within an if statement.
For example:
var photo = "yes";
if (photo=="yes") {
capturePhoto();
}
else {
//do nothing
};
This does nothing though. The function is clearly defined above this if statement.
Edit: Wow, downboated to hell! capturePhoto(); was just an example function that didn't really need any more explanation in this scenario?
That should work. Maybe capturePhoto() has a bug?
Insert an alert() or console.log():
var photo = "yes";
if (photo == "yes") {
alert("Thank you StackOverflow, you're a very big gift for all programmers!");
capturePhoto();
} else {
alert("StackOverflow.com must help me!");
}
I'm not seeing any problems here. I used this code and the function call worked. I kept your code and just added a function called capturePhoto().
Are you sure that the code you're using to call the function is firing?
var photo = "yes";
if (photo=="yes")
{
capturePhoto();
}
else
{
//do nothing
};
function capturePhoto()
{
alert("Pop up Message");
}
You probably missed something, a quotation, a semicolon or something like that. I would recommend you to use a debugger like Firebug or even Google Chrome's Web Developer Tool. You will know what's wrong with your code and where it is wrong.
You may take a look at this live code that your code above works: http://jsfiddle.net/ZHbqK/
The code looks fine to me (except you don't need the ; at the end of the last line). Check your error log; perhaps the browser thinks capturePhoto is not defined for some reason. You can also add alert statements to make sure the code is actually running:
var photo = "yes";
alert('Entering if statement');
if (photo=="yes") {
alert('then');
capturePhoto();
} else {
alert('else');
//do nothing
}
When you encounter a situation where it seems like a fundamental language feature is not working, get some more information about what is going on. It is almost never the platform's fault. It is occasionally a misunderstanding of how the feature works (e.g. why does parseInt('031') == 25 ?). It is usually a violation of an assumption you're making about the code that isn't holding up because of a problem elsewhere.
You should also consider using true and false instead of strings that could be manipulated depending on input.
If I had to correct the following code, then I should've done it like this;
var photo = true; // Will capture picture.
if (photo) { // 'true' is a truthy value.
capturePhoto();
} else {
// Do nothing
}
The code that you posted does work.
I copied it and tested it.
Demo: http://jsfiddle.net/Guffa/vraPQ/
The only thing wrong with it that I can see is a semicolon after the closing bracket, but that is only a style problem. It will form an extra empty statement, but that doesn't cause any problems.

Javascript Value Assignment Delay?

I'm at a loss right now. I'm using a simple variable, whose value is assigned during a loop. After exiting the loop, the value of the variable is still undefined, unless I alert it's value first. Then everything works fine. What's going on here?
$(myarray).each(function(idx, item)
{
fetchSomethingRemotely( success: function(data) {
item.someValue = data; });
// if the following alert is not there, doSomething will never get called
// and the alert after the else will show item.someValue as undefined.
alert(item.someValue);
if (item.someValue != null) { doSomething(item.someValue); }
else { alert(item.someValue); }
});
Edit:
Okay, so I've got a better handle in this now. The value assignment (item.someValue=123) happens inside of a callback function within this iteration. So the value is probably not there yet when I serially try to access it a couple of code lines below. How could I wait for the value to be assigned?
How could I wait for the value to be assigned?
The answer is already in your code. Just move doSomething into the callback function.
fetchSomethingRemotely( { success: function(data) {
item.someValue = data;
if (item.someValue != null) doSomething(item.someValue);
} });
Note that this will still move on to the next item before the current item has got its value. If you must perform all of the iteration sequentially, you can do something like this:
function iterate(index) {
var item = myarray[index];
fetchSomethingRemotely( { success: function(data) {
item.someValue = data;
if (item.someValue != null) doSomething(item.someValue);
if (index < myarray.length - 1) iterate(index + 1);
} });
}
And then you would fire off the whole process with iterate(0).
Did you remember to use var to define the variable. Are you sure the variable exists in the scopes you are using it. If you do for ( var i ... then it will only exist in the for scope, not outside it. You can use Webkit (Chrome, Safari)'s Developer Tools to debug your script by setting a breakpoint on the problem line, and then in the right column you can see all variables defined in the related scopes.
"How could I wait for the value to be
assigned?"
Welcome to asyncronous programming!
You're going to need to put everything in the callback, not just the variable assignment.

Categories