-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
async errors in executeAsync are not getting caught by Selenium #999
Comments
+1 |
@georgecrawford I am not sure what you mean by standardise on the const result = browser.executeAsync(function(param, done) {
setTimeout(function() {
const result = getResult();
if (result) {
done([null, result]);
} else {
throw new Error('getResult() failed because...']);
}
}, 1000);
}); |
Throwing an error in the browser's context? I haven't tried that, but had assumed Selenium wouldn't catch and return it. Am I wrong? |
It's a good question, window.onerror = error => {
console.log(error); // Uncaught Error: error!
}
throw new Error('error!'); window.onerror = error => {
console.log(error); // Nothing
}
try {
throw new Error('error!');
}
catch (error) {
console.log(error); //Uncaught Error: error!
} And new Promise((resolve, reject) => {
try {
throw new Error('error!');
}
catch (error) {
resolve(error);
}
})
.then(result => {
console.log(result); // throw new Error('error!');
})
.catch(error => {
console.log(error); // Nothing
}) Unlike a local try/catch block, the window.onerror handler doesn’t have direct access to the exception object, and is executed in the global context rather than locally where the error occurred. So, we have to implement |
I'm going to bow out of this thread, because @christian-bromann is right - throwing an error in the browser context is picked up by Selenium, and reported to webdriverio. I hadn't realised this. So I have what I need. |
👍 |
window.onerror = error => {
// But here is a place where you can change the behavior on the site
// and exception from WD is not expected.
} |
What do you mean? |
// Index.js
window.onerror = function (error) {
document.body.backgroundColor = 'red';
}; // Tests.js
it ('do something', function () {
...
browser.executeAsync(function (param, done) {
throw new Error('failed because...']);
});
});
it ('check background color', function () {
...
browser.getCssProperty('body', 'color').then(function (color) {
return color.value;
})
.should.be.eventually.equal('white'); // "red" is not expected for this test
}) Do you see what I mean, now? ) |
One exception in a single test may affect other tests, I don't like it. |
Damn, I've just realised that this doesn't get caught by Selenium, so I just get a timeout instead: browser.executeAsync(function(done) {
setTimeout(function() {
throw Error('George error')
}, 10)
}) As that's a primary use-case for me (async errors), I now think once again that we should have a better system for reporting async browser-land errors. |
I think we can build that in and catch errors as they occur |
How? |
We could register error handler here |
I think you misunderstood me - in my example above, there is no HTTP response from Selenium when the error is thrown in the browser, so there's nothing webdriverio can do to catch it. Instead, there's just an async script execution timeout. At least, that's what I see with Chromedriver. Can you reproduce? I can't find a spec of any kind for what the defined behaviour of executeAsyncScript should be wrt errors. Do you know of one? |
browser.executeAsync
On my test running on real device Ipad Mini the test hangs forever after appium try to execute async script: using appium with selenium grid ... appium server exe the comand but gets no response and does not communicate with grid to stop the test .... [debug] [MJSONWP] Responding to client with driver.getStatus() result: {"build":{"version":"1.6.3","revision":null}} |
and the same happen with another script .... |
I was just reading specs, and I think you can return promise from a passed function.. But you still will have to call callback in the end: https://www.w3.org/TR/webdriver/#h-execute-async-script my current understanding of spec (timeout handling skipped): // request.script === 'return (<function>).apply(null, arguments)' // wdio wrapper
// request.args === whatever
// Execute Async Script
const f = new Function(request.script);
return Promise((resolve, reject) => {
const result = promiseCall(f, ...(args.concat(resolve)));
result.catch(reject);
// but `result`'s resolved value is never used
})
// Promise-Calling
function promiseCall(f, ...args) {
try {
return Promise.resolve(f(...args));
} catch (e) {
return Promise.reject(e);
}
} So if that's true, at least we can return promise from function, and reject it to pass error back to wdio. Unfortunately, Chrome implementation is different: https://github.com/bayandin/chromedriver/blob/37323a96c0ba20c1eeb6bcccd44bc59bcd800e67/js/execute_async_script.js#L53 |
I'm almost sure in my understanding of how this should work, according to spec. |
@glukki Chromedriver has a lot of things not implemented according to the WebDriver spec. We will have to wait until they catch up with the development. I am sure once they release a new version it will be working like that. |
This behavior can not be influenced by WebdriverIO and needs to get fixed on the protocol level. There is already activity on this by the browser vendors: web-platform-tests/wpt#13781 |
In my tests, I'm using this pattern when I need to run
browser.executeAsync
:It'd be quite nice if webdriverio could do this automatically, and we could standardise on the
[(err), res]
format for async responses. It's somewhat related to the idea of making WebElement JSON objects first-class citizens.The text was updated successfully, but these errors were encountered: