diff --git a/__tests__/commands/_helpers.js b/__tests__/commands/_helpers.js index 1a1caacb50..cb52648172 100644 --- a/__tests__/commands/_helpers.js +++ b/__tests__/commands/_helpers.js @@ -122,9 +122,10 @@ export async function run( const config = await Config.create({ binLinks: !!flags.binLinks, cwd, - globalFolder: path.join(cwd, '.yarn-global'), + globalFolder: flags.globalFolder || path.join(cwd, '.yarn-global'), cacheFolder: flags.cacheFolder || path.join(cwd, '.yarn-cache'), linkFolder: flags.linkFolder || path.join(cwd, '.yarn-link'), + prefix: flags.prefix, production: flags.production, }, reporter); diff --git a/__tests__/commands/global.js b/__tests__/commands/global.js index 624cc0a57c..669f867896 100644 --- a/__tests__/commands/global.js +++ b/__tests__/commands/global.js @@ -5,6 +5,7 @@ import {ConsoleReporter} from '../../src/reporters/index.js'; import {run as buildRun} from './_helpers.js'; import {run as global} from '../../src/cli/commands/global.js'; import * as fs from '../../src/util/fs.js'; +import mkdir from '../_temp.js'; const isCI = require('is-ci'); jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000; @@ -34,7 +35,16 @@ function getTempGlobalFolder(): string { return path.join(os.tmpdir(), `yarn-global-${Math.random()}`); } -// this test has global folder side effects, run it only in CI +async function createTempGlobalFolder(): Promise { + return await mkdir('yarn-global'); +} + +async function createTempPrefixFolder(): Promise { + const prefixFolder = await mkdir('yarn-prefix'); + return path.join(prefixFolder, 'bin'); +} + +// these tests have global folder side or prefix folder effects, run it only in CI if (isCI) { test.concurrent('add without flag', (): Promise => { return runGlobal(['add', 'react-native-cli'], {}, 'add-without-flag', async (config) => { @@ -42,23 +52,79 @@ if (isCI) { expect(await fs.exists(path.join(config.globalFolder, 'node_modules', '.bin', 'react-native'))).toEqual(true); }); }); + + test.concurrent('add with prefix flag', (): Promise => { + const tmpGlobalFolder = getTempGlobalFolder(); + return runGlobal(['add', 'react-native-cli'], {prefix: tmpGlobalFolder}, 'add-with-prefix-flag', async (config) => { + expect(await fs.exists(getGlobalPath(tmpGlobalFolder, 'react-native'))).toEqual(true); + }); + }); + + // don't run this test in `concurrent`, it will affect other tests + test('add with PREFIX enviroment variable', (): Promise => { + const tmpGlobalFolder = getTempGlobalFolder(); + const envPrefix = process.env.PREFIX; + process.env.PREFIX = tmpGlobalFolder; + return runGlobal(['add', 'react-native-cli'], {}, 'add-with-prefix-env', async (config) => { + expect(await fs.exists(getGlobalPath(tmpGlobalFolder, 'react-native'))).toEqual(true); + // restore env + process.env.PREFIX = envPrefix; + }); + }); } -test.concurrent('add with prefix flag', (): Promise => { +test.concurrent('bin', (): Promise => { const tmpGlobalFolder = getTempGlobalFolder(); - return runGlobal(['add', 'react-native-cli'], {prefix: tmpGlobalFolder}, 'add-with-prefix-flag', async (config) => { - expect(await fs.exists(getGlobalPath(tmpGlobalFolder, 'react-native'))).toEqual(true); + return runGlobal(['bin'], {prefix: tmpGlobalFolder}, 'add-with-prefix-flag', + (config, reporter, install, getStdout) => { + expect(getStdout()).toContain(tmpGlobalFolder); }); }); -// don't run this test in `concurrent`, it will affect other tests -test('add with PREFIX enviroment variable', (): Promise => { - const tmpGlobalFolder = getTempGlobalFolder(); - const envPrefix = process.env.PREFIX; - process.env.PREFIX = tmpGlobalFolder; - return runGlobal(['add', 'react-native-cli'], {}, 'add-with-prefix-env', async (config) => { - expect(await fs.exists(getGlobalPath(tmpGlobalFolder, 'react-native'))).toEqual(true); - // restore env - process.env.PREFIX = envPrefix; +test.concurrent('add', async (): Promise => { + const tmpGlobalFolder = await createTempGlobalFolder(); + const tmpPrefixFolder = await createTempPrefixFolder(); + const flags = {globalFolder: tmpGlobalFolder, prefix: tmpPrefixFolder}; + return runGlobal(['add', 'react-native-cli'], flags, 'add-with-prefix-flag', + async (config) => { + expect(await fs.exists(path.join(tmpGlobalFolder, 'node_modules', 'react-native-cli'))).toEqual(true); + }); +}); + +test.concurrent('remove', async (): Promise => { + const tmpGlobalFolder = await createTempGlobalFolder(); + const tmpPrefixFolder = await createTempPrefixFolder(); + const flags = {globalFolder: tmpGlobalFolder, prefix: tmpPrefixFolder}; + return runGlobal(['add', 'react-native-cli'], flags, 'add-with-prefix-flag', () => {}) + .then(() => { + return runGlobal(['remove', 'react-native-cli'], flags, 'add-with-prefix-flag', async (config) => { + expect(await fs.exists(path.join(tmpGlobalFolder, 'node_modules', 'react-native-cli'))).toEqual(false); + }); + }); +}); + +test.concurrent('ls', async (): Promise => { + const tmpGlobalFolder = await createTempGlobalFolder(); + const tmpPrefixFolder = await createTempPrefixFolder(); + const flags = {globalFolder: tmpGlobalFolder, prefix: tmpPrefixFolder}; + return runGlobal(['add', 'react-native-cli'], flags, 'add-with-prefix-flag', () => {}) + .then(() => { + return runGlobal(['ls'], flags, 'add-with-prefix-flag', (config, reporter, install, getStdout) => { + expect(getStdout()).toContain('react-native-cli'); + }); + }); +}); + +test.concurrent('upgrade', async (): Promise => { + const tmpGlobalFolder = await createTempGlobalFolder(); + const tmpPrefixFolder = await createTempPrefixFolder(); + const flags = {globalFolder: tmpGlobalFolder, prefix: tmpPrefixFolder}; + return runGlobal(['add', 'react-native-cli@2.0.0'], flags, 'add-with-prefix-flag', () => {}) + .then(() => { + return runGlobal(['upgrade', 'react-native-cli'], flags, 'add-with-prefix-flag', + (config, reporter, install, getStdout) => { + expect(getStdout()).toContain('react-native-cli'); + expect(getStdout()).not.toContain('react-native-cli@2.0.0'); + }); }); }); diff --git a/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/react-native-cli/-/react-native-cli-2.0.0.tgz.bin b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/react-native-cli/-/react-native-cli-2.0.0.tgz.bin new file mode 100644 index 0000000000..c2beaf817c Binary files /dev/null and b/__tests__/fixtures/request-cache/GET/registry.yarnpkg.com/react-native-cli/-/react-native-cli-2.0.0.tgz.bin differ diff --git a/src/cli/commands/global.js b/src/cli/commands/global.js index 05d4e6e980..7697d239bb 100644 --- a/src/cli/commands/global.js +++ b/src/cli/commands/global.js @@ -201,7 +201,7 @@ const {run, setFlags: _setFlags} = buildSubCommands('global', { flags: Object, args: Array, ) { - console.log(getBinFolder(config, flags)); + reporter.log(getBinFolder(config, flags)); }, async ls( @@ -214,7 +214,7 @@ const {run, setFlags: _setFlags} = buildSubCommands('global', { // install so we get hard file paths const lockfile = await Lockfile.fromDirectory(config.cwd); - const install = new Install({skipIntegrity: true}, config, new NoopReporter(), lockfile); + const install = new Install({skipIntegrityCheck: true}, config, new NoopReporter(), lockfile); const patterns = await install.init(); // dump global modules diff --git a/src/cli/index.js b/src/cli/index.js index d56fd91ffb..f5c5ce9484 100644 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -51,7 +51,7 @@ commander.option('--no-lockfile', "don't read or generate a lockfile"); commander.option('--pure-lockfile', "don't generate a lockfile"); commander.option('--frozen-lockfile', "don't generate a lockfile and fail if an update is needed"); commander.option('--link-duplicates', 'create hardlinks to the repeated modules in node_modules'); -commander.option('--global-folder ', ''); +commander.option('--global-folder ', 'specify a custom folder to store global packages'); commander.option( '--modules-folder ', 'rather than installing modules into the node_modules folder relative to the cwd, output them here', @@ -299,7 +299,6 @@ function writeErrorReport(log) : ?string { return errorReportLoc; } -// config.init({ binLinks: commander.binLinks, modulesFolder: commander.modulesFolder, @@ -319,7 +318,6 @@ config.init({ nonInteractive: commander.nonInteractive, commandName: commandName === 'run' ? commander.args[0] : commandName, }).then(() => { - // option "no-progress" stored in yarn config const noProgressConfig = config.registries.yarn.getOption('no-progress');