spectron icon indicating copy to clipboard operation
spectron copied to clipboard

Client is not accessing second window. Is it possible?

Open 3n-mb opened this issue 8 years ago • 9 comments

I have an app that opens first window, does a little thing, closes the first window, and opens the second one.

When in the first window, all client APIs work.

But when in the second one, app.client.getHTML('body') throws

  Stack:
    RuntimeError: no such window: target window already closed
    from unknown error: web view not found
        at execute(<Function>) - selectorExecute.js:97:75
        at execute("return !!document.evaluate;") - ensureClientSideSelectorSupport.js:23:17

Is it possible at all to web-drive the second window?

Note that in both cases, app.client.getWindowCount() produces 1, as only one window is open, and app.client.windowHandles() changes as well.

Can a handle be used to redirect client to a new window? Or, something like this.

3n-mb avatar Jul 15 '16 02:07 3n-mb

It is possible to redirect client to other window by "focusing" function app.client.windowByIndex(0)

But:

  • There is a bug. After this refocusing of client on a different window, console's calls in app.client.execute() and app.client.executeAsync() are not showing in a list of all logs from renderer.
  • Is this refocusing of client a point of app.client.windowByIndex(0)? And if so, we should highlight it in the doc. See #88

3n-mb avatar Jul 15 '16 02:07 3n-mb

Would it be better to rename app.client.windowByIndex(...) to app.client.targetWindowByIndex(...), or to app.client.targetWindow(...) ?

3n-mb avatar Jul 15 '16 03:07 3n-mb

I'm experiencing a similar issue in a multi-window app. Would be great to see better support for this.

Aerlinger avatar Jul 17 '16 00:07 Aerlinger

I'm not sure I see the issue here. You are initially targeting Window A. You close Window A and open Window B and suddenly you expect it to be pointing to Window B instead?

You need to call

app.client.windowByIndex(0)

To refocus onto the new window (The 0 index thing is a bit misleading) but when you think about it it makes sense.

MarshallOfSound avatar Jul 17 '16 00:07 MarshallOfSound

Yes, @MarshallOfSound . Quote, _The 0 index thing is a bit misleading_, needs to change.

It would be wonderful to have targeting methods to use some unique identifiers from handlers, enumerated by app.client.windowHandles(), and be able in code to say window A, window B, etc., and .targetWindow() with such unique ids.

It would also be wonderful to have a method 'app.client.targetedWindow()` that produces such identifier for a currently targeted window.

3n-mb avatar Jul 17 '16 23:07 3n-mb

The unique ID's are in the values property of app.client.windowHandles() and you can call app.client.window(windowHandleValue) to focus a different window.

Don't forget we have full access to WebDriver IO methods.

http://webdriver.io/api/protocol/window.html

So you could do this yourself with.

app.client.windowHandles()
  .then((handles) => {
    const windowA = handles.values[0];
    const windowB = handles.values[1];

    // app.client.window(windowA);  <-- Will focus windowA
    // app.client.window(windowB);  <-- Will focus windowB
  });

Most of what spectron does is expose the WebDriver methods and the Electron methods in the same object to make testing ridiculously easy. Lots of the power / methods you are asking for is already part of the WebDriver methods.

MarshallOfSound avatar Jul 17 '16 23:07 MarshallOfSound

@MarshallOfSound now you are talking business! There is even a current target/handle available! client.windowHandle(). Although, in docs we should mention that it is WebDriver's API that deals with multiple windows/tabs.

Thus, the only unresolved point from this issue is a bug with console:

After this refocusing of client on a different window, console's calls in app.client.execute() and app.client.executeAsync() are not showing in a list of all logs from renderer.

3n-mb avatar Jul 18 '16 00:07 3n-mb

app.client.windowHandles() .then((handles) => { //const windowA = handles.values[0]; // throwing error "can not read property 0 of undefined". //const windowB = handles.values[1]; // Its a typo I guess, value is the correct field not values

  const windowA = handles.value[0];
  const windowB = handles.value[0];

  app.client.window(windowA).click('#elementIdA');  // will click element of windowA
  app.client.window(windowB).click('#elementIdB');  // will click element of windowB

});

ps1011 avatar Jul 24 '18 02:07 ps1011

app.client.window is not exists...

I can get

[
  'CDwindow-3A94A50FD4E46F979A459297ECFF60D4',
  'CDwindow-4E0C8E41B579F69C850DEC94861CC0B3'
]

from const handles = await this.app?.client?.getWindowHandles();

but how to get actual window handle, and do window.$(selector)?

linonetwo avatar Apr 18 '21 18:04 linonetwo