diff --git a/tests/legacy-cli/e2e/initialize/300-log-environment.ts b/tests/legacy-cli/e2e/initialize/300-log-environment.ts index a6c268e094bd..0a787dc10206 100644 --- a/tests/legacy-cli/e2e/initialize/300-log-environment.ts +++ b/tests/legacy-cli/e2e/initialize/300-log-environment.ts @@ -1,4 +1,4 @@ -import { ng } from '../utils/process'; +import { exec, ng } from '../utils/process'; export default async function () { console.log('Environment:'); @@ -13,5 +13,6 @@ export default async function () { console.log(` ${envName}: ${process.env[envName]!.replace(/[\n\r]+/g, '\n ')}`); }); + await exec('which', 'ng', 'yarn', 'npm'); await ng('version'); } diff --git a/tests/legacy-cli/e2e/setup/002-npm-sandbox.ts b/tests/legacy-cli/e2e/setup/002-npm-sandbox.ts index 5d58d8369ae3..e1629552df23 100644 --- a/tests/legacy-cli/e2e/setup/002-npm-sandbox.ts +++ b/tests/legacy-cli/e2e/setup/002-npm-sandbox.ts @@ -1,6 +1,6 @@ import { mkdir, writeFile } from 'fs/promises'; import { join } from 'path'; -import { getGlobalVariable } from '../utils/env'; +import { getGlobalVariable, setGlobalVariable } from '../utils/env'; /** * Configure npm to use a unique sandboxed environment. @@ -8,16 +8,22 @@ import { getGlobalVariable } from '../utils/env'; export default async function () { const tempRoot: string = getGlobalVariable('tmp-root'); const npmModulesPrefix = join(tempRoot, 'npm-global'); + const yarnModulesPrefix = join(tempRoot, 'yarn-global'); const npmRegistry: string = getGlobalVariable('package-registry'); const npmrc = join(tempRoot, '.npmrc'); + const yarnrc = join(tempRoot, '.yarnrc'); - // Configure npm to use the sandboxed npm globals and rc file - // From this point onward all npm transactions use the "global" npm cache - // isolated within this e2e test invocation. + // Change the npm+yarn userconfig to the sandboxed npmrc to override the default ~ process.env.NPM_CONFIG_USERCONFIG = npmrc; - process.env.NPM_CONFIG_PREFIX = npmModulesPrefix; + + // The npm+yarn registry URL process.env.NPM_CONFIG_REGISTRY = npmRegistry; + // Configure npm+yarn to use a sandboxed bin directory + // From this point onward all yarn/npm bin files/symlinks are put into the prefix directories + process.env.NPM_CONFIG_PREFIX = npmModulesPrefix; + process.env.YARN_CONFIG_PREFIX = yarnModulesPrefix; + // Snapshot builds may contain versions that are not yet released (e.g., RC phase main branch). // In this case peer dependency ranges may not resolve causing npm 7+ to fail during tests. // To support this case, legacy peer dependency mode is enabled for snapshot builds. @@ -25,9 +31,16 @@ export default async function () { process.env['NPM_CONFIG_legacy_peer_deps'] = 'true'; } - // Configure the registry and prefix used within the test sandbox + // Configure the registry and prefix used within the test sandbox via rc files await writeFile(npmrc, `registry=${npmRegistry}\nprefix=${npmModulesPrefix}`); + await writeFile(yarnrc, `registry ${npmRegistry}\nprefix ${yarnModulesPrefix}`); + await mkdir(npmModulesPrefix); + await mkdir(yarnModulesPrefix); + + setGlobalVariable('npm-global', npmModulesPrefix); + setGlobalVariable('yarn-global', yarnModulesPrefix); - console.log(` Using "${npmModulesPrefix}" as e2e test global npm cache.`); + console.log(` Using "${npmModulesPrefix}" as e2e test global npm bin dir.`); + console.log(` Using "${yarnModulesPrefix}" as e2e test global yarn bin dir.`); } diff --git a/tests/legacy-cli/e2e/utils/process.ts b/tests/legacy-cli/e2e/utils/process.ts index 88dcce6353dc..33b9ec8054ff 100644 --- a/tests/legacy-cli/e2e/utils/process.ts +++ b/tests/legacy-cli/e2e/utils/process.ts @@ -16,7 +16,7 @@ interface ExecOptions { cwd?: string; } -const NPM_CONFIG_RE = /^npm_config_/i; +const NPM_CONFIG_RE = /^(npm_config_|yarn_)/i; let _processes: child_process.ChildProcess[] = []; @@ -32,11 +32,19 @@ function _exec(options: ExecOptions, cmd: string, args: string[]): Promise x !== undefined); const flags = [ options.silent && 'silent', @@ -51,7 +59,7 @@ function _exec(options: ExecOptions, cmd: string, args: string[]): Promise { - err.message += `${err}...\n\nSTDOUT:\n${stdout}\n\nSTDERR:\n${stderr}\n`; + err.message += `${err}...\n\nENV:${JSON.stringify( + process.env, + null, + 2, + )}\n\nSTDOUT:\n${stdout}\n\nSTDERR:\n${stderr}\n`; reject(err); }); @@ -146,15 +160,10 @@ function _exec(options: ExecOptions, cmd: string, args: string[]): Promise NPM_CONFIG_RE.test(v)) - .reduce( - (vars, n) => { - vars[n] = process.env[n]; - return vars; - }, - { - PATH: process.env.PATH, - }, - ); + .reduce((vars, n) => { + vars[n] = process.env[n]; + return vars; + }, {}); } export function waitForAnyProcessOutputToMatch( @@ -364,20 +373,12 @@ export async function launchTestProcess(entry: string, ...args: any[]) { }; // Modify the PATH environment variable... - let paths = process.env.PATH!.split(delimiter); + let paths = (env.PATH || process.env.PATH)!.split(delimiter); // Only include paths within the sandboxed test environment or external // non angular-cli paths such as /usr/bin for generic commands. paths = paths.filter((p) => p.startsWith(tempRoot) || !p.includes('angular-cli')); - // Ensure the custom npm global bin is on the PATH - // https://docs.npmjs.com/cli/v8/configuring-npm/folders#executables - if (process.platform.startsWith('win')) { - paths.unshift(env.NPM_CONFIG_PREFIX!); - } else { - paths.unshift(join(env.NPM_CONFIG_PREFIX!, 'bin')); - } - env.PATH = paths.join(delimiter); return _exec({ env }, process.execPath, [resolve(__dirname, 'run_test_process'), entry, ...args]);