mirror of
https://github.com/pnpm/pnpm.git
synced 2026-06-28 09:55:39 -04:00
A non-retryable error code (e.g. SELF_SIGNED_CERT_IN_CHAIN) was thrown inside the detached op.attempt callback, so the governing promise never settled: the caller hung and the throw surfaced as an unhandled rejection that crashed the process. Reject the promise instead, mirroring the retries-exhausted path right below it. Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Zoltan Kochan <z@kochan.io>
41 lines
1.5 KiB
TypeScript
41 lines
1.5 KiB
TypeScript
/// <reference path="../../../__typings__/index.d.ts"/>
|
|
import { expect, test } from '@jest/globals'
|
|
import { fetch } from '@pnpm/network.fetch'
|
|
import { type Dispatcher, getGlobalDispatcher, MockAgent, setGlobalDispatcher } from 'undici'
|
|
|
|
test('fetch rejects, and does not hang, on a non-retryable error code', async () => {
|
|
const originalDispatcher: Dispatcher = getGlobalDispatcher()
|
|
const mockAgent = new MockAgent()
|
|
mockAgent.disableNetConnect()
|
|
setGlobalDispatcher(mockAgent)
|
|
try {
|
|
const tlsError = Object.assign(
|
|
new Error('self signed certificate in certificate chain'),
|
|
{ code: 'SELF_SIGNED_CERT_IN_CHAIN' }
|
|
)
|
|
mockAgent
|
|
.get('http://registry.pnpm.io')
|
|
.intercept({ path: '/is-positive', method: 'GET' })
|
|
.replyWithError(tlsError)
|
|
|
|
const TIMEOUT = Symbol('timeout')
|
|
let timer: NodeJS.Timeout | undefined
|
|
const outcome = await Promise.race([
|
|
fetch('http://registry.pnpm.io/is-positive', { retry: { retries: 0 } })
|
|
.then(() => 'resolved', (err: unknown) => err),
|
|
new Promise<typeof TIMEOUT>((resolve) => {
|
|
timer = setTimeout(() => resolve(TIMEOUT), 2000)
|
|
}),
|
|
])
|
|
if (timer) clearTimeout(timer)
|
|
|
|
expect(outcome).not.toBe(TIMEOUT)
|
|
expect(outcome).not.toBe('resolved')
|
|
const err = outcome as Error & { code?: string, cause?: { code?: string } }
|
|
expect(err.code ?? err.cause?.code).toBe('SELF_SIGNED_CERT_IN_CHAIN')
|
|
} finally {
|
|
await mockAgent.close()
|
|
setGlobalDispatcher(originalDispatcher)
|
|
}
|
|
})
|