88
99const fs = require ( 'fs' ) ;
1010const path = require ( 'path' ) ;
11- const { jestRunner } = require ( './jest' ) ;
12- const shell = require ( './shell' ) ;
13-
14- const { error, info } = require ( '../log' ) ;
11+ const { spawn } = require ( 'child_process' ) ;
1512
1613const { PROJECT_ROOT , getSfdxProjectJson } = require ( './project' ) ;
1714
18- const { jestConfig, expectedApiVersion, jestPath } = require ( '../config' ) ;
19-
20- // CLI options we do not want to pass along to Jest
21- // prettier-ignore
22- const OPTIONS_DISALLOW_LIST = [
23- '_' ,
24- '$0' ,
25- 'debug' , 'd' ,
26- 'skipApiVersionCheck' , 'skip-api-version-check'
27- ] ;
28-
29- function getOptions ( argv ) {
30- let options = [ ] ;
15+ const { error, info } = require ( '../log' ) ;
16+ const { jestConfig, expectedApiVersion } = require ( '../config' ) ;
3117
32- Object . keys ( argv ) . forEach ( ( arg ) => {
33- if ( argv [ arg ] && ! OPTIONS_DISALLOW_LIST . includes ( arg ) ) {
34- options . push ( `--${ arg } ` ) ;
35- }
36- } ) ;
37- return options . concat ( argv . _ ) ;
38- }
18+ // List of CLI options that should be passthrough to jest.
19+ const JEST_PASSTHROUGH_OPTIONS = new Set ( [ 'coverage' , 'updateSnapshot' , 'verbose' , 'watch' ] ) ;
3920
4021function validSourceApiVersion ( ) {
4122 const sfdxProjectJson = getSfdxProjectJson ( ) ;
@@ -47,33 +28,61 @@ function validSourceApiVersion() {
4728 }
4829}
4930
31+ function getJestPath ( ) {
32+ const packageJsonPath = require . resolve ( 'jest/package.json' ) ;
33+
34+ const { bin } = require ( packageJsonPath ) ;
35+ return path . resolve ( path . dirname ( packageJsonPath ) , bin ) ;
36+ }
37+
38+ function getJestArgs ( argv ) {
39+ // Extract known options from parsed arguments
40+ const knownOptions = Object . keys ( argv )
41+ . filter ( ( key ) => argv [ key ] && JEST_PASSTHROUGH_OPTIONS . has ( key ) )
42+ . map ( ( key ) => `--${ key } ` ) ;
43+
44+ // Extract remaining options after `--`
45+ const rest = argv . _ ;
46+
47+ const jestArgs = [ ...knownOptions , ...rest ] ;
48+
49+ // Force jest to run in band when debugging.
50+ if ( argv . debug ) {
51+ jestArgs . unshift ( '--runInBand' ) ;
52+ }
53+
54+ // Provide default configuration when none is present at the project root.
55+ const hasCustomConfig = fs . existsSync ( path . resolve ( PROJECT_ROOT , 'jest.config.js' ) ) ;
56+ if ( ! hasCustomConfig ) {
57+ jestArgs . unshift ( `--config=${ JSON . stringify ( jestConfig ) } ` ) ;
58+ }
59+
60+ return jestArgs ;
61+ }
62+
5063async function testRunner ( argv ) {
5164 if ( ! argv . skipApiVersionCheck ) {
5265 validSourceApiVersion ( ) ;
5366 }
5467
55- const hasCustomConfig = fs . existsSync ( path . resolve ( PROJECT_ROOT , 'jest.config.js' ) ) ;
56- const config = hasCustomConfig ? [ ] : [ '--config' , JSON . stringify ( jestConfig ) ] ;
68+ const spawnCommand = 'node' ;
69+ const spawnArgs = [ getJestPath ( ) , ... getJestArgs ( argv ) ] ;
5770
58- const options = getOptions ( argv ) ;
5971 if ( argv . debug ) {
72+ spawnArgs . unshift ( '--inspect-brk' ) ;
73+
6074 info ( 'Running in debug mode...' ) ;
61- let commandArgs = [ '--inspect-brk' , jestPath , '--runInBand' ] ;
62- commandArgs = commandArgs . concat ( options ) ;
63- if ( ! hasCustomConfig ) {
64- commandArgs . push ( '--config=' + JSON . stringify ( jestConfig ) ) ;
65- }
66- const command = 'node' ;
67- info ( command + ' ' + commandArgs . join ( ' ' ) ) ;
68-
69- shell . runCommand ( command , commandArgs ) ;
70- } else {
71- // Jest will not set the env if not run from the bin executable
72- if ( process . env . NODE_ENV == null ) {
73- process . env . NODE_ENV = 'test' ;
74- }
75- jestRunner . run ( [ ...config , ...options ] ) ;
75+ info ( `${ spawnCommand } ${ spawnArgs . join ( ' ' ) } ` ) ;
7676 }
77+
78+ return new Promise ( ( resolve ) => {
79+ const jest = spawn ( spawnCommand , spawnArgs , {
80+ env : process . env ,
81+ stdio : 'inherit' ,
82+ } ) ;
83+
84+ jest . on ( 'close' , ( code ) => resolve ( code ) ) ;
85+ } ) ;
7786}
7887
7988module . exports = testRunner ;
0 commit comments