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:
authorRuy Adorno <ruyadorno@hotmail.com>2020-07-15 22:38:23 +0300
committerRuy Adorno <ruyadorno@hotmail.com>2020-07-21 06:03:34 +0300
commit433c5e5822d13251a5a26e7252707d34f55702fd (patch)
tree3ae8a1f50cbfce0e20b4443e5a7df0b9bed3a31f /test/lib/ls.js
parent7fbd867f6bae059a24ad6c80989ad8cf1fa5be72 (diff)
BREAKING: rewrite npm ls
- Rewrites lib/ls.js command to use @npmcli/arborist - Updates unit tests - Breaking changes: - added error codes: ELSPROBLEMS, EJSONPARSE to callback errors - extraneous deps depth will match current location in nm folder - mark top-level deps as extraneous when missing root package.json - don't mark deps as extraneous if they're valid deps of invalid deps - peer deps are now listed as regular deps, removed oddities such as peerinvalid label and stops labeling peer deps extraneous - might print diff git resolved values, see: https://github.com/npm/hosted-git-info - Parseable (--parseable) output: - possible order of printed elements changed - fixed consistency problems in which it would print root folder name if using a filter argument that could not match against any of the deps in the current installed tree - fixed printing non-existing paths for missing dependencies - fixed undefined symlink output when using --long output - JSON (--json) output: - removed: `from` property from --json output - removed: "[Circular]" references - added "missing" to list of peer-dep problems listed - added peerDependencies ref when using --long output - removed readme properties using --long output - Renamed error msg: `Failed to parse json` -> `Failed to parse root package.json` refs: - https://github.com/npm/statusboard/issues/99 - https://github.com/npm/statusboard/issues/103
Diffstat (limited to 'test/lib/ls.js')
-rw-r--r--test/lib/ls.js801
1 files changed, 664 insertions, 137 deletions
diff --git a/test/lib/ls.js b/test/lib/ls.js
index ae9aabaee..db19c33e9 100644
--- a/test/lib/ls.js
+++ b/test/lib/ls.js
@@ -78,7 +78,10 @@ const diffDepTypesNmFixture = {
let prefix
let result = ''
+// note this _flatOptions representations is for tests-only and does not
+// represent exactly the properties found in the actual flatOptions obj
const _flatOptions = {
+ color: false,
dev: false,
depth: Infinity,
json: false,
@@ -93,7 +96,7 @@ const ls = requireInject('../../lib/ls.js', {
limit: {
fetch: 3
},
- get dir () { return prefix + '/node_modules/' },
+ get prefix () { return prefix },
globalDir: '/foo',
config: {
get (key) {
@@ -105,12 +108,18 @@ const ls = requireInject('../../lib/ls.js', {
})
const redactCwd = res =>
- res.replace(/\\/g, '/').replace(new RegExp(__dirname.replace(/\\/g, '/'), 'gi'), '{CWD}')
+ res && res.replace(/\\/g, '/').replace(new RegExp(__dirname.replace(/\\/g, '/'), 'gi'), '{CWD}')
const jsonParse = res =>
JSON.parse(redactCwd(res))
+const cleanUpResult = (done, t) => {
+ result = ''
+ done()
+}
+
test('ls', (t) => {
+ t.beforeEach(cleanUpResult)
_flatOptions.json = false
_flatOptions.unicode = false
t.test('no args', (t) => {
@@ -137,8 +146,12 @@ test('ls', (t) => {
...simpleNmFixture
})
ls([], (err) => {
- t.ifError(err, 'npm ls')
- t.matchSnapshot(redactCwd(result), 'should output json missing name/version of top-level package')
+ t.match(err.code, 'ELSPROBLEMS', 'should have ELSPROBLEMS error code')
+ t.matchSnapshot(
+ redactCwd(err.message),
+ 'should log all extraneous deps on error msg'
+ )
+ t.matchSnapshot(redactCwd(result), 'should output tree missing name/version of top-level package')
t.end()
})
})
@@ -155,8 +168,9 @@ test('ls', (t) => {
...simpleNmFixture
})
ls([], (err) => {
+ t.equal(err.code, 'ELSPROBLEMS', 'should have error code')
t.equal(
- redactCwd(err),
+ redactCwd(err.message),
'extraneous: lorem@1.0.0 {CWD}/ls-ls-extraneous-deps/node_modules/lorem',
'should log extraneous dep as error'
)
@@ -184,6 +198,53 @@ test('ls', (t) => {
})
})
+ t.test('with filter arg nested dep', (t) => {
+ prefix = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'test-npm-ls',
+ version: '1.0.0',
+ dependencies: {
+ foo: '^1.0.0',
+ lorem: '^1.0.0'
+ }
+ }),
+ ...simpleNmFixture
+ })
+ ls(['bar'], (err) => {
+ t.ifError(err, 'npm ls')
+ t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurences of filtered package and its ancestors')
+ t.end()
+ })
+ })
+
+ t.test('with multiple filter args', (t) => {
+ prefix = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'test-npm-ls',
+ version: '1.0.0',
+ dependencies: {
+ foo: '^1.0.0',
+ lorem: '^1.0.0',
+ ipsum: '^1.0.0'
+ }
+ }),
+ node_modules: {
+ ...simpleNmFixture.node_modules,
+ ipsum: {
+ 'package.json': JSON.stringify({
+ name: 'ipsum',
+ version: '1.0.0'
+ })
+ }
+ }
+ })
+ ls(['bar@*', 'lorem@1.0.0'], (err) => {
+ t.ifError(err, 'npm ls')
+ t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurences of multiple filtered packages and their ancestors')
+ t.end()
+ })
+ })
+
t.test('with missing filter arg', (t) => {
prefix = t.testdir({
'package.json': JSON.stringify({
@@ -237,11 +298,49 @@ test('ls', (t) => {
name: 'test-npm-ls',
version: '1.0.0',
dependencies: {
- foo: '^1.0.0',
- lorem: '^1.0.0'
+ a: '^1.0.0',
+ e: '^1.0.0'
}
}),
- ...simpleNmFixture
+ node_modules: {
+ a: {
+ 'package.json': JSON.stringify({
+ name: 'a',
+ version: '1.0.0',
+ dependencies: {
+ b: '^1.0.0'
+ }
+ })
+ },
+ b: {
+ 'package.json': JSON.stringify({
+ name: 'b',
+ version: '1.0.0',
+ dependencies: {
+ c: '^1.0.0',
+ d: '*'
+ }
+ })
+ },
+ c: {
+ 'package.json': JSON.stringify({
+ name: 'c',
+ version: '1.0.0'
+ })
+ },
+ d: {
+ 'package.json': JSON.stringify({
+ name: 'd',
+ version: '1.0.0'
+ })
+ },
+ e: {
+ 'package.json': JSON.stringify({
+ name: 'e',
+ version: '1.0.0'
+ })
+ }
+ }
})
ls([], (err) => {
t.ifError(err, 'npm ls')
@@ -264,13 +363,42 @@ test('ls', (t) => {
}),
...simpleNmFixture
})
- ls([], () => {
- t.matchSnapshot(redactCwd(result), 'should output tree containing top-level deps and their deps only')
+ ls([], (err) => {
+ t.equal(err.code, 'ELSPROBLEMS', 'should have error code')
+ t.equal(
+ redactCwd(err.message),
+ 'invalid: foo@1.0.0 {CWD}/ls-ls-missing-invalid-extraneous/node_modules/foo\n' +
+ 'missing: ipsum@^1.0.0, required by test-npm-ls@1.0.0\n' +
+ 'extraneous: lorem@1.0.0 {CWD}/ls-ls-missing-invalid-extraneous/node_modules/lorem',
+ 'should log missing/invalid/extraneous errors'
+ )
+ t.matchSnapshot(redactCwd(result), 'should output tree containing missing, invalid, extraneous labels')
_flatOptions.depth = Infinity
t.end()
})
})
+ t.test('coloured output', (t) => {
+ _flatOptions.color = true
+ prefix = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'test-npm-ls',
+ version: '1.0.0',
+ dependencies: {
+ foo: '^2.0.0',
+ ipsum: '^1.0.0'
+ }
+ }),
+ ...simpleNmFixture
+ })
+ ls([], (err) => {
+ t.equal(err.code, 'ELSPROBLEMS', 'should have error code')
+ t.matchSnapshot(redactCwd(result), 'should output tree containing color info')
+ _flatOptions.color = false
+ t.end()
+ })
+ })
+
t.test('--dev', (t) => {
_flatOptions.dev = true
prefix = t.testdir({
@@ -491,7 +619,7 @@ test('ls', (t) => {
'package.json': '{broken json'
})
ls([], (err) => {
- t.match(err, /Failed to parse json/)
+ t.match(err, { code: 'EJSONPARSE' }, 'should throw EJSONPARSE error')
t.matchSnapshot(redactCwd(result), 'should print empty result')
t.end()
})
@@ -506,7 +634,7 @@ test('ls', (t) => {
})
})
- t.test('unmet peer dep', (t) => {
+ t.test('invalid peer dep', (t) => {
prefix = t.testdir({
'package.json': JSON.stringify({
name: 'test-npm-ls',
@@ -528,12 +656,31 @@ test('ls', (t) => {
...diffDepTypesNmFixture
})
ls([], () => {
+ t.matchSnapshot(redactCwd(result), 'should output tree signaling mismatching peer dep in problems')
+ t.end()
+ })
+ })
+
+ t.test('unmet peer dep', (t) => {
+ prefix = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'test-npm-ls',
+ version: '1.0.0',
+ peerDependencies: {
+ 'peer-dep': '*'
+ }
+ })
+ })
+ ls([], (err) => {
+ t.match(err.code, 'ELSPROBLEMS', 'should have ELSPROBLEMS error code')
+ t.match(err.message, 'missing: peer-dep@*, required by test-npm-ls@1.0.0', 'should have missing peer-dep error msg')
t.matchSnapshot(redactCwd(result), 'should output tree signaling missing peer dep in problems')
t.end()
})
})
t.test('unmet optional dep', (t) => {
+ _flatOptions.color = true
prefix = t.testdir({
'package.json': JSON.stringify({
name: 'test-npm-ls',
@@ -555,8 +702,11 @@ test('ls', (t) => {
}),
...diffDepTypesNmFixture
})
- ls([], () => {
+ ls([], (err) => {
+ t.match(err.code, 'ELSPROBLEMS', 'should have ELSPROBLEMS error code')
+ t.match(err.message, /invalid: optional-dep@1.0.0/, 'should have invalid dep error msg')
t.matchSnapshot(redactCwd(result), 'should output tree with empty entry for missing optional deps')
+ _flatOptions.color = false
t.end()
})
})
@@ -591,7 +741,8 @@ test('ls', (t) => {
}
}
})
- ls([], () => {
+ ls([], (err) => {
+ t.ifError(err, 'npm ls')
t.matchSnapshot(redactCwd(result), 'should print tree output containing deduped ref')
t.end()
})
@@ -655,12 +806,57 @@ test('ls', (t) => {
}
}
})
- ls([], () => {
+ ls([], (err) => {
+ t.ifError(err, 'npm ls')
t.matchSnapshot(redactCwd(result), 'should output tree containing git refs')
t.end()
})
})
+ t.test('broken resolved field', (t) => {
+ prefix = t.testdir({
+ node_modules: {
+ a: {
+ 'package.json': JSON.stringify({
+ name: 'a',
+ version: '1.0.1'
+ })
+ }
+ },
+ 'package-lock.json': JSON.stringify({
+ 'name': 'npm-broken-resolved-field-test',
+ 'version': '1.0.0',
+ 'lockfileVersion': 2,
+ 'requires': true,
+ 'packages': {
+ '': {
+ 'name': 'a',
+ 'version': '1.0.1'
+ }
+ },
+ 'dependencies': {
+ a: {
+ 'version': '1.0.1',
+ 'resolved': 'foo@bar://b8f3a2fc0c3bb8ffd8b0d0072cc6b5a3667e963c',
+ 'integrity': 'sha512-8AN9lNCcBt5Xeje7fMEEpp5K3rgcAzIpTtAjYb/YMUYu8SbIVF6wz0WqACDVKvpQOUcSfNHZQNLNmue0QSwXOQ=='
+ }
+ }
+ }),
+ 'package.json': JSON.stringify({
+ 'name': 'npm-broken-resolved-field-test',
+ 'version': '1.0.0',
+ 'dependencies': {
+ 'a': '^1.0.1'
+ }
+ })
+ })
+ ls([], (err) => {
+ t.ifError(err, 'npm ls')
+ t.matchSnapshot(redactCwd(result), 'should NOT print git refs in output tree')
+ t.end()
+ })
+ })
+
t.test('from and resolved properties', (t) => {
prefix = t.testdir({
'package.json': JSON.stringify({
@@ -708,6 +904,7 @@ test('ls', (t) => {
})
test('ls --parseable', (t) => {
+ t.beforeEach(cleanUpResult)
_flatOptions.json = false
_flatOptions.unicode = false
_flatOptions.parseable = true
@@ -725,7 +922,7 @@ test('ls --parseable', (t) => {
})
ls([], (err) => {
t.ifError(err, 'npm ls')
- t.matchSnapshot(redactCwd(result), 'should output tree representation of dependencies structure')
+ t.matchSnapshot(redactCwd(result), 'should output parseable representation of dependencies structure')
t.end()
})
})
@@ -735,8 +932,12 @@ test('ls --parseable', (t) => {
...simpleNmFixture
})
ls([], (err) => {
- t.ifError(err, 'npm ls')
- t.matchSnapshot(redactCwd(result), 'should output json missing name/version of top-level package')
+ t.match(err.code, 'ELSPROBLEMS', 'should have ELSPROBLEMS error code')
+ t.matchSnapshot(
+ redactCwd(err.message),
+ 'should log all extraneous deps on error msg'
+ )
+ t.matchSnapshot(redactCwd(result), 'should output parseable missing name/version of top-level package')
t.end()
})
})
@@ -753,11 +954,7 @@ test('ls --parseable', (t) => {
...simpleNmFixture
})
ls([], (err) => {
- t.equal(
- redactCwd(err),
- 'extraneous: lorem@1.0.0 {CWD}/ls-ls-parseable-extraneous-deps/node_modules/lorem',
- 'should log extraneous dep as error'
- )
+ t.equal(err.code, 'ELSPROBLEMS', 'should have error code')
t.matchSnapshot(redactCwd(result), 'should output containing problems info')
t.end()
})
@@ -777,7 +974,54 @@ test('ls --parseable', (t) => {
})
ls(['lorem'], (err) => {
t.ifError(err, 'npm ls')
- t.matchSnapshot(redactCwd(result), 'should output tree contaning only occurences of filtered by package')
+ t.matchSnapshot(redactCwd(result), 'should output parseable contaning only occurences of filtered by package')
+ t.end()
+ })
+ })
+
+ t.test('with filter arg nested dep', (t) => {
+ prefix = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'test-npm-ls',
+ version: '1.0.0',
+ dependencies: {
+ foo: '^1.0.0',
+ lorem: '^1.0.0'
+ }
+ }),
+ ...simpleNmFixture
+ })
+ ls(['bar'], (err) => {
+ t.ifError(err, 'npm ls')
+ t.matchSnapshot(redactCwd(result), 'should output parseable contaning only occurences of filtered package')
+ t.end()
+ })
+ })
+
+ t.test('with multiple filter args', (t) => {
+ prefix = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'test-npm-ls',
+ version: '1.0.0',
+ dependencies: {
+ foo: '^1.0.0',
+ lorem: '^1.0.0',
+ ipsum: '^1.0.0'
+ }
+ }),
+ node_modules: {
+ ...simpleNmFixture.node_modules,
+ ipsum: {
+ 'package.json': JSON.stringify({
+ name: 'ipsum',
+ version: '1.0.0'
+ })
+ }
+ }
+ })
+ ls(['bar@*', 'lorem@1.0.0'], (err) => {
+ t.ifError(err, 'npm ls')
+ t.matchSnapshot(redactCwd(result), 'should output parseable contaning only occurences of multiple filtered packages and their ancestors')
t.end()
})
})
@@ -843,14 +1087,13 @@ test('ls --parseable', (t) => {
})
ls([], (err) => {
t.ifError(err, 'npm ls')
- t.matchSnapshot(redactCwd(result), 'should output tree containing top-level deps and their deps only')
+ t.matchSnapshot(redactCwd(result), 'should output parseable containing top-level deps and their deps only')
_flatOptions.depth = Infinity
t.end()
})
})
t.test('missing/invalid/extraneous', (t) => {
- _flatOptions.depth = 1
prefix = t.testdir({
'package.json': JSON.stringify({
name: 'test-npm-ls',
@@ -862,9 +1105,9 @@ test('ls --parseable', (t) => {
}),
...simpleNmFixture
})
- ls([], () => {
- t.matchSnapshot(redactCwd(result), 'should output tree containing top-level deps and their deps only')
- _flatOptions.depth = Infinity
+ ls([], (err) => {
+ t.match(err, { code: 'ELSPROBLEMS' }, 'should list dep problems')
+ t.matchSnapshot(redactCwd(result), 'should output parseable containing top-level deps and their deps only')
t.end()
})
})
@@ -1053,6 +1296,86 @@ test('ls --parseable', (t) => {
})
})
+ t.test('--long with extraneous deps', (t) => {
+ prefix = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'test-npm-ls',
+ version: '1.0.0',
+ dependencies: {
+ foo: '^1.0.0'
+ }
+ }),
+ ...simpleNmFixture
+ })
+ ls([], (err) => {
+ t.equal(err.code, 'ELSPROBLEMS', 'should have error code')
+ t.match(err.message, 'extraneous: lorem@1.0.0 /Users/ruyadorno/Documents/workspace/cli/test/lib/ls-ls-parseable--long-with-extraneous-deps/node_modules/lorem', 'should have error code')
+ t.matchSnapshot(redactCwd(result), 'should output long parseable output with extraneous info')
+ t.end()
+ })
+ })
+
+ t.test('--long missing/invalid/extraneous', (t) => {
+ _flatOptions.long = true
+ prefix = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'test-npm-ls',
+ version: '1.0.0',
+ dependencies: {
+ foo: '^2.0.0',
+ ipsum: '^1.0.0'
+ }
+ }),
+ ...simpleNmFixture
+ })
+ ls([], (err) => {
+ t.match(err, { code: 'ELSPROBLEMS' }, 'should list dep problems')
+ t.matchSnapshot(redactCwd(result), 'should output parseable result containing EXTRANEOUS/INVALID labels')
+ _flatOptions.long = false
+ t.end()
+ })
+ })
+
+ t.test('--long print symlink target location', (t) => {
+ _flatOptions.long = true
+ prefix = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'test-npm-ls',
+ version: '1.0.0',
+ dependencies: {
+ 'prod-dep': '^1.0.0',
+ 'lorem': '^1.0.0',
+ 'linked-dep': '^1.0.0'
+ },
+ devDependencies: {
+ 'dev-dep': '^1.0.0'
+ },
+ optionalDependencies: {
+ 'optional-dep': '^1.0.0'
+ },
+ peerDependencies: {
+ 'peer-dep': '^1.0.0'
+ }
+ }),
+ 'linked-dep': {
+ 'package.json': JSON.stringify({
+ name: 'linked-dep',
+ version: '1.0.0'
+ })
+ },
+ node_modules: {
+ 'linked-dep': t.fixture('symlink', '../linked-dep'),
+ ...diffDepTypesNmFixture.node_modules
+ }
+ })
+ ls([], (err) => {
+ t.ifError(err, 'npm ls')
+ t.matchSnapshot(redactCwd(result), 'should output parseable results with symlink targets')
+ _flatOptions.long = false
+ t.end()
+ })
+ })
+
t.test('--long --depth=0', (t) => {
_flatOptions.depth = 0
_flatOptions.long = true
@@ -1089,7 +1412,7 @@ test('ls --parseable', (t) => {
'package.json': '{broken json'
})
ls([], (err) => {
- t.match(err, /Failed to parse json/)
+ t.match(err, { code: 'EJSONPARSE' }, 'should throw EJSONPARSE error')
t.matchSnapshot(redactCwd(result), 'should print empty result')
t.end()
})
@@ -1126,7 +1449,7 @@ test('ls --parseable', (t) => {
...diffDepTypesNmFixture
})
ls([], () => {
- t.matchSnapshot(redactCwd(result), 'should output tree signaling missing peer dep in problems')
+ t.matchSnapshot(redactCwd(result), 'should output parseable signaling missing peer dep in problems')
t.end()
})
})
@@ -1153,8 +1476,10 @@ test('ls --parseable', (t) => {
}),
...diffDepTypesNmFixture
})
- ls([], () => {
- t.matchSnapshot(redactCwd(result), 'should output tree with empty entry for missing optional deps')
+ ls([], (err) => {
+ t.match(err.code, 'ELSPROBLEMS', 'should have ELSPROBLEMS error code')
+ t.match(err.message, /invalid: optional-dep@1.0.0/, 'should have invalid dep error msg')
+ t.matchSnapshot(redactCwd(result), 'should output parseable with empty entry for missing optional deps')
t.end()
})
})
@@ -1306,6 +1631,7 @@ test('ls --parseable', (t) => {
})
test('ls --json', (t) => {
+ t.beforeEach(cleanUpResult)
_flatOptions.json = true
_flatOptions.parseable = false
t.test('no args', (t) => {
@@ -1352,13 +1678,29 @@ test('ls --json', (t) => {
...simpleNmFixture
})
ls([], (err) => {
- t.ifError(err, 'npm ls')
+ t.match(err, { code: 'ELSPROBLEMS' }, 'should list dep problems')
t.deepEqual(
jsonParse(result),
{
+ 'problems': [
+ 'extraneous: bar@1.0.0 {CWD}/ls-ls-json-missing-package-json/node_modules/bar',
+ 'extraneous: foo@1.0.0 {CWD}/ls-ls-json-missing-package-json/node_modules/foo',
+ 'extraneous: lorem@1.0.0 {CWD}/ls-ls-json-missing-package-json/node_modules/lorem'
+ ],
'dependencies': {
+ 'bar': {
+ 'version': '1.0.0',
+ 'extraneous': true,
+ 'problems': [
+ 'extraneous: bar@1.0.0 {CWD}/ls-ls-json-missing-package-json/node_modules/bar'
+ ]
+ },
'foo': {
'version': '1.0.0',
+ 'extraneous': true,
+ 'problems': [
+ 'extraneous: foo@1.0.0 {CWD}/ls-ls-json-missing-package-json/node_modules/foo'
+ ],
'dependencies': {
'bar': {
'version': '1.0.0'
@@ -1366,7 +1708,11 @@ test('ls --json', (t) => {
}
},
'lorem': {
- 'version': '1.0.0'
+ 'version': '1.0.0',
+ 'extraneous': true,
+ 'problems': [
+ 'extraneous: lorem@1.0.0 {CWD}/ls-ls-json-missing-package-json/node_modules/lorem'
+ ]
}
}
},
@@ -1389,10 +1735,15 @@ test('ls --json', (t) => {
})
ls([], (err) => {
t.equal(
- redactCwd(err),
+ redactCwd(err.message),
'extraneous: lorem@1.0.0 {CWD}/ls-ls-json-extraneous-deps/node_modules/lorem',
'should log extraneous dep as error'
)
+ t.equal(
+ err.code,
+ 'ELSPROBLEMS',
+ 'should have ELSPROBLEMS error code'
+ )
t.deepEqual(
jsonParse(result),
{
@@ -1456,6 +1807,90 @@ test('ls --json', (t) => {
})
})
+ t.test('with filter arg nested dep', (t) => {
+ prefix = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'test-npm-ls',
+ version: '1.0.0',
+ dependencies: {
+ foo: '^1.0.0',
+ lorem: '^1.0.0'
+ }
+ }),
+ ...simpleNmFixture
+ })
+ ls(['bar'], (err) => {
+ t.ifError(err, 'npm ls')
+ t.deepEqual(
+ jsonParse(result),
+ {
+ name: 'test-npm-ls',
+ version: '1.0.0',
+ dependencies: {
+ foo: {
+ version: '1.0.0',
+ dependencies: {
+ bar: {
+ version: '1.0.0'
+ }
+ }
+ }
+ }
+ },
+ 'should output json contaning only occurences of filtered by package'
+ )
+ t.end()
+ })
+ })
+
+ t.test('with multiple filter args', (t) => {
+ prefix = t.testdir({
+ 'package.json': JSON.stringify({
+ name: 'test-npm-ls',
+ version: '1.0.0',
+ dependencies: {
+ foo: '^1.0.0',
+ lorem: '^1.0.0',
+ ipsum: '^1.0.0'
+ }
+ }),
+ node_modules: {
+ ...simpleNmFixture.node_modules,
+ ipsum: {
+ 'package.json': JSON.stringify({
+ name: 'ipsum',
+ version: '1.0.0'
+ })
+ }
+ }
+ })
+ ls(['bar@*', 'lorem@1.0.0'], (err) => {
+ t.ifError(err, 'npm ls')
+ t.deepEqual(
+ jsonParse(result),
+ {
+ 'version': '1.0.0',
+ 'name': 'test-npm-ls',
+ 'dependencies': {
+ 'foo': {
+ 'version': '1.0.0',
+ 'dependencies': {
+ 'bar': {
+ 'version': '1.0.0'
+ }
+ }
+ },
+ 'lorem': {
+ 'version': '1.0.0'
+ }
+ }
+ },
+ 'should output json contaning only occurences of multiple filtered packages and their ancestors'
+ )
+ t.end()
+ })
+ })
+
t.test('with missing filter arg', (t) => {
prefix = t.testdir({
'package.json': JSON.stringify({
@@ -1578,16 +2013,16 @@ test('ls --json', (t) => {
}),
...simpleNmFixture
})
- ls([], () => {
+ ls([], (err) => {
+ t.match(err, { code: 'ELSPROBLEMS' }, 'should list dep problems')
t.deepEqual(
jsonParse(result),
{
'name': 'test-npm-ls',
'version': '1.0.0',
'problems': [
- 'missing: ipsum@^1.0.0, required by test-npm-ls@1.0.0',
'invalid: foo@1.0.0 {CWD}/ls-ls-json-missing-invalid-extraneous/node_modules/foo',
- 'extraneous: bar@1.0.0 {CWD}/ls-ls-json-missing-invalid-extraneous/node_modules/bar',
+ 'missing: ipsum@^1.0.0, required by test-npm-ls@1.0.0',
'extraneous: lorem@1.0.0 {CWD}/ls-ls-json-missing-invalid-extraneous/node_modules/lorem'
],
'dependencies': {
@@ -1595,16 +2030,11 @@ test('ls --json', (t) => {
'version': '1.0.0',
'invalid': true,
'problems': [
- 'invalid: foo@1.0.0 {CWD}/ls-ls-json-missing-invalid-extraneous/node_modules/foo',
- 'extraneous: bar@1.0.0 {CWD}/ls-ls-json-missing-invalid-extraneous/node_modules/bar'
+ 'invalid: foo@1.0.0 {CWD}/ls-ls-json-missing-invalid-extraneous/node_modules/foo'
],
'dependencies': {
'bar': {
- 'version': '1.0.0',
- 'extraneous': true,
- 'problems': [
- 'extraneous: bar@1.0.0 {CWD}/ls-ls-json-missing-invalid-extraneous/node_modules/bar'
- ]
+ 'version': '1.0.0'
}
}
},
@@ -1617,7 +2047,10 @@ test('ls --json', (t) => {
},
'ipsum': {
'required': '^1.0.0',
- 'missing': true
+ 'missing': true,
+ 'problems': [
+ 'missing: ipsum@^1.0.0, required by test-npm-ls@1.0.0'
+ ]
}
}
},
@@ -1761,7 +2194,10 @@ test('ls --json', (t) => {
name: 'test-npm-ls',
version: '1.0.0',
dependencies: {
- 'linked-dep': { version: '1.0.0' }
+ 'linked-dep': {
+ version: '1.0.0',
+ resolved: 'file:../linked-dep'
+ }
}
},
'should output json containing linked deps'
@@ -1853,6 +2289,135 @@ test('ls --json', (t) => {
})
})
+ t.test('from lockfile', (t) => {
+ prefix = t.testdir({
+ node_modules: {
+ '@isaacs': {
+ 'dedupe-tests-a': {
+ 'package.json': JSON.stringify({
+ name: '@isaacs/dedupe-tests-a',
+ version: '1.0.1'
+ }),
+ node_modules: {
+ '@isaacs': {
+ 'dedupe-tests-b': {
+ name: '@isaacs/dedupe-tests-b',
+ version: '1.0.0'
+ }
+ }
+ }
+ },
+ 'dedupe-tests-b': {
+ 'package.json': JSON.stringify({
+ name: '@isaacs/dedupe-tests-b',
+ version: '2.0.0'
+ })
+ }
+ }
+ },
+ 'package-lock.json': JSON.stringify({
+ 'name': 'dedupe-lockfile',
+ 'version': '1.0.0',
+ 'lockfileVersion': 2,
+ 'requires': true,
+ 'packages': {
+ '': {
+ 'name': 'dedupe-lockfile',
+ 'version': '1.0.0',
+ 'dependencies': {
+ '@isaacs/dedupe-tests-a': '1.0.1',
+ '@isaacs/dedupe-tests-b': '1||2'
+ }
+ },
+ 'node_modules/@isaacs/dedupe-tests-a': {
+ 'name': '@isaacs/dedupe-tests-a',
+ 'version': '1.0.1',
+ 'resolved': 'https://registry.npmjs.org/@isaacs/dedupe-tests-a/-/dedupe-tests-a-1.0.1.tgz',
+ 'integrity': 'sha512-8AN9lNCcBt5Xeje7fMEEpp5K3rgcAzIpTtAjYb/YMUYu8SbIVF6wz0WqACDVKvpQOUcSfNHZQNLNmue0QSwXOQ==',
+ 'dependencies': {
+ '@isaacs/dedupe-tests-b': '1'
+ }
+ },
+ 'node_modules/@isaacs/dedupe-tests-a/node_modules/@isaacs/dedupe-tests-b': {
+ 'name': '@isaacs/dedupe-tests-b',
+ 'version': '1.0.0',
+ 'resolved': 'https://registry.npmjs.org/@isaacs/dedupe-tests-b/-/dedupe-tests-b-1.0.0.tgz',
+ 'integrity': 'sha512-3nmvzIb8QL8OXODzipwoV3U8h9OQD9g9RwOPuSBQqjqSg9JZR1CCFOWNsDUtOfmwY8HFUJV9EAZ124uhqVxq+w=='
+ },
+ 'node_modules/@isaacs/dedupe-tests-b': {
+ 'name': '@isaacs/dedupe-tests-b',
+ 'version': '2.0.0',
+ 'resolved': 'https://registry.npmjs.org/@isaacs/dedupe-tests-b/-/dedupe-tests-b-2.0.0.tgz',
+ 'integrity': 'sha512-KTYkpRv9EzlmCg4Gsm/jpclWmRYFCXow8GZKJXjK08sIZBlElTZEa5Bw/UQxIvEfcKmWXczSqItD49Kr8Ax4UA=='
+ }
+ },
+ 'dependencies': {
+ '@isaacs/dedupe-tests-a': {
+ 'version': '1.0.1',
+ 'resolved': 'https://registry.npmjs.org/@isaacs/dedupe-tests-a/-/dedupe-tests-a-1.0.1.tgz',
+ 'integrity': 'sha512-8AN9lNCcBt5Xeje7fMEEpp5K3rgcAzIpTtAjYb/YMUYu8SbIVF6wz0WqACDVKvpQOUcSfNHZQNLNmue0QSwXOQ==',
+ 'requires': {
+ '@isaacs/dedupe-tests-b': '1'
+ },
+ 'dependencies': {
+ '@isaacs/dedupe-tests-b': {
+ 'version': '1.0.0',
+ 'resolved': 'https://registry.npmjs.org/@isaacs/dedupe-tests-b/-/dedupe-tests-b-1.0.0.tgz',
+ 'integrity': 'sha512-3nmvzIb8QL8OXODzipwoV3U8h9OQD9g9RwOPuSBQqjqSg9JZR1CCFOWNsDUtOfmwY8HFUJV9EAZ124uhqVxq+w=='
+ }
+ }
+ },
+ '@isaacs/dedupe-tests-b': {
+ 'version': '2.0.0',
+ 'resolved': 'https://registry.npmjs.org/@isaacs/dedupe-tests-b/-/dedupe-tests-b-2.0.0.tgz',
+ 'integrity': 'sha512-KTYkpRv9EzlmCg4Gsm/jpclWmRYFCXow8GZKJXjK08sIZBlElTZEa5Bw/UQxIvEfcKmWXczSqItD49Kr8Ax4UA=='
+ }
+ }
+ }),
+ 'package.json': JSON.stringify({
+ 'name': 'dedupe-lockfile',
+ 'version': '1.0.0',
+ 'dependencies': {
+ '@isaacs/dedupe-tests-a': '1.0.1',
+ '@isaacs/dedupe-tests-b': '1||2'
+ }
+ })
+ })
+ ls([], () => {
+ t.deepEqual(
+ jsonParse(result),
+ {
+ 'version': '1.0.0',
+ 'name': 'dedupe-lockfile',
+ 'dependencies': {
+ '@isaacs/dedupe-tests-a': {
+ 'version': '1.0.1',
+ 'resolved': 'https://registry.npmjs.org/@isaacs/dedupe-tests-a/-/dedupe-tests-a-1.0.1.tgz',
+ 'dependencies': {
+ '@isaacs/dedupe-tests-b': {
+ 'resolved': 'https://registry.npmjs.org/@isaacs/dedupe-tests-b/-/dedupe-tests-b-1.0.0.tgz',
+ 'extraneous': true,
+ 'problems': [
+ 'extraneous: @isaacs/dedupe-tests-b@ {CWD}/ls-ls-json-from-lockfile/node_modules/@isaacs/dedupe-tests-a/node_modules/@isaacs/dedupe-tests-b'
+ ]
+ }
+ }
+ },
+ '@isaacs/dedupe-tests-b': {
+ 'version': '2.0.0',
+ 'resolved': 'https://registry.npmjs.org/@isaacs/dedupe-tests-b/-/dedupe-tests-b-2.0.0.tgz'
+ }
+ },
+ 'problems': [
+ 'extraneous: @isaacs/dedupe-tests-b@ {CWD}/ls-ls-json-from-lockfile/node_modules/@isaacs/dedupe-tests-a/node_modules/@isaacs/dedupe-tests-b'
+ ]
+ },
+ 'should output json containing only prod deps'
+ )
+ t.end()
+ })
+ })
+
t.test('--long', (t) => {
_flatOptions.long = true
prefix = t.testdir({
@@ -1886,15 +2451,12 @@ test('ls --json', (t) => {
name: 'peer-dep',
description: 'Peer-dep description here',
version: '1.0.0',
- readme: 'ERROR: No README data found!',
_id: 'peer-dep@1.0.0',
- dependencies: {},
devDependencies: {},
- optionalDependencies: {},
+ peerDependencies: {},
_dependencies: {},
path: '{CWD}/ls-ls-json--long/node_modules/peer-dep',
- error: null,
- extraneous: true
+ extraneous: false
},
'dev-dep': {
name: 'dev-dep',
@@ -1908,61 +2470,48 @@ test('ls --json', (t) => {
bar: {
name: 'bar',
version: '1.0.0',
- readme: 'ERROR: No README data found!',
_id: 'bar@1.0.0',
- dependencies: {},
devDependencies: {},
- optionalDependencies: {},
+ peerDependencies: {},
_dependencies: {},
path: '{CWD}/ls-ls-json--long/node_modules/bar',
- error: '[Circular]',
extraneous: false
}
},
- readme: 'ERROR: No README data found!',
_id: 'foo@1.0.0',
devDependencies: {},
- optionalDependencies: {},
+ peerDependencies: {},
_dependencies: { bar: '^1.0.0' },
path: '{CWD}/ls-ls-json--long/node_modules/foo',
- error: '[Circular]',
extraneous: false
}
},
- readme: 'ERROR: No README data found!',
_id: 'dev-dep@1.0.0',
devDependencies: {},
- optionalDependencies: {},
+ peerDependencies: {},
_dependencies: { foo: '^1.0.0' },
path: '{CWD}/ls-ls-json--long/node_modules/dev-dep',
- error: '[Circular]',
extraneous: false
},
lorem: {
name: 'lorem',
version: '1.0.0',
- readme: 'ERROR: No README data found!',
_id: 'lorem@1.0.0',
- dependencies: {},
devDependencies: {},
- optionalDependencies: {},
+ peerDependencies: {},
_dependencies: {},
path: '{CWD}/ls-ls-json--long/node_modules/lorem',
- error: '[Circular]',
extraneous: false
},
'optional-dep': {
name: 'optional-dep',
description: 'Maybe a dep?',
version: '1.0.0',
- readme: 'ERROR: No README data found!',
_id: 'optional-dep@1.0.0',
- dependencies: {},
devDependencies: {},
- optionalDependencies: {},
+ peerDependencies: {},
_dependencies: {},
path: '{CWD}/ls-ls-json--long/node_modules/optional-dep',
- error: '[Circular]',
extraneous: false
},
'prod-dep': {
@@ -1974,36 +2523,28 @@ test('ls --json', (t) => {
name: 'bar',
description: 'A dep that bars',
version: '2.0.0',
- readme: 'ERROR: No README data found!',
_id: 'bar@2.0.0',
- dependencies: {},
devDependencies: {},
- optionalDependencies: {},
+ peerDependencies: {},
_dependencies: {},
path: '{CWD}/ls-ls-json--long/node_modules/prod-dep/node_modules/bar',
- error: '[Circular]',
extraneous: false
}
},
- readme: 'ERROR: No README data found!',
_id: 'prod-dep@1.0.0',
devDependencies: {},
- optionalDependencies: {},
+ peerDependencies: {},
_dependencies: { bar: '^2.0.0' },
path: '{CWD}/ls-ls-json--long/node_modules/prod-dep',
- error: '[Circular]',
extraneous: false
}
},
devDependencies: { 'dev-dep': '^1.0.0' },
optionalDependencies: { 'optional-dep': '^1.0.0' },
peerDependencies: { 'peer-dep': '^1.0.0' },
- readme: 'ERROR: No README data found!',
_id: 'test-npm-ls@1.0.0',
- _shrinkwrap: '[Circular]',
_dependencies: { 'prod-dep': '^1.0.0', lorem: '^1.0.0', 'optional-dep': '^1.0.0' },
path: '{CWD}/ls-ls-json--long',
- error: '[Circular]',
extraneous: false
},
'should output long json info'
@@ -2047,76 +2588,63 @@ test('ls --json', (t) => {
name: 'peer-dep',
description: 'Peer-dep description here',
version: '1.0.0',
- readme: 'ERROR: No README data found!',
_id: 'peer-dep@1.0.0',
devDependencies: {},
- optionalDependencies: {},
+ peerDependencies: {},
_dependencies: {},
path: '{CWD}/ls-ls-json--long-depth-0/node_modules/peer-dep',
- error: null,
- extraneous: true
+ extraneous: false
},
'dev-dep': {
name: 'dev-dep',
description: 'A DEV dep kind of dep',
version: '1.0.0',
- readme: 'ERROR: No README data found!',
_id: 'dev-dep@1.0.0',
devDependencies: {},
- optionalDependencies: {},
+ peerDependencies: {},
_dependencies: { foo: '^1.0.0' },
path: '{CWD}/ls-ls-json--long-depth-0/node_modules/dev-dep',
- error: '[Circular]',
extraneous: false
},
lorem: {
name: 'lorem',
version: '1.0.0',
- readme: 'ERROR: No README data found!',
_id: 'lorem@1.0.0',
devDependencies: {},
- optionalDependencies: {},
+ peerDependencies: {},
_dependencies: {},
path: '{CWD}/ls-ls-json--long-depth-0/node_modules/lorem',
- error: '[Circular]',
extraneous: false
},
'optional-dep': {
name: 'optional-dep',
description: 'Maybe a dep?',
version: '1.0.0',
- readme: 'ERROR: No README data found!',
_id: 'optional-dep@1.0.0',
devDependencies: {},
- optionalDependencies: {},
+ peerDependencies: {},
_dependencies: {},
path: '{CWD}/ls-ls-json--long-depth-0/node_modules/optional-dep',
- error: '[Circular]',
extraneous: false
},
'prod-dep': {
name: 'prod-dep',
description: 'A PROD dep kind of dep',
version: '1.0.0',
- readme: 'ERROR: No README data found!',
_id: 'prod-dep@1.0.0',
devDependencies: {},
- optionalDependencies: {},
+ peerDependencies: {},
_dependencies: { bar: '^2.0.0' },
path: '{CWD}/ls-ls-json--long-depth-0/node_modules/prod-dep',
- error: '[Circular]',
extraneous: false
}
},
devDependencies: { 'dev-dep': '^1.0.0' },
optionalDependencies: { 'optional-dep': '^1.0.0' },
peerDependencies: { 'peer-dep': '^1.0.0' },
- readme: 'ERROR: No README data found!',
_id: 'test-npm-ls@1.0.0',
- _shrinkwrap: '[Circular]',
_dependencies: { 'prod-dep': '^1.0.0', lorem: '^1.0.0', 'optional-dep': '^1.0.0' },
path: '{CWD}/ls-ls-json--long-depth-0',
- error: '[Circular]',
extraneous: false
},
'should output json containing top-level deps in long format'
@@ -2132,13 +2660,14 @@ test('ls --json', (t) => {
'package.json': '{broken json'
})
ls([], (err) => {
- t.match(err, /Failed to parse json/)
+ t.match(err.message, 'Failed to parse root package.json', 'should have missin root package.json msg')
+ t.match(err.code, 'EJSONPARSE', 'should have EJSONPARSE error code')
t.deepEqual(
jsonParse(result),
{
invalid: true,
problems: [
- "error in {CWD}/ls-ls-json-json-read-problems: Failed to parse json/nUnexpected token b in JSON at position 1 while parsing near '{broken json'"
+ 'error in {CWD}/ls-ls-json-json-read-problems: Failed to parse root package.json'
]
},
'should print empty json result'
@@ -2181,38 +2710,23 @@ test('ls --json', (t) => {
}),
...diffDepTypesNmFixture
})
- ls([], () => {
+ ls([], (err) => {
+ t.match(err.code, 'ELSPROBLEMS', 'Should have ELSPROBLEMS error code')
t.deepEqual(
jsonParse(result),
{
name: 'test-npm-ls',
version: '1.0.0',
problems: [
- 'peer dep missing: peer-dep@^2.0.0, required by test-npm-ls@1.0.0'
+ 'invalid: peer-dep@1.0.0 {CWD}/ls-ls-json-unmet-peer-dep/node_modules/peer-dep'
],
dependencies: {
'peer-dep': {
- required: {
- name: 'peer-dep',
- description: 'Peer-dep description here',
- version: '1.0.0',
- readme: 'ERROR: No README data found!',
- _id: 'peer-dep@1.0.0',
- dependencies: {},
- devDependencies: {},
- optionalDependencies: {},
- _dependencies: {},
- path: '{CWD}/ls-ls-json-unmet-peer-dep/node_modules/peer-dep',
- error: null,
- extraneous: true,
- peerMissing: [
- {
- requiredBy: 'test-npm-ls@1.0.0',
- requires: 'peer-dep@^2.0.0'
- }
- ]
- },
- peerMissing: true
+ version: '1.0.0',
+ invalid: true,
+ problems: [
+ 'invalid: peer-dep@1.0.0 {CWD}/ls-ls-json-unmet-peer-dep/node_modules/peer-dep'
+ ]
},
'dev-dep': {
version: '1.0.0',
@@ -2256,15 +2770,16 @@ test('ls --json', (t) => {
}),
...diffDepTypesNmFixture
})
- ls([], () => {
+ ls([], (err) => {
+ t.match(err.code, 'ELSPROBLEMS', 'should have ELSPROBLEMS error code')
+ t.match(err.message, /invalid: optional-dep@1.0.0/, 'should have invalid dep error msg')
t.deepEqual(
jsonParse(result),
{
name: 'test-npm-ls',
version: '1.0.0',
problems: [
- 'invalid: optional-dep@1.0.0 {CWD}/ls-ls-json-unmet-optional-dep/node_modules/optional-dep', // mismatching optional deps get flagged in problems
- 'extraneous: peer-dep@1.0.0 {CWD}/ls-ls-json-unmet-optional-dep/node_modules/peer-dep'
+ 'invalid: optional-dep@1.0.0 {CWD}/ls-ls-json-unmet-optional-dep/node_modules/optional-dep' // mismatching optional deps get flagged in problems
],
dependencies: {
'optional-dep': {
@@ -2275,11 +2790,7 @@ test('ls --json', (t) => {
]
},
'peer-dep': {
- version: '1.0.0',
- extraneous: true,
- problems: [
- 'extraneous: peer-dep@1.0.0 {CWD}/ls-ls-json-unmet-optional-dep/node_modules/peer-dep'
- ]
+ version: '1.0.0'
},
'dev-dep': {
version: '1.0.0',
@@ -2389,7 +2900,6 @@ test('ls --json', (t) => {
dependencies: {
a: {
version: '1.0.0',
- from: 'a@npm:b',
resolved: 'https://localhost:8080/abbrev/-/abbrev-1.1.1.tgz'
}
}
@@ -2438,8 +2948,7 @@ test('ls --json', (t) => {
dependencies: {
abbrev: {
version: '1.1.1',
- from: 'git+https://github.com/isaacs/abbrev-js.git',
- resolved: 'git+https://github.com/isaacs/abbrev-js.git#b8f3a2fc0c3bb8ffd8b0d0072cc6b5a3667e963c'
+ resolved: 'git+ssh://git@github.com/isaacs/abbrev-js.git#b8f3a2fc0c3bb8ffd8b0d0072cc6b5a3667e963c'
}
}
},
@@ -2495,7 +3004,6 @@ test('ls --json', (t) => {
dependencies: {
'simple-output': {
version: '2.1.1',
- from: 'simple-output',
resolved: 'https://registry.npmjs.org/simple-output/-/simple-output-2.1.1.tgz'
}
}
@@ -2506,5 +3014,24 @@ test('ls --json', (t) => {
})
})
+ t.test('node.name fallback if missing root package name', (t) => {
+ prefix = t.testdir({
+ 'package.json': JSON.stringify({
+ version: '1.0.0'
+ })
+ })
+ ls([], () => {
+ t.deepEqual(
+ jsonParse(result),
+ {
+ 'version': '1.0.0',
+ 'name': 'ls-ls-json-node-name-fallback-if-missing-root-package-name'
+ },
+ 'should use node.name as key in json result obj'
+ )
+ t.end()
+ })
+ })
+
t.end()
})