Files
pnpm/cli/cli-utils/test/getConfig.test.ts
T
Zoltan Kochan e7888e5ea8 fix(self-update): trust only non-project config on pnpm 10 (#14169)
The pnpm 10 self-update handler passed the general resolved configuration to both the package resolver and the engine identity verifier. Workspace settings can preserve otherwise unknown runtime keys, so repository configuration could overwrite the internal package-manager registry and the verifier's test-only trusted-key override.

Construct resolver and installer options from the dedicated package-manager bootstrap configuration, which is captured from non-project sources before workspace settings are merged. Move the shared bootstrap helper into `@pnpm/config` so automatic version switching and self-update use the same boundary. Pass unsigned-fixture keys through a separate explicit test argument instead of the runtime command options.

Also skip automatic loading of the default project pnpmfile for self-update, while preserving its behavior for other commands. Add regressions for registry redirection, identity-verification bypass, trusted bootstrap config, and pnpmfile loading.
2026-08-25 18:15:01 +02:00

120 lines
2.9 KiB
TypeScript

/// <reference path="../../../__typings__/index.d.ts"/>
import fs from 'fs'
import { getConfig } from '@pnpm/cli-utils'
import { prepare } from '@pnpm/prepare'
beforeEach(() => {
jest.spyOn(console, 'warn')
})
afterEach(() => {
jest.mocked(console.warn).mockRestore()
})
test('console a warning when the .npmrc has an env variable that does not exist', async () => {
prepare()
fs.writeFileSync('.npmrc', 'foo=${ENV_VAR_123}', 'utf8') // eslint-disable-line
await getConfig({
json: false,
}, {
workspaceDir: '.',
excludeReporter: false,
rcOptionsTypes: {},
})
// eslint-disable-next-line no-template-curly-in-string
expect(console.warn).toHaveBeenCalledWith(expect.stringContaining('Failed to replace env in config: ${ENV_VAR_123}'))
})
test('hoist: false removes hoistPattern', async () => {
prepare()
const config = await getConfig({
hoist: false,
}, {
workspaceDir: '.',
excludeReporter: false,
rcOptionsTypes: {},
})
expect(config.hoist).toBe(false)
expect(config.hoistPattern).toBeUndefined()
})
test('allowBuilds populates onlyBuiltDependencies and ignoredBuiltDependencies', async () => {
prepare()
const config = await getConfig({
allowBuilds: {
'allowed-pkg': true,
'another-allowed': true,
'blocked-pkg': false,
},
}, {
workspaceDir: '.',
excludeReporter: false,
rcOptionsTypes: {},
})
expect(config.onlyBuiltDependencies).toContain('allowed-pkg')
expect(config.onlyBuiltDependencies).toContain('another-allowed')
expect(config.ignoredBuiltDependencies).toContain('blocked-pkg')
})
test('allowBuilds does not add duplicates', async () => {
prepare()
const config = await getConfig({
onlyBuiltDependencies: ['already-allowed'],
ignoredBuiltDependencies: ['already-blocked'],
allowBuilds: {
'already-allowed': true,
'already-blocked': false,
},
}, {
workspaceDir: '.',
excludeReporter: false,
rcOptionsTypes: {},
})
expect(config.onlyBuiltDependencies).toEqual(['already-allowed'])
expect(config.ignoredBuiltDependencies).toEqual(['already-blocked'])
})
test('self-update does not load the default project pnpmfile', async () => {
prepare()
fs.writeFileSync('.pnpmfile.cjs', `
require('fs').writeFileSync('pnpmfile-was-loaded', '')
module.exports = { hooks: {} }
`)
await getConfig({}, {
workspaceDir: process.cwd(),
excludeReporter: false,
rcOptionsTypes: {},
forSelfUpdate: true,
})
expect(fs.existsSync('pnpmfile-was-loaded')).toBe(false)
})
test('the default project pnpmfile is loaded for other commands', async () => {
prepare()
fs.writeFileSync('.pnpmfile.cjs', `
require('fs').writeFileSync('pnpmfile-was-loaded', '')
module.exports = { hooks: {} }
`)
await getConfig({}, {
workspaceDir: process.cwd(),
excludeReporter: false,
rcOptionsTypes: {},
})
expect(fs.existsSync('pnpmfile-was-loaded')).toBe(true)
})