@@ -3,8 +3,9 @@ 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
+ import { delimiter , join , resolve } from 'path' ;
8
9
const treeKill = require ( 'tree-kill' ) ;
9
10
10
11
interface ExecOptions {
@@ -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 (
@@ -285,22 +286,21 @@ export function silentNpm(
285
286
{
286
287
silent : true ,
287
288
cwd : ( options as { cwd ?: string } | undefined ) ?. cwd ,
288
- env : extractNpmEnv ( ) ,
289
289
} ,
290
290
'npm' ,
291
291
params ,
292
292
) ;
293
293
} else {
294
- return _exec ( { silent : true , env : extractNpmEnv ( ) } , 'npm' , args as string [ ] ) ;
294
+ return _exec ( { silent : true } , 'npm' , args as string [ ] ) ;
295
295
}
296
296
}
297
297
298
298
export function silentYarn ( ...args : string [ ] ) {
299
- return _exec ( { silent : true , env : extractNpmEnv ( ) } , 'yarn' , args ) ;
299
+ return _exec ( { silent : true } , 'yarn' , args ) ;
300
300
}
301
301
302
302
export function npm ( ...args : string [ ] ) {
303
- return _exec ( { env : extractNpmEnv ( ) } , 'npm' , args ) ;
303
+ return _exec ( { } , 'npm' , args ) ;
304
304
}
305
305
306
306
export function node ( ...args : string [ ] ) {
@@ -314,3 +314,39 @@ export function git(...args: string[]) {
314
314
export function silentGit ( ...args : string [ ] ) {
315
315
return _exec ( { silent : true } , 'git' , args ) ;
316
316
}
317
+
318
+ /**
319
+ * Launch the given entry in an child process isolated to the test environment.
320
+ *
321
+ * The test environment includes the local NPM registry, isolated NPM globals,
322
+ * the PATH variable only referencing the local node_modules and local NPM
323
+ * registry (not the test runner or standard global node_modules).
324
+ */
325
+ export async function launchTestProcess ( entry : string , ...args : any [ ] ) {
326
+ const tempRoot : string = getGlobalVariable ( 'tmp-root' ) ;
327
+
328
+ // Extract explicit environment variables for the test process.
329
+ const env = {
330
+ ...extractNpmEnv ( ) ,
331
+ ...getGlobalVariablesEnv ( ) ,
332
+ } ;
333
+
334
+ // Modify the PATH environment variable...
335
+ let paths = process . env . PATH . split ( delimiter ) ;
336
+
337
+ // Only include paths within the sandboxed test environment or external
338
+ // non angular-cli paths such as /usr/bin for generic commands.
339
+ paths = paths . filter ( ( p ) => p . startsWith ( tempRoot ) || ! p . includes ( 'angular-cli' ) ) ;
340
+
341
+ // Ensure the custom npm global bin is on the PATH
342
+ // https://docs.npmjs.com/cli/v8/configuring-npm/folders#executables
343
+ if ( process . platform . startsWith ( 'win' ) ) {
344
+ paths . unshift ( env . NPM_CONFIG_PREFIX ) ;
345
+ } else {
346
+ paths . unshift ( join ( env . NPM_CONFIG_PREFIX , 'bin' ) ) ;
347
+ }
348
+
349
+ env . PATH = paths . join ( delimiter ) ;
350
+
351
+ return _exec ( { env } , process . execPath , [ resolve ( __dirname , 'run_test_process' ) , entry , ...args ] ) ;
352
+ }
0 commit comments