Catch and Handle CasperError - casperjs

Using CasperJS how do I catch and handle CasperError?
The default appears to continue execution of the program (which does nothing but propagates the error).
These errors are logged to the console/stdout but I don't seem to see a way (from the docs) to catch and handle these errors.
Example:
this.fillSelectors(selector, data);
May produce:
CasperError: Errors encountered while filling form: form not found
I know I can check to make sure everything exists before calling, but is there a way to catch after the fact? (this applies to many other operations like casper.click as well)

I use something currently like this:
casper.on('error', function(msg,backtrace) {
this.capture('./out/error.png');
throw new ErrorFunc("fatal","error","filename",backtrace,msg);
});
and then I have a custom function ErrorFunc to process array of any warnings or a fatal error.
If you have an unsuccessful click it should throw the casper.on('error'). So you can put custom code there for how you would like to handle the error.
Here's the documentation for Casper events.

var casper = require('casper').create({
onError: function(msg, backtrace) {
this.capture('error.png');
throw new ErrorFunc("fatal","error","filename",backtrace,msg);
}
});
This works pretty well.
(See http://docs.casperjs.org/en/latest/modules/casper.html#index-1)

This is the complete solution for who need it ^^
casper.on('error', function(msg, backtrace) {
this.capture('/tmp/error.png');
console.log('backtrace: ' + JSON.stringify(backtrace, null, 4));
console.log('message: ' + JSON.stringify(msg, null, 4));
console.log('check capture in /tmp/error.png');
casper.exit(1);
})

Related

Axios async/await flow

I'm dipping my toe into the waters of Axios and async/await at the same time, and am trying to understand something about the control flow. Is the following legitimate?
let loading=true;
(async() => {
let response = null;
try {
response = await axios.get('https://whatever.com/api');
} finally {
loading=false;
}
if(response){
//do something with response here
}
})();
That is, can I count on the request to have returned at the point I am accessing the response variable? I appreciate I could guarantee it is by moving it into the 'try' immediately after the axios get, but then I would have to have the loading=false line before it, as well as in 'finally' (or 'catch'). I need to ensure that loading is set to false before any further actions, whether the request succeeds or fails, and I don't want to repeat myself. Maybe there's a better way of doing this?
Edit
Now that you have changed the question, the previous solution will not be working correctly. The issue is that the code inside the IIFE will be executed after everything else is finished, so loading will never be set to false from the perspective of the outside code. (the other code will be executed, and thеn the IIFE. That's because of the event loop). Your best bet is to make the outside code async and await the axios promise.
If you provide the problem details I might be able to help you refactor it.
Previous answer
I need to ensure that loading is set to false before any further actions
Any code after the await is guaranteed to NOT be loading:
(async() => {
let response = await axios.get('https://whatever.com/api');
// the request is finished, the await guarantees that
})();
If you need error handling, you can wrap it in a try/catch:
(async() => {
try {
let response = await axios.get('https://whatever.com/api');
// definitely not loading
}
catch (e) {
// definitely not loading, but an error occurred
}
})();

google.picker.DocsUploadView().setParent('XXXX') issue

Trying to get some help with this code block.
My script first looks for a specific folder and if it exists the pass the id of the folder to the google.picker.DocsUploadView(). When I hard-code the value of setParent to 'gdfid', everything works well. On the other hand, I need the code to be parameterized.
thanks in advance for any assistance
Pete
here's my code:
var gdfid;
function createPicker() {
if (pickerApiLoaded && oauthToken) {
gapi.client.drive.files.list({
"corpora": "user",
"spaces": "drive",
"fields": "files(id,name)",
"q": "name = 'myUploads"
}).then(function(response) {
console.log( response.result.files.length );
if (response.result.files.length > 0) {
console.log( response.result );
gdfid = response.result.files[0].id;
}
//alert('Folder ID: ' + gdfid);
});
var picker = new google.picker.PickerBuilder().
setTitle('Upload to myPratt Folder').
enableFeature(google.picker.Feature.MULTISELECT_ENABLED).
enableFeature(google.picker.Feature.NAV_HIDDEN).
addView(new google.picker.DocsUploadView().
setIncludeFolders(false).
setParent('gdfid')). //tried with and without quotes
setOAuthToken(oauthToken).
setDeveloperKey(developerKey).
setCallback(pickerCallback).
build();
picker.setVisible(true);
}
}
It's probably the .then{} promise code block. I've had lots of trouble with them. The problem is that the .then{} code block has a closed scope.
When you assign gdfid = response.result.files[0].id; it's assumed that it is changing the global variable. But it isn't. It's only creating a local version of gdfid.
I ran around in circles myself for ages trying to figure out how to save external state information from within a .then{} block. Any possible solutions I came up with, were invariably no better than the callback hell that promises were supposed to solve in the first place. I even had problems returning objects out from it. I think the problem is that a .then{} block needs to run from a returned promise. Promises are actually functions earmarked to run in the future. They are subject to scoping restrictions, because they cannot make assumptions about the state of code outside the function. And they only pass object/variables a certain way. Trying to assign globals or returning data the regular way, from inside the .then{} block, is fraught with problems. It will often leave you tearing your hair out.
Try refactoring your code into a function with async/await, and use a try-catch statement to capture promise fails (Note: The try-catch statement still suffers from the global variable isolation problem, but at least it seems to be solely within the catch block. This is only an issue when an error occurs). I find async await much cleaner and easier to understand, and the scoping of variables works more intuitively.
In your case you could rewrite the code thus:
function async createPicker() {
var gdfid;
if (pickerApiLoaded && oauthToken) {
try {
var response = await gapi.client.drive.files.list({
"corpora": "user",
"spaces": "drive",
"fields": "files(id,name)",
"q": "name = 'myUploads"
});
console.log( response.result.files.length );
if (response.result.files.length > 0) {
console.log( response.result );
gdfid = response.result.files[0].id;
}
//alert('Folder ID: ' + gdfid);
var picker = new google.picker.PickerBuilder()
.setTitle('Upload to myPratt Folder')
.enableFeature(google.picker.Feature.MULTISELECT_ENABLED)
.enableFeature(google.picker.Feature.NAV_HIDDEN)
.addView(new google.picker.DocsUploadView()
.setIncludeFolders(false)
.setParent(gdfid)) //tried with and without quotes
.setOAuthToken(oauthToken)
.setDeveloperKey(developerKey)
.setCallback(pickerCallback)
.build();
picker.setVisible(true);
} catch (e) {
console.log("Error displaying file list");
}
};
}
The only real difference here, is the await in front of the gapi.client.drive.files
function forces the code to wait for a callback to assign the response variable. This is not too much of a slowdown issue when running single popup UI elements that the user interacts with.
The gdfid variable is no longer global. In fact you don't even need it. You could setParent directly from the response variable.

Sinon useFakeTimers() creates a timeout in before/afterEach

I'm using Sinon with Mocha to test some expiration date values. I used the same code a few months ago and it worked fine, but somewhere between v1.12.x and v1.17.x, something has changed and I can't seem to find the right path.
let sinon = require('sinon');
describe('USER & AUTHENTICATION ENDPOINTS', function(done) {
beforeEach(function() {
this.clock = sinon.useFakeTimers(new Date().getTime());
return fixtures.load(data);
});
afterEach(function() {
this.clock.restore();
return fixtures.clear(data);
});
context('POST /users', function() { ... }
});
I've tried with and without the new Date().getTime() argument.
I've tried passing in and explicitly calling done().
I've tried removing my fixture load/clear processes.
The end result is always the same:
Error: timeout of 5000ms exceeded. Ensure the done() callback is being called in this test.
Has something changed that I just haven't noticed in the documentation? Do I have some kind of error in there that I can't see?
Any thoughts would be appreciated.
UPDATE
So a little more info here. This clearly has something to do with my code, but I'm at a loss.
If I comment every actual test, the tests run and give me a green "0 passing".
If I run an actual test, even one that just this:
context('POST /users', function() {
it('should create a new user', function(done) {
done();
})
});
I'm right back to the timeout. What am I missing?
Mystery solved. It appears to be a conflict between Sinon and versions of Knex > 0.7.6.
Seems to be because pool2 relies on behavior of setTimeout. Using sinon.useFakeTimers(...) replaces several methods including setTimeout with synchronous versions which breaks it. Can fix by replacing with: clock = sinon.useFakeTimers(Number(date), 'Date');
My original code was written in a world where Knex v0.7.6 was the latest version. Now that it's not everything failed even though the code itself was the same. I used the fix mentioned and things look to be fine.
You are passing done to your describe callback in line 2:
describe('USER & AUTHENTICATION ENDPOINTS', function(done) {
Mocha expects you to invoke it... To get rid of the timeout error, just remove the done parameter from the callback.

promise.try vs promise.resolve error handling

I've been looking at bluebird promises and how promise.try differs from a promise.resolve.then when an error is thrown. Firstly some code using promise.try where it throws a synchronous error
Promise.try(function() {
throw new Error('error');
}).catch(function(e) {
console.log(e);
});
secondly some code which throws a synchronous error on resolve
Promise.resolve().then(function() {
throw new Error('error');
}).catch(function(e) {
console.log(e);
});
As far as I'm aware they both behave the same. Is promise.try essentially a cleaner way of resolving the promise?
The docs says promise.try:
will catch all errors in their Promise .catch handlers instead of having to handle both synchronous and asynchronous exception flows.
In the case of the example given in the docs:
function getUserById(id) {
return Promise.try(function() {
if (typeof id !== "number") {
throw new Error("id must be a number");
}
return db.getUserById(id);
});
}
if the synchronous error is thrown the asynchronous code will never be reached. Would there be any difference if you put the code above in a promise.resolve().then(..)?
Any clarification/examples of promise.try will be much appreciated.
Adding to Bergi's answer: Promise.try is for those times you can't use Promise.method. The goal is to avoid cases where you have sync exceptions mixed with rejections.
Generally, whenever you're considering using Promise.try give Promise.method a spin.
var fn = Promise.method(function(){
// can throw or return here, and it'll behave correctly
});
Is roughly the same as:
var fn = function(){
return Promise.try(function(){
// can throw or return here, and it'll behave correctly
});
});
As far as I'm aware they both behave the same.
Yes, mostly. However, the .then(…) callback will be invoked asynchronously, while Promise.try is synchronously executing your function.
Is promise.try essentially a cleaner way of resolving the promise?
Yes, it does provide a cleaner (less confusing) notation. But it's more of an optimisation, because it doesn't create any Promise.resolve(undefined) in the first place.

Alert with jqGrid error messages

I would like to get an alert when errors occur when loading my jqGrid table. For instance, when the jsonReader is not well configured, like when repeatitems is true instead of false, U can see in Firebug the error:
ccur is undefined
[Break On This Error] idr = ccur[idn] || idr;
How can I place such an error in an alert? I have already tried using loadError, but it doesn't work, because it is not even triggered.
It seems for me that you should just use try - catch block over jqGrid code:
try {
// create the grid
$("#list").jqGrid({
// all jqGrid options
});
} catch (err) {
// display the error message which you want
alert(err);
}
UPDATED: You are right, the try {...} catch (err) {...} which I described before work in IE only with reading local data. In case of getting data from the server the exception take place inside of success callback of $.ajax. To be exactly it take place inside of addJSONData or addXmlData depend of the type of data which you use. To catch the exception you should modify code of jqGrid in the place. The modified code can be about the following
success:function(data,st, xhr) {
if ($.isFunction(ts.p.beforeProcessing)) {
ts.p.beforeProcessing.call(ts, data, st, xhr);
}
try {
if(dt === "xml") { addXmlData(data,ts.grid.bDiv,rcnt,npage>1,adjust); }
else { addJSONData(data,ts.grid.bDiv,rcnt,npage>1,adjust); }
if(lc) { lc.call(ts,data); }
if (pvis) { ts.grid.populateVisible(); }
} catch (err) {
alert(err);
}
if( ts.p.loadonce || ts.p.treeGrid) {ts.p.datatype = "local";}
data=null;
if (npage === 1) { endReq(); }
}
I tested in the demo the corresponding modified version of jquery.jqGrid.src.js which display error message. I don't reproduced exactly the error which you described so the error message is a little other as in your case.
If you need minimized version of the modified jquery.jqGrid.src.js file you can produce it yourself with any JavaScript minimizer. For example Microsoft Ajax Minifier can be free downloaded and installed. The usage as
ajaxmin.exe jquery.jqGrid.src.js -out jquery.jqGrid.min.js
will produce the new minimized version of jquery.jqGrid.src.js which will be even a little smaller as the original jquery.jqGrid.min.js.
Another good minimizer is available online here. You should use "Simple" Optimization only.

Resources