From 9e2e87060aeab7a81fe8ac5385761620e7fec191 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Wed, 26 Aug 2020 13:33:37 -0700 Subject: [PATCH] test: switch browserType.connect tests to use remoteServer (#3646) This way we test the real scenario where server is not launched in the same node process. Additionally, move all connect-related tests to a single file and clean them up. --- test/browsertype-connect.spec.ts | 159 +++++++++++++++++-------- test/browsertype-launch-server.spec.ts | 88 -------------- test/multiclient.spec.ts | 101 ---------------- 3 files changed, 111 insertions(+), 237 deletions(-) delete mode 100644 test/multiclient.spec.ts diff --git a/test/browsertype-connect.spec.ts b/test/browsertype-connect.spec.ts index d9c9e071f8..635bc2694d 100644 --- a/test/browsertype-connect.spec.ts +++ b/test/browsertype-connect.spec.ts @@ -19,55 +19,86 @@ import { options } from './playwright.fixtures'; import utils from './utils'; import './remoteServer.fixture'; -it.skip(options.WIRE).slow()('should be able to reconnect to a browser', async({browserType, defaultBrowserOptions, server}) => { - const browserServer = await browserType.launchServer(defaultBrowserOptions); +it.skip(options.WIRE).slow()('should be able to reconnect to a browser', async({browserType, remoteServer, server}) => { { - const browser = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); + const browser = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint() }); + const browserContext = await browser.newContext(); + expect(browserContext.pages().length).toBe(0); + const page = await browserContext.newPage(); + expect(await page.evaluate('11 * 11')).toBe(121); + await page.goto(server.EMPTY_PAGE); + await browser.close(); + } + { + const browser = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint() }); const browserContext = await browser.newContext(); const page = await browserContext.newPage(); await page.goto(server.EMPTY_PAGE); await browser.close(); } - { - const browser = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); - const browserContext = await browser.newContext(); - const page = await browserContext.newPage(); - await page.goto(server.EMPTY_PAGE); - await browser.close(); - } - await browserServer.close(); }); -it.skip(options.WIRE)('should connect to a remote server', async({ browserType, remoteServer }) => { - const browser = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint() }); - const page = await browser.newPage(); - expect(await page.evaluate('2 + 3')).toBe(5); - await browser.close(); +it.skip(options.WIRE).slow()('should be able to connect two browsers at the same time', async ({browserType, remoteServer}) => { + const browser1 = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint() }); + expect(browser1.contexts().length).toBe(0); + await browser1.newContext(); + expect(browser1.contexts().length).toBe(1); + + const browser2 = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint() }); + expect(browser2.contexts().length).toBe(0); + await browser2.newContext(); + expect(browser2.contexts().length).toBe(1); + expect(browser1.contexts().length).toBe(1); + + await browser1.close(); + const page2 = await browser2.newPage(); + expect(await page2.evaluate(() => 7 * 6)).toBe(42); // original browser should still work + + await browser2.close(); }); -it.skip(options.WIRE).fail(options.CHROMIUM && WIN).slow()('should handle exceptions during connect', async({browserType, defaultBrowserOptions}) => { - const browserServer = await browserType.launchServer(defaultBrowserOptions); +it.skip(options.WIRE).slow()('disconnected event should be emitted when browser is closed or server is closed', async ({browserType, remoteServer}) => { + const browser1 = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint() }); + const browser2 = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint() }); + + let disconnected1 = 0; + let disconnected2 = 0; + browser1.on('disconnected', () => ++disconnected1); + browser2.on('disconnected', () => ++disconnected2); + + await Promise.all([ + new Promise(f => browser1.on('disconnected', f)), + browser1.close(), + ]); + expect(disconnected1).toBe(1); + expect(disconnected2).toBe(0); + + await Promise.all([ + new Promise(f => browser2.on('disconnected', f)), + remoteServer.close(), + ]); + expect(disconnected1).toBe(1); + expect(disconnected2).toBe(1); +}); + +it.skip(options.WIRE).fail(options.CHROMIUM && WIN).slow()('should handle exceptions during connect', async({browserType, remoteServer}) => { const __testHookBeforeCreateBrowser = () => { throw new Error('Dummy') }; - const error = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint(), __testHookBeforeCreateBrowser } as any).catch(e => e); - await browserServer.close(); + const error = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint(), __testHookBeforeCreateBrowser } as any).catch(e => e); expect(error.message).toContain('Dummy'); }); -it.skip(options.WIRE)('should set the browser connected state', async ({browserType, defaultBrowserOptions}) => { - const browserServer = await browserType.launchServer(defaultBrowserOptions); - const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); +it.skip(options.WIRE).slow()('should set the browser connected state', async ({browserType, remoteServer}) => { + const remote = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint() }); expect(remote.isConnected()).toBe(true); await remote.close(); expect(remote.isConnected()).toBe(false); - await browserServer.close(); }); -it.skip(options.WIRE)('should throw when used after isConnected returns false', async({browserType, defaultBrowserOptions}) => { - const browserServer = await browserType.launchServer(defaultBrowserOptions); - const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); +it.skip(options.WIRE).slow()('should throw when used after isConnected returns false', async({browserType, remoteServer}) => { + const remote = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint() }); const page = await remote.newPage(); await Promise.all([ - browserServer.close(), + remoteServer.close(), new Promise(f => remote.once('disconnected', f)), ]); expect(remote.isConnected()).toBe(false); @@ -75,28 +106,60 @@ it.skip(options.WIRE)('should throw when used after isConnected returns false', expect(error.message).toContain('has been closed'); }); -it.skip(options.WIRE)('should respect selectors', async({playwright, browserType, defaultBrowserOptions}) => { - const mycss = () => ({ - create(root, target) {}, - query(root, selector) { - return root.querySelector(selector); - }, - queryAll(root: HTMLElement, selector: string) { - return Array.from(root.querySelectorAll(selector)); - } - }); - await utils.registerEngine(playwright, 'mycss', mycss); - - const browserServer = await browserType.launchServer(defaultBrowserOptions); - const browser = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); - const page = await browser.newPage(); - await page.setContent(`
hello
`); - expect(await page.innerHTML('css=div')).toBe('hello'); - expect(await page.innerHTML('mycss=div')).toBe('hello'); - await browserServer.close(); +it.skip(options.WIRE).slow()('should reject navigation when browser closes', async({browserType, remoteServer, server}) => { + server.setRoute('/one-style.css', () => {}); + const remote = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint() }); + const page = await remote.newPage(); + const navigationPromise = page.goto(server.PREFIX + '/one-style.html', {timeout: 60000}).catch(e => e); + await server.waitForRequest('/one-style.css'); + await remote.close(); + const error = await navigationPromise; + expect(error.message).toContain('Navigation failed because page was closed!'); }); -it.skip(options.WIRE).fail(true)('should respect selectors when connected remotely', async({ playwright, browserType, remoteServer }) => { +it.skip(options.WIRE).slow()('should reject waitForSelector when browser closes', async({browserType, remoteServer, server}) => { + server.setRoute('/empty.html', () => {}); + const remote = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint() }); + const page = await remote.newPage(); + const watchdog = page.waitForSelector('div', { state: 'attached', timeout: 60000 }).catch(e => e); + + // Make sure the previous waitForSelector has time to make it to the browser before we disconnect. + await page.waitForSelector('body', { state: 'attached' }); + + await remote.close(); + const error = await watchdog; + expect(error.message).toContain('Protocol error'); +}); + +it.skip(options.WIRE).slow()('should emit close events on pages and contexts', async({browserType, remoteServer}) => { + const remote = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint() }); + const context = await remote.newContext(); + const page = await context.newPage(); + let pageClosed = false; + page.on('close', () => pageClosed = true); + await Promise.all([ + new Promise(f => context.on('close', f)), + remoteServer.close() + ]); + expect(pageClosed).toBeTruthy(); +}); + +it.skip(options.WIRE).slow()('should terminate network waiters', async({browserType, remoteServer, server}) => { + const remote = await browserType.connect({ wsEndpoint: remoteServer.wsEndpoint() }); + const newPage = await remote.newPage(); + const results = await Promise.all([ + newPage.waitForRequest(server.EMPTY_PAGE).catch(e => e), + newPage.waitForResponse(server.EMPTY_PAGE).catch(e => e), + remoteServer.close(), + ]); + for (let i = 0; i < 2; i++) { + const message = results[i].message; + expect(message).toContain('Page closed'); + expect(message).not.toContain('Timeout'); + } +}); + +it.skip(options.WIRE).fail(true).slow()('should respect selectors', async({ playwright, browserType, remoteServer }) => { const mycss = () => ({ create(root, target) {}, query(root, selector) { diff --git a/test/browsertype-launch-server.spec.ts b/test/browsertype-launch-server.spec.ts index 05e17b8920..98c23f790e 100644 --- a/test/browsertype-launch-server.spec.ts +++ b/test/browsertype-launch-server.spec.ts @@ -19,29 +19,10 @@ import { options } from './playwright.fixtures'; it.skip(options.WIRE)('should work', async({browserType, defaultBrowserOptions}) => { const browserServer = await browserType.launchServer(defaultBrowserOptions); - const browser = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); - const browserContext = await browser.newContext(); - expect(browserContext.pages().length).toBe(0); expect(browserServer.wsEndpoint()).not.toBe(null); - const page = await browserContext.newPage(); - expect(await page.evaluate('11 * 11')).toBe(121); - await page.close(); - await browser.close(); await browserServer.close(); }); -it.skip(options.WIRE)('should fire "disconnected" when closing the server', async({browserType, defaultBrowserOptions}) => { - const browserServer = await browserType.launchServer(defaultBrowserOptions); - const browser = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); - const disconnectedEventPromise = new Promise(resolve => browser.once('disconnected', resolve)); - const closedPromise = new Promise(f => browserServer.on('close', f)); - browserServer.kill(); - await Promise.all([ - disconnectedEventPromise, - closedPromise, - ]); -}); - it.skip(options.WIRE)('should fire "close" event during kill', async({browserType, defaultBrowserOptions}) => { const order = []; const browserServer = await browserType.launchServer(defaultBrowserOptions); @@ -71,72 +52,3 @@ it.skip(options.WIRE)('should fire close event', async ({browserType, defaultBro expect(result['exitCode']).toBe(0); expect(result['signal']).toBe(null); }); - -it.skip(options.WIRE)('should reject navigation when browser closes', async({browserType, defaultBrowserOptions, server}) => { - server.setRoute('/one-style.css', () => {}); - const browserServer = await browserType.launchServer(defaultBrowserOptions); - const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); - const page = await remote.newPage(); - const navigationPromise = page.goto(server.PREFIX + '/one-style.html', {timeout: 60000}).catch(e => e); - await server.waitForRequest('/one-style.css'); - await remote.close(); - const error = await navigationPromise; - expect(error.message).toContain('Navigation failed because page was closed!'); - await browserServer.close(); -}); - -it.skip(options.WIRE)('should reject waitForSelector when browser closes', async({browserType, defaultBrowserOptions, server}) => { - server.setRoute('/empty.html', () => {}); - const browserServer = await browserType.launchServer(defaultBrowserOptions); - const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); - const page = await remote.newPage(); - const watchdog = page.waitForSelector('div', { state: 'attached', timeout: 60000 }).catch(e => e); - - // Make sure the previous waitForSelector has time to make it to the browser before we disconnect. - await page.waitForSelector('body', { state: 'attached' }); - - await remote.close(); - const error = await watchdog; - expect(error.message).toContain('Protocol error'); - await browserServer.close(); -}); - -it.skip(options.WIRE)('should throw if used after disconnect', async({browserType, defaultBrowserOptions}) => { - const browserServer = await browserType.launchServer(defaultBrowserOptions); - const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); - const page = await remote.newPage(); - await remote.close(); - const error = await page.evaluate('1 + 1').catch(e => e); - expect((error as Error).message).toContain('has been closed'); - await browserServer.close(); -}); - -it.skip(options.WIRE)('should emit close events on pages and contexts', async({browserType, defaultBrowserOptions}) => { - const browserServer = await browserType.launchServer(defaultBrowserOptions); - const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); - const context = await remote.newContext(); - const page = await context.newPage(); - let pageClosed = false; - page.on('close', () => pageClosed = true); - await Promise.all([ - new Promise(f => context.on('close', f)), - browserServer.close() - ]); - expect(pageClosed).toBeTruthy(); -}); - -it.skip(options.WIRE)('should terminate network waiters', async({browserType, defaultBrowserOptions, server}) => { - const browserServer = await browserType.launchServer(defaultBrowserOptions); - const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); - const newPage = await remote.newPage(); - const results = await Promise.all([ - newPage.waitForRequest(server.EMPTY_PAGE).catch(e => e), - newPage.waitForResponse(server.EMPTY_PAGE).catch(e => e), - browserServer.close() - ]); - for (let i = 0; i < 2; i++) { - const message = results[i].message; - expect(message).toContain('Page closed'); - expect(message).not.toContain('Timeout'); - } -}); diff --git a/test/multiclient.spec.ts b/test/multiclient.spec.ts deleted file mode 100644 index 7d4c368ce5..0000000000 --- a/test/multiclient.spec.ts +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Copyright 2017 Google Inc. All rights reserved. - * Modifications copyright (c) Microsoft Corporation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { options } from './playwright.fixtures'; - -it.skip(options.WIRE)('should work across sessions', async ({browserType, defaultBrowserOptions}) => { - const browserServer = await browserType.launchServer(defaultBrowserOptions); - const browser1 = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); - expect(browser1.contexts().length).toBe(0); - await browser1.newContext(); - expect(browser1.contexts().length).toBe(1); - - const browser2 = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); - expect(browser2.contexts().length).toBe(0); - await browser2.newContext(); - expect(browser2.contexts().length).toBe(1); - - expect(browser1.contexts().length).toBe(1); - - await browser1.close(); - await browser2.close(); - - await browserServer.close(); -}); - -it.skip(options.WIRE).slow()('should be emitted when: browser gets closed, disconnected or underlying websocket gets closed', async ({browserType, defaultBrowserOptions}) => { - const browserServer = await browserType.launchServer(defaultBrowserOptions); - const originalBrowser = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); - const wsEndpoint = browserServer.wsEndpoint(); - const remoteBrowser1 = await browserType.connect({ wsEndpoint }); - const remoteBrowser2 = await browserType.connect({ wsEndpoint }); - - let disconnectedOriginal = 0; - let disconnectedRemote1 = 0; - let disconnectedRemote2 = 0; - originalBrowser.on('disconnected', () => ++disconnectedOriginal); - remoteBrowser1.on('disconnected', () => ++disconnectedRemote1); - remoteBrowser2.on('disconnected', () => ++disconnectedRemote2); - - await Promise.all([ - new Promise(f => remoteBrowser2.on('disconnected', f)), - remoteBrowser2.close(), - ]); - - expect(disconnectedOriginal).toBe(0); - expect(disconnectedRemote1).toBe(0); - expect(disconnectedRemote2).toBe(1); - - await Promise.all([ - new Promise(f => remoteBrowser1.on('disconnected', f)), - new Promise(f => originalBrowser.on('disconnected', f)), - browserServer.close(), - ]); - - expect(disconnectedOriginal).toBe(1); - expect(disconnectedRemote1).toBe(1); - expect(disconnectedRemote2).toBe(1); -}); - -it.skip(options.WIRE)('should be able to connect multiple times to the same browser', async({browserType, defaultBrowserOptions}) => { - const browserServer = await browserType.launchServer(defaultBrowserOptions); - const browser1 = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); - const browser2 = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); - const page1 = await browser1.newPage(); - expect(await page1.evaluate(() => 7 * 8)).toBe(56); - browser1.close(); - - const page2 = await browser2.newPage(); - expect(await page2.evaluate(() => 7 * 6)).toBe(42); // original browser should still work - await browser2.close(); - await browserServer.close(); -}); - -it.skip(options.WIRE)('should not be able to close remote browser', async({browserType, defaultBrowserOptions}) => { - const browserServer = await browserType.launchServer(defaultBrowserOptions); - { - const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); - await remote.newContext(); - await remote.close(); - } - { - const remote = await browserType.connect({ wsEndpoint: browserServer.wsEndpoint() }); - await remote.newContext(); - await remote.close(); - } - await browserServer.close(); -});