protractor - try catch - error handling - protractor

I am looking for an element and if the element is not present, I want to give a decent error message saying "element not present"; but it comes out of the block and throwing a message like element not found for the xpath.
Below is the code I have tried but I'm still getting the same error.
For example a=protractor and if the value is present, it says text prevails - protractor; and in case it is not there, instead of saying element not present/error occurs it says "no element found element(by.xpath("//div[#title='"protractor"']")) followed by a big error message.
How to resolve this?
this.gridverify = function (a) {
browser.sleep(10000);
try {
var elm = element(by.xpath("//div[#title='" + a + "']"));
if (elm.isPresent) {
elm.getText().then(function (x) {
console.log("text Prevails: " + x);
})
}
else {
console.log('element not present');
}
}
catch (err) {
console.log('error occured');
}
}

Try:
browser.wait(until.presenceOf(element(by.className("user-thumb"))),5000,'Element not present');
browser.wait(until.presenceOf(element(Add Locator here)),wait time,'Add Message you want to print in case element not found');
This might resolve your problem.

Consider digging more deeply into promises. Your code has a lot of errors. http://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/lib/promise.html
this.gridverify = function (a) {
browser.sleep(10000); // Why this needed? Can you update to .wait() ?
var elm = element(by.xpath("//div[#title='" + a + "']"));
elm.isPresent().then(present => {
if (present) {
elm.getText().then(function (x) {
console.log("text Prevails: " + x);
})
} else {
console.log('element not present');
}
}, err => {
console.log('error occured', err);
})
}
Your try/catch won't work as you expecting in async code.

Related

Why items are not being pushed in array

