mirror of
https://github.com/microsoft/playwright.git
synced 2024-12-01 08:34:02 +03:00
chore(jest): run tests with jest (#2754)
Experimentally run `npx jest` to run our tests with jest.
This commit is contained in:
parent
6a1bd3ae6e
commit
040c6a6a41
5
jest.config.json
Normal file
5
jest.config.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"runner": "./jest-runner.js",
|
||||
"rootDir": "./test/",
|
||||
"testMatch": ["**/?(*.)spec.[jt]s"]
|
||||
}
|
4352
package-lock.json
generated
4352
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -37,7 +37,8 @@
|
||||
"watch": "node utils/runWebpack.js --mode='development' --watch --silent | tsc -w -p .",
|
||||
"test-types": "npm run generate-types && npx -p typescript@3.7.5 tsc -p utils/generate_types/test/tsconfig.json && npm run typecheck-tests",
|
||||
"generate-types": "node utils/generate_types/",
|
||||
"typecheck-tests": "tsc -p ./test/"
|
||||
"typecheck-tests": "tsc -p ./test/",
|
||||
"jest": "jest"
|
||||
},
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
@ -60,6 +61,7 @@
|
||||
"@babel/core": "^7.10.3",
|
||||
"@babel/preset-env": "^7.10.3",
|
||||
"@babel/preset-typescript": "^7.10.1",
|
||||
"@playwright/jest-wrapper": "0.0.8",
|
||||
"@types/debug": "0.0.31",
|
||||
"@types/extract-zip": "^1.6.2",
|
||||
"@types/mime": "^2.0.1",
|
||||
@ -79,6 +81,7 @@
|
||||
"eslint-plugin-notice": "^0.9.10",
|
||||
"esprima": "^4.0.0",
|
||||
"formidable": "^1.2.1",
|
||||
"jest": "^26.1.0",
|
||||
"ncp": "^2.0.0",
|
||||
"node-stream-zip": "^1.8.2",
|
||||
"pirates": "^4.0.1",
|
||||
|
187
test/jest-runner.js
Normal file
187
test/jest-runner.js
Normal file
@ -0,0 +1,187 @@
|
||||
/**
|
||||
* 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 path = require('path');
|
||||
const wrapper = require('@playwright/jest-wrapper');
|
||||
const DefaultTestRunner = require('../utils/testrunner');
|
||||
const {TestRunner, TestRun} = require('../utils/testrunner/TestRunner');
|
||||
const { PlaywrightEnvironment, BrowserTypeEnvironment, BrowserEnvironment, PageEnvironment} = require('./environments.js');
|
||||
const fs = require('fs');
|
||||
const pirates = require('pirates');
|
||||
const babel = require('@babel/core');
|
||||
const testRunnerInfo = makeTestRunnerInfo();
|
||||
|
||||
|
||||
module.exports = wrapper.createJestRunner(async ({path: filePath}) => {
|
||||
const config = require('./test.config');
|
||||
const spec = config.specs.find(spec => {
|
||||
return spec.files.some(f => path.join(__dirname, f) === filePath);
|
||||
});
|
||||
if (!spec) {
|
||||
console.error('cannot find spec for', filePath);
|
||||
return [];
|
||||
}
|
||||
const {testRunner, browserInfo} = testRunnerInfo;
|
||||
testRunner.collector()._tests = [];
|
||||
for (const [key, value] of Object.entries(testRunner.api()))
|
||||
global[key] = value;
|
||||
for (const {browserEnvironment, browserTypeEnvironment, browserName, browserType, pageEnvironment, launchOptions} of browserInfo) {
|
||||
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.browserType = browserType;
|
||||
global.HEADLESS = !!launchOptions.headless;
|
||||
|
||||
testRunner.collector().useEnvironment(browserTypeEnvironment);
|
||||
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);
|
||||
}
|
||||
}
|
||||
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(filePath);
|
||||
revert();
|
||||
delete require.cache[require.resolve(filePath)];
|
||||
});
|
||||
|
||||
delete global.HEADLESS;
|
||||
delete global.browserType;
|
||||
});
|
||||
}
|
||||
for (const key of Object.keys(testRunner.api())) {
|
||||
// expect is used when running tests, while the rest of api is not.
|
||||
if (key !== 'expect')
|
||||
delete global[key];
|
||||
}
|
||||
|
||||
return testRunner._filter.filter(testRunner.collector().tests()).map(test => {
|
||||
return {
|
||||
titles: test.titles(),
|
||||
test
|
||||
};
|
||||
});
|
||||
}, async (tests, options, onStart, onResult) => {
|
||||
const parallel = Math.min(options.workers, 30);
|
||||
require('events').defaultMaxListeners *= parallel;
|
||||
const runner = new TestRunner();
|
||||
const runs = tests.map(test => {
|
||||
const run = new TestRun(test.test);
|
||||
run.__test__ = test;
|
||||
return run;
|
||||
});
|
||||
await runner.run(runs, {
|
||||
parallel,
|
||||
breakOnFailure: false,
|
||||
hookTimeout: options.timeout,
|
||||
totalTimeout: options.timeout,
|
||||
// onStarted = async (testRuns) => {},
|
||||
// onFinished = async (result) => {},
|
||||
onTestRunStarted: async testRun => {
|
||||
onStart(testRun.__test__);
|
||||
},
|
||||
onTestRunFinished: async testRun => {
|
||||
let status = 'skip';
|
||||
if (testRun.isFailure())
|
||||
status = 'fail';
|
||||
else if (testRun.result() === 'ok')
|
||||
status = 'pass';
|
||||
else if (testRun.test().expectation() === 'fail')
|
||||
status = 'todo';
|
||||
onResult(testRun.__test__, {
|
||||
status,
|
||||
error: testRun.error(),
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function makeTestRunnerInfo() {
|
||||
const parallel = 1;
|
||||
const timeout = process.env.CI ? 30 * 1000 : 10 * 1000;
|
||||
const config = require('./test.config');
|
||||
const testRunner = new DefaultTestRunner({
|
||||
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,
|
||||
});
|
||||
if (config.setupTestRunner)
|
||||
config.setupTestRunner(testRunner);
|
||||
|
||||
// TODO: this should be a preinstalled playwright by default.
|
||||
const playwrightPath = config.playwrightPath;
|
||||
const playwright = require('..');
|
||||
const { setUnderTest } = require(require('path').join(playwrightPath, 'lib/helper.js'));
|
||||
setUnderTest();
|
||||
|
||||
const playwrightEnvironment = new PlaywrightEnvironment(playwright);
|
||||
|
||||
testRunner.collector().useEnvironment(playwrightEnvironment);
|
||||
for (const e of config.globalEnvironments || [])
|
||||
testRunner.collector().useEnvironment(e);
|
||||
|
||||
global.playwright = playwright;
|
||||
const browserNames = ['chromium'];
|
||||
const browserInfo = browserNames.map(browserName => {
|
||||
const browserType = playwright[browserName];
|
||||
|
||||
const browserTypeEnvironment = new BrowserTypeEnvironment(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 BrowserEnvironment(launchOptions, config.dumpLogOnFailure);
|
||||
|
||||
const pageEnvironment = new PageEnvironment();
|
||||
return {browserName, browserType, browserEnvironment, browserTypeEnvironment, pageEnvironment, launchOptions};
|
||||
});
|
||||
return {testRunner, browserInfo};
|
||||
}
|
1
test/types.d.ts
vendored
1
test/types.d.ts
vendored
@ -117,7 +117,6 @@ declare const xit: ItFunction<PageState>;
|
||||
|
||||
declare const browserType: import('../index').BrowserType<import('../index').Browser>;
|
||||
|
||||
|
||||
// global variables in assets
|
||||
|
||||
// keyboard.html
|
||||
|
@ -36,6 +36,12 @@ class Test {
|
||||
this.Expectations = { ...TestExpectation };
|
||||
}
|
||||
|
||||
titles() {
|
||||
if (!this._name)
|
||||
return this._suite.titles();
|
||||
return [...this._suite.titles(), this._name];
|
||||
}
|
||||
|
||||
suite() {
|
||||
return this._suite;
|
||||
}
|
||||
@ -128,6 +134,12 @@ class Suite {
|
||||
globalSetup(callback) { this._addHook('globalSetup', callback); }
|
||||
globalTeardown(callback) { this._addHook('globalTeardown', callback); }
|
||||
|
||||
titles() {
|
||||
if (!this._parentSuite)
|
||||
return this._name ? [this._name] : [];
|
||||
return this._name ? [...this._parentSuite.titles(), this._name] : this._parentSuite.titles();
|
||||
}
|
||||
|
||||
parentSuite() { return this._parentSuite; }
|
||||
|
||||
name() { return this._name; }
|
||||
|
Loading…
Reference in New Issue
Block a user