Casperjs not triggering page.error event on errors in evaluate - events

I want to catch errors on the remote page in Casper.
casper.thenEvaluate ->
document.querySelector("#selector-doesnt-exist").attribute-doesnt-exist = 'value'
I have the following listeners set up:
casper.on "page.error", (message, trace) ->
console.log(message)
casper.on "remote.message", (message) ->
console.log(message)
Neither of these is being triggered when the evaluate fails. Is there any way to listen to errors on the remote page?

I don't know how to do this either, and there's probably a more proper way.
Assuming you only want to catch errors in your own evaluate code (not errors on the part of the site you're loading), one solution would be to wrap the casper evaluate function to include a try-catch, and handle the error by returning it from the evaluate:
casper.myevaluate = (fn, args...) ->
s = #evaluate (fn,args) ->
try
fn.apply(this,args)
catch e
return {'ourError':e}
, fn, args
if s.ourError?
ErrorHandler.Exception(s.ourError)
return s
E.g. calling:
casper.myevaluate ()-> silly
...would call your error handler code with ReferenceError: Can't find variable: silly

Related

PowerQuery: Getting error info when it's too late to `try`?

Short Version
In PowerQuery, when the error occurs before I'm able to use try, how do I catch an error and get the reason and message strings?
Long Version
In PowerQuery (using Excel if that matters),
OleDb.DataSource(
MyConnectionString,
[Query="SELECT * FROM NonExistingTable"]
)
returns an error. Great. I want that because I'm trying to make a quick and dirty tool that grabs data from multiple tables, but some people don't have access to all tables and who knows what else will happen in the future. However, I want to handle that error so it degrades gracefully, preferably presenting an explanation to the user based on the info within the error.
Therefore, I attempted error handling with try, like so:
try OleDb.DataSource(
MyConnectionString,
[Query="SELECT * FROM NonExistingTable"]
)
and I had expected it to return something like
[
HasError = true,
Error = [
Reason = "OLE DB",
Message = "Invalid object name: 'NonExistingTable'.",
Details = ...
]
]
but instead, what's returned is
[
HasError = false,
Value = Error
]
where Error is an error object containing the information I want.
I had then tried to make a workaround with something like
let
tryRecord = try OleDb.DataSource(MyConnectionString, [Query="SELECT * FROM NonExistingTable"]),
ret = if (tryRecord[HasError]) then
// It's an error
tryRecord
else try
// If Value.Type() doesn't throw an error then tryRecord[Value] isn't an error, so return it.
(if Value.Type(tryRecord[Value]) = null then null else tryRecord)
otherwise
// tryRecord[Value] contains an error!
try error tryRecord[Value]
in
ret
but try error tryRecord[Value] is not unpacking the error object within tryRecord[Value] like I had hoped.
How do I get the reason and message strings from an error object?

Can I get Protractor/Jasmine to hit a breakpoint when an element locator fails to find its target?

Every time a Protractor element locator fails, it prints an error and continues down a horrible path of endless cascading failures in my spec and suite. Every test that follows depends on the element locator finding its element, and depends on the current spec passing.
I would like to keep the web page under test open while I use the console. The goal is to debug the current state of the page and investigate why the element locator may have failed to find its target.
I'm not too concerned about failing the entire suite and exiting on the first spec failure (I've seen other answers on --fail-fast and stopping on first spec failure.) This is not the approach I would like to take. I want to set a breakpoint, and inspect the environment while the page is running.
Maybe there's something like a Jasmine option for doThisOnFailure: () => { debugger }, which would work for me I think.
I really do not like the solution of using a spec reporter to execute during afterEach and check the failed spec count on the Jasmine environment for the entire spec function. I want to immediately know when an element locator has failed and immediately break as soon as it has failed.
Maybe something really gross would work $('element').click().catch(() => { debugger }).
EDIT: Please, note that I am asking about breaking in a spec, not breaking at the end of the spec.
it('should execute deadly code', function () {
p.navigation.openStorageConfigTab()
$$('.bad-selector').get(0).click() /* IMPORTANT: I want to break here */
p.volume.navigateTo()
})
it('should not execute this spec', function () {
$$('.bad-selector').get(0).click()
})
And the output
✗ should execute deadly code
- Failed: Index out of bound. Trying to access element at index: 0, but there are only 0 elements that match locator By(css selector, .bad-selector)
✗ should not execute this spec
- Failed: Index out of bound. Trying to access element at index: 0, but there are only 0 elements that match locator By(css selector, .bad-selector)
I can recommend you the approach I use, and I hope you can take it from here
Overall approach is to wait until until you type close/ command in browser url:
await browser.waitForAngularEnabled(false);
await browser.wait(
async () => {
let url = await browser.getCurrentUrl();
return url.includes('close/');
},
5 * 60 * 1000,
'Keep-alive timeout reached, closing the session...'
);
The question is when you want to call it. I use the advantage of onComplete callback function in config file. When it's called, the browser is still available. So once all tests are completed, it doesn't exit for 5 minutes unless I submit close/ to the url field. Obviously that can be conditional, by adding something like if (DEBUG === true)
A downside of this setup is it's called when all tests are completed, and it's possible your spec has navigated away from the page where there was error. So what you can also do is to use advantage of jasmine reporter (if you use jasmine). Roughly, you just need to add this to your onPrepare func:
jasmine.getEnv().addReporter({
jasmineStarted: function(suiteInfo) {},
suiteStarted: function(result) {},
specStarted: function(result) {},
specDone: async function(spec) {
if (spec.status === 'failed') {
await browser.waitForAngularEnabled(false);
await browser.wait(
async () => {
let url = await browser.getCurrentUrl();
return url.includes('close/');
},
5 * 60 * 1000,
'Keep-alive timeout reached, closing the session...'
);
await browser.close();
process.exit(35);
}
},
suiteDone: function(result) {},
jasmineDone: function(result) {},
});
So if any it block has failed status, then it'll stop. BUT, I have not tested it, I'll leave it up to you. And second, I didn't think about what will happen to the rest of queued specs since you're redirected to non existing url close/, but I believe it'll still work for you. Worst case scenario, you can play around and make it continue or close the browser instance, as long as you understood the concept
P.S.
I modified the code to close the browser when you type close/, by adding
await browser.close();
process.exit(35);
I tested this code with the following scenarios:
happy path: all 5 it are successful
first element finder of second it block fails
second element finder of second it block fails
All passed. The code works as expected

