chore(testrunner): complete ts migration (#3587)
This commit is contained in:
parent
224d3df899
commit
53ac35a613
58
package-lock.json
generated
58
package-lock.json
generated
|
|
@ -1168,6 +1168,47 @@
|
||||||
"defer-to-connect": "^1.0.1"
|
"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": {
|
"@types/color-name": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
||||||
|
|
@ -1287,6 +1328,23 @@
|
||||||
"@types/node": "*"
|
"@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": {
|
"@types/stack-utils": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@
|
||||||
"@babel/core": "^7.10.3",
|
"@babel/core": "^7.10.3",
|
||||||
"@babel/preset-env": "^7.10.3",
|
"@babel/preset-env": "^7.10.3",
|
||||||
"@babel/preset-typescript": "^7.10.1",
|
"@babel/preset-typescript": "^7.10.1",
|
||||||
|
"@types/babel__core": "^7.1.9",
|
||||||
"@types/debug": "0.0.31",
|
"@types/debug": "0.0.31",
|
||||||
"@types/extract-zip": "^1.6.2",
|
"@types/extract-zip": "^1.6.2",
|
||||||
"@types/mime": "^2.0.1",
|
"@types/mime": "^2.0.1",
|
||||||
|
|
@ -63,6 +64,7 @@
|
||||||
"@types/progress": "^2.0.3",
|
"@types/progress": "^2.0.3",
|
||||||
"@types/proxy-from-env": "^1.0.0",
|
"@types/proxy-from-env": "^1.0.0",
|
||||||
"@types/rimraf": "^2.0.2",
|
"@types/rimraf": "^2.0.2",
|
||||||
|
"@types/source-map-support": "^0.5.3",
|
||||||
"@types/stack-utils": "^1.0.1",
|
"@types/stack-utils": "^1.0.1",
|
||||||
"@types/ws": "^6.0.1",
|
"@types/ws": "^6.0.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^2.6.1",
|
"@typescript-eslint/eslint-plugin": "^2.6.1",
|
||||||
|
|
|
||||||
|
|
@ -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');
|
|
||||||
|
|
@ -14,7 +14,8 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import GoldenUtils from './GoldenUtils';
|
import { compare } from './golden';
|
||||||
|
import { RunnerConfig } from './runnerConfig';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
const expect: typeof import('expect');
|
const expect: typeof import('expect');
|
||||||
|
|
@ -28,16 +29,16 @@ declare module 'expect/build/types' {
|
||||||
|
|
||||||
global['expect'] = require('expect');
|
global['expect'] = require('expect');
|
||||||
|
|
||||||
let relativeTestFile: string;
|
let testFile: string;
|
||||||
|
|
||||||
export function initializeImageMatcher(options) {
|
export function initializeImageMatcher(config: RunnerConfig) {
|
||||||
function toMatchImage(received, name, config) {
|
function toMatchImage(received: Buffer, name: string, options?: { threshold?: number }) {
|
||||||
const { pass, message } = GoldenUtils.compare(received, name, { ...options, relativeTestFile, config });
|
const { pass, message } = compare(received, name, config, testFile, options);
|
||||||
return { pass, message: () => message };
|
return { pass, message: () => message };
|
||||||
};
|
};
|
||||||
expect.extend({ toMatchImage });
|
expect.extend({ toMatchImage });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function setCurrentTestFile(testFile: string) {
|
export function setCurrentTestFile(file: string) {
|
||||||
relativeTestFile = testFile;
|
testFile = file;
|
||||||
}
|
}
|
||||||
|
|
@ -17,32 +17,29 @@
|
||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
import { Test } from './test';
|
import { Test } from './test';
|
||||||
|
|
||||||
declare global {
|
type Scope = 'test' | 'worker';
|
||||||
interface WorkerState {
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TestState {
|
type FixtureRegistration = {
|
||||||
}
|
name: string;
|
||||||
|
scope: Scope;
|
||||||
|
fn: Function;
|
||||||
|
};
|
||||||
|
|
||||||
interface FixtureParameters {
|
const registrations = new Map<string, FixtureRegistration>();
|
||||||
}
|
const registrationsByFile = new Map<string, FixtureRegistration[]>();
|
||||||
}
|
export let parameters: any = {};
|
||||||
|
|
||||||
const registrations = new Map();
|
|
||||||
const registrationsByFile = new Map();
|
|
||||||
export let parameters: FixtureParameters = {} as FixtureParameters;
|
|
||||||
export const parameterRegistrations = new Map();
|
export const parameterRegistrations = new Map();
|
||||||
|
|
||||||
export function setParameters(params: any) {
|
export function setParameters(params: any) {
|
||||||
parameters = Object.assign(parameters, params);
|
parameters = Object.assign(parameters, params);
|
||||||
for (const name of Object.keys(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> {
|
class Fixture<Config> {
|
||||||
pool: FixturePool<Config>;
|
pool: FixturePool<Config>;
|
||||||
name: string;
|
name: string;
|
||||||
scope: string;
|
scope: Scope;
|
||||||
fn: Function;
|
fn: Function;
|
||||||
deps: string[];
|
deps: string[];
|
||||||
usages: Set<string>;
|
usages: Set<string>;
|
||||||
|
|
@ -53,7 +50,7 @@ class Fixture<Config> {
|
||||||
_setup = false;
|
_setup = false;
|
||||||
_teardown = 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.pool = pool;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.scope = scope;
|
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);
|
const names = fixtureParameterNames(fn);
|
||||||
for (const name of names)
|
for (const name of names)
|
||||||
await this.setupFixture(name, config, test);
|
await this.setupFixture(name, config, test);
|
||||||
|
|
@ -148,7 +145,7 @@ export class FixturePool<Config> {
|
||||||
if (!timeout)
|
if (!timeout)
|
||||||
return fn(params);
|
return fn(params);
|
||||||
|
|
||||||
let timer;
|
let timer: NodeJS.Timer;
|
||||||
let timerPromise = new Promise(f => timer = setTimeout(f, timeout));
|
let timerPromise = new Promise(f => timer = setTimeout(f, timeout));
|
||||||
return Promise.race([
|
return Promise.race([
|
||||||
Promise.resolve(fn(params)).then(() => clearTimeout(timer)),
|
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 names = new Set<string>();
|
||||||
const visit = (callback: any) => {
|
const visit = (callback: Function) => {
|
||||||
for (const name of fixtureParameterNames(callback)) {
|
for (const name of fixtureParameterNames(callback)) {
|
||||||
if (name in names)
|
if (name in names)
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -189,7 +186,7 @@ export function fixturesForCallback(callback: any): string[] {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function fixtureParameterNames(fn: { toString: () => any; }): string[] {
|
function fixtureParameterNames(fn: Function): string[] {
|
||||||
const text = fn.toString();
|
const text = fn.toString();
|
||||||
const match = text.match(/async(?:\s+function)?\s*\(\s*{\s*([^}]*)\s*}/);
|
const match = text.match(/async(?:\s+function)?\s*\(\s*{\s*([^}]*)\s*}/);
|
||||||
if (!match || !match[1].trim())
|
if (!match || !match[1].trim())
|
||||||
|
|
@ -198,7 +195,7 @@ function fixtureParameterNames(fn: { toString: () => any; }): string[] {
|
||||||
return signature.split(',').map((t: string) => t.trim());
|
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: ''};
|
const obj = {stack: ''};
|
||||||
Error.captureStackTrace(obj, caller);
|
Error.captureStackTrace(obj, caller);
|
||||||
const stackFrame = obj.stack.split('\n')[2];
|
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);
|
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);
|
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);
|
innerRegisterFixture(name, 'worker', fn, registerWorkerFixture);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function registerParameter<T extends keyof WorkerState>(name: T, fn: () => WorkerState[T][]) {
|
export function registerParameter(name: string, fn: () => any) {
|
||||||
registerWorkerFixture(name, async ({}: any, test: (arg0: any) => any) => await test(parameters[name]));
|
registerWorkerFixture(name, async ({}: any, test: Function) => await test(parameters[name]));
|
||||||
parameterRegistrations.set(name, fn);
|
parameterRegistrations.set(name, fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
function collectRequires(file: string | number, result: Set<unknown>) {
|
function collectRequires(file: string, result: Set<string>) {
|
||||||
if (result.has(file))
|
if (result.has(file))
|
||||||
return;
|
return;
|
||||||
result.add(file);
|
result.add(file);
|
||||||
|
|
@ -236,8 +233,8 @@ function collectRequires(file: string | number, result: Set<unknown>) {
|
||||||
collectRequires(dep, result);
|
collectRequires(dep, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function lookupRegistrations(file: any, scope: any) {
|
export function lookupRegistrations(file: string, scope: Scope) {
|
||||||
const deps = new Set();
|
const deps = new Set<string>();
|
||||||
collectRequires(file, deps);
|
collectRequires(file, deps);
|
||||||
const allDeps = [...deps].reverse();
|
const allDeps = [...deps].reverse();
|
||||||
let result = new Map();
|
let result = new Map();
|
||||||
|
|
@ -254,7 +251,7 @@ export function lookupRegistrations(file: any, scope: any) {
|
||||||
return result;
|
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
|
// 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.
|
// each file. That way we erase potential fixture overrides from the previous test runs.
|
||||||
for (const registration of lookupRegistrations(file, scope).values())
|
for (const registration of lookupRegistrations(file, scope).values())
|
||||||
|
|
|
||||||
|
|
@ -14,15 +14,14 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
const path = require('path');
|
import c from 'colors/safe';
|
||||||
const fs = require('fs');
|
import fs from 'fs';
|
||||||
const Diff = require('text-diff');
|
import jpeg from 'jpeg-js';
|
||||||
const PNG = require('pngjs').PNG;
|
import path from 'path';
|
||||||
const jpeg = require('jpeg-js');
|
import pixelmatch from 'pixelmatch';
|
||||||
const pixelmatch = require('pixelmatch');
|
import { PNG } from 'pngjs';
|
||||||
const c = require('colors/safe');
|
import Diff from 'text-diff';
|
||||||
|
import { RunnerConfig } from './runnerConfig';
|
||||||
module.exports = {compare};
|
|
||||||
|
|
||||||
const extensionToMimeType = {
|
const extensionToMimeType = {
|
||||||
'png': 'image/png',
|
'png': 'image/png',
|
||||||
|
|
@ -37,14 +36,7 @@ const GoldenComparators = {
|
||||||
'text/plain': compareText
|
'text/plain': compareText
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function compareImages(actualBuffer: Buffer, expectedBuffer: Buffer, mimeType: string, options = {}): { diff?: object; errorMessage?: string; } | null {
|
||||||
/**
|
|
||||||
* @param {?Object} actualBuffer
|
|
||||||
* @param {!Buffer} expectedBuffer
|
|
||||||
* @param {!string} mimeType
|
|
||||||
* @return {?{diff?: Object, errorMessage?: string}}
|
|
||||||
*/
|
|
||||||
function compareImages(actualBuffer, expectedBuffer, mimeType, config = {}) {
|
|
||||||
if (!actualBuffer || !(actualBuffer instanceof Buffer))
|
if (!actualBuffer || !(actualBuffer instanceof Buffer))
|
||||||
return { errorMessage: 'Actual result should be 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 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;
|
return count > 0 ? { diff: PNG.sync.write(diff) } : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function compareText(actual: Buffer, expectedBuffer: Buffer): { diff?: object; errorMessage?: string; diffExtension?: string; } | null {
|
||||||
* @param {?Object} actual
|
|
||||||
* @param {!Buffer} expectedBuffer
|
|
||||||
* @return {?{diff?: Object, errorMessage?: string, diffExtension?: string}}
|
|
||||||
*/
|
|
||||||
function compareText(actual, expectedBuffer) {
|
|
||||||
if (typeof actual !== 'string')
|
if (typeof actual !== 'string')
|
||||||
return { errorMessage: 'Actual result should be string' };
|
return { errorMessage: 'Actual result should be string' };
|
||||||
const expected = expectedBuffer.toString('utf-8');
|
const expected = expectedBuffer.toString('utf-8');
|
||||||
|
|
@ -83,19 +70,14 @@ function compareText(actual, expectedBuffer) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
export function compare(actual: Buffer, name: string, config: RunnerConfig, testFile: string, options?: { threshold?: number } ): { pass: boolean; message?: string; } {
|
||||||
* @param {?Object} actual
|
let expectedPath: string;
|
||||||
* @param {string} name
|
const relativeTestFile = path.relative(config.testDir, testFile);
|
||||||
* @return {!{pass: boolean, message?: string}}
|
|
||||||
*/
|
|
||||||
function compare(actual, name, options) {
|
|
||||||
const { relativeTestFile, snapshotDir, outputDir, updateSnapshots } = options;
|
|
||||||
let expectedPath;
|
|
||||||
const testAssetsDir = relativeTestFile.replace(/\.spec\.[jt]s/, '');
|
const testAssetsDir = relativeTestFile.replace(/\.spec\.[jt]s/, '');
|
||||||
if (path.isAbsolute(name))
|
if (path.isAbsolute(name))
|
||||||
expectedPath = name;
|
expectedPath = name;
|
||||||
else
|
else
|
||||||
expectedPath = path.join(snapshotDir, testAssetsDir, name);
|
expectedPath = path.join(config.snapshotDir, testAssetsDir, name);
|
||||||
if (!fs.existsSync(expectedPath)) {
|
if (!fs.existsSync(expectedPath)) {
|
||||||
fs.mkdirSync(path.dirname(expectedPath), { recursive: true });
|
fs.mkdirSync(path.dirname(expectedPath), { recursive: true });
|
||||||
fs.writeFileSync(expectedPath, actual);
|
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)
|
if (!result)
|
||||||
return { pass: true };
|
return { pass: true };
|
||||||
|
|
||||||
if (updateSnapshots) {
|
if (config.updateSnapshots) {
|
||||||
fs.mkdirSync(path.dirname(expectedPath), { recursive: true });
|
fs.mkdirSync(path.dirname(expectedPath), { recursive: true });
|
||||||
fs.writeFileSync(expectedPath, actual);
|
fs.writeFileSync(expectedPath, actual);
|
||||||
return {
|
return {
|
||||||
|
|
@ -134,7 +116,7 @@ function compare(actual, name, options) {
|
||||||
actualPath = addSuffix(expectedPath, '-actual');
|
actualPath = addSuffix(expectedPath, '-actual');
|
||||||
diffPath = addSuffix(expectedPath, '-diff', result.diffExtension);
|
diffPath = addSuffix(expectedPath, '-diff', result.diffExtension);
|
||||||
} else {
|
} else {
|
||||||
const outputPath = path.join(outputDir, testAssetsDir, name);
|
const outputPath = path.join(config.outputDir, testAssetsDir, name);
|
||||||
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
||||||
const expectedPathOut = addSuffix(outputPath, '-expected');
|
const expectedPathOut = addSuffix(outputPath, '-expected');
|
||||||
actualPath = addSuffix(outputPath, '-actual');
|
actualPath = addSuffix(outputPath, '-actual');
|
||||||
|
|
@ -162,13 +144,7 @@ function compare(actual, name, options) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
function addSuffix(filePath: string, suffix: string, customExtension?: string): string {
|
||||||
* @param {string} filePath
|
|
||||||
* @param {string} suffix
|
|
||||||
* @param {string=} customExtension
|
|
||||||
* @return {string}
|
|
||||||
*/
|
|
||||||
function addSuffix(filePath, suffix, customExtension) {
|
|
||||||
const dirname = path.dirname(filePath);
|
const dirname = path.dirname(filePath);
|
||||||
const ext = path.extname(filePath);
|
const ext = path.extname(filePath);
|
||||||
const name = path.basename(filePath, ext);
|
const name = path.basename(filePath, ext);
|
||||||
|
|
@ -30,6 +30,17 @@ export { parameters, registerParameter } from './fixtures';
|
||||||
export { RunnerConfig } from './runnerConfig';
|
export { RunnerConfig } from './runnerConfig';
|
||||||
export { Suite, Test } from './test';
|
export { Suite, Test } from './test';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface WorkerState {
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TestState {
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FixtureParameters {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let beforeFunctions: Function[] = [];
|
let beforeFunctions: Function[] = [];
|
||||||
let afterFunctions: Function[] = [];
|
let afterFunctions: Function[] = [];
|
||||||
let matrix: Matrix = {};
|
let matrix: Matrix = {};
|
||||||
|
|
@ -39,11 +50,11 @@ global['after'] = (fn: Function) => afterFunctions.push(fn);
|
||||||
global['matrix'] = (m: Matrix) => matrix = m;
|
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>) {
|
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>) {
|
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 {
|
export function collectTests(config: RunnerConfig, files: string[]): Suite {
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import crypto from 'crypto';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import { lookupRegistrations, FixturePool } from './fixtures';
|
import { lookupRegistrations, FixturePool } from './fixtures';
|
||||||
import { Suite } from './test';
|
import { Suite, Test, Configuration } from './test';
|
||||||
import { TestRunnerEntry } from './testRunner';
|
import { TestRunnerEntry } from './testRunner';
|
||||||
import { RunnerConfig } from './runnerConfig';
|
import { RunnerConfig } from './runnerConfig';
|
||||||
|
|
||||||
|
|
@ -29,8 +29,7 @@ export class Runner extends EventEmitter {
|
||||||
private _workerClaimers: (() => void)[] = [];
|
private _workerClaimers: (() => void)[] = [];
|
||||||
stats: { duration: number; failures: number; passes: number; pending: number; tests: number; };
|
stats: { duration: number; failures: number; passes: number; pending: number; tests: number; };
|
||||||
|
|
||||||
private _testById = new Map<any, any>();
|
private _testById = new Map<string, Test>();
|
||||||
private _testsByConfiguredFile = new Map<any, any>();
|
|
||||||
private _queue: TestRunnerEntry[] = [];
|
private _queue: TestRunnerEntry[] = [];
|
||||||
private _stopCallback: () => void;
|
private _stopCallback: () => void;
|
||||||
readonly _config: RunnerConfig;
|
readonly _config: RunnerConfig;
|
||||||
|
|
@ -48,37 +47,34 @@ export class Runner extends EventEmitter {
|
||||||
tests: 0,
|
tests: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
this._testById = new Map();
|
|
||||||
this._testsByConfiguredFile = new Map();
|
|
||||||
this._suite = suite;
|
this._suite = suite;
|
||||||
this._suite.eachTest(test => {
|
for (const suite of this._suite.suites) {
|
||||||
const configuredFile = `${test.file}::[${test._configurationString}]`;
|
suite.eachTest(test => {
|
||||||
if (!this._testsByConfiguredFile.has(configuredFile)) {
|
this._testById.set(`${test._ordinal}@${suite.file}::[${suite._configurationString}]`, test);
|
||||||
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);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (process.stdout.isTTY) {
|
if (process.stdout.isTTY) {
|
||||||
const total = suite.total();
|
const total = suite.total();
|
||||||
console.log();
|
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' : ''}`);
|
console.log(`Running ${total} test${ total > 1 ? 's' : '' } using ${jobs} worker${ jobs > 1 ? 's' : ''}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_filesSortedByWorkerHash() {
|
_filesSortedByWorkerHash(): TestRunnerEntry[] {
|
||||||
const result = [];
|
const result: TestRunnerEntry[] = [];
|
||||||
for (const entry of this._testsByConfiguredFile.values())
|
for (const suite of this._suite.suites) {
|
||||||
result.push({ ...entry, hash: entry.configurationString + '@' + computeWorkerHash(entry.file) });
|
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));
|
result.sort((a, b) => a.hash < b.hash ? -1 : (a.hash === b.hash ? 0 : 1));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -258,7 +254,7 @@ class OopWorker extends Worker {
|
||||||
await new Promise(f => this.process.once('message', f)); // Ready ack
|
await new Promise(f => this.process.once('message', f)); // Ready ack
|
||||||
}
|
}
|
||||||
|
|
||||||
run(entry) {
|
run(entry: TestRunnerEntry) {
|
||||||
this.hash = entry.hash;
|
this.hash = entry.hash;
|
||||||
this.process.send({ method: 'run', params: { entry, config: this.runner._config } });
|
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')
|
if (typeof params === 'string')
|
||||||
return params;
|
return params;
|
||||||
return Buffer.from(params.buffer, 'base64');
|
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.
|
// 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.
|
// 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".
|
// 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);
|
hash.update(registration.location);
|
||||||
return hash.digest('hex');
|
return hash.digest('hex');
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { Runner };
|
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,6 @@ export class Test {
|
||||||
error: any;
|
error: any;
|
||||||
|
|
||||||
_ordinal: number;
|
_ordinal: number;
|
||||||
_configurationObject: Configuration;
|
|
||||||
_configurationString: string;
|
|
||||||
_overriddenFn: Function;
|
_overriddenFn: Function;
|
||||||
_startTime: number;
|
_startTime: number;
|
||||||
|
|
||||||
|
|
@ -68,6 +66,7 @@ export class Suite {
|
||||||
pending = false;
|
pending = false;
|
||||||
file: string;
|
file: string;
|
||||||
configuration: Configuration;
|
configuration: Configuration;
|
||||||
|
_configurationString: string;
|
||||||
|
|
||||||
_hooks: { type: string, fn: Function } [] = [];
|
_hooks: { type: string, fn: Function } [] = [];
|
||||||
_entries: (Suite | Test)[] = [];
|
_entries: (Suite | Test)[] = [];
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { fixturesForCallback } from './fixtures';
|
import { fixturesForCallback } from './fixtures';
|
||||||
import { Configuration, Test, Suite } from './test';
|
import { Test, Suite } from './test';
|
||||||
import { fixturesUI } from './fixturesUI';
|
import { fixturesUI } from './fixturesUI';
|
||||||
import { RunnerConfig } from './runnerConfig';
|
import { RunnerConfig } from './runnerConfig';
|
||||||
|
|
||||||
|
|
@ -51,7 +51,7 @@ export class TestCollector {
|
||||||
return this._hasOnly;
|
return this._hasOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
_addFile(file: string) {
|
private _addFile(file: string) {
|
||||||
const suite = new Suite('');
|
const suite = new Suite('');
|
||||||
const revertBabelRequire = fixturesUI(suite, file, this._config.timeout);
|
const revertBabelRequire = fixturesUI(suite, file, this._config.timeout);
|
||||||
require(file);
|
require(file);
|
||||||
|
|
@ -83,35 +83,36 @@ export class TestCollector {
|
||||||
if (!generatorConfigurations.length)
|
if (!generatorConfigurations.length)
|
||||||
generatorConfigurations.push([]);
|
generatorConfigurations.push([]);
|
||||||
|
|
||||||
for (const configurationObject of generatorConfigurations) {
|
for (const configuration of generatorConfigurations) {
|
||||||
// Serialize configuration as readable string, we will use it as a hash.
|
// Serialize configuration as readable string, we will use it as a hash.
|
||||||
const tokens = [];
|
const tokens = [];
|
||||||
for (const { name, value } of configurationObject)
|
for (const { name, value } of configuration)
|
||||||
tokens.push(`${name}=${value}`);
|
tokens.push(`${name}=${value}`);
|
||||||
const configurationString = tokens.join(', ');
|
const configurationString = tokens.join(', ');
|
||||||
// Allocate worker for this configuration, add test into it.
|
// Allocate worker for this configuration, add test into it.
|
||||||
if (!workerGeneratorConfigurations.has(configurationString))
|
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);
|
workerGeneratorConfigurations.get(configurationString).tests.add(test);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Clone the suite as many times as there are worker hashes.
|
// Clone the suite as many times as there are worker hashes.
|
||||||
// Only include the tests that requested these generations.
|
// Only include the tests that requested these generations.
|
||||||
for (const [hash, {configurationObject, configurationString, tests}] of workerGeneratorConfigurations.entries()) {
|
for (const [hash, {configuration, configurationString, tests}] of workerGeneratorConfigurations.entries()) {
|
||||||
const clone = this._cloneSuite(suite, configurationObject, configurationString, tests);
|
const clone = this._cloneSuite(suite, tests);
|
||||||
this.suite._addSuite(clone);
|
this.suite._addSuite(clone);
|
||||||
clone.title = path.basename(file) + (hash.length ? `::[${hash}]` : '');
|
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();
|
const copy = suite._clone();
|
||||||
copy.only = suite.only;
|
copy.only = suite.only;
|
||||||
copy.configuration = configurationObject;
|
|
||||||
for (const entry of suite._entries) {
|
for (const entry of suite._entries) {
|
||||||
if (entry instanceof Suite) {
|
if (entry instanceof Suite) {
|
||||||
copy._addSuite(this._cloneSuite(entry, configurationObject, configurationString, tests));
|
copy._addSuite(this._cloneSuite(entry, tests));
|
||||||
} else {
|
} else {
|
||||||
const test = entry;
|
const test = entry;
|
||||||
if (!tests.has(test))
|
if (!tests.has(test))
|
||||||
|
|
@ -121,15 +122,13 @@ export class TestCollector {
|
||||||
const testCopy = test._clone();
|
const testCopy = test._clone();
|
||||||
testCopy.only = test.only;
|
testCopy.only = test.only;
|
||||||
testCopy._ordinal = test._ordinal;
|
testCopy._ordinal = test._ordinal;
|
||||||
testCopy._configurationObject = configurationObject;
|
|
||||||
testCopy._configurationString = configurationString;
|
|
||||||
copy._addTest(testCopy);
|
copy._addTest(testCopy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
_filterOnly(suite) {
|
private _filterOnly(suite) {
|
||||||
const onlySuites = suite.suites.filter(child => this._filterOnly(child) || child.only);
|
const onlySuites = suite.suites.filter(child => this._filterOnly(child) || child.only);
|
||||||
const onlyTests = suite.tests.filter(test => test.only);
|
const onlyTests = suite.tests.filter(test => test.only);
|
||||||
if (onlySuites.length || onlyTests.length) {
|
if (onlySuites.length || onlyTests.length) {
|
||||||
|
|
@ -140,5 +139,3 @@ export class TestCollector {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { TestCollector };
|
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,10 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import path from 'path';
|
|
||||||
import { FixturePool, rerunRegistrations, setParameters } from './fixtures';
|
import { FixturePool, rerunRegistrations, setParameters } from './fixtures';
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import { setCurrentTestFile } from './expect';
|
import { setCurrentTestFile } from './expect';
|
||||||
import { Test, Suite } from './test';
|
import { Test, Suite, Configuration } from './test';
|
||||||
import { fixturesUI } from './fixturesUI';
|
import { fixturesUI } from './fixturesUI';
|
||||||
import { RunnerConfig } from './runnerConfig';
|
import { RunnerConfig } from './runnerConfig';
|
||||||
|
|
||||||
|
|
@ -27,8 +26,8 @@ export const fixturePool = new FixturePool<RunnerConfig>();
|
||||||
export type TestRunnerEntry = {
|
export type TestRunnerEntry = {
|
||||||
file: string;
|
file: string;
|
||||||
ordinals: number[];
|
ordinals: number[];
|
||||||
configuredFile: string;
|
configurationString: string;
|
||||||
configurationObject: any;
|
configuration: Configuration;
|
||||||
hash: string;
|
hash: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -53,11 +52,11 @@ export class TestRunner extends EventEmitter {
|
||||||
this._trialRun = config.trialRun;
|
this._trialRun = config.trialRun;
|
||||||
this._timeout = config.timeout;
|
this._timeout = config.timeout;
|
||||||
this._config = config;
|
this._config = config;
|
||||||
this._configuredFile = entry.configuredFile;
|
this._configuredFile = entry.file + `::[${entry.configurationString}]`;
|
||||||
for (const {name, value} of entry.configurationObject)
|
for (const {name, value} of entry.configuration)
|
||||||
this._parsedGeneratorConfiguration[name] = value;
|
this._parsedGeneratorConfiguration[name] = value;
|
||||||
this._parsedGeneratorConfiguration['parallelIndex'] = workerId;
|
this._parsedGeneratorConfiguration['parallelIndex'] = workerId;
|
||||||
setCurrentTestFile(path.relative(config.testDir, this._file));
|
setCurrentTestFile(this._file);
|
||||||
}
|
}
|
||||||
|
|
||||||
stop() {
|
stop() {
|
||||||
|
|
|
||||||
|
|
@ -13,18 +13,18 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
const crypto = require('crypto');
|
|
||||||
const os = require('os');
|
import * as crypto from 'crypto';
|
||||||
const path = require('path');
|
import * as os from 'os';
|
||||||
const fs = require('fs');
|
import * as path from 'path';
|
||||||
const pirates = require('pirates');
|
import * as fs from 'fs';
|
||||||
const babel = require('@babel/core');
|
import * as pirates from 'pirates';
|
||||||
const sourceMapSupport = require('source-map-support');
|
import * as babel from '@babel/core';
|
||||||
|
import * as sourceMapSupport from 'source-map-support';
|
||||||
|
|
||||||
const version = 1;
|
const version = 1;
|
||||||
const cacheDir = path.join(os.tmpdir(), 'playwright-transform-cache');
|
const cacheDir = path.join(os.tmpdir(), 'playwright-transform-cache');
|
||||||
/** @type {Map<string, string>} */
|
const sourceMaps: Map<string, string> = new Map();
|
||||||
const sourceMaps = new Map();
|
|
||||||
|
|
||||||
sourceMapSupport.install({
|
sourceMapSupport.install({
|
||||||
environment: 'node',
|
environment: 'node',
|
||||||
|
|
@ -42,19 +42,13 @@ sourceMapSupport.install({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
function calculateCachePath(content: string, filePath: string): string {
|
||||||
* @param {string} content
|
|
||||||
* @param {string} filePath
|
|
||||||
* @return {string}
|
|
||||||
*/
|
|
||||||
function calculateCachePath(content, filePath) {
|
|
||||||
const hash = crypto.createHash('sha1').update(content).update(filePath).update(String(version)).digest('hex');
|
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;
|
const fileName = path.basename(filePath, path.extname(filePath)).replace(/\W/g, '') + '_' + hash;
|
||||||
|
|
||||||
return path.join(cacheDir, hash[0] + hash[1], fileName);
|
return path.join(cacheDir, hash[0] + hash[1], fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
function installTransform() {
|
export function installTransform(): () => void {
|
||||||
return pirates.addHook((code, filename) => {
|
return pirates.addHook((code, filename) => {
|
||||||
const cachePath = calculateCachePath(code, filename);
|
const cachePath = calculateCachePath(code, filename);
|
||||||
const codePath = cachePath + '.js';
|
const codePath = cachePath + '.js';
|
||||||
|
|
@ -80,5 +74,3 @@ function installTransform() {
|
||||||
exts: ['.ts']
|
exts: ['.ts']
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {installTransform};
|
|
||||||
Loading…
Reference in a new issue