@@ -9,6 +9,7 @@ import * as path from 'path';
99import { setGlobalVariable } from './e2e/utils/env' ;
1010import { gitClean } from './e2e/utils/git' ;
1111import { createNpmRegistry } from './e2e/utils/registry' ;
12+ import { AddressInfo , createServer , Server } from 'net' ;
1213
1314Error . stackTraceLimit = Infinity ;
1415
@@ -122,93 +123,99 @@ if (testsToRun.length == allTests.length) {
122123setGlobalVariable ( 'argv' , argv ) ;
123124setGlobalVariable ( 'ci' , process . env [ 'CI' ] ?. toLowerCase ( ) === 'true' || process . env [ 'CI' ] === '1' ) ;
124125setGlobalVariable ( 'package-manager' , argv . yarn ? 'yarn' : 'npm' ) ;
125- setGlobalVariable ( 'package-registry' , 'http://localhost:4873' ) ;
126126
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 ) ;
129131
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 ) ;
137134
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+ }
141142
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 ( ) ;
146146
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+ } ;
155151
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+ } ;
158160
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 ;
177163
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 (
189170 ( ) => logStack . pop ( ) ,
190171 ( err ) => {
191172 logStack . pop ( ) ;
192173 throw err ;
193174 } ,
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+ } ,
194209 ) ;
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+ } )
207217 . then (
208218 ( ) => {
209- registryProcess . kill ( ) ;
210- secureRegistryProcess . kill ( ) ;
211-
212219 console . log ( colors . green ( 'Done.' ) ) ;
213220 process . exit ( 0 ) ;
214221 } ,
@@ -218,9 +225,6 @@ testsToRun
218225 console . error ( colors . red ( err . message ) ) ;
219226 console . error ( colors . red ( err . stack ) ) ;
220227
221- registryProcess . kill ( ) ;
222- secureRegistryProcess . kill ( ) ;
223-
224228 if ( argv . debug ) {
225229 console . log ( `Current Directory: ${ process . cwd ( ) } ` ) ;
226230 console . log ( 'Will loop forever while you debug... CTRL-C to quit.' ) ;
@@ -257,3 +261,15 @@ function printFooter(testName: string, startTime: number) {
257261 console . log ( colors . green ( 'Last step took ' ) + colors . bold . blue ( '' + t ) + colors . green ( 's...' ) ) ;
258262 console . log ( '' ) ;
259263}
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