Files
pnpm/cli/default-reporter/test/reportingPeerDependencyIssues.ts
Zoltan Kochan 55de4febeb fix: render peer dependency issues on strict error (#11450)
Fixes #11439.

When `strictPeerDependencies: true` causes `ERR_PNPM_PEER_DEP_ISSUES`, the peer dependency issues are again rendered inline — using the **same format as `pnpm peers check`** — so users (and CI tools like Renovate) can see what failed without running another command.

The non-strict warning path is unchanged: it still emits the short "Run `pnpm peers check`" hint.

### Behavior

`strictPeerDependencies: true`:
```
 ERR_PNPM_PEER_DEP_ISSUES  Unmet peer dependencies

✕ unmet peer react
  Installed: 17.0.2
  Wanted:
    ^18.2.0:
      react-dom@18.2.0
hint: To disable failing on peer dependency issues, add the following to pnpm-workspace.yaml in your project root:

  strictPeerDependencies: false
```

`strictPeerDependencies: false` (unchanged):
```
 WARN  Issues with peer dependencies found. Run "pnpm peers check" to list them.
```

### Implementation

- Added a new `@pnpm/deps.inspection.peers-issues-renderer` package at `deps/inspection/peers-issues-renderer/`, alongside its data producer `@pnpm/deps.inspection.peers-checker`. It exposes a single `renderPeerIssues()` that emits the flat issue list previously inlined in `pnpm peers check`.
- Removed the duplicated formatter from `deps/inspection/commands/src/peers.ts` and made the `pnpm peers check` command consume the new renderer.
- `cli/default-reporter/src/reportError.ts`: `reportPeerDependencyIssuesError` now calls the shared `renderPeerIssues()` and prefixes the hint block with the rendered output. Tests strip ANSI escapes before substring assertions so they stay correct under `FORCE_COLOR=1`.

Result: a single renderer is shared between the install error and the `pnpm peers check` command — output is identical between the two paths.
2026-05-04 19:44:30 +02:00

93 lines
2.1 KiB
TypeScript

import { stripVTControlCharacters as stripAnsi } from 'node:util'
import { expect, test } from '@jest/globals'
import { toOutput$ } from '@pnpm/cli.default-reporter'
import { peerDependencyIssuesLogger } from '@pnpm/core-loggers'
import {
createStreamParser,
logger,
} from '@pnpm/logger'
import { firstValueFrom } from 'rxjs'
test('print peer dependency issues warning', async () => {
const output$ = toOutput$({
context: {
argv: ['install'],
},
streamParser: createStreamParser(),
})
peerDependencyIssuesLogger.debug({
issuesByProjects: {
'.': {
missing: {},
bad: {
a: [
{
parents: [
{
name: 'b',
version: '1.0.0',
},
],
foundVersion: '2',
resolvedFrom: [],
optional: false,
wantedRange: '3',
},
],
},
conflicts: [],
intersections: {},
},
},
})
expect.assertions(1)
const output = await firstValueFrom(output$)
expect(stripAnsi(output)).toContain('pnpm peers check')
})
test('print peer dependency issues error', async () => {
const output$ = toOutput$({
context: { argv: ['install'] },
streamParser: createStreamParser(),
})
const err = Object.assign(new Error('some error'), {
code: 'ERR_PNPM_PEER_DEP_ISSUES',
issuesByProjects: {
'.': {
missing: {},
bad: {
a: [
{
foundVersion: '2',
parents: [
{
name: 'b',
version: '1.0.0',
},
],
optional: false,
resolvedFrom: [],
wantedRange: '3',
},
],
},
conflicts: [],
intersections: {},
},
},
})
logger.error(err, err)
expect.assertions(3)
const output = stripAnsi(await firstValueFrom(output$))
expect(output).toContain('unmet peer a')
expect(output).toContain('Installed: 2')
expect(output).toContain('b@1.0.0')
})