From 075fe50565ae5c66df727cdd7df9dd5ed8cd4015 Mon Sep 17 00:00:00 2001 From: gfyoung Date: Sun, 26 Sep 2021 03:18:17 +0000 Subject: [PATCH] fix: restore exit code on "npm outdated" closes: https://github.com/npm/cli/issues/2556 xref: https://github.com/npm/cli/pull/1750 The xref'ed PR apparently dropped this behavior without any explanation. PR-URL: https://github.com/npm/cli/pull/3799 Credit: @gfyoung Close: #3799 Reviewed-by: @wraithgar --- lib/outdated.js | 3 +++ smoke-tests/index.js | 8 ++++++-- test/lib/outdated.js | 26 ++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/lib/outdated.js b/lib/outdated.js index 01e268fe96aee..a5be13cdaf108 100644 --- a/lib/outdated.js +++ b/lib/outdated.js @@ -87,6 +87,9 @@ class Outdated extends ArboristWorkspaceCmd { // sorts list alphabetically const outdated = this.list.sort((a, b) => a.name.localeCompare(b.name, 'en')) + if (outdated.length > 0) + process.exitCode = 1 + // return if no outdated packages if (outdated.length === 0 && !this.npm.config.get('json')) return diff --git a/smoke-tests/index.js b/smoke-tests/index.js index 5e2d5e071ae12..076c53e78a0b7 100644 --- a/smoke-tests/index.js +++ b/smoke-tests/index.js @@ -174,9 +174,13 @@ t.test('npm diff', async t => { t.test('npm outdated', async t => { const cmd = `${npmBin} outdated` - const cmdRes = await exec(cmd) + const cmdRes = await exec(cmd).catch(err => { + t.equal(err.code, 1, 'should exit with error code') + return err + }) - t.matchSnapshot(cmdRes, + t.not(cmdRes.stderr, '', 'should have stderr output') + t.matchSnapshot(String(cmdRes.stdout), 'should have expected outdated output') }) diff --git a/test/lib/outdated.js b/test/lib/outdated.js index 34a0aa6c9e03e..518436d0af4ec 100644 --- a/test/lib/outdated.js +++ b/test/lib/outdated.js @@ -102,6 +102,10 @@ const outdated = (dir, opts) => { t.beforeEach(() => logs = '') +const { exitCode } = process + +t.afterEach(() => process.exitCode = exitCode) + const redactCwd = (path) => { const normalizePath = p => p .replace(/\\+/g, '/') @@ -175,6 +179,7 @@ t.test('should display outdated deps', t => { outdated(null, { config: { global: true }, }).exec([], () => { + t.equal(process.exitCode, 1) t.matchSnapshot(logs) t.end() }) @@ -187,6 +192,7 @@ t.test('should display outdated deps', t => { }, color: true, }).exec([], () => { + t.equal(process.exitCode, 1) t.matchSnapshot(logs) t.end() }) @@ -200,6 +206,7 @@ t.test('should display outdated deps', t => { }, color: true, }).exec([], () => { + t.equal(process.exitCode, 1) t.matchSnapshot(logs) t.end() }) @@ -213,6 +220,7 @@ t.test('should display outdated deps', t => { }, color: true, }).exec([], () => { + t.equal(process.exitCode, 1) t.matchSnapshot(logs) t.end() }) @@ -226,6 +234,7 @@ t.test('should display outdated deps', t => { }, color: true, }).exec([], () => { + t.equal(process.exitCode, 1) t.matchSnapshot(logs) t.end() }) @@ -238,6 +247,7 @@ t.test('should display outdated deps', t => { long: true, }, }).exec([], () => { + t.equal(process.exitCode, 1) t.matchSnapshot(logs) t.end() }) @@ -250,6 +260,7 @@ t.test('should display outdated deps', t => { json: true, }, }).exec([], () => { + t.equal(process.exitCode, 1) t.matchSnapshot(logs) t.end() }) @@ -263,6 +274,7 @@ t.test('should display outdated deps', t => { long: true, }, }).exec([], () => { + t.equal(process.exitCode, 1) t.matchSnapshot(logs) t.end() }) @@ -275,6 +287,7 @@ t.test('should display outdated deps', t => { parseable: true, }, }).exec([], () => { + t.equal(process.exitCode, 1) t.matchSnapshot(logs) t.end() }) @@ -288,6 +301,7 @@ t.test('should display outdated deps', t => { long: true, }, }).exec([], () => { + t.equal(process.exitCode, 1) t.matchSnapshot(logs) t.end() }) @@ -299,6 +313,7 @@ t.test('should display outdated deps', t => { all: true, }, }).exec([], () => { + t.equal(process.exitCode, 1) t.matchSnapshot(logs) t.end() }) @@ -310,6 +325,7 @@ t.test('should display outdated deps', t => { global: false, }, }).exec(['cat'], () => { + t.equal(process.exitCode, 1) t.matchSnapshot(logs) t.end() }) @@ -540,6 +556,7 @@ t.test('workspaces', async t => { rej(err) t.matchSnapshot(logs, 'should display ws outdated deps human output') + t.equal(process.exitCode, 1) res() }) }) @@ -554,6 +571,7 @@ t.test('workspaces', async t => { rej(err) t.matchSnapshot(logs, 'should display ws outdated deps json output') + t.equal(process.exitCode, 1) res() }) }) @@ -568,6 +586,7 @@ t.test('workspaces', async t => { rej(err) t.matchSnapshot(logs, 'should display ws outdated deps parseable output') + t.equal(process.exitCode, 1) res() }) }) @@ -582,6 +601,7 @@ t.test('workspaces', async t => { rej(err) t.matchSnapshot(logs, 'should display all dependencies') + t.equal(process.exitCode, 1) res() }) }) @@ -594,6 +614,7 @@ t.test('workspaces', async t => { rej(err) t.matchSnapshot(logs, 'should highlight ws in dependend by section') + t.equal(process.exitCode, 1) res() }) }) @@ -604,6 +625,7 @@ t.test('workspaces', async t => { rej(err) t.matchSnapshot(logs, 'should display results filtered by ws') + t.equal(process.exitCode, 1) res() }) }) @@ -618,6 +640,7 @@ t.test('workspaces', async t => { rej(err) t.matchSnapshot(logs, 'should display json results filtered by ws') + t.equal(process.exitCode, 1) res() }) }) @@ -632,6 +655,7 @@ t.test('workspaces', async t => { rej(err) t.matchSnapshot(logs, 'should display parseable results filtered by ws') + t.equal(process.exitCode, 1) res() }) }) @@ -647,6 +671,7 @@ t.test('workspaces', async t => { t.matchSnapshot(logs, 'should display nested deps when filtering by ws and using --all') + t.equal(process.exitCode, 1) res() }) }) @@ -669,6 +694,7 @@ t.test('workspaces', async t => { t.matchSnapshot(logs, 'should display missing deps when filtering by ws') + t.equal(process.exitCode, 1) res() }) })