diff options
Diffstat (limited to 'test/lib/commands/outdated.js')
-rw-r--r-- | test/lib/commands/outdated.js | 610 |
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') +}) |