Files
pnpm/__utils__/test-ipc-server
Zoltan Kochan 187049055f chore: upgrade @typescript/native-preview to 7.0.0-dev.20260421.2 (#11332)
* chore: upgrade @typescript/native-preview to 7.0.0-dev.20260421.2

- Add explicit `types: ["node"]` to the shared tsconfig because tsgo
  20260421 no longer auto-acquires `@types/*` from `node_modules`.
- Refactor test files to explicitly import jest globals (`describe`,
  `it`, `test`, `expect`, `beforeEach`, etc.) from `@jest/globals`
  instead of relying on `@types/jest` ambient declarations. Under the
  new tsgo build, `import { jest } from '@jest/globals'` shadows the
  ambient `jest` namespace, breaking `@types/jest`'s `declare var
  describe: jest.Describe;` globals.
- Add `@jest/globals` to each package's devDependencies where tests
  now import from it, and add `@types/node` to packages that need it
  but were relying on hoisted resolution.
- Replace `fail()` calls with `throw new Error(...)` since `fail` is
  no longer globally available.

* chore: fix remaining tsgo type-strictness errors

- Strip `as <PnpmType>` casts on objects passed to toMatchObject /
  toStrictEqual / toEqual; @jest/globals rejects the typed objects
  (which include AsymmetricMatchers) vs. the repo-specific type.
- Type `jest.fn<...>()` explicitly where the mock's signature matters
  for toHaveBeenCalledWith.
- Replace `beforeEach(() => X)` with `beforeEach(() => { X })` so the
  return value is void, as the stricter jest typing requires.
- Use `expect.objectContaining({...})` in one place where the full
  expected object triggered stricter type resolution.
- Cast `prompt.mock.calls` arg through `as unknown as Record<...>[]`
  for patch.test.ts's nested-array matchers.
- Fix off-by-one `<reference path>` in pnpm/test/getConfig.test.ts
  that only surfaced now.
- Move `@jest/globals` from devDependencies to dependencies in the
  two `__utils__` packages that import it from `src/`.
- Clean up unused imports from the @jest/globals migration.

* chore: address Copilot review on #11332

- Move misplaced `@jest/globals` imports to the top import block in
  checkEngine, run.ts, and workspace/root-finder tests where the
  script dropped them below executable code.
- Replace `try { await x(); throw new Error('should have thrown') } catch`
  in bins/linker, lockfile/fs, and resolving/local-resolver tests with
  `await expect(x()).rejects.toMatchObject({...})`. The old pattern
  swallowed an unrelated `throw` if the under-test call silently
  succeeded, which would fail on the catch-block assertion with a
  misleading message.
2026-04-21 22:50:40 +02:00
..
2026-04-10 18:30:33 +02:00

@pnpm/test-ipc-server

The TestIpcServer is a simple Inter-Process Communication (IPC) server written specifically for usage in pnpm tests.

It's a simple wrapper around Node.js's builtin IPC support. Messages sent to the server are saved to a buffer that can be retrieved for assertions.

Rationale

In the past, many pnpm tests contained scripts that wrote output to the same file. Writing to the same file concurrently causes race conditions resulting in flaky CI tests. The race conditions occur due to multiple processes reading a file, appending data, and writing the file back out. If two processes start at the same time and read the same input, one of the process's output would be overwritten by the other.

At the time of writing (December 2023), there's no great cross-platform way to append to a file atomically. From https://www.man7.org/linux/man-pages/man2/open.2.html

O_APPEND may lead to corrupted files on NFS filesystems if more than one process appends data to a file at once. This is because NFS does not support appending to a file, so the client kernel has to simulate it, which can't be done without a race condition.

The TestIpcServer doesn't drop messages the same way since it's using Node.js's IPC mechanism that is specifically designed to handle multiple clients.

Example

A common testing pattern in the pnpm repo is to ensure package scripts runs as expected or in particular orders.

{
  "name": "@pnpm/example-test-fixture",
  "private": true,
  "scripts": {
    "build": "echo 'This script should run'"
  }
}

This can be tested through the TestIpcServer,

import { prepare } from '@pnpm/prepare'
import { createTestIpcServer } from '@pnpm/test-ipc-server'

test('example test', async () => {
  await using server = await createTestIpcServer()
  prepare({
    scripts: {
      build: server.sendLineScript('this is a built script that should run'),
    },
  })

  await execa('node', [pnpmBin, 'run', 'build'])

  expect(server.getLines()).toStrictEqual(['this is a built script that should run'])
})

License

MIT