From bf656ea3187ded8e3225713a6a598982c721d3e4 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Fri, 10 Apr 2020 20:31:50 -0700 Subject: [PATCH] fix(tests): accomodate isplaywrightready (#1746) --- test/test.js | 355 +++++++++++++++++++++++++------------------------- test/utils.js | 13 +- 2 files changed, 191 insertions(+), 177 deletions(-) diff --git a/test/test.js b/test/test.js index 0557c646a2..df48f7078d 100644 --- a/test/test.js +++ b/test/test.js @@ -20,189 +20,196 @@ const readline = require('readline'); const TestRunner = require('../utils/testrunner/'); const {Environment} = require('../utils/testrunner/Test'); -let parallel = 1; -if (process.env.PW_PARALLEL_TESTS) - parallel = parseInt(process.env.PW_PARALLEL_TESTS.trim(), 10); -const parallelArgIndex = process.argv.indexOf('-j'); -if (parallelArgIndex !== -1) - parallel = parseInt(process.argv[parallelArgIndex + 1], 10); -require('events').defaultMaxListeners *= parallel; +function collect(browserNames) { + let parallel = 1; + if (process.env.PW_PARALLEL_TESTS) + parallel = parseInt(process.env.PW_PARALLEL_TESTS.trim(), 10); + const parallelArgIndex = process.argv.indexOf('-j'); + if (parallelArgIndex !== -1) + parallel = parseInt(process.argv[parallelArgIndex + 1], 10); + require('events').defaultMaxListeners *= parallel; -let timeout = process.env.CI ? 30 * 1000 : 10 * 1000; -if (!isNaN(process.env.TIMEOUT)) - timeout = parseInt(process.env.TIMEOUT * 1000, 10); -const MAJOR_NODEJS_VERSION = parseInt(process.version.substring(1).split('.')[0], 10); -if (MAJOR_NODEJS_VERSION >= 8 && require('inspector').url()) { - console.log('Detected inspector - disabling timeout to be debugger-friendly'); - timeout = 0; -} - -const config = require('./test.config'); - -const testRunner = new TestRunner({ - timeout, - totalTimeout: process.env.CI ? 15 * 60 * 1000 : 0, - parallel, - breakOnFailure: process.argv.indexOf('--break-on-failure') !== -1, - verbose: process.argv.includes('--verbose'), - summary: !process.argv.includes('--verbose'), - showSlowTests: process.env.CI ? 5 : 0, - showMarkedAsFailingTests: 10, -}); -if (config.setupTestRunner) - config.setupTestRunner(testRunner); - -console.log('Testing on Node', process.version); - -const browserNames = ['chromium', 'firefox', 'webkit'].filter(name => { - return process.env.BROWSER === name || process.env.BROWSER === 'all'; -}); - -for (const [key, value] of Object.entries(testRunner.api())) - global[key] = value; - -// TODO: this should be a preinstalled playwright by default. -const playwrightPath = config.playwrightPath; -const playwright = require(playwrightPath); - -const playwrightEnvironment = new Environment('Playwright'); -playwrightEnvironment.beforeAll(async state => { - state.playwright = playwright; - global.playwright = playwright; -}); -playwrightEnvironment.afterAll(async state => { - delete state.playwright; - delete global.playwright; -}); - -testRunner.collector().useEnvironment(playwrightEnvironment); -for (const e of config.globalEnvironments || []) - testRunner.collector().useEnvironment(e); - -for (const browserName of browserNames) { - const browserType = playwright[browserName]; - const browserTypeEnvironment = new Environment('BrowserType'); - browserTypeEnvironment.beforeAll(async state => { - state.browserType = browserType; - }); - browserTypeEnvironment.afterAll(async state => { - delete state.browserType; - }); - - // TODO: maybe launch options per browser? - const launchOptions = { - ...(config.launchOptions || {}), - handleSIGINT: false, - }; - if (launchOptions.executablePath) - launchOptions.executablePath = launchOptions.executablePath[browserName]; - if (launchOptions.executablePath) { - const YELLOW_COLOR = '\x1b[33m'; - const RESET_COLOR = '\x1b[0m'; - console.warn(`${YELLOW_COLOR}WARN: running ${browserName} tests with ${launchOptions.executablePath}${RESET_COLOR}`); - browserType._executablePath = launchOptions.executablePath; - delete launchOptions.executablePath; - } else { - if (!fs.existsSync(browserType.executablePath())) - throw new Error(`Browser is not downloaded. Run 'npm install' and try to re-run tests`); + let timeout = process.env.CI ? 30 * 1000 : 10 * 1000; + if (!isNaN(process.env.TIMEOUT)) + timeout = parseInt(process.env.TIMEOUT * 1000, 10); + const MAJOR_NODEJS_VERSION = parseInt(process.version.substring(1).split('.')[0], 10); + if (MAJOR_NODEJS_VERSION >= 8 && require('inspector').url()) { + console.log('Detected inspector - disabling timeout to be debugger-friendly'); + timeout = 0; } - const browserEnvironment = new Environment(browserName); - browserEnvironment.beforeAll(async state => { - state.browser = await state.browserType.launch(launchOptions); - // TODO: remove browserServer from state. - state.browserServer = state.browser._ownedServer; - state._stdout = readline.createInterface({ input: state.browserServer.process().stdout }); - state._stderr = readline.createInterface({ input: state.browserServer.process().stderr }); - }); - browserEnvironment.afterAll(async state => { - await state.browserServer.close(); - delete state.browser; - delete state.browserServer; - state._stdout.close(); - state._stderr.close(); - delete state._stdout; - delete state._stderr; - }); - browserEnvironment.beforeEach(async(state, testRun) => { - const dumpout = data => testRun.log(`\x1b[33m[pw:stdio:out]\x1b[0m ${data}`); - const dumperr = data => testRun.log(`\x1b[31m[pw:stdio:err]\x1b[0m ${data}`); - state._stdout.on('line', dumpout); - state._stderr.on('line', dumperr); - // TODO: figure out debug options. - if (config.dumpProtocolOnFailure) { - state.browser._debugProtocol.log = data => testRun.log(`\x1b[32m[pw:protocol]\x1b[0m ${data}`); - state.browser._debugProtocol.enabled = true; - } - state._browserTearDown = async (testRun) => { - state._stdout.off('line', dumpout); - state._stderr.off('line', dumperr); - if (config.dumpProtocolOnFailure) { - delete state.browser._debugProtocol.log; - state.browser._debugProtocol.enabled = false; - if (testRun.ok()) - testRun.output().splice(0); - } - }; - }); - browserEnvironment.afterEach(async (state, testRun) => { - await state._browserTearDown(testRun); - delete state._browserTearDown; - }); + const config = require('./test.config'); - const pageEnvironment = new Environment('Page'); - pageEnvironment.beforeEach(async state => { - state.context = await state.browser.newContext(); - state.page = await state.context.newPage(); - }); - pageEnvironment.afterEach(async state => { - await state.context.close(); - state.context = null; - state.page = null; + const testRunner = new TestRunner({ + timeout, + totalTimeout: process.env.CI ? 15 * 60 * 1000 : 0, + parallel, + breakOnFailure: process.argv.indexOf('--break-on-failure') !== -1, + verbose: process.argv.includes('--verbose'), + summary: !process.argv.includes('--verbose'), + showSlowTests: process.env.CI ? 5 : 0, + showMarkedAsFailingTests: 10, }); + if (config.setupTestRunner) + config.setupTestRunner(testRunner); - const suiteName = { 'chromium': 'Chromium', 'firefox': 'Firefox', 'webkit': 'WebKit' }[browserName]; - describe(suiteName, () => { - // In addition to state, expose these two on global so that describes can access them. + for (const [key, value] of Object.entries(testRunner.api())) + global[key] = value; + + // TODO: this should be a preinstalled playwright by default. + const playwrightPath = config.playwrightPath; + const playwright = require(playwrightPath); + + const playwrightEnvironment = new Environment('Playwright'); + playwrightEnvironment.beforeAll(async state => { + state.playwright = playwright; global.playwright = playwright; - global.browserType = browserType; - - testRunner.collector().useEnvironment(browserTypeEnvironment); - - for (const spec of config.specs || []) { - const skip = spec.browsers && !spec.browsers.includes(browserName); - (skip ? xdescribe : describe)(spec.title || '', () => { - for (const e of spec.environments || ['page']) { - if (e === 'browser') { - testRunner.collector().useEnvironment(browserEnvironment); - } else if (e === 'page') { - testRunner.collector().useEnvironment(browserEnvironment); - testRunner.collector().useEnvironment(pageEnvironment); - } else { - testRunner.collector().useEnvironment(e); - } - } - for (const file of spec.files || []) { - require(file); - delete require.cache[require.resolve(file)]; - } - }); - } - - delete global.browserType; + }); + playwrightEnvironment.afterAll(async state => { + delete state.playwright; delete global.playwright; }); -} -for (const [key, value] of Object.entries(testRunner.api())) { - // expect is used when running tests, while the rest of api is not. - if (key !== 'expect') - delete global[key]; + + testRunner.collector().useEnvironment(playwrightEnvironment); + for (const e of config.globalEnvironments || []) + testRunner.collector().useEnvironment(e); + + for (const browserName of browserNames) { + const browserType = playwright[browserName]; + const browserTypeEnvironment = new Environment('BrowserType'); + browserTypeEnvironment.beforeAll(async state => { + state.browserType = browserType; + }); + browserTypeEnvironment.afterAll(async state => { + delete state.browserType; + }); + + // TODO: maybe launch options per browser? + const launchOptions = { + ...(config.launchOptions || {}), + handleSIGINT: false, + }; + if (launchOptions.executablePath) + launchOptions.executablePath = launchOptions.executablePath[browserName]; + if (launchOptions.executablePath) { + const YELLOW_COLOR = '\x1b[33m'; + const RESET_COLOR = '\x1b[0m'; + console.warn(`${YELLOW_COLOR}WARN: running ${browserName} tests with ${launchOptions.executablePath}${RESET_COLOR}`); + browserType._executablePath = launchOptions.executablePath; + delete launchOptions.executablePath; + } else { + if (!fs.existsSync(browserType.executablePath())) + throw new Error(`Browser is not downloaded. Run 'npm install' and try to re-run tests`); + } + + const browserEnvironment = new Environment(browserName); + browserEnvironment.beforeAll(async state => { + state.browser = await state.browserType.launch(launchOptions); + // TODO: remove browserServer from state. + state.browserServer = state.browser._ownedServer; + state._stdout = readline.createInterface({ input: state.browserServer.process().stdout }); + state._stderr = readline.createInterface({ input: state.browserServer.process().stderr }); + }); + browserEnvironment.afterAll(async state => { + await state.browserServer.close(); + delete state.browser; + delete state.browserServer; + state._stdout.close(); + state._stderr.close(); + delete state._stdout; + delete state._stderr; + }); + browserEnvironment.beforeEach(async(state, testRun) => { + const dumpout = data => testRun.log(`\x1b[33m[pw:stdio:out]\x1b[0m ${data}`); + const dumperr = data => testRun.log(`\x1b[31m[pw:stdio:err]\x1b[0m ${data}`); + state._stdout.on('line', dumpout); + state._stderr.on('line', dumperr); + // TODO: figure out debug options. + if (config.dumpProtocolOnFailure) { + state.browser._debugProtocol.log = data => testRun.log(`\x1b[32m[pw:protocol]\x1b[0m ${data}`); + state.browser._debugProtocol.enabled = true; + } + state._browserTearDown = async (testRun) => { + state._stdout.off('line', dumpout); + state._stderr.off('line', dumperr); + if (config.dumpProtocolOnFailure) { + delete state.browser._debugProtocol.log; + state.browser._debugProtocol.enabled = false; + if (testRun.ok()) + testRun.output().splice(0); + } + }; + }); + browserEnvironment.afterEach(async (state, testRun) => { + await state._browserTearDown(testRun); + delete state._browserTearDown; + }); + + const pageEnvironment = new Environment('Page'); + pageEnvironment.beforeEach(async state => { + state.context = await state.browser.newContext(); + state.page = await state.context.newPage(); + }); + pageEnvironment.afterEach(async state => { + await state.context.close(); + state.context = null; + state.page = null; + }); + + const suiteName = { 'chromium': 'Chromium', 'firefox': 'Firefox', 'webkit': 'WebKit' }[browserName]; + describe(suiteName, () => { + // In addition to state, expose these two on global so that describes can access them. + global.playwright = playwright; + global.browserType = browserType; + + testRunner.collector().useEnvironment(browserTypeEnvironment); + + for (const spec of config.specs || []) { + const skip = spec.browsers && !spec.browsers.includes(browserName); + (skip ? xdescribe : describe)(spec.title || '', () => { + for (const e of spec.environments || ['page']) { + if (e === 'browser') { + testRunner.collector().useEnvironment(browserEnvironment); + } else if (e === 'page') { + testRunner.collector().useEnvironment(browserEnvironment); + testRunner.collector().useEnvironment(pageEnvironment); + } else { + testRunner.collector().useEnvironment(e); + } + } + for (const file of spec.files || []) { + require(file); + delete require.cache[require.resolve(file)]; + } + }); + } + + delete global.browserType; + delete global.playwright; + }); + } + for (const [key, value] of Object.entries(testRunner.api())) { + // expect is used when running tests, while the rest of api is not. + if (key !== 'expect') + delete global[key]; + } + + const filterArgIndex = process.argv.indexOf('--filter'); + if (filterArgIndex !== -1) { + const filter = process.argv[filterArgIndex + 1]; + testRunner.focusMatchingTests(new RegExp(filter, 'i')); + } + + return testRunner; } -const filterArgIndex = process.argv.indexOf('--filter'); -if (filterArgIndex !== -1) { - const filter = process.argv[filterArgIndex + 1]; - testRunner.focusMatchingTests(new RegExp(filter, 'i')); -} +module.exports = collect; -testRunner.run().then(() => { delete global.expect; }); +if (require.main === module) { + console.log('Testing on Node', process.version); + const browserNames = ['chromium', 'firefox', 'webkit'].filter(name => { + return process.env.BROWSER === name || process.env.BROWSER === 'all'; + }); + const testRunner = collect(browserNames); + testRunner.run().then(() => { delete global.expect; }); +} diff --git a/test/utils.js b/test/utils.js index 7df59eff0e..277be1236d 100644 --- a/test/utils.js +++ b/test/utils.js @@ -27,6 +27,8 @@ const PROJECT_ROOT = fs.existsSync(path.join(__dirname, '..', 'package.json')) ? const mkdtempAsync = util.promisify(require('fs').mkdtemp); const removeFolderAsync = util.promisify(removeFolder); +let platform = os.platform(); + const utils = module.exports = { /** * @return {string} @@ -182,9 +184,9 @@ const utils = module.exports = { FFOX: browserType.name() === 'firefox', WEBKIT: browserType.name() === 'webkit', CHROMIUM: browserType.name() === 'chromium', - MAC: os.platform() === 'darwin', - LINUX: os.platform() === 'linux', - WIN: os.platform() === 'win32', + MAC: platform === 'darwin', + LINUX: platform === 'linux', + WIN: platform === 'win32', browserType, defaultBrowserOptions, playwrightPath: PROJECT_ROOT, @@ -193,6 +195,11 @@ const utils = module.exports = { OUTPUT_DIR, }; }, + + setPlatform(p) { + // To support isplaywrightready. + platform = p; + }, }; function valueFromEnv(name, defaultValue) {