fix(chromium): wait for existing pages when connecting (#6511)

This commit is contained in:
Joel Einbinder 2021-05-13 14:10:52 -07:00 committed by GitHub
parent 92fa7ddead
commit 3bded35834
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 24 additions and 11 deletions

View File

@ -67,14 +67,18 @@ export class ElectronApplication extends ChannelOwner<channels.ElectronApplicati
constructor(parent: ChannelOwner, type: string, guid: string, initializer: channels.ElectronApplicationInitializer) {
super(parent, type, guid, initializer);
this._context = BrowserContext.from(initializer.context);
this._context.on(Events.BrowserContext.Page, page => {
this._windows.add(page);
this.emit(Events.ElectronApplication.Window, page);
page.once(Events.Page.Close, () => this._windows.delete(page));
});
for (const page of this._context._pages)
this._onPage(page);
this._context.on(Events.BrowserContext.Page, page => this._onPage(page));
this._channel.on('close', () => this.emit(Events.ElectronApplication.Close));
}
_onPage(page: Page) {
this._windows.add(page);
this.emit(Events.ElectronApplication.Window, page);
page.once(Events.Page.Close, () => this._windows.delete(page));
}
windows(): Page[] {
// TODO: add ElectronPage class inherting from Page.
return [...this._windows];

View File

@ -61,12 +61,16 @@ export class CRBrowser extends Browser {
return browser;
}
browser._defaultContext = new CRBrowserContext(browser, undefined, options.persistent);
await Promise.all([
session.send('Target.setAutoAttach', { autoAttach: true, waitForDebuggerOnStart: true, flatten: true }),
session.send('Target.setAutoAttach', { autoAttach: true, waitForDebuggerOnStart: true, flatten: true }).then(async () => {
// Target.setAutoAttach has a bug where it does not wait for new Targets being attached.
// However making a dummy call afterwards fixes this.
// This can be removed after https://chromium-review.googlesource.com/c/chromium/src/+/2885888 lands in stable.
await session.send('Target.getTargetInfo');
}),
(browser._defaultContext as CRBrowserContext)._initialize(),
]);
await browser._waitForAllPagesToBeInitialized();
return browser;
}
@ -104,6 +108,10 @@ export class CRBrowser extends Browser {
return this.options.name === 'clank';
}
async _waitForAllPagesToBeInitialized() {
await Promise.all([...this._crPages.values()].map(page => page.pageOrError()));
}
_onAttachedToTarget({targetInfo, sessionId, waitingForDebugger}: Protocol.Target.attachedToTargetPayload) {
if (targetInfo.type === 'browser')
return;

View File

@ -63,6 +63,8 @@ export class ElectronApplication extends SdkObject {
// Emit application closed after context closed.
Promise.resolve().then(() => this.emit(ElectronApplication.Events.Close));
});
for (const page of this._browserContext.pages())
this._onPage(page);
this._browserContext.on(BrowserContext.Events.Page, event => this._onPage(event));
this._nodeConnection = nodeConnection;
this._nodeSession = nodeConnection.rootSession;
@ -77,7 +79,7 @@ export class ElectronApplication extends SdkObject {
this._nodeSession.send('Runtime.enable', {}).catch(e => {});
}
private async _onPage(page: Page) {
private _onPage(page: Page) {
// Needs to be sync.
const windowId = ++this._lastWindowId;
(page as any)._browserWindowId = windowId;

View File

@ -240,7 +240,6 @@ playwrightTest('should send extra headers with connect request', async ({browser
});
playwrightTest('should report all pages in an existing browser', async ({ browserType, browserOptions }, testInfo) => {
playwrightTest.fail();
const port = 9339 + testInfo.workerIndex;
const browserServer = await browserType.launch({
...browserOptions,

View File

@ -102,7 +102,7 @@ test('should return browser window', async ({ playwright }) => {
const electronApp = await playwright._electron.launch({
args: [path.join(__dirname, 'electron-window-app.js')],
});
const page = await electronApp.waitForEvent('window');
const page = await electronApp.firstWindow();
const bwHandle = await electronApp.browserWindow(page);
expect(await bwHandle.evaluate((bw: BrowserWindow) => bw.title)).toBe('Electron');
await electronApp.close();