diff --git a/__tests__/__snapshots__/index.js.snap b/__tests__/__snapshots__/index.js.snap new file mode 100644 index 0000000000..c7154dd81b --- /dev/null +++ b/__tests__/__snapshots__/index.js.snap @@ -0,0 +1,78 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should add lockfile package 1`] = ` +Array [ + "info No lockfile found.", + "[1/4] Resolving packages...", + "[2/4] Fetching packages...", + "[3/4] Linking dependencies...", + "[4/4] Building fresh packages...", + "success Saved lockfile.", + "success Saved 1 new dependency.", + "info Direct dependencies", + "└─ lockfile@1.0.3", + "info All dependencies", + "└─ lockfile@1.0.3", +] +`; + +exports[`should add package 1`] = ` +Array [ + "info No lockfile found.", + "[1/4] Resolving packages...", + "[2/4] Fetching packages...", + "[3/4] Linking dependencies...", + "[4/4] Building fresh packages...", + "success Saved lockfile.", + "success Saved 1 new dependency.", + "info Direct dependencies", + "└─ left-pad@1.2.0", + "info All dependencies", + "└─ left-pad@1.2.0", +] +`; + +exports[`should add package with frozen-lockfile option 1`] = ` +Array [ + "info No lockfile found.", + "[1/4] Resolving packages...", + "[2/4] Fetching packages...", + "[3/4] Linking dependencies...", + "[4/4] Building fresh packages...", + "success Saved 1 new dependency.", + "info Direct dependencies", + "└─ repeating@3.0.0", + "info All dependencies", + "└─ repeating@3.0.0", +] +`; + +exports[`should add package with no-lockfile option 1`] = ` +Array [ + "info No lockfile found.", + "[1/4] Resolving packages...", + "[2/4] Fetching packages...", + "[3/4] Linking dependencies...", + "[4/4] Building fresh packages...", + "success Saved 1 new dependency.", + "info Direct dependencies", + "└─ repeating@3.0.0", + "info All dependencies", + "└─ repeating@3.0.0", +] +`; + +exports[`should add package with no-lockfile option in front 1`] = ` +Array [ + "info No lockfile found.", + "[1/4] Resolving packages...", + "[2/4] Fetching packages...", + "[3/4] Linking dependencies...", + "[4/4] Building fresh packages...", + "success Saved 1 new dependency.", + "info Direct dependencies", + "└─ split-lines@1.1.0", + "info All dependencies", + "└─ split-lines@1.1.0", +] +`; diff --git a/__tests__/__snapshots__/integration.js.snap b/__tests__/__snapshots__/integration.js.snap index 88b894d032..e736395656 100644 --- a/__tests__/__snapshots__/integration.js.snap +++ b/__tests__/__snapshots__/integration.js.snap @@ -8,5 +8,8 @@ exports[`yarnrc-args 1`] = ` {\\"type\\":\\"step\\",\\"data\\":{\\"message\\":\\"Building fresh packages\\",\\"current\\":4,\\"total\\":4}} {\\"type\\":\\"success\\",\\"data\\":\\"Saved lockfile.\\"} {\\"type\\":\\"success\\",\\"data\\":\\"Saved 1 new dependency.\\"} -{\\"type\\":\\"tree\\",\\"data\\":{\\"type\\":\\"newDependencies\\",\\"trees\\":[{\\"name\\":\\"left-pad@1.1.3\\",\\"children\\":[],\\"hint\\":null,\\"color\\":null,\\"depth\\":0}]}}" +{\\"type\\":\\"info\\",\\"data\\":\\"Direct dependencies\\"} +{\\"type\\":\\"tree\\",\\"data\\":{\\"type\\":\\"newDirectDependencies\\",\\"trees\\":[{\\"name\\":\\"left-pad@1.1.3\\",\\"children\\":[],\\"hint\\":null,\\"color\\":null,\\"depth\\":0}]}} +{\\"type\\":\\"info\\",\\"data\\":\\"All dependencies\\"} +{\\"type\\":\\"tree\\",\\"data\\":{\\"type\\":\\"newAllDependencies\\",\\"trees\\":[{\\"name\\":\\"left-pad@1.1.3\\",\\"children\\":[],\\"hint\\":null,\\"color\\":null,\\"depth\\":0}]}}" `; diff --git a/__tests__/commands/upgrade.js b/__tests__/commands/upgrade.js index c70a3272cf..07be7d78be 100644 --- a/__tests__/commands/upgrade.js +++ b/__tests__/commands/upgrade.js @@ -275,6 +275,34 @@ test.concurrent('upgrades optional dependency packages not in registry', (): Pro }); }); +test.concurrent('informs the type of dependency after upgrade', (): Promise => { + return buildRun( + reporters.BufferReporter, + fixturesLoc, + async (args, flags, config, reporter): Promise => { + await upgrade(config, reporter, flags, args); + + const output = reporter.getBuffer(); + const infos = output.filter(({type}) => type === 'info'); + const getTreeInfo = pkgName => + output.filter( + ({type, data: {trees = []}}) => type === 'tree' && trees.some(({name}) => name.indexOf(pkgName) > -1), + ); + + expect( + infos.some(info => { + return info.data.toString().indexOf('Direct dependencies') > -1; + }), + ).toEqual(true); + expect(getTreeInfo('async')).toHaveLength(2); + expect(getTreeInfo('lodash')).toHaveLength(1); + }, + ['async'], + {latest: true}, + 'direct-dependency', + ); +}); + test.concurrent('warns when peer dependency is not met after upgrade', (): Promise => { return buildRun( reporters.BufferReporter, diff --git a/__tests__/fixtures/upgrade/direct-dependency/package.json b/__tests__/fixtures/upgrade/direct-dependency/package.json new file mode 100644 index 0000000000..ace0343538 --- /dev/null +++ b/__tests__/fixtures/upgrade/direct-dependency/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "async": "2.0.0" + } +} diff --git a/__tests__/fixtures/upgrade/direct-dependency/yarn.lock b/__tests__/fixtures/upgrade/direct-dependency/yarn.lock new file mode 100644 index 0000000000..7228efd284 --- /dev/null +++ b/__tests__/fixtures/upgrade/direct-dependency/yarn.lock @@ -0,0 +1,13 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +async@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/async/-/async-2.0.0.tgz#d0900ad385af13804540a109c42166e3ae7b2b9d" + dependencies: + lodash "^4.8.0" + +lodash@^4.8.0: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" diff --git a/__tests__/index.js b/__tests__/index.js index 88541afc5b..48b8cec5f1 100644 --- a/__tests__/index.js +++ b/__tests__/index.js @@ -60,20 +60,8 @@ async function execCommand( }); } -function expectAddSuccessfullOutput(stdout, pkg) { - const lastLines = stdout.slice(stdout.length - 4); - expect(lastLines[0]).toEqual('success Saved lockfile.'); - expect(lastLines[1]).toEqual('success Saved 1 new dependency.'); - expect(lastLines[2]).toContain(pkg); - expect(lastLines[3]).toContain('Done'); -} - -function expectAddSuccessfullOutputWithNoLockFile(stdout, pkg) { - const lastLines = stdout.slice(stdout.length - 4); - expect(lastLines[0]).not.toEqual('success Saved lockfile.'); - expect(lastLines[1]).toEqual('success Saved 1 new dependency.'); - expect(lastLines[2]).toContain(pkg); - expect(lastLines[3]).toContain('Done'); +function expectAddOutput(stdout) { + expect(stdout.slice(1, stdout.length - 1)).toMatchSnapshot(); } function expectRunOutput(stdout) { @@ -112,29 +100,29 @@ function expectAnInfoMessageAfterError(command: Promise>, expecte .catch(error => expect(error.stdout).toContain(expectedInfo)); } -test.concurrent('should add package', async () => { +test('should add package', async () => { const stdout = await execCommand('add', ['left-pad'], 'run-add', true); - expectAddSuccessfullOutput(stdout, 'left-pad'); + expectAddOutput(stdout); }); -test.concurrent('should add package with no-lockfile option', async () => { +test('should add package with no-lockfile option', async () => { const stdout = await execCommand('add', ['repeating', '--no-lockfile'], 'run-add-option', true); - expectAddSuccessfullOutputWithNoLockFile(stdout, 'repeating'); + expectAddOutput(stdout); }); -test.concurrent('should add package with frozen-lockfile option', async () => { +test('should add package with frozen-lockfile option', async () => { const stdout = await execCommand('add', ['repeating', '--frozen-lockfile'], 'run-add-option', true); - expectAddSuccessfullOutputWithNoLockFile(stdout, 'repeating'); + expectAddOutput(stdout); }); -test.concurrent('should add package with no-lockfile option in front', async () => { +test('should add package with no-lockfile option in front', async () => { const stdout = await execCommand('add', ['--no-lockfile', 'split-lines'], 'run-add-option-in-front', true); - expectAddSuccessfullOutputWithNoLockFile(stdout, 'split-lines'); + expectAddOutput(stdout); }); -test.concurrent('should add lockfile package', async () => { +test('should add lockfile package', async () => { const stdout = await execCommand('add', ['lockfile'], 'run-add-lockfile', true); - expectAddSuccessfullOutput(stdout, 'lockfile'); + expectAddOutput(stdout); }); // test is failing on Node 4, https://travis-ci.org/yarnpkg/yarn/jobs/216254539 diff --git a/src/cli/commands/add.js b/src/cli/commands/add.js index 5d14bc698c..617c676397 100644 --- a/src/cli/commands/add.js +++ b/src/cli/commands/add.js @@ -204,10 +204,28 @@ export class Add extends Install { const merged = [...patterns, ...this.addedPatterns]; const {trees, count} = await buildTree(this.resolver, this.linker, merged, opts, true, true); - this.reporter.success( - count === 1 ? this.reporter.lang('savedNewDependency') : this.reporter.lang('savedNewDependencies', count), - ); - this.reporter.tree('newDependencies', trees); + + if (count === 1) { + this.reporter.success(this.reporter.lang('savedNewDependency')); + } else { + this.reporter.success(this.reporter.lang('savedNewDependencies', count)); + } + + if (!count) { + return; + } + + const resolverPatterns = new Set(); + for (const pattern of patterns) { + const {version, name} = this.resolver.getResolvedPattern(pattern) || {}; + resolverPatterns.add(`${name}@${version}`); + } + const directRequireDependencies = trees.filter(({name}) => resolverPatterns.has(name)); + + this.reporter.info(this.reporter.lang('directDependencies')); + this.reporter.tree('newDirectDependencies', directRequireDependencies); + this.reporter.info(this.reporter.lang('allDependencies')); + this.reporter.tree('newAllDependencies', trees); } /** diff --git a/src/reporters/lang/en.js b/src/reporters/lang/en.js index dfaa37c0ee..0fc262aa51 100644 --- a/src/reporters/lang/en.js +++ b/src/reporters/lang/en.js @@ -239,6 +239,8 @@ const messages = { savedNewDependency: 'Saved 1 new dependency.', savedNewDependencies: 'Saved $0 new dependencies.', + directDependencies: 'Direct dependencies', + allDependencies: 'All dependencies', foundWarnings: 'Found $0 warnings.', foundErrors: 'Found $0 errors.',