diff --git a/src/errors.test.ts b/src/errors.test.ts index a5cdd2d9b..12d07c54b 100644 --- a/src/errors.test.ts +++ b/src/errors.test.ts @@ -164,6 +164,44 @@ describe('wrapError', () => { }); }); + describe('if the original error has a length === 2', () => { + it('returns an error with cause', () => { + // Save original Error + const OriginalError = global.Error; + + // Create a mock error with a cause + class MockError extends Error { + constructor(message: string, options: { cause?: Error } = {}) { + super(message); + this.cause = options.cause; + } + + cause: Error | undefined; + } + // Set length to 2 + Object.defineProperty(MockError, 'length', { value: 2 }); + + // Replace global Error with MockError + // NOTE: when we upgrade jest, change this to use: + // jest.replaceProperty(global, 'Error', MockError); + global.Error = MockError as unknown as ErrorConstructor; + + // Define your original error and message + const originalError = new Error('original error'); + const message = 'new error message'; + + // Call your function + const result = wrapError(originalError, message); + + // Assert that the error has the expected properties + expect(result.message).toBe(message); + expect(result.cause).toBe(originalError); + + // Restore the original Error constructor + global.Error = OriginalError; + }); + }); + describe('if the original error is an object but not an Error instance', () => { describe('if the message is a non-empty string', () => { it('combines a string version of the original error and message together in a new Error', () => { diff --git a/src/errors.ts b/src/errors.ts index 40d03d423..72e6dc22c 100644 --- a/src/errors.ts +++ b/src/errors.ts @@ -92,19 +92,19 @@ export function wrapError( message: string, ): Error & { code?: string } { if (isError(originalError)) { - const error: Error & { code?: string } = - Error.length === 2 - ? // This branch is getting tested by using the Node version that - // supports `cause` on the Error constructor. - // istanbul ignore next - // Also, for some reason `tsserver` is not complaining that the - // Error constructor doesn't support a second argument in the editor, - // but `tsc` does. I'm not sure why, but we disable this in the - // meantime. - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - new Error(message, { cause: originalError }) - : new ErrorWithCause(message, { cause: originalError }); + let error: Error & { code?: string }; + if (Error.length === 2) { + // for some reason `tsserver` is not complaining that the + // Error constructor doesn't support a second argument in the editor, + // but `tsc` does. Error causes are not supported by our current tsc target (ES2020, we need ES2022 to make this work) + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + error = new Error(message, { cause: originalError }); + } else { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + error = new ErrorWithCause(message, { cause: originalError }); + } if (isErrorWithCode(originalError)) { error.code = originalError.code;