Files
pnpm/packages/lockfile-file/test/write.test.ts
Brandon Cheng 4fa1091c80 feat: add experimental use-inline-specifiers-lockfile-format (#5091)
* feat: add experimental use-inline-specifiers-lockfile-format

* fix(lockfile-file): check importers key for shared lockfile format

The `convertFromLockfileFileMutable` function reverts changes from
`normalizeLockfile` when not using the shared lockfile format.

  - The non-shared lockfile format puts fields like `specifiers`,
    `dependencies`, `devDependencies`, `optionalDependencies`, and
    `dependenciesMeta` on the root of the lockfile. This is typically
    the case for a repo not using pnpm workspaces.
  - The shared lockfile format puts these under a `importers` block
    scoped by a path.

The `use-inline-specifiers-lockfile-format` feature flag removes the
`specifiers` block in favor of putting each specifier next to the
resolved version within each `dependencies`, `devDependencies`, etc
block.

This means the `convertFromLockfileFileMutable` function can no longer
check for `specifiers` to detect the whether the "shared" format is
used. @zkochan suggested checking for `importers` instead, which should
have the same effect.
https://github.com/pnpm/pnpm/pull/5091#discussion_r929326835

* test(lockfile-file): add read & write test for useInlineSpecifiersFormat
2022-07-27 12:27:41 +03:00

270 lines
7.3 KiB
TypeScript

import fs from 'fs'
import path from 'path'
import { LOCKFILE_VERSION, WANTED_LOCKFILE } from '@pnpm/constants'
import {
readCurrentLockfile,
readWantedLockfile,
writeLockfiles,
} from '@pnpm/lockfile-file'
import tempy from 'tempy'
import yaml from 'yaml-tag'
import { getCurrentBranch } from '@pnpm/git-utils'
jest.mock('@pnpm/git-utils', () => ({ getCurrentBranch: jest.fn() }))
test('writeLockfiles()', async () => {
const projectPath = tempy.directory()
const wantedLockfile = {
importers: {
'.': {
dependencies: {
'is-negative': '1.0.0',
'is-positive': '1.0.0',
},
specifiers: {
'is-negative': '^1.0.0',
'is-positive': '^1.0.0',
},
},
},
lockfileVersion: LOCKFILE_VERSION,
packages: {
'/is-negative/1.0.0': {
os: ['darwin'],
dependencies: {
'is-positive': '2.0.0',
},
cpu: ['x86'],
libc: ['glibc'],
engines: {
node: '>=10',
npm: '\nfoo\n',
},
resolution: {
integrity: 'sha1-ChbBDewTLAqLCzb793Fo5VDvg/g=',
},
},
'/is-positive/1.0.0': {
resolution: {
integrity: 'sha1-ChbBDewTLAqLCzb793Fo5VDvg/g=',
},
},
'/is-positive/2.0.0': {
resolution: {
integrity: 'sha1-ChbBDewTLAqLCzb793Fo5VDvg/g=',
},
},
},
}
await writeLockfiles({
currentLockfile: wantedLockfile,
currentLockfileDir: projectPath,
wantedLockfile,
wantedLockfileDir: projectPath,
})
expect(await readCurrentLockfile(projectPath, { ignoreIncompatible: false })).toEqual(wantedLockfile)
expect(await readWantedLockfile(projectPath, { ignoreIncompatible: false })).toEqual(wantedLockfile)
// Verifying the formatting of the lockfile
expect(fs.readFileSync(path.join(projectPath, WANTED_LOCKFILE), 'utf8')).toMatchSnapshot()
})
test('writeLockfiles() when no specifiers but dependencies present', async () => {
const projectPath = tempy.directory()
const wantedLockfile = {
importers: {
'.': {
dependencies: {
'is-positive': 'link:../is-positive',
},
specifiers: {},
},
},
lockfileVersion: LOCKFILE_VERSION,
}
await writeLockfiles({
currentLockfile: wantedLockfile,
currentLockfileDir: projectPath,
wantedLockfile,
wantedLockfileDir: projectPath,
})
expect(await readCurrentLockfile(projectPath, { ignoreIncompatible: false })).toEqual(wantedLockfile)
expect(await readWantedLockfile(projectPath, { ignoreIncompatible: false })).toEqual(wantedLockfile)
})
test('write does not use yaml anchors/aliases', async () => {
const projectPath = tempy.directory()
const wantedLockfile = {
importers: {
'.': {
dependencies: {
'is-negative': '1.0.0',
'is-positive': '1.0.0',
},
specifiers: {
'is-negative': '1.0.0',
'is-positive': '1.0.0',
},
},
},
lockfileVersion: LOCKFILE_VERSION,
packages: yaml`
/react-dnd/2.5.4/react@15.6.1:
dependencies:
disposables: 1.0.2
dnd-core: 2.5.4
hoist-non-react-statics: 2.5.0
invariant: 2.2.3
lodash: 4.15.0
prop-types: 15.6.1
react: 15.6.1
dev: false
id: registry.npmjs.org/react-dnd/2.5.4
peerDependencies: &ref_11
react: '1'
resolution:
integrity: sha512-y9YmnusURc+3KPgvhYKvZ9oCucj51MSZWODyaeV0KFU0cquzA7dCD1g/OIYUKtNoZ+MXtacDngkdud2TklMSjw==
/react-dnd/2.5.4/react@15.6.2:
dependencies:
disposables: 1.0.2
dnd-core: 2.5.4
hoist-non-react-statics: 2.5.0
invariant: 2.2.3
lodash: 4.15.0
prop-types: 15.6.1
react: 15.6.2
dev: false
id: registry.npmjs.org/react-dnd/2.5.4
peerDependencies: *ref_11
resolution:
integrity: sha512-y9YmnusURc+3KPgvhYKvZ9oCucj51MSZWODyaeV0KFU0cquzA7dCD1g/OIYUKtNoZ+MXtacDngkdud2TklMSjw==
`,
}
await writeLockfiles({
currentLockfile: wantedLockfile,
currentLockfileDir: projectPath,
wantedLockfile,
wantedLockfileDir: projectPath,
})
const lockfileContent = fs.readFileSync(path.join(projectPath, WANTED_LOCKFILE), 'utf8')
expect(lockfileContent).not.toMatch('&')
expect(lockfileContent).not.toMatch('*')
})
test('writeLockfiles() does not fail if the lockfile has undefined properties', async () => {
const projectPath = tempy.directory()
const wantedLockfile = {
importers: {
'.': {
dependencies: {
'is-negative': '1.0.0',
'is-positive': '1.0.0',
},
specifiers: {
'is-negative': '^1.0.0',
'is-positive': '^1.0.0',
},
},
},
lockfileVersion: LOCKFILE_VERSION,
packages: {
'/is-negative/1.0.0': {
// eslint-disable-next-line
dependencies: undefined as any,
resolution: {
integrity: 'sha1-ChbBDewTLAqLCzb793Fo5VDvg/g=',
},
},
'/is-positive/1.0.0': {
resolution: {
integrity: 'sha1-ChbBDewTLAqLCzb793Fo5VDvg/g=',
},
},
'/is-positive/2.0.0': {
resolution: {
integrity: 'sha1-ChbBDewTLAqLCzb793Fo5VDvg/g=',
},
},
},
}
await writeLockfiles({
currentLockfile: wantedLockfile,
currentLockfileDir: projectPath,
wantedLockfile,
wantedLockfileDir: projectPath,
})
})
test('writeLockfiles() when useGitBranchLockfile', async () => {
const branchName: string = 'branch'
getCurrentBranch['mockReturnValue'](branchName)
const projectPath = tempy.directory()
const wantedLockfile = {
importers: {
'.': {
dependencies: {
foo: '1.0.0',
},
specifiers: {
foo: '^1.0.0',
},
},
},
lockfileVersion: LOCKFILE_VERSION,
packages: {
'/foo/1.0.0': {
resolution: {
integrity: 'sha1-ChbBDewTLAqLCzb793Fo5VDvg/g=',
},
},
},
}
await writeLockfiles({
currentLockfile: wantedLockfile,
currentLockfileDir: projectPath,
wantedLockfile,
wantedLockfileDir: projectPath,
useGitBranchLockfile: true,
})
expect(fs.existsSync(path.join(projectPath, WANTED_LOCKFILE))).toBeFalsy()
expect(fs.existsSync(path.join(projectPath, `pnpm-lock.${branchName}.yaml`))).toBeTruthy()
})
test('writeLockfiles() when useInlineSpecifiersFormat', async () => {
const projectPath = tempy.directory()
const wantedLockfile = {
importers: {
'.': {
dependencies: {
foo: '1.0.0',
},
specifiers: {
foo: '^1.0.0',
},
},
},
lockfileVersion: LOCKFILE_VERSION,
packages: {
'/foo/1.0.0': {
resolution: {
integrity: 'sha1-ChbBDewTLAqLCzb793Fo5VDvg/g=',
},
},
},
}
await writeLockfiles({
currentLockfile: wantedLockfile,
currentLockfileDir: projectPath,
wantedLockfile,
wantedLockfileDir: projectPath,
useInlineSpecifiersFormat: true,
})
expect(await readCurrentLockfile(projectPath, { ignoreIncompatible: false })).toEqual(wantedLockfile)
expect(await readWantedLockfile(projectPath, { ignoreIncompatible: false })).toEqual(wantedLockfile)
expect(fs.readFileSync(path.join(projectPath, WANTED_LOCKFILE), 'utf8')).toMatchSnapshot()
})