diff --git a/package.json b/package.json index daf6116..1a25e25 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ts-patch", - "version": "1.2.5", + "version": "1.3.0", "description": "Patch typescript to support custom transformers in tsconfig.json", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -65,6 +65,7 @@ "jest-mock-process": "^1.4.0", "mock-fs": "^4.12.0", "resolve": "^1.15.1", + "rfdc": "^1.1.4", "rimraf": "^3.0.2", "rollup": "^2.1.0", "rollup-plugin-dts": "^1.4.7", diff --git a/test/lib/mock-utils.ts b/test/lib/mock-utils.ts index a984ab4..3014c7d 100755 --- a/test/lib/mock-utils.ts +++ b/test/lib/mock-utils.ts @@ -7,19 +7,21 @@ import { resourcesDir, testAssetsDir, tsInstallationDirs, tsProjectsDir } from ' import { patch } from '../../src/installer'; import { normalizeSlashes } from 'ts-node'; import resolve from 'resolve'; +import FileSystem from 'mock-fs/lib/filesystem'; /* ****************************************************************************************************************** */ // region: Constants /* ****************************************************************************************************************** */ -const vanillaFiles = [ - ...cacheDirectory(tsProjectsDir), - ...cacheDirectory(resourcesDir), - ...cacheDirectory(testAssetsDir) -]; +const vanillaFiles = cacheDirectories( + tsProjectsDir, + resourcesDir, + testAssetsDir +); let patchedFiles = new Map(); +const cachedFiles = new Map(); // endregion @@ -28,11 +30,28 @@ let patchedFiles = new Map(); // region: Helpers /* ****************************************************************************************************************** */ -function cacheDirectory(dir: string): [ string, string | {} ][] { - return (shell.ls('-RAl', dir) as unknown as (fs.Stats & { name: string })[]).map(stat => { - const statPath = normalizeSlashes(path.join(dir, stat.name)); - return [ statPath, stat.isFile() ? fs.readFileSync(statPath, 'utf-8') : {} ] - }); +/** + * Create a DirectoryItems from actual files and directories for mock-fs (uses caching) + */ +function cacheDirectories(...directory: string[]): FileSystem.DirectoryItems { + const res: FileSystem.DirectoryItems = {}; + for (const dir of directory) + for (const stat of shell.ls('-RAl', dir) as unknown as (fs.Stats & { name: string })[]) { + const statPath = normalizeSlashes(path.join(dir, stat.name)); + res[statPath] = + !stat.isFile() ? {} : + >(() => { + const fileData = fs.readFileSync(statPath); + cachedFiles.set(statPath, fileData); + + return Object.defineProperty(mock.file({ content: '' })(), '_content', { + get: () => cachedFiles.get(statPath), + set: (data: any) => cachedFiles.set(statPath, data) + }); + }); + } + + return res; } // endregion @@ -42,12 +61,13 @@ function cacheDirectory(dir: string): [ string, string | {} ][] { // region: FileSystem /* ****************************************************************************************************************** */ -export function mockFs(fileEntries: [ string, string | {} ][] = vanillaFiles) { - mock(fileEntries.reduce((p, [key, value]) => { p[key] = value; return p; }, >{})); +export function mockFs() { + mock(vanillaFiles); } export function restoreFs() { mock.restore(); + cachedFiles.clear(); } export function resetFs() { diff --git a/test/patch/specified-project.test.ts b/test/patch/specified-project.test.ts index a611d6f..c1fdaf0 100755 --- a/test/patch/specified-project.test.ts +++ b/test/patch/specified-project.test.ts @@ -1,7 +1,7 @@ /** * Test cases for specifying tsconfig as 'project' in config. * - * Note: Unfortunately, because of jest's sandbox, we cannot directly test path mapping. It is not able to resolve + * Notes: Unfortunately, because of jest's sandbox, we cannot directly test path mapping. It is not able to resolve * mapped paths. Ideally, we'd be able to execute virtually in a context outside of * jest, but there is not currently a clear way to do this. * @@ -16,14 +16,20 @@ import child_process from 'child_process'; import { getPatchedTS } from '../lib/mock-utils'; +/* ****************************************************************************************************************** * + * Config + * ****************************************************************************************************************** */ + +const srcFilesPath = path.join(testAssetsDir, 'src-files/transformer-with-project'); +const destDir = path.join(os.tmpdir(), 'tmpTSC'); +const tscPath = path.join(destDir, 'node_modules/typescript/lib/tsc.js'); + + /* ****************************************************************************************************************** * * Tests * ****************************************************************************************************************** */ describe('Specify Project', () => { - const srcFilesPath = path.join(testAssetsDir, 'src-files/transformer-with-project'); - const destDir = path.join(os.tmpdir(), 'tmpTSC'); - const tscPath = path.join(destDir, 'node_modules/typescript/lib/tsc.js'); beforeAll(() => { const { tscCode } = getPatchedTS('latest'); @@ -39,21 +45,21 @@ describe('Specify Project', () => { test(`Loads project file & path mapping works`, () => { const cmd = `node ${tscPath} --noEmit false -p ${srcFilesPath}`; - const res = child_process.execSync(cmd, { stdio: 'pipe' }); - expect(res.toString()).toMatch(/Path-Mapping Success!/); + const res = child_process.spawnSync(cmd, { stdio: 'pipe', shell: true }); + expect(res.stdout.toString()).toMatch(/Path-Mapping Success!/); }); test(`Mapping fails without project specified`, () => { const cmd = `node ${tscPath} --noEmit false -p ${path.join(srcFilesPath, 'tsconfig.noproject.json')}`; - const fail = () => child_process.execSync(cmd, { stdio: 'pipe' }); - expect(fail).toThrow(/Cannot find module '#a'/); + const res = child_process.spawnSync(cmd, { stdio: 'pipe', shell: true }); + expect(res.stderr.toString()).toMatch(/Cannot find module '#a'/); }); test(`Logs warning if can't find tsconfig-paths`, () => { shell.rm('-r', path.join(destDir, 'node_modules/tsconfig-paths')); const cmd = `node ${tscPath} --noEmit false -p ${srcFilesPath}`; - const fail = () => child_process.execSync(cmd, { stdio: 'pipe' }); - expect(fail).toThrow(/Try adding 'tsconfig-paths'/); + const res = child_process.spawnSync(cmd, { stdio: 'pipe', shell: true }); + expect(res.stderr.toString()).toMatch(/Try adding 'tsconfig-paths'/); }); }); diff --git a/tsconfig.base.json b/tsconfig.base.json index de2bb6b..b6fe486 100755 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -9,7 +9,7 @@ "lib": [ "es2019" ], "outDir": "dist", "target": "es5", - "module":"CommonJS", + "module": "CommonJS", "moduleResolution": "node", "newLine": "LF", diff --git a/yarn.lock b/yarn.lock index f9c3758..921dc83 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3439,6 +3439,11 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== +rfdc@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.1.4.tgz#ba72cc1367a0ccd9cf81a870b3b58bd3ad07f8c2" + integrity sha512-5C9HXdzK8EAqN7JDif30jqsBzavB7wLpaubisuQIGHWf2gUXSpzy6ArX/+Da8RjFpagWsCn+pIgxTMAmKw9Zug== + rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"