test: consolidate runner files (#3415)
This commit is contained in:
parent
7e07634cc6
commit
962ddc09c4
10
.github/workflows/tests.yml
vendored
10
.github/workflows/tests.yml
vendored
|
|
@ -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*"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
});
|
||||
|
|
@ -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": {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
|
@ -1 +0,0 @@
|
|||
module.exports = require('./playwrightEnvironment').default
|
||||
|
|
@ -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();
|
||||
|
|
@ -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);
|
||||
});
|
||||
|
|
@ -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 });
|
||||
};
|
||||
|
|
@ -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() {
|
||||
};
|
||||
|
|
@ -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; });
|
||||
}
|
||||
|
|
@ -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';
|
||||
|
||||
|
|
@ -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 => {
|
||||
|
|
@ -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;
|
||||
|
|
@ -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,
|
||||
|
|
@ -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);
|
||||
|
|
@ -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;
|
||||
|
||||
Loading…
Reference in a new issue