protractor wait timeout catch and continue

Viewed 7829

I have a piece of code in protractor to do a wait:

public waitForElement() {
    return browser.wait(
        ExpectedConditions.visibilityOf(element(by.id('#someEl'))),
        10000,
        'Unable to find the element'
        );
}

My issue is that I cannot seem to catch this exception if it times out. I tried adding a catch() clause, which does not work, e.g.:

this.waitForElement()
    .then(() => { /* do something */ })
    .catch(() => { /* handle the error -- this code never happens if there is a timeout!!! */ });

I tried putting the code in a try-catch block, but that doesn't help either:

try { this.waitForElement().then(() => { }); }
catch (ex) { /* this exception is never caught, the test just fails!! */ }

I'm stumped: how can I catch the wait timeout and continue with the test without the test failing?

2 Answers

Un-picking the particularly important part from @wswebcreation's useful answer: in order to make this work, I've found you must specify an explicit timeout.

The following works:

return browser.wait(ExpectedConditions.visibilityOf(...), 5000)
  .catch(() => { throw new Error('my error'); });

But this does not:

return browser.wait(ExpectedConditions.visibilityOf(...))
  .catch(() => { throw new Error('my error'); });

giving:

 Error: function timed out after 11000 milliseconds
     at Timeout._onTimeout (C:\project\node_modules\cucumber\lib\user_code_runner.js:91:22)
     at ontimeout (timers.js:498:11)
     at tryOnTimeout (timers.js:323:5)
     at Timer.listOnTimeout (timers.js:290:5)

Where 11000 is just the default Protractor timeout we have configured.

Note also that although the documentation for browser.wait implies that the promise form is only required if you want to pause all Javascript execution, not just WebDriver:

This function blocks WebDriver's control flow, not the javascript runtime. It will only delay future webdriver commands from being executed (e.g. it will cause Protractor to wait before sending future commands to the selenium server), and only when the webdriver control flow is enabled.

This function returnes a promise, which can be used if you need to block javascript execution and not just the control flow.

...it is apparently also not possible to catch the result of a timeout-less, promise-less browser.wait in a try-catch, as the condition runs in a setTimeout.

The above all apparently true with protractor 5.3.2 when used with protractor-cucumber-framework 4.2.0.

Related