Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/npm/cli.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'test/lib/commands/outdated.js')
-rw-r--r--test/lib/commands/outdated.js610
1 files changed, 610 insertions, 0 deletions
diff --git a/test/lib/commands/outdated.js b/test/lib/commands/outdated.js
new file mode 100644
index 000000000..1841ea9b1
--- /dev/null
+++ b/test/lib/commands/outdated.js
@@ -0,0 +1,610 @@
+const t = require('tap')
+const { fake: mockNpm } = require('../../fixtures/mock-npm')
+
+const packument = spec => {
+ const mocks = {
+ cat: {
+ name: 'cat',
+ 'dist-tags': {
+ latest: '1.0.1',
+ },
+ versions: {
+ '1.0.1': {
+ version: '1.0.1',
+ dependencies: {
+ dog: '2.0.0',
+ },
+ },
+ },
+ },
+ chai: {
+ name: 'chai',
+ 'dist-tags': {
+ latest: '1.0.1',
+ },
+ versions: {
+ '1.0.1': {
+ version: '1.0.1',
+ },
+ },
+ },
+ dog: {
+ name: 'dog',
+ 'dist-tags': {
+ latest: '2.0.0',
+ },
+ versions: {
+ '1.0.1': {
+ version: '1.0.1',
+ },
+ '2.0.0': {
+ version: '2.0.0',
+ },
+ },
+ },
+ theta: {
+ name: 'theta',
+ 'dist-tags': {
+ latest: '1.0.1',
+ },
+ versions: {
+ '1.0.1': {
+ version: '1.0.1',
+ },
+ },
+ },
+ }
+
+ if (spec.name === 'eta')
+ throw new Error('There is an error with this package.')
+
+ if (!mocks[spec.name]) {
+ const err = new Error()
+ err.code = 'E404'
+ throw err
+ }
+
+ return mocks[spec.name]
+}
+
+let logs
+const output = (msg) => {
+ logs = `${logs}\n${msg}`
+}
+
+const globalDir = t.testdir({
+ node_modules: {
+ cat: {
+ 'package.json': JSON.stringify({
+ name: 'cat',
+ version: '1.0.0',
+ }, null, 2),
+ },
+ },
+})
+
+const flatOptions = {
+ workspacesEnabled: true,
+}
+
+const outdated = (dir, opts) => {
+ logs = ''
+ const Outdated = t.mock('../../../lib/commands/outdated.js', {
+ pacote: {
+ packument,
+ },
+ })
+ const npm = mockNpm({
+ ...opts,
+ localPrefix: dir,
+ prefix: dir,
+ flatOptions,
+ globalDir: `${globalDir}/node_modules`,
+ output,
+ })
+ return new Outdated(npm)
+}
+
+t.beforeEach(() => logs = '')
+
+const { exitCode } = process
+
+t.afterEach(() => process.exitCode = exitCode)
+
+const redactCwd = (path) => {
+ const normalizePath = p => p
+ .replace(/\\+/g, '/')
+ .replace(/\r\n/g, '\n')
+ return normalizePath(path)
+ .replace(new RegExp(normalizePath(process.cwd()), 'g'), '{CWD}')
+}
+
+t.cleanSnapshot = (str) => redactCwd(str)
+
+t.test('should display outdated deps', t => {
+ const testDir = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'delta',
+ version: '1.0.0',
+ dependencies: {
+ cat: '^1.0.0',
+ dog: '^1.0.0',
+ theta: '^1.0.0',
+ },
+ devDependencies: {
+ zeta: '^1.0.0',
+ },
+ optionalDependencies: {
+ lorem: '^1.0.0',
+ },
+ peerDependencies: {
+ chai: '^1.0.0',
+ },
+ }, null, 2),
+ node_modules: {
+ cat: {
+ 'package.json': JSON.stringify({
+ name: 'cat',
+ version: '1.0.0',
+ dependencies: {
+ dog: '2.0.0',
+ },
+ }, null, 2),
+ node_modules: {
+ dog: {
+ 'package.json': JSON.stringify({
+ name: 'dog',
+ version: '2.0.0',
+ }, null, 2),
+ },
+ },
+ },
+ chai: {
+ 'package.json': JSON.stringify({
+ name: 'chai',
+ version: '1.0.0',
+ }, null, 2),
+ },
+ dog: {
+ 'package.json': JSON.stringify({
+ name: 'dog',
+ version: '1.0.1',
+ }, null, 2),
+ },
+ zeta: {
+ 'package.json': JSON.stringify({
+ name: 'zeta',
+ version: '1.0.0',
+ }, null, 2),
+ },
+ },
+ })
+
+ t.test('outdated global', async t => {
+ await outdated(null, {
+ config: { global: true },
+ }).exec([])
+ t.equal(process.exitCode, 1)
+ t.matchSnapshot(logs)
+ })
+
+ t.test('outdated', async t => {
+ await outdated(testDir, {
+ config: {
+ global: false,
+ },
+ color: true,
+ }).exec([])
+ t.equal(process.exitCode, 1)
+ t.matchSnapshot(logs)
+ })
+
+ t.test('outdated --omit=dev', async t => {
+ await outdated(testDir, {
+ config: {
+ global: false,
+ omit: ['dev'],
+ },
+ color: true,
+ }).exec([])
+ t.equal(process.exitCode, 1)
+ t.matchSnapshot(logs)
+ })
+
+ t.test('outdated --omit=dev --omit=peer', async t => {
+ await outdated(testDir, {
+ config: {
+ global: false,
+ omit: ['dev', 'peer'],
+ },
+ color: true,
+ }).exec([])
+ t.equal(process.exitCode, 1)
+ t.matchSnapshot(logs)
+ })
+
+ t.test('outdated --omit=prod', async t => {
+ await outdated(testDir, {
+ config: {
+ global: false,
+ omit: ['prod'],
+ },
+ color: true,
+ }).exec([])
+ t.equal(process.exitCode, 1)
+ t.matchSnapshot(logs)
+ })
+
+ t.test('outdated --long', async t => {
+ await outdated(testDir, {
+ config: {
+ global: false,
+ long: true,
+ },
+ }).exec([])
+ t.equal(process.exitCode, 1)
+ t.matchSnapshot(logs)
+ })
+
+ t.test('outdated --json', async t => {
+ await outdated(testDir, {
+ config: {
+ global: false,
+ json: true,
+ },
+ }).exec([])
+ t.equal(process.exitCode, 1)
+ t.matchSnapshot(logs)
+ })
+
+ t.test('outdated --json --long', async t => {
+ await outdated(testDir, {
+ config: {
+ global: false,
+ json: true,
+ long: true,
+ },
+ }).exec([])
+ t.equal(process.exitCode, 1)
+ t.matchSnapshot(logs)
+ })
+
+ t.test('outdated --parseable', async t => {
+ await outdated(testDir, {
+ config: {
+ global: false,
+ parseable: true,
+ },
+ }).exec([])
+ t.equal(process.exitCode, 1)
+ t.matchSnapshot(logs)
+ })
+
+ t.test('outdated --parseable --long', async t => {
+ await outdated(testDir, {
+ config: {
+ global: false,
+ parseable: true,
+ long: true,
+ },
+ }).exec([])
+ t.equal(process.exitCode, 1)
+ t.matchSnapshot(logs)
+ })
+
+ t.test('outdated --all', async t => {
+ await outdated(testDir, {
+ config: {
+ all: true,
+ },
+ }).exec([])
+ t.equal(process.exitCode, 1)
+ t.matchSnapshot(logs)
+ })
+
+ t.test('outdated specific dep', async t => {
+ await outdated(testDir, {
+ config: {
+ global: false,
+ },
+ }).exec(['cat'])
+ t.equal(process.exitCode, 1)
+ t.matchSnapshot(logs)
+ })
+
+ t.end()
+})
+
+t.test('should return if no outdated deps', async t => {
+ const testDir = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'delta',
+ version: '1.0.0',
+ dependencies: {
+ cat: '^1.0.0',
+ },
+ }, null, 2),
+ node_modules: {
+ cat: {
+ 'package.json': JSON.stringify({
+ name: 'cat',
+ version: '1.0.1',
+ }, null, 2),
+ },
+ },
+ })
+
+ await outdated(testDir, {
+ global: false,
+ }).exec([])
+ t.equal(logs.length, 0, 'no logs')
+})
+
+t.test('throws if error with a dep', async t => {
+ const testDir = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'delta',
+ version: '1.0.0',
+ dependencies: {
+ eta: '^1.0.0',
+ },
+ }, null, 2),
+ node_modules: {
+ eta: {
+ 'package.json': JSON.stringify({
+ name: 'eta',
+ version: '1.0.1',
+ }, null, 2),
+ },
+ },
+ })
+
+ await t.rejects(
+ outdated(testDir, {
+ global: false,
+ }).exec([]),
+ 'There is an error with this package.'
+ )
+})
+
+t.test('should skip missing non-prod deps', async t => {
+ const testDir = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'delta',
+ version: '1.0.0',
+ devDependencies: {
+ chai: '^1.0.0',
+ },
+ }, null, 2),
+ node_modules: {},
+ })
+
+ await outdated(testDir, {
+ global: false,
+ }).exec([])
+ t.equal(logs.length, 0, 'no logs')
+})
+
+t.test('should skip invalid pkg ranges', async t => {
+ const testDir = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'delta',
+ version: '1.0.0',
+ dependencies: {
+ cat: '>=^2',
+ },
+ }, null, 2),
+ node_modules: {
+ cat: {
+ 'package.json': JSON.stringify({
+ name: 'cat',
+ version: '1.0.0',
+ }, null, 2),
+ },
+ },
+ })
+
+ await outdated(testDir, {}).exec([])
+ t.equal(logs.length, 0, 'no logs')
+})
+
+t.test('should skip git specs', async t => {
+ const testDir = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'delta',
+ version: '1.0.0',
+ dependencies: {
+ cat: 'github:username/foo',
+ },
+ }, null, 2),
+ node_modules: {
+ cat: {
+ 'package.json': JSON.stringify({
+ name: 'cat',
+ version: '1.0.0',
+ }, null, 2),
+ },
+ },
+ })
+
+ await outdated(testDir, {}).exec([])
+ t.equal(logs.length, 0, 'no logs')
+})
+
+t.test('workspaces', async t => {
+ const testDir = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'workspaces-project',
+ version: '1.0.0',
+ workspaces: ['packages/*'],
+ dependencies: {
+ dog: '^1.0.0',
+ },
+ }),
+ node_modules: {
+ a: t.fixture('symlink', '../packages/a'),
+ b: t.fixture('symlink', '../packages/b'),
+ c: t.fixture('symlink', '../packages/c'),
+ cat: {
+ 'package.json': JSON.stringify({
+ name: 'cat',
+ version: '1.0.0',
+ dependencies: {
+ dog: '2.0.0',
+ },
+ }),
+ node_modules: {
+ dog: {
+ 'package.json': JSON.stringify({
+ name: 'dog',
+ version: '2.0.0',
+ }),
+ },
+ },
+ },
+ chai: {
+ 'package.json': JSON.stringify({
+ name: 'chai',
+ version: '1.0.0',
+ }),
+ },
+ dog: {
+ 'package.json': JSON.stringify({
+ name: 'dog',
+ version: '1.0.1',
+ }),
+ },
+ foo: {
+ 'package.json': JSON.stringify({
+ name: 'foo',
+ version: '1.0.0',
+ dependencies: {
+ chai: '^1.0.0',
+ },
+ }),
+ },
+ zeta: {
+ 'package.json': JSON.stringify({
+ name: 'zeta',
+ version: '1.0.0',
+ }),
+ },
+ },
+ packages: {
+ a: {
+ 'package.json': JSON.stringify({
+ name: 'a',
+ version: '1.0.0',
+ dependencies: {
+ b: '^1.0.0',
+ cat: '^1.0.0',
+ foo: '^1.0.0',
+ },
+ }),
+ },
+ b: {
+ 'package.json': JSON.stringify({
+ name: 'b',
+ version: '1.0.0',
+ dependencies: {
+ zeta: '^1.0.0',
+ },
+ }),
+ },
+ c: {
+ 'package.json': JSON.stringify({
+ name: 'c',
+ version: '1.0.0',
+ dependencies: {
+ theta: '^1.0.0',
+ },
+ }),
+ },
+ },
+ })
+
+ await outdated(testDir, {}).exec([])
+
+ t.matchSnapshot(logs, 'should display ws outdated deps human output')
+ t.equal(process.exitCode, 1)
+
+ flatOptions.workspacesEnabled = false
+ await outdated(testDir, {}).exec([])
+
+ // TODO: This should display dog, but doesn't because arborist filters
+ // workspace deps even if they're also root deps
+ // This will be fixed in a future arborist version
+ t.matchSnapshot(logs, 'should display only root outdated when ws disabled')
+ flatOptions.workspacesEnabled = true
+
+ await outdated(testDir, {
+ config: {
+ json: true,
+ },
+ }).exec([])
+ t.matchSnapshot(logs, 'should display ws outdated deps json output')
+ t.equal(process.exitCode, 1)
+
+ await outdated(testDir, {
+ config: {
+ parseable: true,
+ },
+ }).exec([])
+
+ t.matchSnapshot(logs, 'should display ws outdated deps parseable output')
+ t.equal(process.exitCode, 1)
+
+ await outdated(testDir, {
+ config: {
+ all: true,
+ },
+ }).exec([])
+
+ t.matchSnapshot(logs, 'should display all dependencies')
+ t.equal(process.exitCode, 1)
+
+ await outdated(testDir, {
+ color: true,
+ }).exec([])
+
+ t.matchSnapshot(logs, 'should highlight ws in dependend by section')
+ t.equal(process.exitCode, 1)
+
+ await outdated(testDir, {}).execWorkspaces([], ['a'])
+ t.matchSnapshot(logs, 'should display results filtered by ws')
+ t.equal(process.exitCode, 1)
+
+ await outdated(testDir, {
+ config: {
+ json: true,
+ },
+ }).execWorkspaces([], ['a'])
+ t.matchSnapshot(logs, 'should display json results filtered by ws')
+ t.equal(process.exitCode, 1)
+
+ await outdated(testDir, {
+ config: {
+ parseable: true,
+ },
+ }).execWorkspaces([], ['a'])
+ t.matchSnapshot(logs, 'should display parseable results filtered by ws')
+ t.equal(process.exitCode, 1)
+
+ await outdated(testDir, {
+ config: {
+ all: true,
+ },
+ }).execWorkspaces([], ['a'])
+
+ t.matchSnapshot(logs,
+ 'should display nested deps when filtering by ws and using --all')
+ t.equal(process.exitCode, 1)
+
+ await outdated(testDir, {}).execWorkspaces([], ['b'])
+ t.matchSnapshot(logs,
+ 'should display no results if ws has no deps to display')
+
+ await outdated(testDir, {}).execWorkspaces([], ['c'])
+ t.matchSnapshot(logs,
+ 'should display missing deps when filtering by ws')
+})