@@ -3,9 +3,10 @@ import { SpawnOptions } from 'child_process';
3
3
import * as child_process from 'child_process' ;
4
4
import { concat , defer , EMPTY , from } from 'rxjs' ;
5
5
import { repeat , takeLast } from 'rxjs/operators' ;
6
- import { getGlobalVariable } from './env' ;
6
+ import { getGlobalVariable , getGlobalVariablesEnv } from './env' ;
7
7
import { catchError } from 'rxjs/operators' ;
8
8
import treeKill from 'tree-kill' ;
9
+ import { delimiter , join , resolve } from 'path' ;
9
10
10
11
interface ExecOptions {
11
12
silent ?: boolean ;
@@ -140,7 +141,7 @@ function _exec(options: ExecOptions, cmd: string, args: string[]): Promise<Proce
140
141
} ) ;
141
142
}
142
143
143
- export function extractNpmEnv ( ) {
144
+ export function extractNpmEnv ( ) : { [ k : string ] : string } {
144
145
return Object . keys ( process . env )
145
146
. filter ( ( v ) => NPM_CONFIG_RE . test ( v ) )
146
147
. reduce (
@@ -299,22 +300,21 @@ export function silentNpm(
299
300
{
300
301
silent : true ,
301
302
cwd : ( options as { cwd ?: string } | undefined ) ?. cwd ,
302
- env : extractNpmEnv ( ) ,
303
303
} ,
304
304
'npm' ,
305
305
params ,
306
306
) ;
307
307
} else {
308
- return _exec ( { silent : true , env : extractNpmEnv ( ) } , 'npm' , args as string [ ] ) ;
308
+ return _exec ( { silent : true } , 'npm' , args as string [ ] ) ;
309
309
}
310
310
}
311
311
312
312
export function silentYarn ( ...args : string [ ] ) {
313
- return _exec ( { silent : true , env : extractNpmEnv ( ) } , 'yarn' , args ) ;
313
+ return _exec ( { silent : true } , 'yarn' , args ) ;
314
314
}
315
315
316
316
export function npm ( ...args : string [ ] ) {
317
- return _exec ( { env : extractNpmEnv ( ) } , 'npm' , args ) ;
317
+ return _exec ( { } , 'npm' , args ) ;
318
318
}
319
319
320
320
export function node ( ...args : string [ ] ) {
@@ -328,3 +328,39 @@ export function git(...args: string[]) {
328
328
export function silentGit ( ...args : string [ ] ) {
329
329
return _exec ( { silent : true } , 'git' , args ) ;
330
330
}
331
+
332
+ /**
333
+ * Launch the given entry in an child process isolated to the test environment.
334
+ *
335
+ * The test environment includes the local NPM registry, isolated NPM globals,
336
+ * the PATH variable only referencing the local node_modules and local NPM
337
+ * registry (not the test runner or standard global node_modules).
338
+ */
339
+ export async function launchTestProcess ( entry : string , ...args : any [ ] ) {
340
+ const tempRoot : string = getGlobalVariable ( 'tmp-root' ) ;
341
+
342
+ // Extract explicit environment variables for the test process.
343
+ const env = {
344
+ ...extractNpmEnv ( ) ,
345
+ ...getGlobalVariablesEnv ( ) ,
346
+ } ;
347
+
348
+ // Modify the PATH environment variable...
349
+ let paths = process . env . PATH . split ( delimiter ) ;
350
+
351
+ // Only include paths within the sandboxed test environment or external
352
+ // non angular-cli paths such as /usr/bin for generic commands.
353
+ paths = paths . filter ( ( p ) => p . startsWith ( tempRoot ) || ! p . includes ( 'angular-cli' ) ) ;
354
+
355
+ // Ensure the custom npm global bin is on the PATH
356
+ // https://docs.npmjs.com/cli/v8/configuring-npm/folders#executables
357
+ if ( process . platform . startsWith ( 'win' ) ) {
358
+ paths . unshift ( env . NPM_CONFIG_PREFIX ) ;
359
+ } else {
360
+ paths . unshift ( join ( env . NPM_CONFIG_PREFIX , 'bin' ) ) ;
361
+ }
362
+
363
+ env . PATH = paths . join ( delimiter ) ;
364
+
365
+ return _exec ( { env } , process . execPath , [ resolve ( __dirname , 'run_test_process' ) , entry , ...args ] ) ;
366
+ }
0 commit comments