waitFor throws misleading error on invalid selector
b5l opened this issue ยท 8 comments
When waitFor(...)
or any function using waitFor(...)
is called with an invalid CSS selector, it will throw an error saying the timeout exceeded. The expected behavior would be a message saying that the CSS selector is invalid.
I am using wendigo@2.11.1
.
Code to reproduce:
let browser
async function main () {
browser = await wendigo.createBrowser({ headless: false })
await browser.open('https://github.com')
await browser.waitAndClick('invalid[selector')
}
main()
.catch(console.error)
.finally(() => browser && browser.close())
Result:
{ TimeoutError: waiting for selector "invalid[selector" failed: timeout 500ms exceeded
at new WaitTask (/workspace/vuer_oss/node_modules/wendigo/node_modules/puppeteer/lib/DOMWorld.js:549:28)
at DOMWorld._waitForSelectorOrXPath (/workspace/vuer_oss/node_modules/wendigo/node_modules/puppeteer/lib/DOMWorld.js:478:22)
at DOMWorld.waitForSelector (/workspace/vuer_oss/node_modules/wendigo/node_modules/puppeteer/lib/DOMWorld.js:432:17)
at Frame.waitForSelector (/workspace/vuer_oss/node_modules/wendigo/node_modules/puppeteer/lib/FrameManager.js:627:47)
at Frame.<anonymous> (/workspace/vuer_oss/node_modules/wendigo/node_modules/puppeteer/lib/helper.js:112:23)
at Frame.waitFor (/workspace/vuer_oss/node_modules/wendigo/node_modules/puppeteer/lib/FrameManager.js:612:19)
at Page.waitFor (/workspace/vuer_oss/node_modules/wendigo/node_modules/puppeteer/lib/Page.js:1116:29)
at PuppeteerPage.<anonymous> (/workspace/vuer_oss/node_modules/wendigo/dist/lib/puppeteer_wrapper/puppeteer_page.js:102:29)
at Generator.next (<anonymous>)
at /workspace/vuer_oss/node_modules/wendigo/dist/lib/puppeteer_wrapper/puppeteer_page.js:8:71
-- ASYNC --
at Frame.<anonymous> (/workspace/vuer_oss/node_modules/wendigo/node_modules/puppeteer/lib/helper.js:111:15)
at Frame.waitFor (/workspace/vuer_oss/node_modules/wendigo/node_modules/puppeteer/lib/FrameManager.js:612:19)
at Page.waitFor (/workspace/vuer_oss/node_modules/wendigo/node_modules/puppeteer/lib/Page.js:1116:29)
at PuppeteerPage.<anonymous> (/workspace/vuer_oss/node_modules/wendigo/dist/lib/puppeteer_wrapper/puppeteer_page.js:102:29)
at Generator.next (<anonymous>)
at /workspace/vuer_oss/node_modules/wendigo/dist/lib/puppeteer_wrapper/puppeteer_page.js:8:71
at new Promise (<anonymous>)
at __awaiter (/workspace/vuer_oss/node_modules/wendigo/dist/lib/puppeteer_wrapper/puppeteer_page.js:4:12)
at PuppeteerPage.waitFor (/workspace/vuer_oss/node_modules/wendigo/dist/lib/puppeteer_wrapper/puppeteer_page.js:101:16)
at obj.<anonymous> (/workspace/vuer_oss/node_modules/wendigo/dist/lib/browser/mixins/browser_wait.js:44:34) name: 'TimeoutError' }
Fix:
Here it should not swallow err
if err
is not a timeout error. The same applies to every function using waitFor(...)
(e.g. waitAndClick(...)
, waitUntilNotVisible(...)
, etc.)
Good catch!, this probably could be solved with the @OverrideError()
decorator I will fix this before the next release
After checking this issue, a few details:
No extra checks on css validity are done by wendigo (the example you provide is actually valid css, at least for document.querySelectorAll
, so in the case you expose, the error should still be timeoutError
Feeding an invalid selector (e.g. p[header=
) that throws a DOMException is swallowed by the try...catch as you said, this behaviour can be changed so a queryError is thrown instead. Does this make sense?
Yes, the CSS selector I wrote in the issue is indeed correct, sorry about that. However when this bug occurred I was using a definitely invalid selector by accident (something along the lines of .some .class[data-hello="world" .otherclass[data-bla="blub"]
, note the missing closing bracket after .class
), which resulted in a SyntaxError
in the browser's context.
I took a look at your commit, and there are two things I noticed:
-
I think instead of swallowing everything that is not a
DOMException
and assuming they are definitelyTimeoutErrors
Wendigo should rather check whethererr
is an instance ofTimeoutError
, which is onpuppeteer.errors
. I looked in puppeteers source and in theory, that should be the error that gets thrown whenever a wait function times out. -
TimeoutError
still gets swallowed in all of the otherwaitFor
functions here, here, here, here, here and here.
Thank you for your quick response! I am sorry for just complaining instead of submitting a PR, I will try to send one today that fixes the aforementioned things.
Thanks for the comprehensive review @benjaminlaib, your comment is completely right,I've reopened this issue
Any progress / workarounds for this?
Hi @facusantillo no progress for now, the PR wasn't updated so it was closed due to inactivity and I have not gotten around to fix this yet.
Sadly, I don't think there is a viable workaround without actually fixing this in Wendigo. I'll try to patch it around as soon as possible if this is generating so many problems, but I'm not sure when I'll be able to fix this
PRs are welcome, the closed PR by @benjaminlaib is actually a good starting point
For others running into the same problem: Temporal solution is to add a plugin with this function:
async waitUntil(condition: Function, timeout: number, name?: string) { let startTime = new Date().getTime(); while (!(await condition())) { if (new Date().getTime() - startTime > timeout) throw ``TimeoutException: condition ${name} didn't solve after ${timeout} seconds``; await this.browser.wait(500); } }
Then can use it as follow:
await this.waitUntil(async () => (await this.newCampaignPopupElements.startButton()) !== null, 60000, 'Wait for start button');
All errors in wait-related messages have been improved to only override timeout errors (following @benjaminlaib recommendation)
This should fix problems with misleading errors in the following methods:
- waitFor
- waitUntilNotVisible
- waitForUrl
- waitForNavigation
- waitForText
- waitAndClick
- waitUntilEnabled
These changes will be available on next release (2.13.1)
More work needed in the error handling as it is starting to take a toll in users experience, I'll open a separate issue for that.
For now, I'll close this issue