From c63de5d2d49a81ca6a3de0094222a504e8ffc009 Mon Sep 17 00:00:00 2001 From: Stephan Noel Date: Thu, 30 Jul 2020 18:31:11 +0100 Subject: [PATCH] fix: Correct unit tests failing on Windows --- core/cli/__tests__/cli.test.ts | 5 +- core/cli/package.json | 3 +- jest.config.js | 3 +- plugins/runner-bin/__tests__/utils.test.ts | 7 ++- .../runner-jest/__tests__/getConfig.test.ts | 18 ++---- .../__snapshots__/default.test.ts.snap | 6 +- .../runner-postcss/__tests__/default.test.ts | 56 ++++++++++++++++++- .../__snapshots__/default.test.ts.snap | 52 +++++++++++++++++ plugins/runner-ts/__tests__/default.test.ts | 29 +++++++++- .../@my-scope/tsconfig/tsconfig.base.json | 8 +++ .../@my-scope/tsconfig/tsconfig.common.json | 9 +++ .../config-extends-npm-module/tsconfig.json | 6 ++ .../__tests__/module-resolution.json | 4 ++ plugins/runner-ts/src/index.ts | 29 +++++----- utils/fixture-helper/package.json | 4 ++ utils/fixture-helper/src/executeRunner.ts | 26 ++++++++- utils/fixture-helper/src/index.ts | 27 ++++++++- utils/fixture-helper/src/initFixtureHelper.ts | 11 +++- utils/fixture-helper/src/resolver.ts | 50 +++++++++++++++++ 19 files changed, 310 insertions(+), 43 deletions(-) create mode 100644 plugins/runner-ts/__tests__/fixtures/config-extends-npm-module/node_modules/@my-scope/tsconfig/tsconfig.base.json create mode 100644 plugins/runner-ts/__tests__/fixtures/config-extends-npm-module/node_modules/@my-scope/tsconfig/tsconfig.common.json create mode 100644 plugins/runner-ts/__tests__/fixtures/config-extends-npm-module/tsconfig.json create mode 100644 plugins/runner-ts/__tests__/module-resolution.json create mode 100644 utils/fixture-helper/src/resolver.ts diff --git a/core/cli/__tests__/cli.test.ts b/core/cli/__tests__/cli.test.ts index 22c1848..beb0064 100644 --- a/core/cli/__tests__/cli.test.ts +++ b/core/cli/__tests__/cli.test.ts @@ -1,6 +1,7 @@ import * as Path from 'path'; import execa = require('execa'); import stripAnsi from 'strip-ansi'; +import { normalizeContainedPath } from '@garment/fixture-helper'; const cwd = Path.join(__dirname + '/fixtures/basic'); const garmentPath = Path.relative(cwd, 'core/cli/lib/cli.js'); @@ -48,12 +49,12 @@ test('cli should fail if given incorrect number of commands', async () => { const { stderr } = await execaSafe('node', [garmentPath, noCacheArg], { cwd: cwd }); - expect(stderr).toMatchSnapshot(); + expect(normalizeContainedPath(stderr)).toMatchSnapshot(); }); test('cli should fail if given unexisting command', async () => { const { stderr } = await execaSafe('node', [garmentPath, 'dep', noCacheArg], { cwd: cwd }); - expect(stderr).toMatchSnapshot(); + expect(normalizeContainedPath(stderr)).toMatchSnapshot(); }); diff --git a/core/cli/package.json b/core/cli/package.json index 3e28f47..fe696c9 100644 --- a/core/cli/package.json +++ b/core/cli/package.json @@ -34,6 +34,7 @@ "@types/update-notifier": "^2.5.0", "@types/yargs": "13.0.3", "execa": "^4.0.0", - "strip-ansi": "^5.2.0" + "strip-ansi": "^5.2.0", + "@garment/fixture-helper": "^0.13.8" } } diff --git a/jest.config.js b/jest.config.js index 4c02ee1..cae32ec 100644 --- a/jest.config.js +++ b/jest.config.js @@ -6,5 +6,6 @@ module.exports = { 'ts-jest': { tsConfig: 'tsconfig.test.json' } - } + }, + resolver: './utils/fixture-helper/lib/resolver' }; diff --git a/plugins/runner-bin/__tests__/utils.test.ts b/plugins/runner-bin/__tests__/utils.test.ts index 1112d2e..68a0fce 100644 --- a/plugins/runner-bin/__tests__/utils.test.ts +++ b/plugins/runner-bin/__tests__/utils.test.ts @@ -1,5 +1,6 @@ import { parseOptions, resolveBin } from '../src/utils'; import * as Path from 'path'; +import os = require('os'); describe('parseOptions function ', () => { const expectedResult = ['prettier', '-o', '--output-dir', 'index.js']; @@ -60,7 +61,11 @@ describe('resolveBin function ', () => { ); test('if gets bin name returns as resolved bin', async () => { - expect(await resolveBin('prettier')).toBe(expectedResult); + const expectedPlatformResult = Path.format({ + name: expectedResult, + ext: os.platform() === 'win32' ? '.CMD' : '' + }); + expect(await resolveBin('prettier')).toBe(expectedPlatformResult); }); test('if gets bin path returns as fullPath', async () => { diff --git a/plugins/runner-jest/__tests__/getConfig.test.ts b/plugins/runner-jest/__tests__/getConfig.test.ts index 4b78549..2bd0d0e 100644 --- a/plugins/runner-jest/__tests__/getConfig.test.ts +++ b/plugins/runner-jest/__tests__/getConfig.test.ts @@ -1,4 +1,8 @@ -import { createBatchContext, initFixtureHelper } from '@garment/fixture-helper'; +import { + createBatchContext, + initFixtureHelper, + replaceTestPath +} from '@garment/fixture-helper'; import { getConfig, JestRunnerOptions } from '../src'; const { initFixture, clean } = initFixtureHelper(module, { @@ -37,15 +41,3 @@ test('Handles multiple projects sharing the same config and one having different expect(replaceTestPath(jestConfig, cwd)).toMatchSnapshot(); }); - -function replaceTestPath( - obj: T, - testPath: string, - replaceWith = '/test_path' -): T { - return JSON.parse( - JSON.stringify(obj, (_, value) => - typeof value === 'string' ? value.replace(testPath, replaceWith) : value - ) - ); -} diff --git a/plugins/runner-postcss/__tests__/__snapshots__/default.test.ts.snap b/plugins/runner-postcss/__tests__/__snapshots__/default.test.ts.snap index 5a4a662..667f017 100644 --- a/plugins/runner-postcss/__tests__/__snapshots__/default.test.ts.snap +++ b/plugins/runner-postcss/__tests__/__snapshots__/default.test.ts.snap @@ -5,7 +5,7 @@ Object { "collectedOutput": Array [ Object { "cacheKeys": Array [ - "8de170ce8b6d1c1aeb78d959f4faa0cf", + "mockHash", " @import './test.css'; .Slideshow { @@ -60,7 +60,7 @@ Object { "collectedOutput": Array [ Object { "cacheKeys": Array [ - "e1c061eef28e0cce2b1ff22fb7f6e12c", + "mockHash", " :root { --color: red; @@ -111,7 +111,7 @@ Object { "collectedOutput": Array [ Object { "cacheKeys": Array [ - "8de170ce8b6d1c1aeb78d959f4faa0cf", + "mockHash", ":fullscreen {}", "index.css", ], diff --git a/plugins/runner-postcss/__tests__/default.test.ts b/plugins/runner-postcss/__tests__/default.test.ts index c7eabc9..c493f26 100644 --- a/plugins/runner-postcss/__tests__/default.test.ts +++ b/plugins/runner-postcss/__tests__/default.test.ts @@ -1,6 +1,11 @@ -import { executeRunner2, initFixtureHelper } from '@garment/fixture-helper'; +import { + executeRunner2, + initFixtureHelper, + ExecuteRunner2Result +} from '@garment/fixture-helper'; import * as Path from 'path'; import handler from '../src'; +import os = require('os'); const { initFixture, clean } = initFixtureHelper(module, { tempDir: __dirname + 'tmp__' @@ -21,7 +26,15 @@ test('Uses postcss.config.js from workspace root', async () => { files: file => [file.text('index.css', `:fullscreen {}`)] }); + const [hash] = extractHashes(result, 'mockHash'); + expect(result).toMatchSnapshot(); + + if (os.platform() === 'win32') { + expect(hash).toBe('b2fa5e79e89879036728c19a038eafac'); + } else { + expect(hash).toBe('8de170ce8b6d1c1aeb78d959f4faa0cf'); + } }); test('Uses postcss.config.js from project', async () => { @@ -47,7 +60,15 @@ test('Uses postcss.config.js from project', async () => { } ); + const [hash] = extractHashes(result, 'mockHash'); + expect(result).toMatchSnapshot(); + + if (os.platform() === 'win32') { + expect(hash).toBe('85e0de080544f7c03f6fa022840ccdaa'); + } else { + expect(hash).toBe('e1c061eef28e0cce2b1ff22fb7f6e12c'); + } }); test('Resolves postcss @import', async () => { @@ -74,5 +95,38 @@ test('Resolves postcss @import', async () => { ] }); + const [hash] = extractHashes(result, 'mockHash'); + expect(result).toMatchSnapshot(); + + if (os.platform() === 'win32') { + expect(hash).toBe('b2fa5e79e89879036728c19a038eafac'); + } else { + expect(hash).toBe('8de170ce8b6d1c1aeb78d959f4faa0cf'); + } }); + +function extractHashes( + result: ExecuteRunner2Result, + replacement: string +): string[] { + const { collectedOutput } = result; + const md5Regex = /^[a-f0-9]{32}$/i; + + const originalHashes: string[] = []; + + collectedOutput.forEach((output: any) => { + if (output.hasOwnProperty('cacheKeys')) { + output.cacheKeys = output.cacheKeys.map((cacheKey: string) => { + if (md5Regex.test(cacheKey)) { + originalHashes.push(cacheKey); + return replacement; + } else { + return cacheKey; + } + }); + } + }); + + return originalHashes; +} diff --git a/plugins/runner-ts/__tests__/__snapshots__/default.test.ts.snap b/plugins/runner-ts/__tests__/__snapshots__/default.test.ts.snap index 17cd295..af46af3 100644 --- a/plugins/runner-ts/__tests__/__snapshots__/default.test.ts.snap +++ b/plugins/runner-ts/__tests__/__snapshots__/default.test.ts.snap @@ -104,6 +104,58 @@ Object { } `; +exports[`Transpiles TypeScript when configFile contains npm module in extends field 1`] = ` +Object { + "collectedOutput": Array [ + Object { + "cacheKeys": Array [ + "3.8.3", + "{\\"declaration\\":true,\\"sourceMap\\":true,\\"noEmitOnError\\":true,\\"skipLibCheck\\":true,\\"target\\":\\"es5\\",\\"module\\":\\"esnext\\",\\"moduleResolution\\":\\"node\\"}", + "export const greet = (str: string) => \`Hello, \${str}\`", + ], + "dependencies": Array [], + "files": Array [ + Object { + "data": "{\\"version\\":3,\\"file\\":\\"index.js\\",\\"sourceRoot\\":\\"\\",\\"sources\\":[\\"index.ts\\"],\\"names\\":[],\\"mappings\\":\\"AAAA,MAAM,CAAC,IAAM,KAAK,GAAG,UAAC,GAAW,IAAK,OAAA,YAAU,GAAK,EAAf,CAAe,CAAA\\"}", + "path": "nested/index.js.map", + "type": "text", + }, + Object { + "data": "export var greet = function (str) { return \\"Hello, \\" + str; }; +//# sourceMappingURL=index.js.map", + "path": "nested/index.js", + "type": "text", + }, + Object { + "data": "export declare const greet: (str: string) => string; +", + "path": "nested/index.d.ts", + "type": "text", + }, + ], + "logs": Array [], + }, + ], + "dependsOnFile": Array [ + "/test_path/tsconfig.json", + "/test_path/node_modules/@my-scope/tsconfig/tsconfig.base.json", + "/test_path/node_modules/@my-scope/tsconfig/tsconfig.common.json", + ], + "isLongRunning": false, + "logs": Array [ + Object { + "args": Array [ + "[TS] Processing", + "index.ts", + ], + "level": "debug", + }, + ], + "onDestroyHandler": undefined, + "shouldWatchDependencies": false, +} +`; + exports[`Transpiles TypeScript with relative imports including not provided as input 1`] = ` Object { "collectedOutput": Array [ diff --git a/plugins/runner-ts/__tests__/default.test.ts b/plugins/runner-ts/__tests__/default.test.ts index e2cdda7..f0a55cf 100644 --- a/plugins/runner-ts/__tests__/default.test.ts +++ b/plugins/runner-ts/__tests__/default.test.ts @@ -3,7 +3,7 @@ import * as Path from 'path'; import handler from '../src'; const { initFixture, clean } = initFixtureHelper(module, { - tempDir: __dirname + 'tmp__' + tempDir: Path.join(__dirname, 'tmp__') }); afterAll(clean); @@ -85,3 +85,30 @@ test('Transpiles TypeScript', async () => { expect(result).toMatchSnapshot(); }); + +test('Transpiles TypeScript when configFile contains npm module in extends field', async () => { + const cwd = await initFixture('config-extends-npm-module', { staticId: 0 }); + + const src = (p = '') => Path.join(cwd, 'test-project', 'src', p); + + const result = await executeRunner2( + handler, + { configFile: 'tsconfig.json' }, + { + projectRelativePath: 'test-project', + cwd, + files: file => [ + file.text( + 'index.ts', + 'export const greet = (str: string) => `Hello, ${str}`', + { + absolutePath: src('nested/index.ts'), + baseDir: src() + } + ) + ] + } + ); + + expect(result).toMatchSnapshot(); +}); diff --git a/plugins/runner-ts/__tests__/fixtures/config-extends-npm-module/node_modules/@my-scope/tsconfig/tsconfig.base.json b/plugins/runner-ts/__tests__/fixtures/config-extends-npm-module/node_modules/@my-scope/tsconfig/tsconfig.base.json new file mode 100644 index 0000000..c6e8e71 --- /dev/null +++ b/plugins/runner-ts/__tests__/fixtures/config-extends-npm-module/node_modules/@my-scope/tsconfig/tsconfig.base.json @@ -0,0 +1,8 @@ +{ + "extends": "@my-scope/tsconfig/tsconfig.common.json", + "compilerOptions": { + "target": "esnext", + "module": "esnext", + "moduleResolution": "node" + } + } \ No newline at end of file diff --git a/plugins/runner-ts/__tests__/fixtures/config-extends-npm-module/node_modules/@my-scope/tsconfig/tsconfig.common.json b/plugins/runner-ts/__tests__/fixtures/config-extends-npm-module/node_modules/@my-scope/tsconfig/tsconfig.common.json new file mode 100644 index 0000000..932f58a --- /dev/null +++ b/plugins/runner-ts/__tests__/fixtures/config-extends-npm-module/node_modules/@my-scope/tsconfig/tsconfig.common.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "declaration": true, + "sourceMap": true, + "noEmitOnError": true, + "skipLibCheck": true + } + } + \ No newline at end of file diff --git a/plugins/runner-ts/__tests__/fixtures/config-extends-npm-module/tsconfig.json b/plugins/runner-ts/__tests__/fixtures/config-extends-npm-module/tsconfig.json new file mode 100644 index 0000000..60b2db5 --- /dev/null +++ b/plugins/runner-ts/__tests__/fixtures/config-extends-npm-module/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "@my-scope/tsconfig/tsconfig.base.json", + "compilerOptions": { + "target": "es5" + } +} diff --git a/plugins/runner-ts/__tests__/module-resolution.json b/plugins/runner-ts/__tests__/module-resolution.json new file mode 100644 index 0000000..ebad639 --- /dev/null +++ b/plugins/runner-ts/__tests__/module-resolution.json @@ -0,0 +1,4 @@ +{ + "@my-scope/tsconfig/tsconfig.base.json": "tmp__/default-config-extends-npm-module-0/node_modules/@my-scope/tsconfig/tsconfig.base.json", + "@my-scope/tsconfig/tsconfig.common.json": "tmp__/default-config-extends-npm-module-0/node_modules/@my-scope/tsconfig/tsconfig.common.json" +} \ No newline at end of file diff --git a/plugins/runner-ts/src/index.ts b/plugins/runner-ts/src/index.ts index 74891f9..12ac2e8 100644 --- a/plugins/runner-ts/src/index.ts +++ b/plugins/runner-ts/src/index.ts @@ -5,6 +5,7 @@ import { } from '@garment/runner'; import * as Path from 'path'; import * as ts from 'typescript'; +import { platform } from 'os'; /** * Runs TypeScript compiler @@ -61,7 +62,7 @@ export default defineRunner(tsRunnerOptions, async ctx => { const parentCompilerOptions = getCompilerOptionsRecursively( ctx.fs.existsSync(parentConfigPath) ? parentConfigPath - : require.resolve(currentConfigPath) + : require.resolve(extendsOption) ); return { ...parentCompilerOptions, @@ -95,47 +96,49 @@ export default defineRunner(tsRunnerOptions, async ctx => { getCurrentDirectory: () => process.cwd(), getDefaultLibFileName: options => ts.getDefaultLibFilePath(options), fileExists: fileName => { - if (filesCache[fileName]) { + if (filesCache[Path.normalize(fileName)]) { return true; } return ts.sys.fileExists(fileName); }, getSourceFile(fileName) { - if (fileName.endsWith('.d.ts')) { - const stats = ctx.fs.statSync(fileName); - let file = filesCache[fileName]; + const normalizedFileName = Path.normalize(fileName); + if (normalizedFileName.endsWith('.d.ts')) { + const stats = ctx.fs.statSync(normalizedFileName); + let file = filesCache[normalizedFileName]; if (!file) { file = { isExternal: true, lastModified: stats.mtimeMs }; - filesCache[fileName] = file; + filesCache[normalizedFileName] = file; } if (stats.mtimeMs > (file.lastModified ?? 0)) { - sourceFilesCache[fileName] = undefined; + sourceFilesCache[normalizedFileName] = undefined; } } - if (!sourceFilesCache[fileName]) { - sourceFilesCache[fileName] = ts.createSourceFile( + if (!sourceFilesCache[normalizedFileName]) { + sourceFilesCache[normalizedFileName] = ts.createSourceFile( fileName, host.readFile(fileName) ?? '', config.options.target ?? ts.ScriptTarget.ES2015, true ); } - return sourceFilesCache[fileName]; + return sourceFilesCache[normalizedFileName]; }, readFile: fileName => { - const file = filesCache[fileName]; + const normalizedFileName = Path.normalize(fileName); + const file = filesCache[normalizedFileName]; if (!file?.isExternal && file?.content) { return file.content; } - return ctx.fs.readFileSync(fileName, 'utf8'); + return ctx.fs.readFileSync(normalizedFileName, 'utf8'); }, readDirectory: ts.sys.readDirectory, directoryExists: fileName => Object.keys(filesCache).some( - _ => Path.dirname(_).indexOf(fileName) === 0 + _ => Path.dirname(_).indexOf(Path.normalize(fileName)) === 0 ) || ts.sys.directoryExists(fileName), getDirectories: ts.sys.getDirectories diff --git a/utils/fixture-helper/package.json b/utils/fixture-helper/package.json index f7de428..f4adff9 100644 --- a/utils/fixture-helper/package.json +++ b/utils/fixture-helper/package.json @@ -14,5 +14,9 @@ "globby": "10.0.1", "strip-ansi": "^5.2.0", "tempy": "0.3.0" + }, + "devDependencies": { + "is-valid-path": "^0.1.1", + "normalize-path": "^3.0.0" } } diff --git a/utils/fixture-helper/src/executeRunner.ts b/utils/fixture-helper/src/executeRunner.ts index c4b1467..617588d 100644 --- a/utils/fixture-helper/src/executeRunner.ts +++ b/utils/fixture-helper/src/executeRunner.ts @@ -10,7 +10,11 @@ import { InputFnCallBack, OutputContainer, renderOptions, - InputFn + InputFn, + TextFile, + JsonFile, + SourceFile, + BinaryFile } from '@garment/runner'; import { Project, ProjectConfig, Workspace } from '@garment/workspace'; import * as fs from 'fs-extra'; @@ -30,6 +34,24 @@ export interface CommonOptions { files?: ((fileFactory: typeof file) => File[]) | File[]; } +export interface ExecuteRunner2Result { + onDestroyHandler: (() => void) | undefined; + collectedOutput: ( + | TextFile + | JsonFile + | SourceFile + | BinaryFile + | OutputContainer + )[]; + logs: { + level: 'silly' | 'debug' | 'info' | 'success' | 'warn' | 'error' | 'silent'; + args: any[]; + }[]; + shouldWatchDependencies: boolean; + isLongRunning: boolean; + dependsOnFile: string[]; +} + const cacheProviderMock: CacheProvider = { has: () => false, get: () => {}, @@ -249,7 +271,7 @@ export async function executeRunner2( runner: { handler: RunnerHandler; options: OptionsSchema | null }, runnerOptions: OptionsSchema['type'], options: CommonOptions = {} -) { +): Promise { let shouldWatchDependencies = false; let isLongRunning = false; let onDestroyHandler: (() => void) | undefined; diff --git a/utils/fixture-helper/src/index.ts b/utils/fixture-helper/src/index.ts index d6f64f2..535512c 100644 --- a/utils/fixture-helper/src/index.ts +++ b/utils/fixture-helper/src/index.ts @@ -1,15 +1,38 @@ export * from './executeRunner'; export * from './initFixtureHelper'; +export * from './resolver'; +import normalizePath = require('normalize-path'); +import isValidPath = require('is-valid-path'); + +const containsValidPath = (value: string): boolean => + value.split(/\s/).some(s => isValidPath(s)); + +export const normalizeContainedPath = (value: string): string => { + return value + .split(/(\s)/) + .map(s => { + if (isValidPath(s)) { + return normalizePath(s); + } else { + return s; + } + }) + .join(''); +}; export function replaceTestPath( obj: T, testPath: string, replaceWith = '/test_path' ): T { + const normalizedTestPathRegEx = new RegExp(normalizePath(testPath), 'g'); return JSON.parse( JSON.stringify(obj, (_, value) => - typeof value === 'string' - ? value.replace(new RegExp(testPath, 'g'), replaceWith) + typeof value === 'string' && containsValidPath(value) + ? normalizeContainedPath(value).replace( + normalizedTestPathRegEx, + replaceWith + ) : value ) ); diff --git a/utils/fixture-helper/src/initFixtureHelper.ts b/utils/fixture-helper/src/initFixtureHelper.ts index dbc7443..aa64235 100644 --- a/utils/fixture-helper/src/initFixtureHelper.ts +++ b/utils/fixture-helper/src/initFixtureHelper.ts @@ -2,7 +2,8 @@ import fs = require('fs-extra'); import path = require('path'); import tempy = require('tempy'); -const getId = ((id = 0) => () => id++)(); +const getId = ((id = 0) => (staticId?: number) => + staticId !== undefined ? staticId : id++)(); export function initFixtureHelper( mdl: NodeModule, @@ -22,11 +23,15 @@ export function initFixtureHelper( initOptions: { files?: { [path: string]: string | object }; copy?: { [fromPath: string]: string }; + staticId?: number; } = {} ) => { - const { copy, files } = initOptions; + const { copy, files, staticId } = initOptions; const tempDir = userTempDir - ? path.resolve(userTempDir, `${testName}-${fixtureName}-${getId()}`) + ? path.resolve( + userTempDir, + `${testName}-${fixtureName}-${getId(staticId)}` + ) : tempy.directory(); const fixtureDir = path.resolve(testDir, 'fixtures', fixtureName); diff --git a/utils/fixture-helper/src/resolver.ts b/utils/fixture-helper/src/resolver.ts new file mode 100644 index 0000000..68c20f2 --- /dev/null +++ b/utils/fixture-helper/src/resolver.ts @@ -0,0 +1,50 @@ +import * as globby from 'globby'; +import Path = require('path'); + +interface ResolutionsByTestDir { + [testDir: string]: Record; +} + +interface ResolverOptions { + basedir: string; + defaultResolver: (request: string, options: ResolverOptions) => string; + extensions: string[]; + moduleDirectory: string[]; + paths: string[]; + rootDir: string[]; +} + +function testDirFromResolutionPath(resPath: string): string { + return Path.normalize(Path.parse(resPath).dir); +} +function testDirFromBase(baseDir: string): string { + return Path.join(baseDir, '../__tests__'); +} + +let mapping: ResolutionsByTestDir = {}; + +globby + .sync([`**/__tests__/module-resolution.json`], { + cwd: process.cwd(), + absolute: true, + ignore: ['node_modules', '.yarn', '.github', 'docs', 'private'] + }) + .forEach(file => { + const testDir = testDirFromResolutionPath(file); + mapping[testDir] = require(file); + }); + +function resolver(path: string, options: ResolverOptions): string { + const testDir = testDirFromBase(options.basedir); + + let actualResolution: string | null = null; + + if (mapping[testDir]) { + const resolutionInFile = mapping[testDir][path]; + actualResolution = resolutionInFile && Path.join(testDir, resolutionInFile); + } + + return actualResolution || options.defaultResolver(path, options); +} + +module.exports = resolver;