diff --git a/pnpm/test/configurationalDependencies.test.ts b/pnpm/test/configurationalDependencies.test.ts index 10cb16512c..529288190f 100644 --- a/pnpm/test/configurationalDependencies.test.ts +++ b/pnpm/test/configurationalDependencies.test.ts @@ -1,7 +1,7 @@ import fs from 'node:fs' import path from 'node:path' -import { expect, test } from '@jest/globals' +import { describe, expect, test } from '@jest/globals' import { readEnvLockfile } from '@pnpm/lockfile.fs' import { prepare } from '@pnpm/prepare' import { getIntegrity } from '@pnpm/registry-mock' @@ -149,21 +149,26 @@ test('package manager from the packageManager field is not saved into the lockfi expect(envLockfile!.importers['.'].packageManagerDependencies).toBeUndefined() }) -test('packageManagerDependencies is refreshed when pnpm is invoked via corepack (#11397)', async () => { - const pnpmVersion = JSON.parse(fs.readFileSync(path.join(path.dirname(pnpmBinLocation), '..', 'package.json'), 'utf8')).version as string - prepare({ - devEngines: { - packageManager: { - name: 'pnpm', - version: pnpmVersion, +// These tests resolve the running pnpm version's integrity from registry-mock, +// which proxies pnpm to npmjs. They fail between a release commit and the +// matching npm publish ("No matching version found for pnpm@"), and +// pass again once the version lands on npmjs. +describe('release-brittle: may fail until current version is published to npm', () => { + test('packageManagerDependencies is refreshed when pnpm is invoked via corepack (#11397)', async () => { + const pnpmVersion = JSON.parse(fs.readFileSync(path.join(path.dirname(pnpmBinLocation), '..', 'package.json'), 'utf8')).version as string + prepare({ + devEngines: { + packageManager: { + name: 'pnpm', + version: pnpmVersion, + }, }, - }, - }) + }) - // Seed the lockfile with a stale packageManagerDependencies entry that no - // longer satisfies devEngines.packageManager. Multi-document YAML: env - // lockfile is the first doc, the (empty) installer lockfile is the second. - fs.writeFileSync('pnpm-lock.yaml', `--- + // Seed the lockfile with a stale packageManagerDependencies entry that no + // longer satisfies devEngines.packageManager. Multi-document YAML: env + // lockfile is the first doc, the (empty) installer lockfile is the second. + fs.writeFileSync('pnpm-lock.yaml', `--- lockfileVersion: '9.0' importers: '.': @@ -178,16 +183,17 @@ snapshots: {} --- `) - // COREPACK_ROOT used to skip the entire pm-handling block, leaving the stale - // 0.0.1 entry untouched. The sync must run regardless of how pnpm was - // invoked. - await execPnpm(['install'], { - env: { COREPACK_ROOT: '/fake/corepack' }, - }) + // COREPACK_ROOT used to skip the entire pm-handling block, leaving the + // stale 0.0.1 entry untouched. The sync must run regardless of how pnpm + // was invoked. + await execPnpm(['install'], { + env: { COREPACK_ROOT: '/fake/corepack' }, + }) - const envLockfile = await readEnvLockfile(process.cwd()) - expect(envLockfile).not.toBeNull() - expect(envLockfile!.importers['.'].packageManagerDependencies?.['pnpm'].version).toBe(pnpmVersion) + const envLockfile = await readEnvLockfile(process.cwd()) + expect(envLockfile).not.toBeNull() + expect(envLockfile!.importers['.'].packageManagerDependencies?.['pnpm'].version).toBe(pnpmVersion) + }) }) test('installing a new configurational dependency', async () => { diff --git a/pnpm/test/packageManagerCheck.test.ts b/pnpm/test/packageManagerCheck.test.ts index 33eee61dc8..51faff9414 100644 --- a/pnpm/test/packageManagerCheck.test.ts +++ b/pnpm/test/packageManagerCheck.test.ts @@ -1,4 +1,4 @@ -import { expect, test } from '@jest/globals' +import { describe, expect, test } from '@jest/globals' import { prepare, prepareEmpty } from '@pnpm/prepare' import { writeYamlFileSync } from 'write-yaml-file' @@ -185,38 +185,6 @@ test('devEngines.packageManager with a different PM name should fail with onFail expect(stderr.toString()).toContain('This project is configured to use yarn') }) -test('pnpm --version exits promptly when devEngines.packageManager matches the running pnpm', async () => { - // Regression test: main.ts's `--version` short-circuit returned before - // the command-handler `finally` that calls finishWorkers(), and - // switchCliVersion had already spawned workers during integrity - // resolution. The worker pool then kept the Node event loop alive long - // past the version print. - // Read the running pnpm version from a fresh empty dir — the previous - // test's prepare() leaves cwd in a manifest with a failing pm check, and - // checkPackageManager runs before the --version short-circuit. - prepareEmpty() - const versionProcess = execPnpmSync(['--version']) - const pnpmVersion = versionProcess.stdout.toString().trim() - - prepare({ - devEngines: { - packageManager: { - name: 'pnpm', - version: pnpmVersion, - onFail: 'download', - }, - }, - }) - - // 30 s is comfortably above the post-fix exit time (~3 s) and far below - // the pre-fix hang. If the regression returns, spawnSync's timeout kicks - // in and execPnpmSync throws from its `error`/`signal` checks. - const { status, stdout } = execPnpmSync(['--version'], { timeout: 30_000 }) - - expect(status).toBe(0) - expect(stdout.toString().trim()).toBe(pnpmVersion) -}) - test('devEngines.packageManager array selects the pnpm entry', async () => { prepare({ devEngines: { @@ -251,22 +219,6 @@ test('devEngines.packageManager array defaults onFail to ignore for non-last ele expect(status).toBe(0) }) -test('devEngines.packageManager with version range should match current version', async () => { - prepare({ - devEngines: { - packageManager: { - name: 'pnpm', - version: '>=1.0.0', - onFail: 'error', - }, - }, - }) - - const { status } = execPnpmSync(['install']) - - expect(status).toBe(0) -}) - test('devEngines.packageManager takes precedence over packageManager field', async () => { const versionProcess = execPnpmSync(['--version']) const pnpmVersion = versionProcess.stdout.toString().trim() @@ -476,3 +428,57 @@ test.each([ expect(status).toBe(0) expect(stderr.toString()).not.toContain('configured to use 0.0.1') }) + +// These tests resolve the running pnpm version's integrity from registry-mock, +// which proxies pnpm to npmjs. They fail between a release commit and the +// matching npm publish ("No matching version found for pnpm@"), and +// pass again once the version lands on npmjs. +describe('release-brittle: may fail until current version is published to npm', () => { + test('pnpm --version exits promptly when devEngines.packageManager matches the running pnpm', async () => { + // Regression test: main.ts's `--version` short-circuit returned before + // the command-handler `finally` that calls finishWorkers(), and + // switchCliVersion had already spawned workers during integrity + // resolution. The worker pool then kept the Node event loop alive long + // past the version print. + // Read the running pnpm version from a fresh empty dir — the previous + // test's prepare() leaves cwd in a manifest with a failing pm check, and + // checkPackageManager runs before the --version short-circuit. + prepareEmpty() + const versionProcess = execPnpmSync(['--version']) + const pnpmVersion = versionProcess.stdout.toString().trim() + + prepare({ + devEngines: { + packageManager: { + name: 'pnpm', + version: pnpmVersion, + onFail: 'download', + }, + }, + }) + + // 30 s is comfortably above the post-fix exit time (~3 s) and far below + // the pre-fix hang. If the regression returns, spawnSync's timeout kicks + // in and execPnpmSync throws from its `error`/`signal` checks. + const { status, stdout } = execPnpmSync(['--version'], { timeout: 30_000 }) + + expect(status).toBe(0) + expect(stdout.toString().trim()).toBe(pnpmVersion) + }) + + test('devEngines.packageManager with version range should match current version', async () => { + prepare({ + devEngines: { + packageManager: { + name: 'pnpm', + version: '>=1.0.0', + onFail: 'error', + }, + }, + }) + + const { status } = execPnpmSync(['install']) + + expect(status).toBe(0) + }) +})