Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions src/errors.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fs from 'fs';

import {
ensureError,
getErrorMessage,
isErrorWithCode,
isErrorWithMessage,
Expand Down Expand Up @@ -320,3 +321,99 @@ describe('getErrorMessage', () => {
expect(getErrorMessage(undefined)).toBe('');
});
});

describe('ensureError', () => {
it('returns Error instance unchanged', () => {
const originalError = new Error('original message');
const result = ensureError(originalError);

expect(result).toBe(originalError);
expect(result.message).toBe('original message');
});

it('returns fs.promises-style error unchanged', async () => {
let originalError;
try {
await fs.promises.readFile('/tmp/nonexistent', 'utf8');
} catch (error: unknown) {
originalError = error;
}

const result = ensureError(originalError);

expect(result).toBe(originalError);
});

it('converts string to Error with string as message', () => {
const result = ensureError('something went wrong');

expect(result).toBeInstanceOf(Error);
expect(result.message).toBe('something went wrong');
});

it('converts number to Error', () => {
Comment thread
abretonc7s marked this conversation as resolved.
Outdated
const result = ensureError(42);

expect(result).toBeInstanceOf(Error);
expect(result.message).toBe('42');
});

it('converts object to Error using String()', () => {
const result = ensureError({ some: 'object' });

expect(result).toBeInstanceOf(Error);
expect(result.message).toBe('[object Object]');
});

it('handles null with descriptive message', () => {
const result = ensureError(null);

expect(result).toBeInstanceOf(Error);
expect(result.message).toBe('Unknown error');
});

it('handles undefined with descriptive message', () => {
const result = ensureError(undefined);

expect(result).toBeInstanceOf(Error);
expect(result.message).toBe('Unknown error');
});

it('appends context to message for null', () => {
const result = ensureError(null, 'fetchData');

expect(result).toBeInstanceOf(Error);
expect(result.message).toBe('Unknown error (fetchData)');
});

it('appends context to message for undefined', () => {
const result = ensureError(undefined, 'processInput');

expect(result).toBeInstanceOf(Error);
expect(result.message).toBe('Unknown error (processInput)');
});

it('appends context for non-Error values', () => {
const result = ensureError('network failure', 'apiCall');

expect(result).toBeInstanceOf(Error);
expect(result.message).toBe('network failure (apiCall)');
});

it('does NOT add context to existing Error instances', () => {
const originalError = new Error('original message');
const result = ensureError(originalError, 'someContext');

expect(result).toBe(originalError);
expect(result.message).toBe('original message');
});

it('preserves stack trace for Error instances', () => {
const originalError = new Error('original message');
const originalStack = originalError.stack;

const result = ensureError(originalError);

expect(result.stack).toBe(originalStack);
});
});
23 changes: 23 additions & 0 deletions src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,26 @@ export function wrapError<Throwable>(

return new Error(String(originalError));
}

/**
* Ensures we have a proper Error object.
* If the input is already an Error, returns it unchanged.
* Otherwise, converts to an Error with an appropriate message.
*
* @param error - The caught error (could be Error, string, or unknown).
* @param context - Optional context to help identify the error source.
Comment thread
abretonc7s marked this conversation as resolved.
Outdated
* @returns A proper Error instance.
*/
export function ensureError(error: unknown, context?: string): Error {
if (isError(error)) {
return error;
}

if (isNullOrUndefined(error)) {
const message = context ? `Unknown error (${context})` : 'Unknown error';
return new Error(message);
}
Comment thread
abretonc7s marked this conversation as resolved.
Outdated

const message = context ? `${String(error)} (${context})` : String(error);
return new Error(message);
Comment thread
Gudahtt marked this conversation as resolved.
Outdated
}
1 change: 1 addition & 0 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ describe('index', () => {
"createNumber",
"createProjectLogger",
"definePattern",
"ensureError",
"exactOptional",
"fromWei",
"getChecksumAddress",
Expand Down
1 change: 1 addition & 0 deletions src/node.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ describe('node', () => {
"definePattern",
"directoryExists",
"ensureDirectoryStructureExists",
"ensureError",
"exactOptional",
"fileExists",
"forceRemove",
Expand Down
Loading