mirror of https://gitee.com/openkylin/npm.git
212 lines
7.5 KiB
JavaScript
212 lines
7.5 KiB
JavaScript
const YarnLock = require('../lib/yarn-lock.js')
|
|
const Arborist = require('../lib/arborist')
|
|
const Node = require('../lib/node.js')
|
|
|
|
const t = require('tap')
|
|
const { resolve, basename } = require('path')
|
|
const fixtures = [
|
|
resolve(__dirname, 'fixtures/tap-with-yarn-lock'),
|
|
resolve(__dirname, 'fixtures/yarn-stuff'),
|
|
]
|
|
const { readFileSync } = require('fs')
|
|
|
|
fixtures.forEach(f => t.test(basename(f), t => {
|
|
const lockdata = readFileSync(f + '/yarn.lock')
|
|
const yarnLock = new YarnLock()
|
|
// parse the data
|
|
yarnLock.parse(lockdata)
|
|
// then turn it into output
|
|
const lockOutput = yarnLock.toString()
|
|
// snapshot the result
|
|
t.matchSnapshot(lockOutput, 'generated output from input')
|
|
const yarnLock2 = new YarnLock()
|
|
yarnLock2.parse(lockOutput)
|
|
t.strictSame(yarnLock2, yarnLock, 'same parsed result from string output')
|
|
t.end()
|
|
}))
|
|
|
|
t.test('invalid yarn lockfile data throws', t => {
|
|
t.throws(() => YarnLock.parse(`
|
|
asdf@foo:
|
|
this !is not vlid
|
|
i mean
|
|
what even is it??
|
|
not yarn lock, that's for sure
|
|
{"maybe":"json"}?
|
|
- or: even
|
|
- yaml?
|
|
- NO
|
|
`), { content: ' this !is not vlid\n', line: 3, position: 11 }, 'just garbage')
|
|
|
|
t.throws(() => YarnLock.parse(`
|
|
asdf@foo:
|
|
dependencies:
|
|
foo bar baz blork
|
|
`), { content: ' foo bar baz blork\n', line: 4 }, 'invalid subkey')
|
|
|
|
t.end()
|
|
})
|
|
|
|
t.test('omits empty dependency list on toString output', t => {
|
|
const y = new YarnLock()
|
|
y.parse(`
|
|
foo@bar:
|
|
version "1.2.3"
|
|
resolved "https://registry.local/foo/-/foo-1.2.3.tgz"
|
|
dependencies:
|
|
|
|
# Note: do not require a \\n at the end of the file, just add it if missing
|
|
# Also: comments are not preserved.
|
|
|
|
bar@foo:
|
|
version "1.2.3"`)
|
|
t.equal(y.toString(), `# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
|
# yarn lockfile v1
|
|
|
|
|
|
"bar@foo":
|
|
"version" "1.2.3"
|
|
|
|
"foo@bar":
|
|
"resolved" "https://registry.local/foo/-/foo-1.2.3.tgz"
|
|
"version" "1.2.3"
|
|
`)
|
|
t.end()
|
|
})
|
|
|
|
t.test('exports YarnLockEntry class', t => {
|
|
t.type(YarnLock.Entry, 'function')
|
|
t.end()
|
|
})
|
|
|
|
t.test('load a yarn lock from an actual tree', t => {
|
|
// make sure the symlinks are loaded
|
|
require('./fixtures/index.js')
|
|
const fixtures = [
|
|
resolve(__dirname, 'fixtures/install-types'),
|
|
resolve(__dirname, 'fixtures/links-all-over'),
|
|
]
|
|
fixtures.forEach(fixture => t.test(basename(fixture), t =>
|
|
new Arborist({ path: fixture }).loadActual().then(tree => {
|
|
const y = YarnLock.fromTree(tree)
|
|
t.matchSnapshot(y.toString(), 'yarn.lock from a package tree')
|
|
})))
|
|
t.end()
|
|
})
|
|
|
|
t.test('yarn lock with dedupes yarn wouldnt do', async t => {
|
|
const tree = new Node({
|
|
path: '/my/project',
|
|
pkg: { dependencies: { x: '1.x', y: '1.x', z: '1.x' } },
|
|
children: [
|
|
{ pkg: { name: 'x', version: '1.2.0' } },
|
|
{ pkg: { name: 'y', version: '1.0.0', dependencies: { x: '1.1', z: '2.x' } },
|
|
children: [
|
|
{ pkg: { name: 'x', version: '1.1.0' } },
|
|
{ pkg: { name: 'z', version: '2.0.0', dependencies: { x: '1.x' } } },
|
|
// note: yarn nests another x@1.2.0 here, because it locks
|
|
// the 1.x resolution to 1.2.0 even when unnecessary
|
|
],
|
|
},
|
|
{ pkg: { name: 'z', version: '1.0.0' } },
|
|
],
|
|
})
|
|
|
|
const y = YarnLock.fromTree(tree)
|
|
t.matchSnapshot(y.toString(), 'yarn.lock from deduped tree')
|
|
})
|
|
|
|
t.test('deduped prior entries that dont match one another', async t => {
|
|
const tree = new Node({
|
|
path: '/my/project',
|
|
pkg: { dependencies: { a: '', b: '' } },
|
|
children: [
|
|
{ pkg: { name: 'a', dependencies: { i: '', x: '1.x', y: '1.x', z: '1.x' } },
|
|
children: [
|
|
{ pkg: { name: 'i', version: '1.0.0', dependencies: { x: '1.2.0' } } },
|
|
{ pkg: { name: 'x', version: '1.2.0' }, integrity: 'x120' },
|
|
{ pkg: { name: 'y', version: '1.0.0', dependencies: { x: '1.1', z: '2.x' } },
|
|
children: [
|
|
{ pkg: { name: 'x', version: '1.1.0' } },
|
|
{ pkg: { name: 'z', version: '2.0.0', dependencies: { x: '1.x' } } },
|
|
],
|
|
},
|
|
{ pkg: { name: 'z', version: '1.0.0' } },
|
|
],
|
|
},
|
|
{ pkg: { name: 'b', dependencies: { j: '', x: '1.x', y: '1.x', z: '1.x' } },
|
|
children: [
|
|
{ pkg: { name: 'j', version: '1.0.0', dependencies: { x: '1.3.0' } } },
|
|
{ pkg: { name: 'x', version: '1.3.0' }, integrity: 'x130' },
|
|
{ pkg: { name: 'y', version: '1.0.0', dependencies: { x: '1.1', z: '2.x' } },
|
|
children: [
|
|
{ pkg: { name: 'x', version: '1.1.0' } },
|
|
{ pkg: { name: 'z', version: '2.0.0', dependencies: { x: '1.x' } } },
|
|
],
|
|
},
|
|
{ pkg: { name: 'z', version: '1.0.0' } },
|
|
],
|
|
},
|
|
],
|
|
})
|
|
|
|
const y = YarnLock.fromTree(tree)
|
|
t.matchSnapshot(y.toString(), 'yarn.lock with mismatching previous resolutions')
|
|
})
|
|
|
|
t.test('more nesting tree complications', async t => {
|
|
const tree = new Node({
|
|
path: '/my/project',
|
|
pkg: { dependencies: { a: '', b: '', c: '', c2: '', d3: '' } },
|
|
children: [
|
|
{ pkg: { name: 'a', dependencies: { x: '', g: '', h: '', i: '', j: '', k: '' } },
|
|
children: [
|
|
{ pkg: { name: 'x', version: '1.0.0' }, resolved: 'https://x100.xyz' },
|
|
{ pkg: { name: 'g', version: '1.0.0', dependencies: { x: '^1.0.0' } } },
|
|
{ pkg: { name: 'h', version: '1.0.0', dependencies: { x: '1.0.0' } } },
|
|
{ pkg: { name: 'i', version: '1.0.0', dependencies: { x: '1.0' } } },
|
|
{ pkg: { name: 'j', version: '1.0.0', dependencies: { x: '1' } } },
|
|
{ pkg: { name: 'k', version: '1.0.0', dependencies: { x: '' } } },
|
|
],
|
|
},
|
|
// previously-seen specs that don't match
|
|
{ pkg: { name: 'b', dependencies: { x: '', l: '', m: '', n: '', n2: '', o: '', p: '' } },
|
|
children: [
|
|
{ pkg: { name: 'x', version: '1.0.1' } },
|
|
{ pkg: { name: 'l', version: '1.0.0', dependencies: { x: '^1.0.1' } } },
|
|
{ pkg: { name: 'm', version: '1.0.0', dependencies: { x: '1.0.1' } } },
|
|
{ pkg: { name: 'n', version: '1.0.0', dependencies: { x: '1.0' } } },
|
|
{ pkg: { name: 'n2', version: '1.0.0', dependencies: { x: '>=1.0' } } },
|
|
{ pkg: { name: 'o', version: '1.0.0', dependencies: { x: '1' } } },
|
|
{ pkg: { name: 'p', version: '1.0.0', dependencies: { x: '' } } },
|
|
],
|
|
},
|
|
// new specs that get added right away to the entry
|
|
{ pkg: { name: 'c', dependencies: { d: '', e: '', f: '' } },
|
|
children: [
|
|
{ pkg: { name: 'x', version: '1.0.1' }, integrity: 'x101', resolved: 'https://x101.xyz' },
|
|
{ pkg: { name: 'd', version: '1.0.0', dependencies: { x: '^1.0.1' } } },
|
|
{ pkg: { name: 'e', version: '1.0.0', dependencies: { x: '>=1.0.1 <2' } } },
|
|
{ pkg: { name: 'f', version: '1.0.0', dependencies: { x: '>=1.0' } } },
|
|
],
|
|
},
|
|
// new specs that later match
|
|
{ pkg: { name: 'c2', dependencies: { d2: '', e2: '', f2: '' } },
|
|
children: [
|
|
{ pkg: { name: 'x', version: '1.0.1' }, resolved: 'https://x101.xyz' },
|
|
{ pkg: { name: 'd2', version: '1.0.0', dependencies: { x: '^1.0.0-x' } } },
|
|
{ pkg: { name: 'e2', version: '1.0.0', dependencies: { x: '>=1.0.0' } } },
|
|
{ pkg: { name: 'f2', version: '1.0.0', dependencies: { x: '1.0.1' } } },
|
|
],
|
|
},
|
|
// no version, resolved, or integrity, we assume a match
|
|
{ pkg: { name: 'd3', dependencies: { x: '' } },
|
|
children: [{ pkg: { name: 'x' } }],
|
|
},
|
|
],
|
|
})
|
|
|
|
const y = YarnLock.fromTree(tree)
|
|
t.matchSnapshot(y.toString(), 'yarn.lock with mismatching previous resolutions')
|
|
})
|