I am using MongoseDB in order to receive some information about an item. When i try to search for it, it finds it with no trouble, but for some reasons this function is not pushing them into my array. I think this might be because of some async functions and that the console.log() is triggered before any item is being pushed in there.
const getOrders = function(allOrders){
let promise = new Promise((succ, fail)=>{
let ordersTodisplay = []
for (let order of allOrders) {
if (!(order.orderId === null || order.orderItem === null)){
postMong.findById(order.orderItem, function (err, item) {
ordersTodisplay.push(item)
})
}
}
if(ordersTodisplay.length > 0){
succ(ordersTodisplay)
} else{
fail("no items")
}
})
return promise
}
router.get('/accountpage',function(req,res){
const userDB = req.session.username
if (userDB !== undefined && userDB){
userForm.findOne({ username : userDB }, function (err, user) {
const userOrders = user.userOrders;
if (userOrders.length > 1) {
getOrders(userOrders).then((result)=>{console.log(result)}, (fail)=>{console.log(fail)})
res.render('../view/accountpage',{username: userDB,orders: itemsToDisplay});
}
else{
res.render('../view/accountpage',{username: userDB,orders: "There are no orders"});
}
});
} else {
res.redirect("/login")
}
});
The result is : no items
You have to for the database call to complete and then push the data in the array like this, using async-await:
const getOrders = function(allOrders){
let promise = new Promise(async (succ, fail)=>{
let ordersTodisplay = []
for (let order of allOrders) {
if (!(order.orderId === null || order.orderItem === null)){
await postMong.findById(order.orderItem, function (err, item) {
ordersTodisplay.push(item)
})
}
}
if(ordersTodisplay.length > 0){
succ(ordersTodisplay)
} else{
fail("no items")
}
})
return promise
}
Your code is quite nested and that makes it hard to reason about what is happening.
To break down your code, you:
get a single user that has several order IDs referenced
load each order
respond with those orders (although you return itemsToDisplay that doesn't seem to be defined anywhere, so I'm a bit confused)
I'd try to capture that logical pattern in the code. A good trick is returning early to make the code less nested and interdependent:
router.get('/accountpage', function(req,res){
const userDB = req.session.username;
if (!userDB){
res.redirect("/login");
return;
}
loadUserOrders(userDB)
.then(function(orders) {
if(orders.length > 0) {
res.render('../view/accountpage', {username: userDB,orders: orders});
return;
}
// Note: consider returning just the empty array here, that already implies no orders
res.render('../view/accountpage', {username: userDB, orders: "There are no orders"});
})
.catch(function(error) {
//TODO: render error -- case not covered by your code
});
});
// Because this is an async function you can now await inside it, meaning no need for the callback syntax for mongoose
async function loadUserOrders(username) {
const user = await userForm.findOne({ username: username });
// Promise.all runs in parallel several promises and returns an array containing their results
// .map here turns the list of userOrders into a list of promises getting each order
return await Promise.all(user.userOrders.map((userOrder) => postMong.findById(userOrder.orderItem));
}
Notice how this code highlights that you are not explicitly handling the error case from loading orders.
You can further simplify this by using something like express-async-handler which will let your endpoint function be async as well:
const asyncHandler = require('express-async-handler');
router.get('/accountpage', asyncHandler(async function(req,res){
const userDB = req.session.username;
if (!userDB){
res.redirect("/login");
return;
}
// Note: there is no try-catch around loadUserOrders right now, so errors will result in a 500 courtesy of express-async-handler -- better than before
const orders = await loadUserOrders(userDB);
if(orders.length > 0) {
res.render('../view/accountpage', {username: userDB,orders: orders});
return;
}
// Note: consider returning just the empty array here, that already implies no orders
res.render('../view/accountpage', {username: userDB, orders: "There are no orders"});
}));
I think using async/await syntax all the way through leaves the code more consistent and easier to reason about than the mix of callbacks, new Promise and await that was suggested in another answer. In the end, the endpoint is not very complex, and I think the code can reflect that.

Getting retry limit exceeded error on uploading a few images to Google Storage

I'm not sure what's going on, because I don't get this issue, but a lot of my users report this issue. I have a page that uploads multiple files (the error is happening at 5). Several users report getting the error "storage/retry-limit-exceeded". What's going on? Please help.
In the code below, each error[i][j] gets the same code, which is "storage/retry-limit-exceeded".
My code looks like:
function SubmitFiles(){
pending=true;
let promises = partsofprobs.map((x,i) => {
return x.map((y,j) => FileUpload(i,j));
});
Promise.all(promises.map(x=>Promise.all(x))).then((values)=>{
//DO SOME STUFF WITH THE VALUES -- code removed for brevity, since the error is thrown by the other function.
});
}
function FileUpload(i,j){
return new Promise((resolve, reject) => {
let file=newpicdata[i][j];
if(file){
currentupload[i][j]=true;
let storageRef = storage.ref();
let fileRef = storageRef.child(examid+'/'+i+'/'+j+'/'+$currentUser.uid+'/'+newfiles[i][j][0].name);
let uploadTask = fileRef.putString(file, 'data_url');
uploadTask.on('state_changed',
function(snapshot) {
// Get task progress, including the number of bytes uploaded and the total number of bytes to be uploaded
let uploadedpercent = (snapshot.bytesTransferred / snapshot.totalBytes)*100;
console.log('Upload is ' + uploadedpercent + '% done');
switch (snapshot.state) {
case 'paused':
console.log('Upload is paused');
break;
case 'running':
console.log('Upload is running');
break;
}
}, function(err) {
console.log("error code: ", err.code);
error[i][j]=err.code;
currentupload[i][j]=false;
reject();
}, function() {
// Upload completed successfully, now we can get the download URL
uploadTask.snapshot.ref.getDownloadURL().then(function(downloadURL) {
uploadedpicsurls[i][j]=downloadURL;
success[i][j]=true;
currentupload[i][j]=false;
console.log('File available at', downloadURL);
resolve({url:downloadURL,graded:false,score:null,problemindex:i,part:j,grader:null,notes:[],outof:partsofprobs[i][j],beinggradedby:[]});
});
});
}else{
resolve(existingrecord ? existingrecord.solutions[i].parts[j]:{url:null,graded:false,score:0,problemindex:i,part:j,grader:null,notes:[],outof:partsofprobs[i][j],beinggradedby:[]});
}
})
}

Call recursive function in Observable not working in ionic3

I have one function in my app getServerData() which I call from home page and passing Token as param in my API calling in this function.
if Token is valid API will return data otherwise it will return unauthorised access with token expired error at that time I am calling same function with new generated token form another API but some how recursive function calling not working in Observable.
Check below code for more detail :
/**
* Get Search result from server.
*/
getServerData(searchText: string): Observable<any> {
let self = this;
return Observable.create(function(observer) {
self.getToken().then((token) => {
console.log('Token : ', token);
self.httpPlugin.get(self.url + searchText, {}, {}).then((response) => {
console.log("Response Success : " + JSON.stringify(response));
observer.next(jsonResponse);
}).catch(error => {
if (error.status == 403) {
//Call Same method Again
self.getServerData(searchText);
} else {
console.log("Error : " + error);
console.log("Error " + JSON.stringify(error));
observer.error(error);
}
});
}).catch((error) => {
observer.error(error);
console.log("Error : " + error);
})
});
}
While calling same function no code execution done.
Edit based on comment:
I am subscribe like below:
this.subscription = this.api.getServerData(this.searchString.toUpperCase()).subscribe((response: any) => {
console.log("back with data :-",response);
}, error => {
console.log("InLine Error : ",error);
});
Not able to understand whats going wrong or Am I doing some mistake in calling function from Observable().
Guide me on this.
Thanks in advance!
It's not good practice to use promise in observable. Use Obserable.fromPromise and also use mergeMap. What will happen if you will use. Whenever any error will come Observable will throw error and you will able to catch. I will suggest to use Subject rather than creating your own observable and also remember one thing that don't subscribe in your service.
Hope it will help
Finally after lots of research I found solution of my issue.
1st thing was I need to update my rxjx library as my installed version of rxjx was 5.5.2 so I upgraded it to latest one 5.5.11.
2nd thing was I am calling Observable without subscribe() to that Observable so it will never return so I updated my recursive call from error block from where I call its subscriber() like below.
getSearchData(){
this.subscription = this.api.getServerData(this.searchString.toUpperCase()).subscribe((response: any) => {
console.log("back with data :-",response);
}, error => {
if (response.status == 403) {
this.getSearchData();
}else{
console.log("InLine Error : ",response);
this.showAlert('Error', 'Something went wrong. please try again.');
}
});
}
By doing above 2 things I am able to solve my issue.
Thanks all for your quick reply on my issue.
Hope this will help someone who is facing same issue like me.

Protractor 'toContain' error

This is my expect:
expect(mandatoryFields[index].getAttribute('class')).toContain('error');
This is the error in console:
Expected['formControl ng-pristine ng-untouched ng-valid ng-empty ng-valid-maxlength error'] to contain 'error'.
Eventhough the class contains ERROR class name, protractor is still throwing error. What could be reason? Any help!!!
Instead of toContain try using toMatch. toContain is used to check whether the required value is present in an array or not. whereas toMatch uses regex for validating the text present in any value.
You could try adding a custom matcher in your beforeEach(), then calling expect(mandatoryFields[index]).toHaveClass('error');
jasmine.addMatchers([
toHaveClass: function () {
return {
compare: function (element, className) {
return {
pass: element.getAttribute('class').then(function (classes) {
return classes.split(' ').indexOf(className) !== -1||classes.split(' ').indexOf(className+"\n") !== -1;
}),
message: "Expected elemenet to have class: "+className
}
},
negativeCompare: function(element, className){
return {
pass: element.getAttribute('class').then(function (classes) {
return classes.split(' ').indexOf(className) !== -1||classes.split(' ').indexOf(className+"\n") === -1;
}),
message: "Expected element not to have class: " + className
}
}
}
}
]);

ERROR:the operation couldn't be completed. (com.facebook.sdk error 5.)

I am getting sdk problem, what I change in the code for removing error?
Please help me, I am new in titanium.
var f = Ti.Filesystem.getFile('pumpkin.jpg');
var blob = f.read();
var data = {
message: 'This is a pumpkin',
picture: blob
};
Titanium.Facebook.requestWithGraphPath('me/photos', data, 'POST', function(e) {
if (e.success) {
alert("Success! From FB: " + e.result);
} else {
if (e.error) {
alert(e.error);
} else {
alert("Unkown result");
}
}
});
you are trying to execute example code from online doc so if you are using traditional structure then put one pic with pumpkin.jpg in resources directory because i think that file should be missing.
and be sure that you are calling after login.