webdriverio-community / wdio-vscode-service

A service to test VSCode extensions from end to end using WebdriverIO

Home Page:https://webdriverio-community.github.io/wdio-vscode-service/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Bug: EditorView#getActiveTab() fails

seanpoulter opened this issue · comments

Context

When I do something to make a Webview open in a new Editor Tab
Then I want to wait for it to appear
And I create a new PageObject with it

Problem

When I run:

const workbench = await browser.getWorkbench();
const editorView = await workbench.getEditorView();
const activeTab = await editorView.getActiveTab();

I see:

TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator)
        at EditorGroup.getOpenTabs

because we're using Promise.all when this.tab$$.map<T> should return a ChainablePromiseArray as a Promise<Array<T>>, not an Array<Promise<T>>. The code is here:

async getOpenTabs (): Promise<EditorTab[]> {
const tabs = await this.tab$$
return Promise.all(

Discussion

  • Let me know if you'd like a PR with a failing test and a fix
  • Is there a better way to wait for the webview? It seems like I should probably be able to new MyWebview().wait()?
  • Let me know if you'd like a PR with a failing test and a fix

Yes! Any contributions would be much appreciated!

I can open a PR with an alternative implementation that avoids the bug but I don't understand the root cause (yet). Even with the Node.js debug tools I haven't found the problem. I'm going to try reproducing the problem unit testing shim.ts* from wdio-utils. That's lovely code BTW! 🎉

Edit: A PR would unblock test development at work. 😊

Awesome, looking forward!

It seems like the issue is with all elem$$ when passed to an API that expects an array
Because elem$$ does not return an array, but something array-looking.

This happens in a few places. It's probably worth doing a global $$ search to make sure they aren't passed to APIs that expect arrays.

@rrousselGit these page objects have been adopted from a different project and rewritten for WebdriverIO. Chances are that there are more locations where this happens. I will go ahead and close this one as it has been resolved. I hope to be able to update the package later this week.

Would the end goal be to support Promise.all(elem$$) from the shim?

Would the end goal be to support Promise.all(elem$$) from the shim?

That would be a nice feature. I was under the assumption that this already works already since internally we create an Array and just extend the prototype object to allow async array methods, like map, filter etc.

I'm poking at cb/driver-setup-update and tsc is flagging this:

> wdio-vscode-service@5.2.3 build:ts
> tsc -b .

src/pageobjects/dialog/ModalDialog.ts:47:42 - error TS2769: No overload matches this call.
  Overload 1 of 2, '(values: readonly unknown[] | []): Promise<[] | unknown[]>', gave the following error.
    Argument of type 'Promise<string[]>' is not assignable to parameter of type 'readonly unknown[] | []'.
  Overload 2 of 2, '(values: Iterable<unknown>): Promise<unknown[]>', gave the following error.
    Argument of type 'Promise<string[]>' is not assignable to parameter of type 'Iterable<unknown>'.
      Property '[Symbol.iterator]' is missing in type 'Promise<string[]>' but required in type 'Iterable<unknown>'.

47         const titles = await Promise.all(buttons.map(async (btn) => btn.getAttribute('title')))
                                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  src/pageobjects/dialog/ModalDialog.ts:47:42
    47         const titles = await Promise.all(buttons.map(async (btn) => btn.getAttribute('title')))
                                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Did you forget to use 'await'?
  node_modules/typescript/lib/lib.es2015.iterable.d.ts:49:5
    49     [Symbol.iterator](): Iterator<T>;
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    '[Symbol.iterator]' is declared here.
  src/pageobjects/dialog/ModalDialog.ts:47:42
    47         const titles = await Promise.all(buttons.map(async (btn) => btn.getAttribute('title')))
                                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Did you forget to use 'await'?


Found 1 error.

ERROR: "build:ts" exited with 1.

All these Promise.all calls are no necessary at all. We can update them like so:

- const titles = await Promise.all(buttons.map(async (btn) => btn.getAttribute('title')))
+ const titles = await buttons.map(async (btn) => btn.getAttribute('title'))

Note that doing Promise.all(Array.from(buttons.map(...))) works.