From 962ddc09c437109c7186b8b365f96453b242a668 Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Wed, 12 Aug 2020 13:47:44 -0700 Subject: [PATCH] test: consolidate runner files (#3415) --- .github/workflows/tests.yml | 10 +- jest.config.js | 28 ---- package.json | 8 +- test/base.fixture.ts | 4 +- test/jest/dot.js | 69 --------- test/jest/index.js | 1 - test/jest/playwrightEnvironment.js | 178 ------------------------ test/jest/reporter.js | 44 ------ test/jest/setup.js | 28 ---- test/jest/teardown.js | 18 --- test/nojest/nojest.js | 157 --------------------- test/{jest => runner}/checkCoverage.js | 2 +- test/{harness => runner}/coverage.js | 0 test/{mocha => runner}/dotReporter.js | 5 +- test/{harness => runner}/fixturePool.js | 0 test/{harness => runner}/fixtures.js | 0 test/{mocha => runner}/fixturesUI.js | 4 +- test/{mocha => runner}/index.js | 11 +- test/{mocha => runner}/runner.js | 3 +- test/{harness => runner}/testOptions.js | 0 test/{harness => runner}/utils.js | 0 test/{mocha => runner}/worker.js | 2 +- 22 files changed, 30 insertions(+), 542 deletions(-) delete mode 100644 jest.config.js delete mode 100644 test/jest/dot.js delete mode 100644 test/jest/index.js delete mode 100644 test/jest/playwrightEnvironment.js delete mode 100644 test/jest/reporter.js delete mode 100644 test/jest/setup.js delete mode 100644 test/jest/teardown.js delete mode 100644 test/nojest/nojest.js rename test/{jest => runner}/checkCoverage.js (97%) rename test/{harness => runner}/coverage.js (100%) rename test/{mocha => runner}/dotReporter.js (93%) rename test/{harness => runner}/fixturePool.js (100%) rename test/{harness => runner}/fixtures.js (100%) rename test/{mocha => runner}/fixturesUI.js (97%) rename test/{mocha => runner}/index.js (87%) rename test/{mocha => runner}/runner.js (98%) rename test/{harness => runner}/testOptions.js (100%) rename test/{harness => runner}/utils.js (100%) rename test/{mocha => runner}/worker.js (98%) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7e8a9ab12b..c804a75bde 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -38,7 +38,7 @@ jobs: # XVFB-RUN merges both STDOUT and STDERR, whereas we need only STDERR # Wrap `npm run` in a subshell to redirect STDERR to file. # Enable core dumps in the subshell. - - run: xvfb-run --auto-servernum -- bash -c "ulimit -c unlimited && node test/mocha/index.js --max-workers=1 --timeout=30000 && npm run coverage" + - run: xvfb-run --auto-servernum -- bash -c "ulimit -c unlimited && node test/runner --max-workers=1 --timeout=30000 && npm run coverage" env: BROWSER: ${{ matrix.browser }} DEBUG: "pw:*,-pw:wrapped*,-pw:test*" @@ -69,7 +69,7 @@ jobs: - uses: microsoft/playwright-github-action@v1 - run: npm ci - run: npm run build - - run: node test/mocha/index.js --max-workers=1 --timeout=30000 + - run: node test/runner --max-workers=1 --timeout=30000 env: BROWSER: ${{ matrix.browser }} DEBUG: "pw:*,-pw:wrapped*,-pw:test*" @@ -103,7 +103,7 @@ jobs: - uses: microsoft/playwright-github-action@v1 - run: npm ci - run: npm run build - - run: node test/mocha/index.js --max-workers=1 --timeout=30000 + - run: node test/runner --max-workers=1 --timeout=30000 shell: bash env: BROWSER: ${{ matrix.browser }} @@ -160,7 +160,7 @@ jobs: # XVFB-RUN merges both STDOUT and STDERR, whereas we need only STDERR # Wrap `npm run` in a subshell to redirect STDERR to file. # Enable core dumps in the subshell. - - run: xvfb-run --auto-servernum -- bash -c "ulimit -c unlimited && node test/mocha/index.js --max-workers=1 --timeout=30000" + - run: xvfb-run --auto-servernum -- bash -c "ulimit -c unlimited && node test/runner --max-workers=1 --timeout=30000" if: ${{ always() }} env: BROWSER: ${{ matrix.browser }} @@ -194,7 +194,7 @@ jobs: # XVFB-RUN merges both STDOUT and STDERR, whereas we need only STDERR # Wrap `npm run` in a subshell to redirect STDERR to file. # Enable core dumps in the subshell. - - run: xvfb-run --auto-servernum -- bash -c "ulimit -c unlimited && node test/mocha/index.js --max-workers=1 --timeout=30000" + - run: xvfb-run --auto-servernum -- bash -c "ulimit -c unlimited && node test/runner --max-workers=1 --timeout=30000" env: BROWSER: ${{ matrix.browser }} DEBUG: "pw:*,-pw:wrapped*,-pw:test*" diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index ff233307aa..0000000000 --- a/jest.config.js +++ /dev/null @@ -1,28 +0,0 @@ -module.exports = /** @type {import('@jest/types').Config.InitialOptions} */ ({ - // all of our tests have a browser and a node process, so the default max workers is too many. - maxWorkers: Math.ceil(require('os').cpus().length / 2), - rootDir: './test', - testEnvironment: './jest', - testMatch: ['**/?(*.)(jest|spec).[jt]s'], - testRunner: 'jest-circus/runner', - testTimeout: 10000, - globalSetup: './jest/setup.js', - globalTeardown: './jest/teardown.js', - transform: { - '^.+\\.ts$': ['babel-jest', { - presets: [ - ['@babel/preset-env', { - targets: { - node: 'current' - } - }], - ['@babel/preset-typescript'] - ], - }], - }, - reporters: [ - 'default', - './jest/reporter' - ], - slowTestThreshold: 30 -}); diff --git a/package.json b/package.json index d50dacf81d..4135bdb4d2 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,9 @@ "node": ">=10.15.0" }, "scripts": { - "ctest": "cross-env BROWSER=chromium node test/mocha/index.js", - "ftest": "cross-env BROWSER=firefox node test/mocha/index.js", - "wtest": "cross-env BROWSER=webkit node test/mocha/index.js", + "ctest": "cross-env BROWSER=chromium node test/runner", + "ftest": "cross-env BROWSER=firefox node test/runner", + "wtest": "cross-env BROWSER=webkit node test/runner", "test": "npm run ctest && npm run ftest && npm run wtest", "eslint": "[ \"$CI\" = true ] && eslint --quiet -f codeframe --ext js,ts ./src || eslint --ext js,ts ./src", "tsc": "tsc -p .", @@ -30,7 +30,7 @@ "generate-channels": "node utils/generate_channels.js", "typecheck-tests": "tsc -p ./test/", "roll-browser": "node utils/roll_browser.js", - "coverage": "node test/jest/checkCoverage.js", + "coverage": "node test/runner/checkCoverage.js", "check-deps": "node utils/check_deps.js" }, "author": { diff --git a/test/base.fixture.ts b/test/base.fixture.ts index 4a99c29529..9c22e1d384 100644 --- a/test/base.fixture.ts +++ b/test/base.fixture.ts @@ -22,8 +22,8 @@ import { TestServer } from '../utils/testserver/'; import { Connection } from '../lib/rpc/client/connection'; import { Transport } from '../lib/rpc/transport'; import { setUnderTest } from '../lib/helper'; -import { installCoverageHooks } from './harness/coverage'; -import { valueFromEnv } from './harness/utils'; +import { installCoverageHooks } from './runner/coverage'; +import { valueFromEnv } from './runner/utils'; setUnderTest(); // Note: we must call setUnderTest before requiring Playwright diff --git a/test/jest/dot.js b/test/jest/dot.js deleted file mode 100644 index 46fcc723a1..0000000000 --- a/test/jest/dot.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright Microsoft Corporation. All rights reserved. - * - * 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. - */ - -const colors = require('colors/safe'); -const failures = []; - -module.exports = function Reporter() { - this.onRunStart = (results, options) => { - process.stdout.write('\n'); - } - - this.onRunComplete = (test, runResults) => { - process.stdout.write('\n'); - - const ranTests = runResults.numFailedTests + runResults.numPassedTests; - const summary = [`ok - ${colors.green(runResults.numPassedTests)}`]; - if (runResults.numFailedTests) - summary.push(`failed - ${colors.red(runResults.numFailedTests)}`); - if (ranTests < runResults.numTotalTests) - summary.push(`skipped - ${colors.yellow(runResults.numTotalTests - ranTests)}`); - const summaryText = `Ran ${ranTests} of ${runResults.numTotalTests} (${summary.join(', ')})`; - process.stdout.write('\n'); - process.stdout.write(summaryText); - process.stdout.write('\n'); - - for (let i = 0; i < failures.length; ++i) { - const [test, testCaseResult] = failures[i]; - const path = test.path.replace(/.*test/, 'test'); - const name = colors.yellow(path) + ' — ' + colors.bold(colors.yellow(testCaseResult.fullName)); - process.stderr.write(`\n${i + 1}) ${colors.red('[FAIL]')} ${name}\n\n`); - process.stderr.write(testCaseResult.failureMessages + '\n'); - } - - }; - - this.onTestCaseResult = (test, testCaseResult) => { - const status = testCaseResult.status; - if (status === 'passed') - process.stdout.write(colors.green('\u00B7')); - if (status === 'failed') - process.stdout.write(colors.red('F')); - if (testCaseResult.status === 'failed') - failures.push([test, testCaseResult]); - } -} - -process.on('SIGINT', async () => { - for (let i = 0; i < failures.length; ++i) { - const [test, testCaseResult] = failures[i]; - const path = test.path.replace(/.*test/, 'test'); - const name = colors.yellow(path) + ' — ' + colors.bold(colors.yellow(testCaseResult.fullName)); - process.stderr.write(`\n${i + 1}) ${colors.red('[FAIL]')} ${name}\n\n`); - process.stderr.write(testCaseResult.failureMessages + '\n'); - } - process.exit(130); -}); diff --git a/test/jest/index.js b/test/jest/index.js deleted file mode 100644 index 4fd9211de1..0000000000 --- a/test/jest/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./playwrightEnvironment').default diff --git a/test/jest/playwrightEnvironment.js b/test/jest/playwrightEnvironment.js deleted file mode 100644 index 1a6ae1b41c..0000000000 --- a/test/jest/playwrightEnvironment.js +++ /dev/null @@ -1,178 +0,0 @@ -/** - * Copyright Microsoft Corporation. All rights reserved. - * - * 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. - */ - -const { FixturePool, registerFixture, registerWorkerFixture } = require('../harness/fixturePool'); -const path = require('path'); -const fs = require('fs'); -const debug = require('debug'); -const util = require('util'); -const GoldenUtils = require('../../utils/testrunner/GoldenUtils'); -const reportOnly = !!process.env.REPORT_ONLY_PLATFORM; -const { ModuleMocker } = require('jest-mock'); - -global.testOptions = require('../harness/testOptions'); -global.registerFixture = registerFixture; -global.registerWorkerFixture = registerWorkerFixture; -global.testPath = null; - -const browserName = process.env.BROWSER || 'chromium'; - -const goldenPath = path.join(__dirname, '..', 'golden-' + browserName); -const outputPath = path.join(__dirname, '..', 'output-' + browserName); - -let currentFixturePool = null; - -process.on('SIGINT', async () => { - if (currentFixturePool) { - await currentFixturePool.teardownScope('test'); - await currentFixturePool.teardownScope('worker'); - } - process.exit(130); -}); - -class PlaywrightEnvironment { - constructor(config, context) { - this.moduleMocker = new ModuleMocker(global); - this.fixturePool = new FixturePool(); - this.global = global; - this.global.testOptions = testOptions; - this.global.testPath = context.testPath; - } - - async setup() { - currentFixturePool = this.fixturePool; - } - - async teardown() { - currentFixturePool = null; - await this.fixturePool.teardownScope('worker'); - } - - runScript(script) { - return script.runInThisContext(); - } - - async handleTestEvent(event, state) { - if (event.name === 'setup') { - this.fixturePool.patchToEnableFixtures(this.global, 'beforeEach'); - this.fixturePool.patchToEnableFixtures(this.global, 'afterEach'); - - const describeSkip = this.global.describe.skip; - this.global.describe.skip = (...args) => { - if (args.length === 1) - return args[0] ? describeSkip : this.global.describe; - return describeSkip(...args); - }; - - function addSlow(f) { - f.slow = () => { - return (...args) => f(...args, 90000); - }; - return f; - } - - const itSkip = this.global.it.skip; - addSlow(itSkip); - addSlow(this.global.it); - this.global.it.skip = (...args) => { - if (args.length === 1) - return args[0] ? itSkip : this.global.it; - return itSkip(...args); - }; - if (reportOnly) { - this.global.it.fail = condition => { - return addSlow((...inner) => { - inner[1].__fail = !!condition; - return this.global.it(...inner); - }); - }; - } else { - this.global.it.fail = this.global.it.skip; - } - - const testOptions = this.global.testOptions; - function toBeGolden(received, goldenName) { - const {snapshotState} = this; - const updateSnapshot = snapshotState._updateSnapshot; - const expectedPath = path.join(goldenPath, goldenName); - const fileExists = fs.existsSync(expectedPath); - if (updateSnapshot === 'all' || (updateSnapshot === 'new' && !fileExists)) { - fs.writeFileSync(expectedPath, received); - if (fileExists) - snapshotState.updated++; - else - snapshotState.added++; - return { - pass: true - } - }; - - const {pass, message} = GoldenUtils.compare(received, { - goldenPath, - outputPath, - goldenName - }); - if (pass) - snapshotState.matched++; - else - snapshotState.unmatched++; - return {pass, message: () => message}; - }; - this.global.expect.extend({ toBeGolden }); - } - - if (event.name === 'test_start') { - const fn = event.test.fn; - this._lastTest = event.test; - event.test.fn = async () => { - if (reportOnly) { - if (fn.__fail) - throw new Error('fail'); - return; - } - debug('pw:test')(`start "${testOrSuiteName(event.test)}"`); - try { - await this.fixturePool.resolveParametersAndRun(fn); - } catch(e) { - debug('pw:test')(`error "${testOrSuiteName(event.test)}"`, util.inspect(e)); - throw e; - } finally { - await this.fixturePool.teardownScope('test'); - debug('pw:test')(`finish "${testOrSuiteName(event.test)}"`); - } - }; - } - - if (event.name === 'error') - debug('pw:test')(`error "${testOrSuiteName(this._lastTest)}"`, util.inspect(event.error)); - - if (event.name === 'test_fn_failure') { - await this.fixturePool.teardownScope('worker'); - } - } -} - -function testOrSuiteName(o) { - if (o.name === 'ROOT_DESCRIBE_BLOCK') - return ''; - let name = o.parent ? testOrSuiteName(o.parent) : ''; - if (name && o.name) - name += ' '; - return name + o.name; -} - -exports.getPlaywrightEnv = () => PlaywrightEnvironment; -exports.default = exports.getPlaywrightEnv(); diff --git a/test/jest/reporter.js b/test/jest/reporter.js deleted file mode 100644 index 169c7bd59d..0000000000 --- a/test/jest/reporter.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Copyright Microsoft Corporation. All rights reserved. - * - * 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. - */ - -const colors = require('colors/safe'); -const fs = require('fs'); -const os = require('os'); - -const failures = []; - -module.exports = function Reporter() { - this.onRunComplete = (test, runResults) => { - runResults.platform = process.env.REPORT_ONLY_PLATFORM || os.platform(); - runResults.browserName = process.env.BROWSER || 'chromium'; - fs.writeFileSync('jest-report.json', JSON.stringify(runResults, undefined, 2)); - }; - this.onTestCaseResult = (test, testCaseResult) => { - if (testCaseResult.status === 'failed') - failures.push([test, testCaseResult]); - } -} - -process.on('SIGINT', async () => { - for (let i = 0; i < failures.length; ++i) { - const [test, testCaseResult] = failures[i]; - const path = test.path.replace(/.*test/, 'test'); - const name = colors.yellow(path) + ' — ' + colors.bold(colors.yellow(testCaseResult.fullName)); - process.stderr.write(`\n${i + 1}) ${colors.red('[FAIL]')} ${name}\n\n`); - process.stderr.write(testCaseResult.failureMessages + '\n'); - } - process.exit(130); -}); diff --git a/test/jest/setup.js b/test/jest/setup.js deleted file mode 100644 index bcb4f4bb20..0000000000 --- a/test/jest/setup.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * Copyright Microsoft Corporation. All rights reserved. - * - * 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. - */ - -const fs = require('fs'); -const path = require('path'); -const rm = require('rimraf').sync; - -const browserName = process.env.BROWSER || 'chromium'; - -module.exports = async function setup() { - const OUTPUT_DIR = path.join(__dirname, '..', 'output-' + browserName); - if (fs.existsSync(OUTPUT_DIR)) - rm(OUTPUT_DIR); - fs.mkdirSync(OUTPUT_DIR, { recursive: true }); -}; diff --git a/test/jest/teardown.js b/test/jest/teardown.js deleted file mode 100644 index 747281ceb3..0000000000 --- a/test/jest/teardown.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Copyright Microsoft Corporation. All rights reserved. - * - * 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. - */ - -module.exports = async function teardown() { -}; diff --git a/test/nojest/nojest.js b/test/nojest/nojest.js deleted file mode 100644 index 0c724eb463..0000000000 --- a/test/nojest/nojest.js +++ /dev/null @@ -1,157 +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. - */ - -const fs = require('fs'); -const path = require('path'); -const os = require('os'); -const pirates = require('pirates'); -const babel = require('@babel/core'); -const TestRunner = require('../../utils/testrunner'); -const { FixturePool, registerFixture, registerWorkerFixture } = require('../harness/fixturePool'); - -Error.stackTraceLimit = 15; -global.testOptions = require('../harness/testOptions'); -global.registerFixture = registerFixture; -global.registerWorkerFixture = registerWorkerFixture; -process.env.JEST_WORKER_ID = 1; -const browserName = process.env.BROWSER || 'chromium'; -const goldenPath = path.join(__dirname, '..', 'golden-' + browserName); -const outputPath = path.join(__dirname, '..', 'output-' + browserName); - -function getCLIArgument(argName) { - for (let i = 0; i < process.argv.length; ++i) { - // Support `./test.js --foo bar - if (process.argv[i] === argName) - return process.argv[i + 1]; - // Support `./test.js --foo=bar - if (argName.startsWith('--') && process.argv[i].startsWith(argName + '=')) - return process.argv[i].substring((argName + '=').length); - // Support `./test.js -j4 - if (!argName.startsWith('--') && argName.startsWith('-') && process.argv[i].startsWith(argName)) - return process.argv[i].substring(argName.length); - } - return null; -} - -function collect(browserNames) { - let parallel = 1; - if (process.env.PW_PARALLEL_TESTS) - parallel = parseInt(process.env.PW_PARALLEL_TESTS.trim(), 10); - if (getCLIArgument('-j')) - parallel = parseInt(getCLIArgument('-j'), 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); - if (require('inspector').url()) { - console.log('Detected inspector - disabling timeout to be debugger-friendly'); - timeout = 0; - } - - const testRunner = new TestRunner({ - timeout, - totalTimeout: process.env.CI ? 30 * 60 * 1000 * browserNames.length : 0, // 30 minutes per browser on CI - 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, - lineBreak: parseInt(getCLIArgument('--line-break') || 0, 10), - outputPath, - goldenPath - }); - - for (const [key, value] of Object.entries(testRunner.api())) - global[key] = value; - - const collector = testRunner.collector(); - collector.addTestModifier('skip', (t, condition) => condition && t.setSkipped(true)); - collector.addSuiteModifier('skip', (s, condition) => condition && s.setSkipped(true)); - collector.addTestModifier('fail', (t, condition) => condition && t.setExpectation(t.Expectations.Fail)); - collector.addSuiteModifier('fail', (s, condition) => condition && s.setExpectation(s.Expectations.Fail)); - collector.addTestModifier('slow', t => t.setTimeout(t.timeout() * 3)); - collector.addTestAttribute('debug', t => TraceTestEnvironment.enableForTest(t)); - testRunner.api().fdescribe = testRunner.api().describe.only; - testRunner.api().xdescribe = testRunner.api().describe.skip(true); - testRunner.api().fit = testRunner.api().it.only; - testRunner.api().xit = testRunner.api().it.skip(true); - testRunner.api().dit = testRunner.api().it.only.debug; - - const fixturePool = new FixturePool(); - fixturePool.patchToEnableFixtures(global, 'beforeEach'); - fixturePool.patchToEnableFixtures(global, 'afterEach'); - collector.addTestCallbackWrapper(callback => fixturePool.wrapTestCallback(callback)); - - describe('', () => { - for (const name of fs.readdirSync('test')) { - const file = path.join(process.cwd(), 'test', name); - if (!name.includes('.spec.')) - continue; - const revert = pirates.addHook((code, filename) => { - const result = babel.transformFileSync(filename, { - presets: [ - ['@babel/preset-env', {targets: {node: 'current'}}], - '@babel/preset-typescript'] - }); - return result.code; - }, { - exts: ['.ts'] - }); - require(file); - revert(); - delete require.cache[require.resolve(file)]; - } - }); - - 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]; - } - - return testRunner; -} - -module.exports = collect; - -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; - }); - const testRunner = collect(browserNames); - - const testNameFilter = getCLIArgument('--filter'); - if (testNameFilter && !testRunner.focusMatchingNameTests(new RegExp(testNameFilter, 'i')).length) { - console.log('ERROR: no tests matched given `--filter` regex.'); - process.exit(1); - } - - const fileNameFilter = getCLIArgument('--file'); - if (fileNameFilter && !testRunner.focusMatchingFileName(new RegExp(fileNameFilter, 'i')).length) { - console.log('ERROR: no files matched given `--file` regex.'); - process.exit(1); - } - - const repeat = parseInt(getCLIArgument('--repeat'), 10); - if (!isNaN(repeat)) - testRunner.repeatAll(repeat); - - testRunner.run().then(() => { delete global.expect; }); -} diff --git a/test/jest/checkCoverage.js b/test/runner/checkCoverage.js similarity index 97% rename from test/jest/checkCoverage.js rename to test/runner/checkCoverage.js index 19562a2fdf..6cda377299 100644 --- a/test/jest/checkCoverage.js +++ b/test/runner/checkCoverage.js @@ -15,7 +15,7 @@ */ const path = require('path'); const fs = require('fs'); -const {installCoverageHooks} = require('../harness/coverage'); +const {installCoverageHooks} = require('./coverage'); const browserName = process.env.BROWSER || 'chromium'; diff --git a/test/harness/coverage.js b/test/runner/coverage.js similarity index 100% rename from test/harness/coverage.js rename to test/runner/coverage.js diff --git a/test/mocha/dotReporter.js b/test/runner/dotReporter.js similarity index 93% rename from test/mocha/dotReporter.js rename to test/runner/dotReporter.js index eff3829415..584152a079 100644 --- a/test/mocha/dotReporter.js +++ b/test/runner/dotReporter.js @@ -22,8 +22,9 @@ class DotReporter extends Base { constructor(runner, options) { super(runner, options); - runner.on(constants.EVENT_RUN_BEGIN, () => { - process.stdout.write('\n'); + process.on('SIGINT', async () => { + Base.list(this.failures); + process.exit(130); }); runner.on(constants.EVENT_TEST_PENDING, test => { diff --git a/test/harness/fixturePool.js b/test/runner/fixturePool.js similarity index 100% rename from test/harness/fixturePool.js rename to test/runner/fixturePool.js diff --git a/test/harness/fixtures.js b/test/runner/fixtures.js similarity index 100% rename from test/harness/fixtures.js rename to test/runner/fixtures.js diff --git a/test/mocha/fixturesUI.js b/test/runner/fixturesUI.js similarity index 97% rename from test/mocha/fixturesUI.js rename to test/runner/fixturesUI.js index bba82cf9fc..82d0dac40e 100644 --- a/test/mocha/fixturesUI.js +++ b/test/runner/fixturesUI.js @@ -14,14 +14,14 @@ * limitations under the License. */ -const { FixturePool, registerFixture, registerWorkerFixture } = require('../harness/fixturePool'); +const { FixturePool, registerFixture, registerWorkerFixture } = require('./fixturePool'); const { Test, Suite } = require('mocha'); const pirates = require('pirates'); const babel = require('@babel/core'); const commonSuite = require('mocha/lib/interfaces/common'); Error.stackTraceLimit = 15; -global.testOptions = require('../harness/testOptions'); +global.testOptions = require('./testOptions'); global.registerFixture = registerFixture; global.registerWorkerFixture = registerWorkerFixture; process.env.JEST_WORKER_ID = 1; diff --git a/test/mocha/index.js b/test/runner/index.js similarity index 87% rename from test/mocha/index.js rename to test/runner/index.js index 99abda1615..cea63f3e23 100644 --- a/test/mocha/index.js +++ b/test/runner/index.js @@ -19,7 +19,9 @@ const path = require('path'); const program = require('commander'); const { Runner } = require('./runner'); const Mocha = require('mocha'); +const constants = require('mocha/lib/runner').constants; const { fixturesUI } = require('./fixturesUI'); +const colors = require('colors/safe'); class NullReporter {} @@ -35,6 +37,7 @@ program collectFiles(path.join(process.cwd(), 'test'), command.args, files); const rootSuite = new Mocha.Suite('', new Mocha.Context(), true); + console.log(`Transpiling ${files.length} test files`); // Build the test model, suite per file. for (const file of files) { const mocha = new Mocha({ @@ -47,8 +50,14 @@ program mocha.suite.title = path.basename(file); mocha.suite.root = false; rootSuite.suites.push(mocha.suite); - await new Promise(f => mocha.run(f)); + await new Promise(f => { + const runner = mocha.run(f); + runner.on(constants.EVENT_RUN_BEGIN, () => { + process.stdout.write(colors.yellow('\u00B7')); + }); + }); } + console.log(); const runner = new Runner(rootSuite, { maxWorkers: command.maxWorkers, diff --git a/test/mocha/runner.js b/test/runner/runner.js similarity index 98% rename from test/mocha/runner.js rename to test/runner/runner.js index 2ea2023822..5c33051812 100644 --- a/test/mocha/runner.js +++ b/test/runner/runner.js @@ -51,7 +51,7 @@ class Runner extends EventEmitter { if (suite.hasOnly()) suite.filterOnly(); - console.log(`Running ${suite.total()} tests`); + console.log(`Running ${suite.total()} tests using ${this._maxWorkers} workers`); this._traverse(suite); } @@ -128,6 +128,7 @@ class Runner extends EventEmitter { const worker = child_process.fork(path.join(__dirname, 'worker.js'), { detached: false, env: process.env, + stdio: 'ignore' }); worker.on('exit', () => { this._workers.delete(worker); diff --git a/test/harness/testOptions.js b/test/runner/testOptions.js similarity index 100% rename from test/harness/testOptions.js rename to test/runner/testOptions.js diff --git a/test/harness/utils.js b/test/runner/utils.js similarity index 100% rename from test/harness/utils.js rename to test/runner/utils.js diff --git a/test/mocha/worker.js b/test/runner/worker.js similarity index 98% rename from test/mocha/worker.js rename to test/runner/worker.js index 470ef21598..c1868a7935 100644 --- a/test/mocha/worker.js +++ b/test/runner/worker.js @@ -24,7 +24,7 @@ const browserName = process.env.BROWSER || 'chromium'; const goldenPath = path.join(__dirname, '..', 'golden-' + browserName); const outputPath = path.join(__dirname, '..', 'output-' + browserName); global.expect = require('expect'); -global.testOptions = require('../harness/testOptions'); +global.testOptions = require('./testOptions'); const constants = Mocha.Runner.constants;