Files
pnpm/deps/path/test/index.ts
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

154 lines
6.8 KiB
TypeScript

/// <reference path="../../../__typings__/index.d.ts"/>
import { expect, test } from '@jest/globals'
import {
depPathToFilename,
getPkgIdWithPatchHash,
isAbsolute,
isRuntimeDepPath,
parse,
refToRelative,
removeSuffix,
tryGetPackageId,
} from '@pnpm/deps.path'
import type { DepPath } from '@pnpm/types'
test('isAbsolute()', () => {
expect(isAbsolute('/foo/1.0.0')).toBeFalsy()
expect(isAbsolute('registry.npmjs.org/foo/1.0.0')).toBeTruthy()
})
test('parse()', () => {
/* eslint-disable @typescript-eslint/no-explicit-any */
expect(() => parse(undefined as any)).toThrow(/got `undefined`/)
expect(() => parse({} as any)).toThrow(/got `object`/)
expect(() => parse(1 as any)).toThrow(/got `number`/)
/* eslint-enable @typescript-eslint/no-explicit-any */
expect(parse('foo@1.0.0')).toStrictEqual({
name: 'foo',
peerDepGraphHash: undefined,
version: '1.0.0',
patchHash: undefined,
})
expect(parse('@foo/bar@1.0.0')).toStrictEqual({
name: '@foo/bar',
peerDepGraphHash: undefined,
version: '1.0.0',
patchHash: undefined,
})
expect(parse('foo@1.0.0(@types/babel__core@7.1.14)')).toStrictEqual({
name: 'foo',
peerDepGraphHash: '(@types/babel__core@7.1.14)',
version: '1.0.0',
patchHash: undefined,
})
expect(parse('foo@1.0.0(@types/babel__core@7.1.14)(foo@1.0.0)')).toStrictEqual({
name: 'foo',
peerDepGraphHash: '(@types/babel__core@7.1.14)(foo@1.0.0)',
version: '1.0.0',
patchHash: undefined,
})
expect(parse('@(-.-)/foo@1.0.0(@types/babel__core@7.1.14)(foo@1.0.0)')).toStrictEqual({
name: '@(-.-)/foo',
peerDepGraphHash: '(@types/babel__core@7.1.14)(foo@1.0.0)',
version: '1.0.0',
patchHash: undefined,
})
expect(parse('tar-pkg@file:../tar-pkg-1.0.0.tgz')).toStrictEqual({
name: 'tar-pkg',
nonSemverVersion: 'file:../tar-pkg-1.0.0.tgz',
peerDepGraphHash: undefined,
patchHash: undefined,
})
expect(parse('foo@1.0.0(patch_hash=0000)(@types/babel__core@7.1.14)')).toStrictEqual({
name: 'foo',
peerDepGraphHash: '(@types/babel__core@7.1.14)',
version: '1.0.0',
patchHash: '(patch_hash=0000)',
})
})
test('refToRelative()', () => {
expect(refToRelative('1.3.0', '@most/multicast')).toBe('@most/multicast@1.3.0')
expect(refToRelative('1.3.0', 'most')).toBe('most@1.3.0')
expect(refToRelative('m@1.3.0', 'most')).toBe('m@1.3.0')
expect(refToRelative('@most/multicast@1.3.0', 'most')).toBe('@most/multicast@1.3.0')
expect(refToRelative('@most/multicast@1.3.0', '@most/multicast')).toBe('@most/multicast@1.3.0')
expect(refToRelative('@most/multicast@1.3.0(@foo/bar@1.0.0)', '@most/multicast')).toBe('@most/multicast@1.3.0(@foo/bar@1.0.0)')
expect(refToRelative('@most/multicast@1.3.0(@foo/bar@1.0.0)(@foo/qar@1.0.0)', '@most/multicast')).toBe('@most/multicast@1.3.0(@foo/bar@1.0.0)(@foo/qar@1.0.0)')
// linked dependencies don't have a relative path
expect(refToRelative('link:../foo', 'foo')).toBeNull()
expect(refToRelative('file:../tarball.tgz', 'foo')).toBe('foo@file:../tarball.tgz')
expect(refToRelative('1.3.0(@foo/bar@1.0.0)', '@qar/bar')).toBe('@qar/bar@1.3.0(@foo/bar@1.0.0)')
expect(refToRelative('1.3.0(@foo/bar@1.0.0)(@foo/qar@1.0.0)', '@qar/bar')).toBe('@qar/bar@1.3.0(@foo/bar@1.0.0)(@foo/qar@1.0.0)')
})
test('depPathToFilename()', () => {
expect(depPathToFilename('/foo@1.0.0', 120)).toBe('foo@1.0.0')
expect(depPathToFilename('/@foo/bar@1.0.0', 120)).toBe('@foo+bar@1.0.0')
expect(depPathToFilename('github.com/something/foo/0000?v=1', 120)).toBe('github.com+something+foo+0000+v=1')
expect(depPathToFilename('\\//:*?"<>|', 120)).toBe('++++++++++')
expect(depPathToFilename('/foo@1.0.0(react@16.0.0)(react-dom@16.0.0)', 120)).toBe('foo@1.0.0_react@16.0.0_react-dom@16.0.0')
expect(depPathToFilename('/foo@1.0.0(react@16.0.0(react-dom@1.0.0))(react-dom@16.0.0)', 120)).toBe('foo@1.0.0_react@16.0.0_react-dom@1.0.0__react-dom@16.0.0')
const filename = depPathToFilename('file:test/foo-1.0.0.tgz_foo@2.0.0', 120)
expect(filename).toBe('file+test+foo-1.0.0.tgz_foo@2.0.0')
expect(filename).not.toContain(':')
expect(depPathToFilename('abcd/'.repeat(200), 120)).toBe('abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+abcd+ab_e7c10c3598ebbc0ca640b6524c68e602') // cspell:disable-line
expect(depPathToFilename('/JSONSteam@1.0.0', 120)).toBe('JSONSteam@1.0.0_533d3b11e9111b7a24f914844c021ddf') // cspell:disable-line
expect(depPathToFilename('foo@git+https://github.com/something/foo#1234', 120)).toBe('foo@git+https+++github.com+something+foo+1234')
expect(depPathToFilename('foo@https://codeload.github.com/something/foo/tar.gz/1234#path:packages/foo', 120)).toBe('foo@https+++codeload.github.com+something+foo+tar.gz+1234+path+packages+foo')
})
test('tryGetPackageId', () => {
expect(tryGetPackageId('/foo@1.0.0(@types/babel__core@7.1.14)' as DepPath)).toBe('/foo@1.0.0')
expect(tryGetPackageId('/foo@1.0.0(@types/babel__core@7.1.14(is-odd@1.0.0))' as DepPath)).toBe('/foo@1.0.0')
expect(tryGetPackageId('/@(-.-)/foo@1.0.0(@types/babel__core@7.1.14)' as DepPath)).toBe('/@(-.-)/foo@1.0.0')
expect(tryGetPackageId('foo@1.0.0(patch_hash=xxxx)(@types/babel__core@7.1.14)' as DepPath)).toBe('foo@1.0.0')
})
test('getPkgIdWithPatchHash', () => {
// Runtime dependency
expect(getPkgIdWithPatchHash('node@runtime:24.11.1' as DepPath)).toBe('node@runtime:24.11.1')
// Regular packages
expect(getPkgIdWithPatchHash('foo@1.0.0' as DepPath)).toBe('foo@1.0.0')
// Packages with patch hash
expect(getPkgIdWithPatchHash('foo@1.0.0(patch_hash=xxxx)' as DepPath)).toBe('foo@1.0.0(patch_hash=xxxx)')
// Packages with peer dependencies (should remove peer dependencies)
expect(getPkgIdWithPatchHash('foo@1.0.0(@types/babel__core@7.1.14)' as DepPath)).toBe('foo@1.0.0')
// Packages with both patch hash and peer dependencies (should keep patch hash, remove peer dependencies)
expect(getPkgIdWithPatchHash('foo@1.0.0(patch_hash=xxxx)(@types/babel__core@7.1.14)' as DepPath)).toBe('foo@1.0.0(patch_hash=xxxx)')
// Scoped packages
expect(getPkgIdWithPatchHash('@foo/bar@1.0.0' as DepPath)).toBe('@foo/bar@1.0.0')
// Scoped packages with patch hash
expect(getPkgIdWithPatchHash('@foo/bar@1.0.0(patch_hash=yyyy)' as DepPath)).toBe('@foo/bar@1.0.0(patch_hash=yyyy)')
// Scoped packages with peer dependencies
expect(getPkgIdWithPatchHash('@foo/bar@1.0.0(@types/node@18.0.0)' as DepPath)).toBe('@foo/bar@1.0.0')
// Scoped packages with both patch hash and peer dependencies
expect(getPkgIdWithPatchHash('@foo/bar@1.0.0(patch_hash=zzzz)(@types/node@18.0.0)' as DepPath)).toBe('@foo/bar@1.0.0(patch_hash=zzzz)')
})
test('isRuntimeDepPath', () => {
expect(isRuntimeDepPath('node@runtime:20.1.0' as DepPath)).toBeTruthy()
expect(isRuntimeDepPath('node@20.1.0' as DepPath)).toBeFalsy()
})
test('removeSuffix', () => {
expect(removeSuffix('foo@1.0.0(patch_hash=0000)(@types/babel__core@7.1.14)')).toBe('foo@1.0.0')
})