chore(testrunner): complete ts migration (#3587)

This commit is contained in:
Pavel Feldman 2020-08-23 11:44:41 -07:00 committed by GitHub
parent 224d3df899
commit 53ac35a613
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 180 additions and 171 deletions

58
package-lock.json generated
View file

@ -1168,6 +1168,47 @@
"defer-to-connect": "^1.0.1"
}
},
"@types/babel__core": {
"version": "7.1.9",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.9.tgz",
"integrity": "sha512-sY2RsIJ5rpER1u3/aQ8OFSI7qGIy8o1NEEbgb2UaJcvOtXOMpd39ko723NBpjQFg9SIX7TXtjejZVGeIMLhoOw==",
"dev": true,
"requires": {
"@babel/parser": "^7.1.0",
"@babel/types": "^7.0.0",
"@types/babel__generator": "*",
"@types/babel__template": "*",
"@types/babel__traverse": "*"
}
},
"@types/babel__generator": {
"version": "7.6.1",
"resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.1.tgz",
"integrity": "sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew==",
"dev": true,
"requires": {
"@babel/types": "^7.0.0"
}
},
"@types/babel__template": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.0.2.tgz",
"integrity": "sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg==",
"dev": true,
"requires": {
"@babel/parser": "^7.1.0",
"@babel/types": "^7.0.0"
}
},
"@types/babel__traverse": {
"version": "7.0.13",
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.13.tgz",
"integrity": "sha512-i+zS7t6/s9cdQvbqKDARrcbrPvtJGlbYsMkazo03nTAK3RX9FNrLllXys22uiTGJapPOTZTQ35nHh4ISph4SLQ==",
"dev": true,
"requires": {
"@babel/types": "^7.3.0"
}
},
"@types/color-name": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
@ -1287,6 +1328,23 @@
"@types/node": "*"
}
},
"@types/source-map-support": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@types/source-map-support/-/source-map-support-0.5.3.tgz",
"integrity": "sha512-fvjMjVH8Rmokw2dWh1dkj90iX5R8FPjeZzjNH+6eFXReh0QnHFf1YBl3B0CF0RohIAA3SDRJsGeeUWKl6d7HqA==",
"dev": true,
"requires": {
"source-map": "^0.6.0"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
}
}
},
"@types/stack-utils": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",

View file

@ -55,6 +55,7 @@
"@babel/core": "^7.10.3",
"@babel/preset-env": "^7.10.3",
"@babel/preset-typescript": "^7.10.1",
"@types/babel__core": "^7.1.9",
"@types/debug": "0.0.31",
"@types/extract-zip": "^1.6.2",
"@types/mime": "^2.0.1",
@ -63,6 +64,7 @@
"@types/progress": "^2.0.3",
"@types/proxy-from-env": "^1.0.0",
"@types/rimraf": "^2.0.2",
"@types/source-map-support": "^0.5.3",
"@types/stack-utils": "^1.0.1",
"@types/ws": "^6.0.1",
"@typescript-eslint/eslint-plugin": "^2.6.1",

View file

@ -1,17 +0,0 @@
/**
* 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.
*/
require('./lib/cli');

View file

