10
10
11
11
import path from 'path' ;
12
12
import fs from 'fs' ;
13
- import execa , { sync as spawnSync } from 'execa' ;
13
+ import execa from 'execa' ;
14
14
import { Writable } from 'readable-stream' ;
15
15
import stripAnsi from 'strip-ansi' ;
16
16
import { normalizeIcons } from './Utils' ;
@@ -20,7 +20,8 @@ const JEST_PATH = path.resolve(__dirname, '../packages/jest-cli/bin/jest.js');
20
20
type RunJestOptions = {
21
21
nodePath ?: string ,
22
22
skipPkgJsonCheck ?: boolean , // don't complain if can't find package.json
23
- stripAnsi ?: boolean , // remove colors from stdout and stderr
23
+ stripAnsi ?: boolean , // remove colors from stdout and stderr,
24
+ timeout ?: number , // kill the Jest process after X milliseconds
24
25
} ;
25
26
26
27
// return the result of the spawned process:
@@ -30,6 +31,16 @@ export default function runJest(
30
31
dir : string ,
31
32
args ?: Array < string > ,
32
33
options : RunJestOptions = { } ,
34
+ ) {
35
+ return normalizeResult ( spawnJest ( dir , args , options ) , options ) ;
36
+ }
37
+
38
+ // Spawns Jest and returns either a Promise (if spawnAsync is true) or the completed child process
39
+ function spawnJest (
40
+ dir : string ,
41
+ args ?: Array < string > ,
42
+ options : RunJestOptions = { } ,
43
+ spawnAsync : boolean = false ,
33
44
) {
34
45
const isRelative = ! path . isAbsolute ( dir ) ;
35
46
@@ -51,12 +62,23 @@ export default function runJest(
51
62
52
63
const env = { ...process . env , FORCE_COLOR : 0 } ;
53
64
if ( options . nodePath ) env [ 'NODE_PATH' ] = options . nodePath ;
54
- const result = spawnSync ( JEST_PATH , args || [ ] , {
65
+
66
+ const spawnArgs = [ JEST_PATH , ...( args || [ ] ) ] ;
67
+ const spawnOptions = {
55
68
cwd : dir ,
56
69
env,
57
70
reject : false ,
58
- } ) ;
71
+ timeout : options . timeout || 0 ,
72
+ } ;
59
73
74
+ return ( spawnAsync ? execa : execa . sync ) (
75
+ process . execPath ,
76
+ spawnArgs ,
77
+ spawnOptions ,
78
+ ) ;
79
+ }
80
+
81
+ function normalizeResult ( result , options ) {
60
82
// For compat with cross-spawn
61
83
result . status = result . code ;
62
84
@@ -101,34 +123,7 @@ export const until = async function(
101
123
text : string ,
102
124
options : RunJestOptions = { } ,
103
125
) {
104
- const isRelative = ! path . isAbsolute ( dir ) ;
105
-
106
- if ( isRelative ) {
107
- dir = path . resolve ( __dirname , dir ) ;
108
- }
109
-
110
- const localPackageJson = path . resolve ( dir , 'package.json' ) ;
111
- if ( ! options . skipPkgJsonCheck && ! fs . existsSync ( localPackageJson ) ) {
112
- throw new Error (
113
- `
114
- Make sure you have a local package.json file at
115
- "${ localPackageJson } ".
116
- Otherwise Jest will try to traverse the directory tree and find the
117
- the global package.json, which will send Jest into infinite loop.
118
- ` ,
119
- ) ;
120
- }
121
-
122
- const env = { ...process . env , FORCE_COLOR : 0 } ;
123
- if ( options . nodePath ) env [ 'NODE_PATH' ] = options . nodePath ;
124
-
125
- const jestPromise = execa ( JEST_PATH , args || [ ] , {
126
- cwd : dir ,
127
- env,
128
- reject : false ,
129
- // this should never take more than 5-6 seconds, bailout after 30
130
- timeout : 30000 ,
131
- } ) ;
126
+ const jestPromise = spawnJest ( dir , args , { timeout : 30000 , ...options } , true ) ;
132
127
133
128
jestPromise . stderr . pipe (
134
129
new Writable ( {
@@ -144,15 +139,5 @@ export const until = async function(
144
139
} ) ,
145
140
) ;
146
141
147
- const result = await jestPromise ;
148
-
149
- // For compat with cross-spawn
150
- result . status = result . code ;
151
-
152
- result . stdout = normalizeIcons ( result . stdout ) ;
153
- if ( options . stripAnsi ) result . stdout = stripAnsi ( result . stdout ) ;
154
- result . stderr = normalizeIcons ( result . stderr ) ;
155
- if ( options . stripAnsi ) result . stderr = stripAnsi ( result . stderr ) ;
156
-
157
- return result ;
142
+ return normalizeResult ( await jestPromise , options ) ;
158
143
} ;
0 commit comments