|
| 1 | +/* @flow */ |
| 2 | + |
| 3 | +jest.mock('../../src/util/execute-lifecycle-script'); |
| 4 | + |
| 5 | +import {BufferReporter} from '../../src/reporters/index.js'; |
| 6 | +import {run} from '../../src/cli/commands/run.js'; |
| 7 | +import * as fs from '../../src/util/fs.js'; |
| 8 | +import * as reporters from '../../src/reporters/index.js'; |
| 9 | +import Config from '../../src/config.js'; |
| 10 | + |
| 11 | +jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000; |
| 12 | + |
| 13 | +const execCommand: $FlowFixMe = require('../../src/util/execute-lifecycle-script').execCommand; |
| 14 | + |
| 15 | +const stream = require('stream'); |
| 16 | +const path = require('path'); |
| 17 | +const os = require('os'); |
| 18 | + |
| 19 | +beforeEach(() => execCommand.mockClear()); |
| 20 | + |
| 21 | +const fixturesLoc = path.join(__dirname, '..', 'fixtures', 'run'); |
| 22 | + |
| 23 | +async function runRun( |
| 24 | + flags: Object, |
| 25 | + args: Array<string>, |
| 26 | + name: string, |
| 27 | + checkRun?: ?(config: Config, reporter: BufferReporter) => ?Promise<void>, |
| 28 | +): Promise<void> { |
| 29 | + const dir = path.join(fixturesLoc, name); |
| 30 | + const cwd = path.join( |
| 31 | + os.tmpdir(), |
| 32 | + `yarn-${path.basename(dir)}-${Math.random()}`, |
| 33 | + ); |
| 34 | + await fs.unlink(cwd); |
| 35 | + await fs.copy(dir, cwd); |
| 36 | + |
| 37 | + for (const {basename, absolute} of await fs.walk(cwd)) { |
| 38 | + if (basename.toLowerCase() === '.ds_store') { |
| 39 | + await fs.unlink(absolute); |
| 40 | + } |
| 41 | + } |
| 42 | + |
| 43 | + let out = ''; |
| 44 | + const stdout = new stream.Writable({ |
| 45 | + decodeStrings: false, |
| 46 | + write(data, encoding, cb) { |
| 47 | + out += data; |
| 48 | + cb(); |
| 49 | + }, |
| 50 | + }); |
| 51 | + |
| 52 | + const reporter = new reporters.BufferReporter({stdout: null, stdin: null}); |
| 53 | + |
| 54 | + // create directories |
| 55 | + await fs.mkdirp(path.join(cwd, '.yarn')); |
| 56 | + await fs.mkdirp(path.join(cwd, 'node_modules')); |
| 57 | + |
| 58 | + try { |
| 59 | + const config = new Config(reporter); |
| 60 | + await config.init({ |
| 61 | + cwd, |
| 62 | + globalFolder: path.join(cwd, '.yarn/.global'), |
| 63 | + cacheFolder: path.join(cwd, '.yarn'), |
| 64 | + linkFolder: path.join(cwd, '.yarn/.link'), |
| 65 | + }); |
| 66 | + |
| 67 | + await run(config, reporter, flags, args); |
| 68 | + |
| 69 | + if (checkRun) { |
| 70 | + await checkRun(config, reporter); |
| 71 | + } |
| 72 | + |
| 73 | + } catch (err) { |
| 74 | + throw new Error(`${err && err.stack} \nConsole output:\n ${out}`); |
| 75 | + } |
| 76 | +} |
| 77 | + |
| 78 | +test('lists all available commands with no arguments', (): Promise<void> => { |
| 79 | + return runRun({}, [], 'no-args', (config, reporter): ?Promise<void> => { |
| 80 | + const rprtr = new reporters.BufferReporter({stdout: null, stdin: null}); |
| 81 | + const scripts = ['build', 'prestart', 'start']; |
| 82 | + // Notice `cat-names` is below twice as there is a bug with output duplication |
| 83 | + const bins = ['cat-names', 'cat-names']; |
| 84 | + |
| 85 | + // Emulate run output |
| 86 | + rprtr.error(rprtr.lang('commandNotSpecified')); |
| 87 | + rprtr.info(`${rprtr.lang('binCommands')}${bins.join(', ')}`); |
| 88 | + rprtr.info(rprtr.lang('possibleCommands')); |
| 89 | + rprtr.list('possibleCommands', scripts); |
| 90 | + rprtr.error(rprtr.lang('commandNotSpecified')); |
| 91 | + |
| 92 | + expect(reporter.getBuffer()).toEqual(rprtr.getBuffer()); |
| 93 | + }); |
| 94 | +}); |
| 95 | + |
| 96 | +test('runs script containing spaces', (): Promise<void> => { |
| 97 | + return runRun({}, ['build'], 'spaces', async (config): ?Promise<void> => { |
| 98 | + const pkg = await fs.readJson(path.join(config.cwd, 'package.json')); |
| 99 | + // The command get's called with a space appended |
| 100 | + const args = ['build', config, pkg.scripts.build + ' ', config.cwd]; |
| 101 | + |
| 102 | + expect(execCommand).toBeCalledWith(...args); |
| 103 | + }); |
| 104 | +}); |
| 105 | + |
| 106 | +test('properly handles extra arguments and pre/post scripts', (): Promise<void> => { |
| 107 | + return runRun({}, ['start', '--hello'], 'extra-args', async (config): ?Promise<void> => { |
| 108 | + const pkg = await fs.readJson(path.join(config.cwd, 'package.json')); |
| 109 | + const poststart = ['poststart', config, pkg.scripts.poststart, config.cwd]; |
| 110 | + const prestart = ['prestart', config, pkg.scripts.prestart, config.cwd]; |
| 111 | + const start = ['start', config, pkg.scripts.start + ' --hello', config.cwd]; |
| 112 | + |
| 113 | + expect(execCommand.mock.calls[0]).toEqual(prestart); |
| 114 | + expect(execCommand.mock.calls[1]).toEqual(start); |
| 115 | + expect(execCommand.mock.calls[2]).toEqual(poststart); |
| 116 | + }); |
| 117 | +}); |
| 118 | + |
| 119 | +test('handles bin scripts', (): Promise<void> => { |
| 120 | + return runRun({}, ['cat-names'], 'bin', (config) => { |
| 121 | + const script = path.join(config.cwd, 'node_modules', '.bin', 'cat-names'); |
| 122 | + const args = ['cat-names', config, `"${script}" `, config.cwd]; |
| 123 | + |
| 124 | + expect(execCommand).toBeCalledWith(...args); |
| 125 | + }); |
| 126 | +}); |
0 commit comments