@@ -9,6 +9,7 @@ import * as path from 'path';
9
9
import { setGlobalVariable } from './e2e/utils/env' ;
10
10
import { gitClean } from './e2e/utils/git' ;
11
11
import { createNpmRegistry } from './e2e/utils/registry' ;
12
+ import { AddressInfo , createServer , Server } from 'net' ;
12
13
13
14
Error . stackTraceLimit = Infinity ;
14
15
@@ -122,93 +123,99 @@ if (testsToRun.length == allTests.length) {
122
123
setGlobalVariable ( 'argv' , argv ) ;
123
124
setGlobalVariable ( 'ci' , process . env [ 'CI' ] ?. toLowerCase ( ) === 'true' || process . env [ 'CI' ] === '1' ) ;
124
125
setGlobalVariable ( 'package-manager' , argv . yarn ? 'yarn' : 'npm' ) ;
125
- setGlobalVariable ( 'package-registry' , 'http://localhost:4873' ) ;
126
126
127
- const registryProcess = createNpmRegistry ( ) ;
128
- const secureRegistryProcess = createNpmRegistry ( true ) ;
127
+ Promise . all ( [ findFreePort ( ) , findFreePort ( ) ] )
128
+ . then ( async ( [ httpPort , httpsPort ] ) => {
129
+ setGlobalVariable ( 'package-registry' , 'http://localhost:' + httpPort ) ;
130
+ setGlobalVariable ( 'package-secure-registry' , 'http://localhost:' + httpsPort ) ;
129
131
130
- testsToRun
131
- . reduce ( ( previous , relativeName , testIndex ) => {
132
- // Make sure this is a windows compatible path.
133
- let absoluteName = path . join ( e2eRoot , relativeName ) ;
134
- if ( / ^ w i n / . test ( process . platform ) ) {
135
- absoluteName = absoluteName . replace ( / \\ / g, path . posix . sep ) ;
136
- }
132
+ const registryProcess = await createNpmRegistry ( httpPort , httpPort ) ;
133
+ const secureRegistryProcess = await createNpmRegistry ( httpPort , httpsPort , true ) ;
137
134
138
- return previous . then ( ( ) => {
139
- currentFileName = relativeName . replace ( / \. t s $ / , '' ) ;
140
- const start = + new Date ( ) ;
135
+ return testsToRun
136
+ . reduce ( ( previous , relativeName , testIndex ) => {
137
+ // Make sure this is a windows compatible path.
138
+ let absoluteName = path . join ( e2eRoot , relativeName ) ;
139
+ if ( / ^ w i n / . test ( process . platform ) ) {
140
+ absoluteName = absoluteName . replace ( / \\ / g, path . posix . sep ) ;
141
+ }
141
142
142
- const module = require ( absoluteName ) ;
143
- const originalEnvVariables = {
144
- ...process . env ,
145
- } ;
143
+ return previous . then ( ( ) => {
144
+ currentFileName = relativeName . replace ( / \. t s $ / , '' ) ;
145
+ const start = + new Date ( ) ;
146
146
147
- const fn : ( skipClean ?: ( ) => void ) => Promise < void > | void =
148
- typeof module == 'function'
149
- ? module
150
- : typeof module . default == 'function'
151
- ? module . default
152
- : ( ) => {
153
- throw new Error ( 'Invalid test module.' ) ;
154
- } ;
147
+ const module = require ( absoluteName ) ;
148
+ const originalEnvVariables = {
149
+ ...process . env ,
150
+ } ;
155
151
156
- let clean = true ;
157
- let previousDir = null ;
152
+ const fn : ( skipClean ?: ( ) => void ) => Promise < void > | void =
153
+ typeof module == 'function'
154
+ ? module
155
+ : typeof module . default == 'function'
156
+ ? module . default
157
+ : ( ) => {
158
+ throw new Error ( 'Invalid test module.' ) ;
159
+ } ;
158
160
159
- return Promise . resolve ( )
160
- . then ( ( ) => printHeader ( currentFileName , testIndex ) )
161
- . then ( ( ) => ( previousDir = process . cwd ( ) ) )
162
- . then ( ( ) => logStack . push ( lastLogger ( ) . createChild ( currentFileName ) ) )
163
- . then ( ( ) => fn ( ( ) => ( clean = false ) ) )
164
- . then (
165
- ( ) => logStack . pop ( ) ,
166
- ( err ) => {
167
- logStack . pop ( ) ;
168
- throw err ;
169
- } ,
170
- )
171
- . then ( ( ) => console . log ( '----' ) )
172
- . then ( ( ) => {
173
- // If we're not in a setup, change the directory back to where it was before the test.
174
- // This allows tests to chdir without worrying about keeping the original directory.
175
- if ( ! allSetups . includes ( relativeName ) && previousDir ) {
176
- process . chdir ( previousDir ) ;
161
+ let clean = true ;
162
+ let previousDir = null ;
177
163
178
- // Restore env variables before each test.
179
- console . log ( ' Restoring original environment variables...' ) ;
180
- process . env = originalEnvVariables ;
181
- }
182
- } )
183
- . then ( ( ) => {
184
- // Only clean after a real test, not a setup step. Also skip cleaning if the test
185
- // requested an exception.
186
- if ( ! allSetups . includes ( relativeName ) && clean ) {
187
- logStack . push ( new logging . NullLogger ( ) ) ;
188
- return gitClean ( ) . then (
164
+ return Promise . resolve ( )
165
+ . then ( ( ) => printHeader ( currentFileName , testIndex ) )
166
+ . then ( ( ) => ( previousDir = process . cwd ( ) ) )
167
+ . then ( ( ) => logStack . push ( lastLogger ( ) . createChild ( currentFileName ) ) )
168
+ . then ( ( ) => fn ( ( ) => ( clean = false ) ) )
169
+ . then (
189
170
( ) => logStack . pop ( ) ,
190
171
( err ) => {
191
172
logStack . pop ( ) ;
192
173
throw err ;
193
174
} ,
175
+ )
176
+ . then ( ( ) => console . log ( '----' ) )
177
+ . then ( ( ) => {
178
+ // If we're not in a setup, change the directory back to where it was before the test.
179
+ // This allows tests to chdir without worrying about keeping the original directory.
180
+ if ( ! allSetups . includes ( relativeName ) && previousDir ) {
181
+ process . chdir ( previousDir ) ;
182
+
183
+ // Restore env variables before each test.
184
+ console . log ( ' Restoring original environment variables...' ) ;
185
+ process . env = originalEnvVariables ;
186
+ }
187
+ } )
188
+ . then ( ( ) => {
189
+ // Only clean after a real test, not a setup step. Also skip cleaning if the test
190
+ // requested an exception.
191
+ if ( ! allSetups . includes ( relativeName ) && clean ) {
192
+ logStack . push ( new logging . NullLogger ( ) ) ;
193
+ return gitClean ( ) . then (
194
+ ( ) => logStack . pop ( ) ,
195
+ ( err ) => {
196
+ logStack . pop ( ) ;
197
+ throw err ;
198
+ } ,
199
+ ) ;
200
+ }
201
+ } )
202
+ . then (
203
+ ( ) => printFooter ( currentFileName , start ) ,
204
+ ( err ) => {
205
+ printFooter ( currentFileName , start ) ;
206
+ console . error ( err ) ;
207
+ throw err ;
208
+ } ,
194
209
) ;
195
- }
196
- } )
197
- . then (
198
- ( ) => printFooter ( currentFileName , start ) ,
199
- ( err ) => {
200
- printFooter ( currentFileName , start ) ;
201
- console . error ( err ) ;
202
- throw err ;
203
- } ,
204
- ) ;
205
- } ) ;
206
- } , Promise . resolve ( ) )
210
+ } ) ;
211
+ } , Promise . resolve ( ) )
212
+ . finally ( ( ) => {
213
+ registryProcess . kill ( ) ;
214
+ secureRegistryProcess . kill ( ) ;
215
+ } ) ;
216
+ } )
207
217
. then (
208
218
( ) => {
209
- registryProcess . kill ( ) ;
210
- secureRegistryProcess . kill ( ) ;
211
-
212
219
console . log ( colors . green ( 'Done.' ) ) ;
213
220
process . exit ( 0 ) ;
214
221
} ,
@@ -218,9 +225,6 @@ testsToRun
218
225
console . error ( colors . red ( err . message ) ) ;
219
226
console . error ( colors . red ( err . stack ) ) ;
220
227
221
- registryProcess . kill ( ) ;
222
- secureRegistryProcess . kill ( ) ;
223
-
224
228
if ( argv . debug ) {
225
229
console . log ( `Current Directory: ${ process . cwd ( ) } ` ) ;
226
230
console . log ( 'Will loop forever while you debug... CTRL-C to quit.' ) ;
@@ -257,3 +261,15 @@ function printFooter(testName: string, startTime: number) {
257
261
console . log ( colors . green ( 'Last step took ' ) + colors . bold . blue ( '' + t ) + colors . green ( 's...' ) ) ;
258
262
console . log ( '' ) ;
259
263
}
264
+
265
+ function findFreePort ( ) {
266
+ return new Promise < number > ( ( resolve , reject ) => {
267
+ const srv = createServer ( ) ;
268
+ srv . once ( 'listening' , ( ) => {
269
+ const port = ( srv . address ( ) as AddressInfo ) . port ;
270
+ srv . close ( ( e ) => ( e ? reject ( e ) : resolve ( port ) ) ) ;
271
+ } ) ;
272
+ srv . once ( 'error' , ( e ) => srv . close ( ( ) => reject ( e ) ) ) ;
273
+ srv . listen ( ) ;
274
+ } ) ;
275
+ }
0 commit comments