Open teameh opened 7 years ago
I am also having the same issue.
Currently I am locating a particular element's id contained by the targeted webview
by iterating over all window handles.
I'm using something like that:
const selectWindow = async function(app, selector) {
const handles = await app.client.windowHandles();
for (const handle of handles.value) {
await app.client.window(handle);
const element = await app.client.element(selector);
if (element.status === 0) {
return element;
}
}
return {};
};
But processing this way seems rather awkward, inefficient and also error prone (duplicate element ids in two different webviews is authorised).
webdriverio window() call is able to retrieve a window by using the tab name
attribute but I do not know if there is a way to associate a tab name
to a webview
element.
I thought of looping trough the webviews but couldn't get it working.. thanks for sharing your example.
Do i get it right that the code will focus each webview until one is found matching the selector? That seems indeed quite inefficient. We could maybe cache the webview.. but that will of course break if you dynamically change your webviews..
webdriverio window() call is able to retrieve a window by using the tab name attribute but I do not know if there is a way to associate a tab name to a webview element.
Me neither, that is something that you can use in the browser when using <a target="my-tab" href=...
right?
Currently I am locating a particular element's id contained by the targeted webview by iterating over all window handles.
Finally got you example working, yeah that's not ideal. Targeting with the id of the webview itself would be better.
I went over the webdriver docs again but I fear this is something that needs changes to the webview implementation in electron..
@tiemevanveen I sadly came up to the same conclusion.
@kevinsawicki I am pretty sure that you are already a lot busy with all the other issues but perhaps can you come up with a better work around than the current one ?
I am pretty sure that you are already a lot busy with all the other issues but perhaps can you come up with a better work around than the current one ?
Nothing I can think of initially but I think something could be added, will have to investigate further.
Thanks, that would be great!
+1.
I'm also looping on the window handles, looking for the URL to determine the <webview>
I need. But that can potentially reduce my tests' range.
Combined with https://github.com/electron/spectron/issues/269 which stops the use of BrowserWindow.getAllWindows()
/ BrowserWindow.getChildWindows()
Spectron is very painful to use with an app which uses multiple windows.
As help to anyone else finding this thread, make sure you use async/await https://github.com/electron/spectron/issues/149#issuecomment-267919689 so the checks run in series rather than a Promise.all(), I wasted much time with the latter before realizing the window needs to be held in focus while the getUrl()
/getTitle()
etc. is run.
Here is my WebdriverIO waitUntil() method which waits for (and leaves in focus) a window based on its url
.waitUntil(() => {
return app
.client
.windowHandles()
.then(async (windowHandles) => {
for (const windowHandleValue of windowHandles.value) {
await app.client.window(windowHandleValue);
const getUrl = await app.client.getUrl();
if (/foobar.html$/.test(getUrl)) {
return Promise.resolve(windowHandleValue);
}
}
return Promise.resolve(false);
});
})
Cf. @ChrisHSandN method to focus by url: we ran into issues in case the index has gone in the meantime. So we made our solution a bit more robust there:
/**
* @param {string} urlFragment - substring
* @returns {Promise<boolean>}
*/
async function focusWindowByUrlFragment(urlFragment) {
const windowHandles = await client.windowHandles();
for (let index = 0; index < windowHandles.value.length; index++) {
let windowUrl;
try {
await raceWithTimeout(5000, client.windowByIndex(index));
windowUrl = await raceWithTimeout(5000, client.getUrl());
} catch (error) {
// index might have gone in the meantime, hence this error handling
return false;
}
if (windowUrl.match(urlFragment)) {
return true;
}
}
return false;
}
Doing some more Spectron work and I have discovered since the last update this has now been implemented via: https://github.com/electron-userland/spectron/pull/365
app.client.switchWindow(String|RegExp);
@teameh I think this issue could be closed now.
Haha it's been more than 3 years. Cool to let us know!
I'm not doing much with electron at the moment so I can't verify this but feel free to close this issue if it's fixed!
as @kevinsawicki points out here https://github.com/electron/spectron/issues/6:
if you have multiple webviews, then working with just the index is very error prone. Would it be possible get the webview based on its id? Something like:
windowById('#my-webview)
?Or could we maybe already achieve this with a couple of promises? I tried but couldn't make it work. Any idea's?