Skip to content

Commit

Permalink
fix: duplicate error message (#47)
Browse files Browse the repository at this point in the history
  • Loading branch information
noomorph authored Jul 13, 2024
1 parent d6baf0c commit 2693295
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 1 deletion.
130 changes: 130 additions & 0 deletions src/utils/getStatusDetails.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { getStatusDetails } from './getStatusDetails';

describe('getStatusDetails', () => {
it('should return undefined for falsy input', () => {
expect(getStatusDetails(null)).toBeUndefined();
expect(getStatusDetails(void 0)).toBeUndefined();
expect(getStatusDetails('')).toBeUndefined();
expect(getStatusDetails(0)).toBeUndefined();
expect(getStatusDetails(false)).toBeUndefined();
});

it('should handle string input', () => {
const input = 'Test error message';
expect(getStatusDetails(input)).toEqual({ message: input });
});

it('should handle Error object with stack trace', () => {
const error = new Error('Test error');
const result = getStatusDetails(error);
expect(result).toHaveProperty('message');
expect(result?.message).toContain('Test error');
expect(result).toHaveProperty('trace');
expect(result?.trace).toContain('at ');
});

it('should not duplicate error message if it starts with empty line', () => {
const error = new Error(' \nERROR:\nExpected: 5\nActual: 4');
const message = getStatusDetails(error)!.message!;
expect(message.indexOf('Expected: 5')).toBeGreaterThan(0);
expect(message.lastIndexOf('Expected: 5')).toBe(message.indexOf('Expected: 5'));
});

it('should handle Error object without stack trace', () => {
const error = new Error('Test error');
Object.defineProperty(error, 'stack', { value: undefined });
const result = getStatusDetails(error);
expect(result).toEqual({ message: 'Error: Test error' });
});

it('should handle custom error objects', () => {
class CustomError extends Error {
constructor(message: string) {
super(message);
this.name = 'CustomError';
}
}
const error = new CustomError('Custom error message');
const result = getStatusDetails(error);
expect(result).toHaveProperty('message');
expect(result?.message).toContain('Custom error message');
expect(result).toHaveProperty('trace');
expect(result?.trace).toContain('at ');
});

it('should handle non-Error objects', () => {
const input = { message: 'Custom error object' };
const result = getStatusDetails(input);
expect(result).toEqual({ message: 'Custom error object' });
});

it('should handle Error with empty message', () => {
// eslint-disable-next-line unicorn/error-message
const error = new Error();
const result = getStatusDetails(error);
expect(result).toHaveProperty('message');
expect(result?.message).toBeTruthy();
expect(result).toHaveProperty('trace');
expect(result?.trace).toContain('at ');
});

it('should handle Error with multiline message', () => {
const error = new Error('Line 1\nLine 2\nLine 3');
const result = getStatusDetails(error);
expect(result).toHaveProperty('message');
expect(result?.message).toContain('Line 1\nLine 2\nLine 3');
expect(result).toHaveProperty('trace');
expect(result?.trace).toContain('at ');
});

it('should handle Error with very long message', () => {
const longMessage = 'a'.repeat(10_000);
const error = new Error(longMessage);
const result = getStatusDetails(error);
expect(result).toHaveProperty('message');
expect(result?.message).toContain(longMessage);
expect(result).toHaveProperty('trace');
expect(result?.trace).toContain('at ');
});

it('should handle Error with non-string properties', () => {
const error: any = new Error('Test error');
error.code = 404;
error.details = { foo: 'bar' };
const result = getStatusDetails(error);
expect(result).toHaveProperty('message');
expect(result?.message).toContain('Test error');
expect(result).toHaveProperty('trace');
expect(result?.trace).toContain('at ');
});

it('should handle thrown string', () => {
let result;
try {
throw 'Thrown string';
} catch (error) {
result = getStatusDetails(error);
}
expect(result).toEqual({ message: 'Thrown string' });
});

it('should handle thrown number', () => {
let result;
try {
throw 404;
} catch (error) {
result = getStatusDetails(error);
}
expect(result).toEqual({ message: '404' });
});

it('should handle thrown object', () => {
let result;
try {
throw { code: 'NETWORK_ERROR', details: 'Connection refused' };
} catch (error) {
result = getStatusDetails(error);
}
expect(result).toEqual({ message: '{"code":"NETWORK_ERROR","details":"Connection refused"}' });
});
});
4 changes: 3 additions & 1 deletion src/utils/getStatusDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import type { StatusDetails } from 'jest-allure2-reporter';
import { autoIndent } from './autoIndent';
import { isError } from './vendor';

const HAS_EMPTY_FIRST_LINE = /^\s*\n/;

export function getStatusDetails(maybeError: unknown): StatusDetails | undefined {
if (!maybeError) {
return;
Expand Down Expand Up @@ -35,7 +37,7 @@ function getTrace(maybeError: unknown): string {

function restoreStack(error: Error): string {
const { message, name, stack } = error;
if (stack && message && hasEmptyFirstLine(stack)) {
if (stack && message && hasEmptyFirstLine(stack) && !HAS_EMPTY_FIRST_LINE.test(message)) {
return `${name}: ${message}${stack.slice(stack.indexOf('\n'))}`;
}

Expand Down

0 comments on commit 2693295

Please sign in to comment.