diff --git a/src/webkit/wkLauncher.ts b/src/webkit/wkLauncher.ts index 20dfdf2799..559235c202 100644 --- a/src/webkit/wkLauncher.ts +++ b/src/webkit/wkLauncher.ts @@ -58,6 +58,7 @@ export class WKLauncher { handleSIGTERM = true, handleSIGHUP = true, slowMo = 0, + timeout = 30000 } = options; const webkitArguments = []; @@ -98,7 +99,7 @@ export class WKLauncher { try { const transport = new PipeTransport(launchedProcess.stdio[3] as NodeJS.WritableStream, launchedProcess.stdio[4] as NodeJS.ReadableStream); browser = new WKBrowser(SlowMoTransport.wrap(transport, slowMo)); - await browser._waitForTarget(t => t._type === 'page'); + await browser._waitForTarget(t => t._type === 'page', {timeout}); return new BrowserServer(browser, launchedProcess, ''); } catch (e) { if (browser) @@ -128,6 +129,7 @@ export type LauncherLaunchOptions = { handleSIGTERM?: boolean, handleSIGHUP?: boolean, headless?: boolean, + timeout?: number, dumpio?: boolean, env?: {[key: string]: string} | undefined, slowMo?: number, diff --git a/test/chromium/browser.spec.js b/test/chromium/browser.spec.js index 9065100587..e97c7b7d09 100644 --- a/test/chromium/browser.spec.js +++ b/test/chromium/browser.spec.js @@ -1,12 +1,15 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT license. -module.exports.describe = function({testRunner, expect, headless, playwright, FFOX, CHROME, WEBKIT}) { +const path = require('path'); +const {spawn, execSync} = require('child_process'); + +module.exports.describe = function({testRunner, expect, defaultBrowserOptions, playwright, playwrightPath}) { const {describe, xdescribe, fdescribe} = testRunner; const {it, fit, xit, dit} = testRunner; const {beforeAll, beforeEach, afterAll, afterEach} = testRunner; - describe('CrBrowser', function() { + describe('CRBrowser', function() { it('should close all belonging targets once closing context', async function({browser, newContext}) { const targets = async () => (await browser.targets()).filter(t => t.type() === 'page'); expect((await targets()).length).toBe(1); @@ -19,5 +22,30 @@ module.exports.describe = function({testRunner, expect, headless, playwright, FF await context.close(); expect((await targets()).length).toBe(1); }); + it('should close the browser when the node process closes', async({ server }) => { + const options = Object.assign({}, defaultBrowserOptions, { + // Disable DUMPIO to cleanly read stdout. + dumpio: false, + }); + const res = spawn('node', [path.join(__dirname, '..', 'fixtures', 'closeme.js'), playwrightPath, JSON.stringify(options)]); + let wsEndPointCallback; + const wsEndPointPromise = new Promise(x => wsEndPointCallback = x); + let output = ''; + res.stdout.on('data', data => { + output += data; + if (output.indexOf('\n')) + wsEndPointCallback(output.substring(0, output.indexOf('\n'))); + }); + const browser = await playwright.connect({ browserWSEndpoint: await wsEndPointPromise }); + const promises = [ + new Promise(resolve => browser.once('disconnected', resolve)), + new Promise(resolve => res.on('close', resolve)) + ]; + if (process.platform === 'win32') + execSync(`taskkill /pid ${res.pid} /T /F`); + else + process.kill(res.pid); + await Promise.all(promises); + }); }); }; diff --git a/test/firefox/browser.spec.js b/test/firefox/browser.spec.js new file mode 100644 index 0000000000..b885a0789e --- /dev/null +++ b/test/firefox/browser.spec.js @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +const path = require('path'); +const {spawn, execSync} = require('child_process'); + +module.exports.describe = function({testRunner, defaultBrowserOptions, playwright, playwrightPath}) { + const {describe, xdescribe, fdescribe} = testRunner; + const {it, fit, xit, dit} = testRunner; + const {beforeAll, beforeEach, afterAll, afterEach} = testRunner; + + describe('FFBrowser', function() { + it('should close the browser when the node process closes', async({ server }) => { + const options = Object.assign({}, defaultBrowserOptions, { + // Disable DUMPIO to cleanly read stdout. + dumpio: false, + }); + const res = spawn('node', [path.join(__dirname, '..', 'fixtures', 'closeme.js'), playwrightPath, JSON.stringify(options)]); + let wsEndPointCallback; + const wsEndPointPromise = new Promise(x => wsEndPointCallback = x); + let output = ''; + res.stdout.on('data', data => { + output += data; + if (output.indexOf('\n')) + wsEndPointCallback(output.substring(0, output.indexOf('\n'))); + }); + const browser = await playwright.connect({ browserWSEndpoint: await wsEndPointPromise }); + const promises = [ + new Promise(resolve => browser.once('disconnected', resolve)), + new Promise(resolve => res.on('close', resolve)) + ]; + if (process.platform === 'win32') + execSync(`taskkill /pid ${res.pid} /T /F`); + else + process.kill(res.pid); + await Promise.all(promises); + }); + }); +}; diff --git a/test/fixtures.spec.js b/test/fixtures.spec.js index 2f7a0f1ea0..82b48d06c5 100644 --- a/test/fixtures.spec.js +++ b/test/fixtures.spec.js @@ -16,65 +16,27 @@ */ const path = require('path'); +const {spawn} = require('child_process'); module.exports.describe = function({testRunner, expect, defaultBrowserOptions, playwright, playwrightPath, FFOX, CHROME, WEBKIT}) { const {describe, xdescribe, fdescribe} = testRunner; const {it, fit, xit, dit} = testRunner; const {beforeAll, beforeEach, afterAll, afterEach} = testRunner; - describe.skip(WEBKIT)('Fixtures', function() { - it.skip(FFOX)('dumpio option should work with pipe option ', async({server}) => { + describe('Fixtures', function() { + it('dumpio option should work with pipe option ', async({server}) => { let dumpioData = ''; - const {spawn} = require('child_process'); - const options = Object.assign({}, defaultBrowserOptions, {pipe: true, dumpio: true}); - const res = spawn('node', - [path.join(__dirname, 'fixtures', 'dumpio.js'), playwrightPath, JSON.stringify(options)]); + const res = spawn('node', [path.join(__dirname, 'fixtures', 'dumpio.js'), playwrightPath, 'use-pipe']); res.stderr.on('data', data => dumpioData += data.toString('utf8')); await new Promise(resolve => res.on('close', resolve)); expect(dumpioData).toContain('message from dumpio'); }); it('should dump browser process stderr', async({server}) => { let dumpioData = ''; - const {spawn} = require('child_process'); - const options = Object.assign({}, defaultBrowserOptions, {dumpio: true}); - const res = spawn('node', - [path.join(__dirname, 'fixtures', 'dumpio.js'), playwrightPath, JSON.stringify(options)]); - if (CHROME || WEBKIT) - res.stderr.on('data', data => dumpioData += data.toString('utf8')); - else - res.stdout.on('data', data => dumpioData += data.toString('utf8')); + const res = spawn('node', [path.join(__dirname, 'fixtures', 'dumpio.js'), playwrightPath]); + res.stderr.on('data', data => dumpioData += data.toString('utf8')); await new Promise(resolve => res.on('close', resolve)); - - if (CHROME || WEBKIT) - expect(dumpioData).toContain('DevTools listening on ws://'); - else - expect(dumpioData).toContain('Juggler listening on ws://'); - }); - it('should close the browser when the node process closes', async({ server }) => { - const {spawn, execSync} = require('child_process'); - const options = Object.assign({}, defaultBrowserOptions, { - // Disable DUMPIO to cleanly read stdout. - dumpio: false, - }); - const res = spawn('node', [path.join(__dirname, 'fixtures', 'closeme.js'), playwrightPath, JSON.stringify(options)]); - let wsEndPointCallback; - const wsEndPointPromise = new Promise(x => wsEndPointCallback = x); - let output = ''; - res.stdout.on('data', data => { - output += data; - if (output.indexOf('\n')) - wsEndPointCallback(output.substring(0, output.indexOf('\n'))); - }); - const browser = await playwright.connect({ browserWSEndpoint: await wsEndPointPromise }); - const promises = [ - new Promise(resolve => browser.once('disconnected', resolve)), - new Promise(resolve => res.on('close', resolve)) - ]; - if (process.platform === 'win32') - execSync(`taskkill /pid ${res.pid} /T /F`); - else - process.kill(res.pid); - await Promise.all(promises); + expect(dumpioData).toContain('message from dumpio'); }); }); }; diff --git a/test/fixtures/dumpio.js b/test/fixtures/dumpio.js index 47b70097de..ea5302b557 100644 --- a/test/fixtures/dumpio.js +++ b/test/fixtures/dumpio.js @@ -1,8 +1,24 @@ (async() => { - const [, , playwrightRoot, options] = process.argv; - const browser = await require(playwrightRoot).launch(JSON.parse(options)); - const page = await browser.defaultContext().newPage(); - await page.evaluate(() => console.error('message from dumpio')); - await page.close(); - await browser.close(); + process.on('unhandledRejection', error => { + // Catch various errors as we launch non-browser binary. + console.log('unhandledRejection', error.message); + }); + + const [, , playwrightRoot, usePipe] = process.argv; + const options = { + pipe: usePipe === 'use-pipe', + ignoreDefaultArgs: true, + dumpio: true, + timeout: 1, + executablePath: 'node', + args: ['-e', 'console.error("message from dumpio")', '--'] + } + console.error('using pipe: ' + options.pipe); + if (playwrightRoot.includes('firefox')) + options.args.push('-juggler', '-profile'); + try { + await require(playwrightRoot).launch(options); + console.error('Browser launch unexpectedly succeeded.'); + } catch (e) { + } })(); diff --git a/test/playwright.spec.js b/test/playwright.spec.js index 40d2f01e8f..23e6e28092 100644 --- a/test/playwright.spec.js +++ b/test/playwright.spec.js @@ -190,6 +190,9 @@ module.exports.describe = ({testRunner, product, playwrightPath}) => { if (CHROME) { testRunner.loadTests(require('./chromium/browser.spec.js'), testOptions); } + if (FFOX) { + testRunner.loadTests(require('./firefox/browser.spec.js'), testOptions); + } }); // Top-level tests that launch Browser themselves.