angrykoala / wendigo

A proper monster for front-end automated testing

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

waitFor throws misleading error on invalid selector

b5l opened this issue · comments

commented

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

@benjaminlaib

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?

commented

@angrykoala

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:

  1. I think instead of swallowing everything that is not a DOMException and assuming they are definitely TimeoutErrors Wendigo should rather check whether err is an instance of TimeoutError, which is on puppeteer.errors. I looked in puppeteers source and in theory, that should be the error that gets thrown whenever a wait function times out.

  2. TimeoutError still gets swallowed in all of the other waitFor 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