Files
pnpm/pkg-manager/core/test/allProjectsAreUpToDate.test.ts

500 lines
11 KiB
TypeScript

import { prepareEmpty } from '@pnpm/prepare'
import { allProjectsAreUpToDate } from '../lib/install/allProjectsAreUpToDate'
import { writeFile, mkdir } from 'fs/promises'
import { type Lockfile } from '@pnpm/lockfile-file'
const fooManifest = {
name: 'foo',
version: '1.0.0',
}
const workspacePackages = {
foo: {
'1.0.0': {
dir: 'foo',
manifest: fooManifest,
},
},
}
test('allProjectsAreUpToDate(): works with packages linked through the workspace protocol using relative path', async () => {
expect(await allProjectsAreUpToDate([
{
buildIndex: 0,
id: 'bar',
manifest: {
dependencies: {
foo: 'workspace:../foo',
},
},
rootDir: 'bar',
},
{
buildIndex: 0,
id: 'foo',
manifest: fooManifest,
rootDir: 'foo',
},
], {
autoInstallPeers: false,
excludeLinksFromLockfile: false,
linkWorkspacePackages: true,
wantedLockfile: {
importers: {
bar: {
dependencies: {
foo: 'link:../foo',
},
specifiers: {
foo: 'workspace:../foo',
},
},
foo: {
specifiers: {},
},
},
lockfileVersion: 5,
},
workspacePackages,
lockfileDir: '',
})).toBeTruthy()
})
test('allProjectsAreUpToDate(): works with aliased local dependencies', async () => {
expect(await allProjectsAreUpToDate([
{
buildIndex: 0,
id: 'bar',
manifest: {
dependencies: {
alias: 'npm:foo',
},
},
rootDir: 'bar',
},
{
buildIndex: 0,
id: 'foo',
manifest: fooManifest,
rootDir: 'foo',
},
], {
autoInstallPeers: false,
excludeLinksFromLockfile: false,
linkWorkspacePackages: true,
wantedLockfile: {
importers: {
bar: {
dependencies: {
alias: 'link:../foo',
},
specifiers: {
alias: 'npm:foo',
},
},
foo: {
specifiers: {},
},
},
lockfileVersion: 5,
},
workspacePackages,
lockfileDir: '',
})).toBeTruthy()
})
test('allProjectsAreUpToDate(): works with aliased local dependencies that specify versions', async () => {
expect(await allProjectsAreUpToDate([
{
buildIndex: 0,
id: 'bar',
manifest: {
dependencies: {
alias: 'npm:foo@1',
},
},
rootDir: 'bar',
},
{
buildIndex: 0,
id: 'foo',
manifest: fooManifest,
rootDir: 'foo',
},
], {
autoInstallPeers: false,
excludeLinksFromLockfile: false,
linkWorkspacePackages: true,
wantedLockfile: {
importers: {
bar: {
dependencies: {
alias: 'link:../foo',
},
specifiers: {
alias: 'npm:foo@1',
},
},
foo: {
specifiers: {},
},
},
lockfileVersion: 5,
},
workspacePackages,
lockfileDir: '',
})).toBeTruthy()
})
test('allProjectsAreUpToDate(): returns false if the aliased dependency version is out of date', async () => {
expect(await allProjectsAreUpToDate([
{
buildIndex: 0,
id: 'bar',
manifest: {
dependencies: {
alias: 'npm:foo@0',
},
},
rootDir: 'bar',
},
{
buildIndex: 0,
id: 'foo',
manifest: fooManifest,
rootDir: 'foo',
},
], {
autoInstallPeers: false,
excludeLinksFromLockfile: false,
linkWorkspacePackages: true,
wantedLockfile: {
importers: {
bar: {
dependencies: {
alias: 'link:../foo',
},
specifiers: {
alias: 'npm:foo@0',
},
},
foo: {
specifiers: {},
},
},
lockfileVersion: 5,
},
workspacePackages,
lockfileDir: '',
})).toBeFalsy()
})
test('allProjectsAreUpToDate(): use link and registry version if linkWorkspacePackages = false', async () => {
expect(
await allProjectsAreUpToDate(
[
{
buildIndex: 0,
id: 'bar',
manifest: {
dependencies: {
foo: 'workspace:*',
foo2: 'workspace:~',
foo3: 'workspace:^',
},
},
rootDir: 'bar',
},
{
buildIndex: 0,
id: 'bar2',
manifest: {
dependencies: {
foo: '1.0.0',
},
},
rootDir: 'bar2',
},
{
buildIndex: 0,
id: 'foo',
manifest: fooManifest,
rootDir: 'foo',
},
{
buildIndex: 0,
id: 'foo2',
manifest: {
name: 'foo2',
version: '1.0.0',
},
rootDir: 'foo2',
},
{
buildIndex: 0,
id: 'foo3',
manifest: {
name: 'foo3',
version: '1.0.0',
},
rootDir: 'foo3',
},
],
{
autoInstallPeers: false,
excludeLinksFromLockfile: false,
linkWorkspacePackages: false,
wantedLockfile: {
importers: {
bar: {
dependencies: {
foo: 'link:../foo',
foo2: 'link:../foo2',
foo3: 'link:../foo3',
},
specifiers: {
foo: 'workspace:*',
foo2: 'workspace:~',
foo3: 'workspace:^',
},
},
bar2: {
dependencies: {
foo: '1.0.0',
},
specifiers: {
foo: '1.0.0',
},
},
foo: {
specifiers: {},
},
foo2: {
specifiers: {},
},
foo3: {
specifiers: {},
},
},
lockfileVersion: 5,
},
workspacePackages,
lockfileDir: '',
}
)
).toBeTruthy()
})
test('allProjectsAreUpToDate(): returns false if dependenciesMeta differs', async () => {
expect(await allProjectsAreUpToDate([
{
buildIndex: 0,
id: 'bar',
manifest: {
dependencies: {
foo: 'workspace:../foo',
},
dependenciesMeta: {
foo: {
injected: true,
},
},
},
rootDir: 'bar',
},
{
buildIndex: 0,
id: 'foo',
manifest: fooManifest,
rootDir: 'foo',
},
], {
autoInstallPeers: false,
excludeLinksFromLockfile: false,
linkWorkspacePackages: true,
wantedLockfile: {
importers: {
bar: {
dependencies: {
foo: 'link:../foo',
},
specifiers: {
foo: 'workspace:../foo',
},
},
foo: {
specifiers: {},
},
},
lockfileVersion: 5,
},
workspacePackages,
lockfileDir: '',
})).toBeFalsy()
})
test('allProjectsAreUpToDate(): returns true if dependenciesMeta matches', async () => {
expect(await allProjectsAreUpToDate([
{
buildIndex: 0,
id: 'bar',
manifest: {
dependencies: {
foo: 'workspace:../foo',
},
dependenciesMeta: {
foo: {
injected: true,
},
},
},
rootDir: 'bar',
},
{
buildIndex: 0,
id: 'foo',
manifest: fooManifest,
rootDir: 'foo',
},
], {
autoInstallPeers: false,
excludeLinksFromLockfile: false,
linkWorkspacePackages: true,
wantedLockfile: {
importers: {
bar: {
dependencies: {
foo: 'link:../foo',
},
dependenciesMeta: {
foo: {
injected: true,
},
},
specifiers: {
foo: 'workspace:../foo',
},
},
foo: {
specifiers: {},
},
},
lockfileVersion: 5,
},
workspacePackages,
lockfileDir: '',
})).toBeTruthy()
})
describe('local file dependency', () => {
beforeEach(async () => {
prepareEmpty()
await mkdir('local-dir')
await writeFile('./local-dir/package.json', JSON.stringify({
name: 'local-dir',
version: '1.0.0',
dependencies: {
'is-positive': '2.0.0',
},
}))
})
const projects = [
{
buildIndex: 0,
id: 'bar',
manifest: {
dependencies: {
local: 'file:./local-dir',
},
},
rootDir: 'bar',
},
{
buildIndex: 0,
id: 'foo',
manifest: fooManifest,
rootDir: 'foo',
},
]
const options = {
autoInstallPeers: false,
excludeLinksFromLockfile: false,
linkWorkspacePackages: true,
wantedLockfile: {
importers: {
bar: {
dependencies: {
local: 'file:./local-dir',
},
specifiers: {
local: 'file:./local-dir',
},
},
foo: {
specifiers: {},
},
},
packages: {
'file:./local-dir': {
resolution: { directory: './local-dir', type: 'directory' },
name: 'local-dir',
version: '1.0.0',
dependencies: {
'is-positive': '2.0.0',
},
dev: false,
},
},
lockfileVersion: 5,
} as Lockfile,
workspacePackages,
lockfileDir: process.cwd(),
}
test('allProjectsAreUpToDate(): returns true if local file not changed', async () => {
expect(await allProjectsAreUpToDate(projects, {
...options,
lockfileDir: process.cwd(),
})).toBeTruthy()
})
test('allProjectsAreUpToDate(): returns false if add new dependency to local file', async () => {
await writeFile('./local-dir/package.json', JSON.stringify({
name: 'local-dir',
version: '1.0.0',
dependencies: {
'is-positive': '2.0.0',
'is-odd': '1.0.0',
},
}))
expect(await allProjectsAreUpToDate(projects, {
...options,
lockfileDir: process.cwd(),
})).toBeFalsy()
})
test('allProjectsAreUpToDate(): returns false if update dependency in local file', async () => {
await writeFile('./local-dir/package.json', JSON.stringify({
name: 'local-dir',
version: '1.0.0',
dependencies: {
'is-positive': '3.0.0',
},
}))
expect(await allProjectsAreUpToDate(projects, {
...options,
lockfileDir: process.cwd(),
})).toBeFalsy()
})
test('allProjectsAreUpToDate(): returns false if remove dependency in local file', async () => {
await writeFile('./local-dir/package.json', JSON.stringify({
name: 'local-dir',
version: '1.0.0',
dependencies: {},
}))
expect(await allProjectsAreUpToDate(projects, {
...options,
lockfileDir: process.cwd(),
})).toBeFalsy()
})
})