Calling Wow64GetThreadContext returns the error "When the file already exists, the file cannot be created."

I am using Wow64GetThreadContext calling from a 64bit process on a 32 bit process. I am catching the WOW64 Context structure with this method.
The MSDN seems to no longer have the documentation for this method available, it is however still referenced on the GetThreadContext documentation page. I am not sure why this is. As the documentation is not available I am having a hard time figuring out why I am getting the error below.
The code where the error is being thrown is below. The error being thrown when I check GetLastWin32Error is: When the file already exists, the file cannot be created.
Does anyone have any ideas why it would throw this error? I am not creating a file at all which is confusing me.
ContextWow = new WOW_CONTEXT();
ContextWow.ContextFlags = CONTEXT_FLAGS.CONTEXT_ALL;
try
{
Wow64GetThreadContext(ThreadHandle, ref ContextWow);
if (new Win32Exception(Marshal.GetLastWin32Error()).Message != "The operation completed successfully")
{
throw new Exception("Win32 Exception encountered when attempting to get thread context" + new Win32Exception(Marshal.GetLastWin32Error()).Message);
}
}
Here is a link to the documentation you want, captured by the Internet Archive on July 10 2019:
Wow64GetThreadContext() function
Per the documentation:
Return Value
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.
Your error handling is wrong. It is the equivalent of doing the following:
ContextWow = new WOW_CONTEXT();
ContextWow.ContextFlags = CONTEXT_FLAGS.CONTEXT_ALL;
try
{
Wow64GetThreadContext(ThreadHandle, ref ContextWow);
if (Marshal.GetLastWin32Error() != 0)
{
throw new Exception("Win32 Exception encountered when attempting to get thread context" + new Win32Exception().Message);
}
}
You are making a very common mistake of calling GetLastError() at the wrong time. As the documentation says, the Win32 error code is valid to use only if Wow64GetThreadContext() returns false, which you are not checking for.
What you are doing is not the correct way to check for an error (either to get the error code, or to perform comparisons on it). The correct code should look more like the following instead:
ContextWow = new WOW_CONTEXT();
ContextWow.ContextFlags = CONTEXT_FLAGS.CONTEXT_ALL;
if (!Wow64GetThreadContext(ThreadHandle, ref ContextWow))
{
throw new Exception("Error encountered when attempting to get thread context", new Win32Exception());
}
That being said, the error message you are seeing, "When the file already exists, the file cannot be created", is your system's text for the ERROR_ALREADY_EXISTS (183) error code, which is not an error code that Wow64GetThreadContext() is documented as reporting on failure, and really just doesn't make much sense for this kind of function to report on failure. So, what is most likely happening is that Wow64GetThreadContext() is actually returning true, but because you are not checking for failure correctly, you are actually seeing an error code from an earlier/internal API call that has not been overwritten when Wow64GetThreadContext() returns true, and so it should be ignored in this situation, not acted on.

Why can't I await calls to LambdaHelper.callAsync?

I'm developing a vue.js application with node.js in the backend. The backend is also hosted by a lambda server on AWS.
On the backend, I'm trying to do the following:
let success = false;
let lh = new LambdaHelper();
success = await lh.callAsync('MyController', 'myMethod', params);
This calls MyController.myMethod(params). But it doesn't await.
If I put a console log immediately after the call to lh.callAsync(...) and print out the value of success, it prints out undefined. And if I put some console logs in myMethod, it prints them out after it prints out the value of success. This means it is not awaiting the call to lh.callAsync(...).
Now if I replace the last line with...
success = await require('MyController').myMethod(params)
...it works just fine (i.e. it awaits myMethod(...) and prints the value of success (true or false) after printing the console logs in myMethod(...)).
Is there a special trick to awaiting calls to methods through LambdaHelper.callAsync(...)? Thanks.

when does bluebird log unhandled rejections?

I'm having trouble understanding when bluebird will log an unhandled rejection versus dropping it. I guess this has something to do with what the documentation calls "the second turn" but I'm not clear what that means.
Promise.reject(new Error("oops"))
-> no log
Promise.reject(new Error("oops")).then(function() {})
-> stack trace logged
Promise.method(function() { throw new Error("oops"); })()
-> no log
Promise.method(function() { throw new Error("oops"); })().then(function() {})
-> stack trace logged
Promise.promisify(function(k) { k(new Error("oops"), null); })()
-> stack trace logged
I am in the middle of converting some code to bluebird promises and I am getting rejections dropped all over the place. (Okay, first it was #100, I'm an idiot.) I guess I will use .promisify rather than .method to get past my current silent failures but I'm frightened that there might be other circumstances where I'll miss a thrown error.
Unhandled rejections should be logged whenever there's an unhandled rejection, so 1 and 3 are bugs because you don't have any handlers for the rejection registered by the "start of the second turn".

Resources