@ -14,7 +14,8 @@
* limitations under the License.
*/
import GoldenUtils from './GoldenUtils';
import { compare } from './golden';
import { RunnerConfig } from './runnerConfig';
declare global {
const expect: typeof import('expect');
@ -28,16 +29,16 @@ declare module 'expect/build/types' {
global['expect'] = require('expect');
let relativeTestFile: string;
let testFile: string;
export function initializeImageMatcher(options) {
function toMatchImage(received, name, config) {
const { pass, message } = GoldenUtils.compare(received, name, { ...options, relativeTestFile, config });
export function initializeImageMatcher(config: RunnerConfig) {
function toMatchImage(received: Buffer, name: string, options?: { threshold?: number }) {
const { pass, message } = compare(received, name, config, testFile, options);
return { pass, message: () => message };
};
expect.extend({ toMatchImage });
}
export function setCurrentTestFile(testFile: string) {
relativeTestFile = testFile;
export function setCurrentTestFile(file: string) {
testFile = file;
}

View file

@ -17,32 +17,29 @@
import debug from 'debug';
import { Test } from './test';
declare global {
interface WorkerState {
}
type Scope = 'test' | 'worker';
interface TestState {
}
type FixtureRegistration = {
name: string;
scope: Scope;
fn: Function;
};
interface FixtureParameters {
}
}
const registrations = new Map();
const registrationsByFile = new Map();
export let parameters: FixtureParameters = {} as FixtureParameters;
const registrations = new Map<string, FixtureRegistration>();
const registrationsByFile = new Map<string, FixtureRegistration[]>();
export let parameters: any = {};
export const parameterRegistrations = new Map();
export function setParameters(params: any) {
parameters = Object.assign(parameters, params);
for (const name of Object.keys(params))
registerWorkerFixture(name as keyof WorkerState, async ({}, test) => await test(parameters[name] as never));
registerWorkerFixture(name, async ({}, test) => await test(parameters[name]));
}
class Fixture<Config> {
pool: FixturePool<Config>;
name: string;
scope: string;
scope: Scope;
fn: Function;
deps: string[];
usages: Set<string>;
@ -53,7 +50,7 @@ class Fixture<Config> {
_setup = false;
_teardown = false;
constructor(pool: FixturePool<Config>, name: string, scope: string, fn: any) {
constructor(pool: FixturePool<Config>, name: string, scope: Scope, fn: any) {
this.pool = pool;
this.name = name;
this.scope = scope;
@ -137,7 +134,7 @@ export class FixturePool<Config> {
}
}
async resolveParametersAndRun(fn: (arg0: {}) => any, timeout: number, config: Config, test?: Test) {
async resolveParametersAndRun(fn: Function, timeout: number, config: Config, test?: Test) {
const names = fixtureParameterNames(fn);
for (const name of names)
await this.setupFixture(name, config, test);
@ -148,7 +145,7 @@ export class FixturePool<Config> {
if (!timeout)
return fn(params);
let timer;
let timer: NodeJS.Timer;
let timerPromise = new Promise(f => timer = setTimeout(f, timeout));
return Promise.race([
Promise.resolve(fn(params)).then(() => clearTimeout(timer)),
@ -169,9 +166,9 @@ export class FixturePool<Config> {
}
}
export function fixturesForCallback(callback: any): string[] {
export function fixturesForCallback(callback: Function): string[] {
const names = new Set<string>();
const visit = (callback: any) => {
const visit = (callback: Function) => {
for (const name of fixtureParameterNames(callback)) {
if (name in names)
continue;
@ -189,7 +186,7 @@ export function fixturesForCallback(callback: any): string[] {
return result;
}
function fixtureParameterNames(fn: { toString: () => any; }): string[] {
function fixtureParameterNames(fn: Function): string[] {
const text = fn.toString();
const match = text.match(/async(?:\s+function)?\s*\(\s*{\s*([^}]*)\s*}/);
if (!match || !match[1].trim())
@ -198,7 +195,7 @@ function fixtureParameterNames(fn: { toString: () => any; }): string[] {
return signature.split(',').map((t: string) => t.trim());
}
function innerRegisterFixture(name: string, scope: string, fn: Function, caller: Function) {
function innerRegisterFixture(name: string, scope: Scope, fn: Function, caller: Function) {
const obj = {stack: ''};
Error.captureStackTrace(obj, caller);
const stackFrame = obj.stack.split('\n')[2];
@ -211,20 +208,20 @@ function innerRegisterFixture(name: string, scope: string, fn: Function, caller:
registrationsByFile.get(file).push(registration);
};
export function registerFixture<Config, T extends keyof TestState>(name: T, fn: (params: FixtureParameters & WorkerState & TestState, runTest: (arg: TestState[T]) => Promise<void>, config: Config, test: Test) => Promise<void>) {
export function registerFixture<Config>(name: string, fn: (params: any, runTest: (arg: any) => Promise<void>, config: Config, test: Test) => Promise<void>) {
innerRegisterFixture(name, 'test', fn, registerFixture);
};
export function registerWorkerFixture<Config, T extends keyof (WorkerState & FixtureParameters)>(name: T, fn: (params: FixtureParameters & WorkerState, runTest: (arg: (WorkerState & FixtureParameters)[T]) => Promise<void>, config: Config) => Promise<void>) {
export function registerWorkerFixture<Config>(name: string, fn: (params: any, runTest: (arg: any) => Promise<void>, config: Config) => Promise<void>) {
innerRegisterFixture(name, 'worker', fn, registerWorkerFixture);
};
export function registerParameter<T extends keyof WorkerState>(name: T, fn: () => WorkerState[T][]) {
registerWorkerFixture(name, async ({}: any, test: (arg0: any) => any) => await test(parameters[name]));
export function registerParameter(name: string, fn: () => any) {
registerWorkerFixture(name, async ({}: any, test: Function) => await test(parameters[name]));
parameterRegistrations.set(name, fn);
}
function collectRequires(file: string | number, result: Set<unknown>) {
function collectRequires(file: string, result: Set<string>) {
if (result.has(file))
return;
result.add(file);
@ -236,8 +233,8 @@ function collectRequires(file: string | number, result: Set<unknown>) {
collectRequires(dep, result);
}
export function lookupRegistrations(file: any, scope: any) {
const deps = new Set();
export function lookupRegistrations(file: string, scope: Scope) {
const deps = new Set<string>();
collectRequires(file, deps);
const allDeps = [...deps].reverse();
let result = new Map();
@ -254,7 +251,7 @@ export function lookupRegistrations(file: any, scope: any) {
return result;
}
export function rerunRegistrations(file: any, scope: any) {
export function rerunRegistrations(file: string, scope: Scope) {
// When we are running several tests in the same worker, we should re-run registrations before
// each file. That way we erase potential fixture overrides from the previous test runs.
for (const registration of lookupRegistrations(file, scope).values())

View file

@ -14,15 +14,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const path = require('path');
const fs = require('fs');
const Diff = require('text-diff');
const PNG = require('pngjs').PNG;
const jpeg = require('jpeg-js');
const pixelmatch = require('pixelmatch');
const c = require('colors/safe');
module.exports = {compare};
import c from 'colors/safe';
import fs from 'fs';
import jpeg from 'jpeg-js';
import path from 'path';
import pixelmatch from 'pixelmatch';
import { PNG } from 'pngjs';
import Diff from 'text-diff';
import { RunnerConfig } from './runnerConfig';
const extensionToMimeType = {
'png': 'image/png',
@ -37,14 +36,7 @@ const GoldenComparators = {
'text/plain': compareText
};
/**
* @param {?Object} actualBuffer
* @param {!Buffer} expectedBuffer
* @param {!string} mimeType
* @return {?{diff?: Object, errorMessage?: string}}
*/
function compareImages(actualBuffer, expectedBuffer, mimeType, config = {}) {
function compareImages(actualBuffer: Buffer, expectedBuffer: Buffer, mimeType: string, options = {}): { diff?: object; errorMessage?: string; } | null {
if (!actualBuffer || !(actualBuffer instanceof Buffer))
return { errorMessage: 'Actual result should be Buffer.' };
@ -56,16 +48,11 @@ function compareImages(actualBuffer, expectedBuffer, mimeType, config = {}) {
};
}
const diff = new PNG({width: expected.width, height: expected.height});
const count = pixelmatch(expected.data, actual.data, diff.data, expected.width, expected.height, {threshold: 0.2, ...config});
const count = pixelmatch(expected.data, actual.data, diff.data, expected.width, expected.height, { threshold: 0.2, ...options });
return count > 0 ? { diff: PNG.sync.write(diff) } : null;
}
/**
* @param {?Object} actual
* @param {!Buffer} expectedBuffer
* @return {?{diff?: Object, errorMessage?: string, diffExtension?: string}}
*/
function compareText(actual, expectedBuffer) {
function compareText(actual: Buffer, expectedBuffer: Buffer): { diff?: object; errorMessage?: string; diffExtension?: string; } | null {
if (typeof actual !== 'string')
return { errorMessage: 'Actual result should be string' };
const expected = expectedBuffer.toString('utf-8');
@ -83,19 +70,14 @@ function compareText(actual, expectedBuffer) {
};
}
/**
* @param {?Object} actual
* @param {string} name
* @return {!{pass: boolean, message?: string}}
*/
function compare(actual, name, options) {
const { relativeTestFile, snapshotDir, outputDir, updateSnapshots } = options;
let expectedPath;
export function compare(actual: Buffer, name: string, config: RunnerConfig, testFile: string, options?: { threshold?: number } ): { pass: boolean; message?: string; } {
let expectedPath: string;
const relativeTestFile = path.relative(config.testDir, testFile);
const testAssetsDir = relativeTestFile.replace(/\.spec\.[jt]s/, '');
if (path.isAbsolute(name))
expectedPath = name;
else
expectedPath = path.join(snapshotDir, testAssetsDir, name);
expectedPath = path.join(config.snapshotDir, testAssetsDir, name);
if (!fs.existsSync(expectedPath)) {
fs.mkdirSync(path.dirname(expectedPath), { recursive: true });
fs.writeFileSync(expectedPath, actual);
@ -115,11 +97,11 @@ function compare(actual, name, options) {
};
}
const result = comparator(actual, expected, mimeType, options.config);
const result = comparator(actual, expected, mimeType, options);
if (!result)
return { pass: true };
if (updateSnapshots) {
if (config.updateSnapshots) {
fs.mkdirSync(path.dirname(expectedPath), { recursive: true });
fs.writeFileSync(expectedPath, actual);
return {
@ -134,7 +116,7 @@ function compare(actual, name, options) {
actualPath = addSuffix(expectedPath, '-actual');
diffPath = addSuffix(expectedPath, '-diff', result.diffExtension);
} else {
const outputPath = path.join(outputDir, testAssetsDir, name);
const outputPath = path.join(config.outputDir, testAssetsDir, name);
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
const expectedPathOut = addSuffix(outputPath, '-expected');
actualPath = addSuffix(outputPath, '-actual');
@ -162,13 +144,7 @@ function compare(actual, name, options) {
};
}
/**
* @param {string} filePath
* @param {string} suffix
* @param {string=} customExtension
* @return {string}
*/
function addSuffix(filePath, suffix, customExtension) {
function addSuffix(filePath: string, suffix: string, customExtension?: string): string {
const dirname = path.dirname(filePath);
const ext = path.extname(filePath);
const name = path.basename(filePath, ext);

View file

@ -30,6 +30,17 @@ export { parameters, registerParameter } from './fixtures';
export { RunnerConfig } from './runnerConfig';
export { Suite, Test } from './test';
declare global {
interface WorkerState {
}
interface TestState {
}
interface FixtureParameters {
}
}
let beforeFunctions: Function[] = [];
let afterFunctions: Function[] = [];
let matrix: Matrix = {};
@ -39,11 +50,11 @@ global['after'] = (fn: Function) => afterFunctions.push(fn);
global['matrix'] = (m: Matrix) => matrix = m;
export function registerFixture<T extends keyof TestState>(name: T, fn: (params: FixtureParameters & WorkerState & TestState, runTest: (arg: TestState[T]) => Promise<void>, config: RunnerConfig, test: Test) => Promise<void>) {
registerFixtureT<RunnerConfig, T>(name, fn);
registerFixtureT<RunnerConfig>(name, fn);
};
export function registerWorkerFixture<T extends keyof (WorkerState & FixtureParameters)>(name: T, fn: (params: FixtureParameters & WorkerState, runTest: (arg: (WorkerState & FixtureParameters)[T]) => Promise<void>, config: RunnerConfig) => Promise<void>) {
registerWorkerFixtureT<RunnerConfig, T>(name, fn);
registerWorkerFixtureT<RunnerConfig>(name, fn);
};
export function collectTests(config: RunnerConfig, files: string[]): Suite {

View file

@ -19,7 +19,7 @@ import crypto from 'crypto';
import path from 'path';
import { EventEmitter } from 'events';
import { lookupRegistrations, FixturePool } from './fixtures';
import { Suite } from './test';
import { Suite, Test, Configuration } from './test';
import { TestRunnerEntry } from './testRunner';
import { RunnerConfig } from './runnerConfig';
@ -29,8 +29,7 @@ export class Runner extends EventEmitter {
private _workerClaimers: (() => void)[] = [];
stats: { duration: number; failures: number; passes: number; pending: number; tests: number; };
private _testById = new Map<any, any>();
private _testsByConfiguredFile = new Map<any, any>();
private _testById = new Map<string, Test>();
private _queue: TestRunnerEntry[] = [];
private _stopCallback: () => void;
readonly _config: RunnerConfig;
@ -48,37 +47,34 @@ export class Runner extends EventEmitter {
tests: 0,
};
this._testById = new Map();
this._testsByConfiguredFile = new Map();
this._suite = suite;
this._suite.eachTest(test => {
const configuredFile = `${test.file}::[${test._configurationString}]`;
if (!this._testsByConfiguredFile.has(configuredFile)) {
this._testsByConfiguredFile.set(configuredFile, {
file: test.file,
configuredFile,
ordinals: [],
configurationObject: test._configurationObject,
configurationString: test._configurationString
});
}
const { ordinals } = this._testsByConfiguredFile.get(configuredFile);
ordinals.push(test._ordinal);
this._testById.set(`${test._ordinal}@${configuredFile}`, test);
});
for (const suite of this._suite.suites) {
suite.eachTest(test => {
this._testById.set(`${test._ordinal}@${suite.file}::[${suite._configurationString}]`, test);
});
}
if (process.stdout.isTTY) {
const total = suite.total();
console.log();
const jobs = Math.min(config.jobs, this._testsByConfiguredFile.size);
const jobs = Math.min(config.jobs, suite.suites.length);
console.log(`Running ${total} test${ total > 1 ? 's' : '' } using ${jobs} worker${ jobs > 1 ? 's' : ''}`);
}
}
_filesSortedByWorkerHash() {
const result = [];
for (const entry of this._testsByConfiguredFile.values())
result.push({ ...entry, hash: entry.configurationString + '@' + computeWorkerHash(entry.file) });
_filesSortedByWorkerHash(): TestRunnerEntry[] {
const result: TestRunnerEntry[] = [];
for (const suite of this._suite.suites) {
const ordinals: number[] = [];
suite.eachTest(test => ordinals.push(test._ordinal) && false);
result.push({
ordinals,
file: suite.file,
configuration: suite.configuration,
configurationString: suite._configurationString,
hash: suite._configurationString + '@' + computeWorkerHash(suite.file)
});
}
result.sort((a, b) => a.hash < b.hash ? -1 : (a.hash === b.hash ? 0 : 1));
return result;
}
@ -258,7 +254,7 @@ class OopWorker extends Worker {
await new Promise(f => this.process.once('message', f)); // Ready ack
}
run(entry) {
run(entry: TestRunnerEntry) {
this.hash = entry.hash;
this.process.send({ method: 'run', params: { entry, config: this.runner._config } });
}
@ -316,13 +312,13 @@ class InProcessWorker extends Worker {
}
}
function chunkFromParams(params) {
function chunkFromParams(params: string | { buffer: string }): string | Buffer {
if (typeof params === 'string')
return params;
return Buffer.from(params.buffer, 'base64');
}
function computeWorkerHash(file) {
function computeWorkerHash(file: string) {
// At this point, registrationsByFile contains all the files with worker fixture registrations.
// For every test, build the require closure and map each file to fixtures declared in it.
// This collection of fixtures is the fingerprint of the worker setup, a "worker hash".
@ -332,5 +328,3 @@ function computeWorkerHash(file) {
hash.update(registration.location);
return hash.digest('hex');
}
module.exports = { Runner };

View file

@ -29,8 +29,6 @@ export class Test {
error: any;
_ordinal: number;
_configurationObject: Configuration;
_configurationString: string;
_overriddenFn: Function;
_startTime: number;
@ -68,6 +66,7 @@ export class Suite {
pending = false;
file: string;
configuration: Configuration;
_configurationString: string;
_hooks: { type: string, fn: Function } [] = [];
_entries: (Suite | Test)[] = [];

View file

@ -16,7 +16,7 @@
import path from 'path';
import { fixturesForCallback } from './fixtures';
import { Configuration, Test, Suite } from './test';
import { Test, Suite } from './test';
import { fixturesUI } from './fixturesUI';
import { RunnerConfig } from './runnerConfig';
@ -51,7 +51,7 @@ export class TestCollector {
return this._hasOnly;
}
_addFile(file: string) {
private _addFile(file: string) {
const suite = new Suite('');
const revertBabelRequire = fixturesUI(suite, file, this._config.timeout);
require(file);
@ -83,35 +83,36 @@ export class TestCollector {
if (!generatorConfigurations.length)
generatorConfigurations.push([]);
for (const configurationObject of generatorConfigurations) {
for (const configuration of generatorConfigurations) {
// Serialize configuration as readable string, we will use it as a hash.
const tokens = [];
for (const { name, value } of configurationObject)
for (const { name, value } of configuration)
tokens.push(`${name}=${value}`);
const configurationString = tokens.join(', ');
// Allocate worker for this configuration, add test into it.
if (!workerGeneratorConfigurations.has(configurationString))
workerGeneratorConfigurations.set(configurationString, { configurationObject, configurationString, tests: new Set() });
workerGeneratorConfigurations.set(configurationString, { configuration, configurationString, tests: new Set() });
workerGeneratorConfigurations.get(configurationString).tests.add(test);
}
});
// Clone the suite as many times as there are worker hashes.
// Only include the tests that requested these generations.
for (const [hash, {configurationObject, configurationString, tests}] of workerGeneratorConfigurations.entries()) {
const clone = this._cloneSuite(suite, configurationObject, configurationString, tests);
for (const [hash, {configuration, configurationString, tests}] of workerGeneratorConfigurations.entries()) {
const clone = this._cloneSuite(suite, tests);
this.suite._addSuite(clone);
clone.title = path.basename(file) + (hash.length ? `::[${hash}]` : '');
clone.configuration = configuration;
clone._configurationString = configurationString;
}
}
_cloneSuite(suite: Suite, configurationObject: Configuration, configurationString: string, tests: Set<Test>) {
private _cloneSuite(suite: Suite, tests: Set<Test>) {
const copy = suite._clone();
copy.only = suite.only;
copy.configuration = configurationObject;
for (const entry of suite._entries) {
if (entry instanceof Suite) {
copy._addSuite(this._cloneSuite(entry, configurationObject, configurationString, tests));
copy._addSuite(this._cloneSuite(entry, tests));
} else {
const test = entry;
if (!tests.has(test))
@ -121,15 +122,13 @@ export class TestCollector {
const testCopy = test._clone();
testCopy.only = test.only;
testCopy._ordinal = test._ordinal;
testCopy._configurationObject = configurationObject;
testCopy._configurationString = configurationString;
copy._addTest(testCopy);
}
}
return copy;
}
_filterOnly(suite) {
private _filterOnly(suite) {
const onlySuites = suite.suites.filter(child => this._filterOnly(child) || child.only);
const onlyTests = suite.tests.filter(test => test.only);
if (onlySuites.length || onlyTests.length) {
@ -140,5 +139,3 @@ export class TestCollector {
return false;
}
}
module.exports = { TestCollector };

View file

@ -14,11 +14,10 @@
* limitations under the License.
*/
import path from 'path';
import { FixturePool, rerunRegistrations, setParameters } from './fixtures';
import { EventEmitter } from 'events';
import { setCurrentTestFile } from './expect';
import { Test, Suite } from './test';
import { Test, Suite, Configuration } from './test';
import { fixturesUI } from './fixturesUI';
import { RunnerConfig } from './runnerConfig';
@ -27,8 +26,8 @@ export const fixturePool = new FixturePool<RunnerConfig>();
export type TestRunnerEntry = {
file: string;
ordinals: number[];
configuredFile: string;
configurationObject: any;
configurationString: string;
configuration: Configuration;
hash: string;
};
@ -53,11 +52,11 @@ export class TestRunner extends EventEmitter {
this._trialRun = config.trialRun;
this._timeout = config.timeout;
this._config = config;
this._configuredFile = entry.configuredFile;
for (const {name, value} of entry.configurationObject)
this._configuredFile = entry.file + `::[${entry.configurationString}]`;
for (const {name, value} of entry.configuration)
this._parsedGeneratorConfiguration[name] = value;
this._parsedGeneratorConfiguration['parallelIndex'] = workerId;
setCurrentTestFile(path.relative(config.testDir, this._file));
setCurrentTestFile(this._file);
}
stop() {

View file

@ -13,18 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const crypto = require('crypto');
const os = require('os');
const path = require('path');
const fs = require('fs');
const pirates = require('pirates');
const babel = require('@babel/core');
const sourceMapSupport = require('source-map-support');
import * as crypto from 'crypto';
import * as os from 'os';
import * as path from 'path';
import * as fs from 'fs';
import * as pirates from 'pirates';
import * as babel from '@babel/core';
import * as sourceMapSupport from 'source-map-support';
const version = 1;
const cacheDir = path.join(os.tmpdir(), 'playwright-transform-cache');
/** @type {Map<string, string>} */
const sourceMaps = new Map();
const sourceMaps: Map<string, string> = new Map();
sourceMapSupport.install({
environment: 'node',
@ -42,19 +42,13 @@ sourceMapSupport.install({
}
});
/**
* @param {string} content
* @param {string} filePath
* @return {string}
*/
function calculateCachePath(content, filePath) {
function calculateCachePath(content: string, filePath: string): string {
const hash = crypto.createHash('sha1').update(content).update(filePath).update(String(version)).digest('hex');
const fileName = path.basename(filePath, path.extname(filePath)).replace(/\W/g, '') + '_' + hash;
return path.join(cacheDir, hash[0] + hash[1], fileName);
}
function installTransform() {
export function installTransform(): () => void {
return pirates.addHook((code, filename) => {
const cachePath = calculateCachePath(code, filename);
const codePath = cachePath + '.js';
@ -80,5 +74,3 @@ function installTransform() {
exts: ['.ts']
});
}
module.exports = {installTransform};