Skip to content

Commit aee8399

Browse files
committed
errors tests
1 parent c23f2a4 commit aee8399

File tree

2 files changed

+80
-40
lines changed

2 files changed

+80
-40
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { ErrorWithStack, copyStackTrace } from '../errors';
2+
3+
describe('ErrorWithStack', () => {
4+
test('should create an error with message and handle stack trace capture', () => {
5+
const error = new ErrorWithStack('Test error', ErrorWithStack);
6+
expect(error.message).toBe('Test error');
7+
expect(error).toBeInstanceOf(Error);
8+
});
9+
10+
test('should capture stack trace if Error.captureStackTrace is available', () => {
11+
const originalCaptureStackTrace = Error.captureStackTrace;
12+
const captureStackTraceSpy = jest.fn();
13+
Error.captureStackTrace = captureStackTraceSpy;
14+
15+
const error = new ErrorWithStack('Test error', ErrorWithStack);
16+
expect(captureStackTraceSpy).toHaveBeenCalledWith(error, ErrorWithStack);
17+
18+
Error.captureStackTrace = originalCaptureStackTrace;
19+
});
20+
21+
test('should work when Error.captureStackTrace is not available', () => {
22+
const originalCaptureStackTrace = Error.captureStackTrace;
23+
// @ts-expect-error - intentionally removing captureStackTrace
24+
delete Error.captureStackTrace;
25+
26+
const error = new ErrorWithStack('Test error', ErrorWithStack);
27+
expect(error.message).toBe('Test error');
28+
expect(error).toBeInstanceOf(Error);
29+
30+
Error.captureStackTrace = originalCaptureStackTrace;
31+
});
32+
});
33+
34+
describe('copyStackTrace', () => {
35+
test('should copy stack trace from source to target when both are Error instances', () => {
36+
const target = new Error('Target error');
37+
const source = new Error('Source error');
38+
source.stack = 'Error: Source error\n at test.js:1:1';
39+
40+
copyStackTrace(target, source);
41+
42+
expect(target.stack).toBe('Error: Target error\n at test.js:1:1');
43+
});
44+
45+
test('should handle stack trace with multiple occurrences of source message', () => {
46+
const target = new Error('Target error');
47+
const source = new Error('Source error');
48+
source.stack =
49+
'Error: Source error\n at test.js:1:1\nError: Source error\n at test.js:2:2';
50+
51+
copyStackTrace(target, source);
52+
53+
// Should replace only the first occurrence
54+
expect(target.stack).toBe(
55+
'Error: Target error\n at test.js:1:1\nError: Source error\n at test.js:2:2',
56+
);
57+
});
58+
59+
test('should not modify target when conditions are not met', () => {
60+
const targetNotError = { message: 'Not an error' };
61+
const source = new Error('Source error');
62+
source.stack = 'Error: Source error\n at test.js:1:1';
63+
64+
copyStackTrace(targetNotError, source);
65+
expect(targetNotError).toEqual({ message: 'Not an error' });
66+
67+
const target = new Error('Target error');
68+
const originalStack = target.stack;
69+
const sourceNotError = { message: 'Not an error' };
70+
71+
copyStackTrace(target, sourceNotError as Error);
72+
expect(target.stack).toBe(originalStack);
73+
74+
const sourceNoStack = new Error('Source error');
75+
delete sourceNoStack.stack;
76+
77+
copyStackTrace(target, sourceNoStack);
78+
expect(target.stack).toBe(originalStack);
79+
});
80+
});

src/helpers/errors.ts

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import prettyFormat from 'pretty-format';
2-
31
export class ErrorWithStack extends Error {
42
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
53
constructor(message: string | undefined, callsite: Function) {
@@ -10,44 +8,6 @@ export class ErrorWithStack extends Error {
108
}
119
}
1210

13-
export const prepareErrorMessage = (
14-
// TS states that error caught in a catch close are of type `unknown`
15-
// most real cases will be `Error`, but better safe than sorry
16-
error: unknown,
17-
name?: string,
18-
value?: unknown,
19-
): string => {
20-
let errorMessage: string;
21-
if (error instanceof Error) {
22-
// Strip info about custom predicate
23-
errorMessage = error.message.replace(/ matching custom predicate[^]*/gm, '');
24-
} else if (error && typeof error === 'object') {
25-
errorMessage = error.toString();
26-
} else {
27-
errorMessage = 'Caught unknown error';
28-
}
29-
30-
if (name && value) {
31-
errorMessage += ` with ${name} ${prettyFormat(value, { min: true })}`;
32-
}
33-
return errorMessage;
34-
};
35-
36-
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
37-
export const createQueryByError = (error: unknown, callsite: Function): null => {
38-
if (error instanceof Error) {
39-
if (error.message.includes('No instances found')) {
40-
return null;
41-
}
42-
throw new ErrorWithStack(error.message, callsite);
43-
}
44-
45-
throw new ErrorWithStack(
46-
`Query: caught unknown error type: ${typeof error}, value: ${error}`,
47-
callsite,
48-
);
49-
};
50-
5111
export function copyStackTrace(target: unknown, stackTraceSource: Error) {
5212
if (target instanceof Error && stackTraceSource.stack) {
5313
target.stack = stackTraceSource.stack.replace(stackTraceSource.message, target.message);

0 commit comments

Comments
 (0)