From 7d3a712a05ca3d032f942e59ba7d2b6f5f096334 Mon Sep 17 00:00:00 2001 From: Ahn Date: Tue, 21 Sep 2021 06:58:38 +0200 Subject: [PATCH] fix(utils): allow skipping `ngcc-jest-processor` via some Jest args (#1013) --- src/__tests__/ngcc-jest-processor.spec.ts | 47 ++++++++++++++ src/utils/ngcc-jest-processor.ts | 75 ++++++++++++----------- 2 files changed, 85 insertions(+), 37 deletions(-) create mode 100644 src/__tests__/ngcc-jest-processor.spec.ts diff --git a/src/__tests__/ngcc-jest-processor.spec.ts b/src/__tests__/ngcc-jest-processor.spec.ts new file mode 100644 index 0000000000..667f26c4c4 --- /dev/null +++ b/src/__tests__/ngcc-jest-processor.spec.ts @@ -0,0 +1,47 @@ +import child_process from 'child_process'; + +describe('ngcc-jest-processor', () => { + test.concurrent.each(['--clearCache', '--help', '--init', '--listTests', '--showConfig'])( + 'should not run ngcc when having excluded Jest args', + async (ignoreArg) => { + child_process.spawnSync = jest.fn(); + process.argv.push(ignoreArg); + + await import('../utils/ngcc-jest-processor'); + + expect(child_process.spawnSync).not.toHaveBeenCalled(); + }, + ); + + test.concurrent('should run ngcc when not having excluded Jest args with successful result', async () => { + const mockedSpawnSync = (child_process.spawnSync = jest.fn().mockReturnValueOnce({ + status: 0, + })); + process.argv = []; + process.stdout.write = jest.fn(); + + await import('../utils/ngcc-jest-processor'); + + expect(process.stdout.write).toHaveBeenCalledWith('ngcc-jest-processor: running ngcc\n'); + expect(mockedSpawnSync).toHaveBeenCalled(); + expect( + mockedSpawnSync.mock.calls[0][1].map((callArg: string) => + callArg.includes('node_modules') + ? callArg.substring(callArg.indexOf('node_modules')).replace(/\\/g, '/') + : callArg, + ), + ).toMatchInlineSnapshot(` + Array [ + "node_modules/@angular/compiler-cli/ngcc/main-ngcc.js", + "--source", + "node_modules/", + "--properties", + "es2015", + "main", + "--first-only", + "false", + "--async", + ] + `); + }); +}); diff --git a/src/utils/ngcc-jest-processor.ts b/src/utils/ngcc-jest-processor.ts index 145a01a76e..ff60ac0630 100644 --- a/src/utils/ngcc-jest-processor.ts +++ b/src/utils/ngcc-jest-processor.ts @@ -8,7 +8,6 @@ import { sep } from 'path'; const IGNORE_ARGS = ['--clearCache', '--help', '--init', '--listTests', '--showConfig']; const ANGULAR_COMPILER_CLI_PKG_NAME = `@angular${sep}compiler-cli`; const nodeModuleDirPath = findNodeModulesDirectory(); -const canRunNgcc = !process.argv.find((arg) => IGNORE_ARGS.includes(arg)) && !!nodeModuleDirPath; function findNodeModulesDirectory(): string { let nodeModulesPath = ''; @@ -23,42 +22,44 @@ function findNodeModulesDirectory(): string { return nodeModulesPath; } -if (canRunNgcc) { - process.stdout.write('ngcc-jest-processor: running ngcc\n'); - // We spawn instead of using the API because: - // - NGCC Async uses clustering which is problematic when used via the API which means - // that we cannot setup multiple cluster masters with different options. - // - We will not be able to have concurrent builds otherwise Ex: App-Shell, - // as NGCC will create a lock file for both builds and it will cause builds to fails. - const { status, error } = spawnSync( - process.execPath, - [ - require.resolve('@angular/compiler-cli/ngcc/main-ngcc.js'), - '--source' /** basePath */, - nodeModuleDirPath, - '--properties' /** propertiesToConsider */, - /** - * There are various properties: fesm2015, fesm5, es2015, esm2015, esm5, main, module, browser to choose from. - * Normally, Jest requires `umd`. If running Jest in ESM mode, Jest will require both `umd` + `esm2015`. - */ - ...['es2015', 'main'], - '--first-only' /** compileAllFormats */, - 'false', // make sure that `ngcc` runs on subfolders as well - '--async', - ], - { - stdio: ['inherit', process.stderr, process.stderr], - }, - ); - if (status !== 0) { - const errorMessage: string = error?.message ?? ''; +if (!process.argv.find((arg) => IGNORE_ARGS.includes(arg))) { + if (nodeModuleDirPath) { + process.stdout.write('ngcc-jest-processor: running ngcc\n'); + // We spawn instead of using the API because: + // - NGCC Async uses clustering which is problematic when used via the API which means + // that we cannot setup multiple cluster masters with different options. + // - We will not be able to have concurrent builds otherwise Ex: App-Shell, + // as NGCC will create a lock file for both builds and it will cause builds to fails. + const { status, error } = spawnSync( + process.execPath, + [ + require.resolve('@angular/compiler-cli/ngcc/main-ngcc.js'), + '--source' /** basePath */, + nodeModuleDirPath, + '--properties' /** propertiesToConsider */, + /** + * There are various properties: fesm2015, fesm5, es2015, esm2015, esm5, main, module, browser to choose from. + * Normally, Jest requires `umd`. If running Jest in ESM mode, Jest will require both `umd` + `esm2015`. + */ + ...['es2015', 'main'], + '--first-only' /** compileAllFormats */, + 'false', // make sure that `ngcc` runs on subfolders as well + '--async', + ], + { + stdio: ['inherit', process.stderr, process.stderr], + }, + ); + if (status !== 0) { + const errorMessage: string = error?.message ?? ''; - throw new Error(`${errorMessage} NGCC failed ${errorMessage ? ', see above' : ''}.`); + throw new Error(`${errorMessage} NGCC failed ${errorMessage ? ', see above' : ''}.`); + } + } else { + console.log( + `Warning: Could not locate '@angular/compiler-cli' to run 'ngcc' automatically.` + + `Please make sure you are running 'ngcc-jest-processor.js' from root level of your project.` + + `'ngcc' must be run before running Jest`, + ); } -} else { - console.log( - `Warning: Could not locate '@angular/compiler-cli' to run 'ngcc' automatically.` + - `Please make sure you are running 'ngcc-jest-processor.js' from root level of your project.` + - `'ngcc' must be run before running Jest`, - ); }