Files
pnpm/deps/inspection/commands/test/docs.ts
Alessio Attilio 2410cf4092 feat: add pnpm docs command and home alias (#11244)
* feat: add pnpm docs command and home alias

* chore: update manifests

* fix: address review comments for pnpm docs command

- Remove 'docs' and 'home' from NOT_IMPLEMENTED_COMMANDS to prevent
  not-implemented handlers from overriding the real implementations
- Change fallback URL from npmjs.com to npmx.dev
- Remove bugs URL as a docs fallback (it's an issue tracker, not docs)
- Fix ESM mock in tests: use jest.unstable_mockModule instead of jest.mock

* refactor: use open package for browser opening in promptBrowserOpen

Replace the hand-rolled platform-specific execFile logic with the open
npm package, which handles WSL, Docker-in-WSL, and Windows edge cases
better. This removes the execFile dependency injection from
promptBrowserOpen, OtpContext, LoginContext, and SharedContext.

* fix: address copilot review comments

- docs: use www.npmjs.com fallback (not npmx.dev) and validate homepage
  URL is http(s) before opening
- promptBrowserOpen: validate authUrl protocol before passing to open(),
  and guard against synchronous throws from open()

* fix: restore npmx.dev fallback for pnpm docs

* chore: expand changeset with web-auth refactor impact

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2026-04-14 16:20:40 +02:00

58 lines
1.7 KiB
TypeScript

import { jest } from '@jest/globals'
import type { Config, ConfigContext } from '@pnpm/config.reader'
import { REGISTRY_MOCK_PORT } from '@pnpm/registry-mock'
const mockOpen = jest.fn()
jest.unstable_mockModule('open', () => ({
default: mockOpen,
}))
const { docs } = await import('@pnpm/deps.inspection.commands')
const REGISTRY_URL = `http://localhost:${REGISTRY_MOCK_PORT}`
const DOCS_OPTIONS = {
registries: { default: REGISTRY_URL },
}
test('docs: command should be available', () => {
expect(docs.handler).toBeDefined()
expect(docs.help).toBeDefined()
expect(docs.commandNames).toBeDefined()
expect(docs.cliOptionsTypes).toBeDefined()
})
test('docs: command should have correct names', () => {
expect(docs.commandNames).toEqual(['docs', 'home'])
})
test('docs: help should return a string', () => {
const help = docs.help()
expect(typeof help).toBe('string')
expect(help.length).toBeGreaterThan(0)
})
test('docs: cliOptionsTypes should return object', () => {
const types = docs.cliOptionsTypes()
expect(typeof types).toBe('object')
})
test('docs: rcOptionsTypes should return object', () => {
const types = docs.rcOptionsTypes()
expect(typeof types).toBe('object')
})
test('docs: missing package name throws error', async () => {
await expect(
docs.handler(DOCS_OPTIONS as unknown as Config & ConfigContext, [])
).rejects.toMatchObject({ code: 'ERR_PNPM_MISSING_PACKAGE_NAME' })
})
test('docs: successful lookup of package opens documentation', async () => {
mockOpen.mockClear()
await docs.handler(DOCS_OPTIONS as unknown as Config & ConfigContext, ['is-negative'])
expect(mockOpen).toHaveBeenCalled()
const calledUrl = mockOpen.mock.calls[0][0]
expect(calledUrl).toBe('https://github.com/kevva/is-negative#readme')
})