Skip to content

Commit a21d015

Browse files
committed
feat: finish implementing toString on exception
1 parent 61c4d6b commit a21d015

File tree

2 files changed

+44
-28
lines changed

2 files changed

+44
-28
lines changed

src/__tests__/exception.test.ts

Lines changed: 43 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -54,20 +54,6 @@ describe('BaseException', () => {
5454
});
5555
});
5656

57-
describe('BaseException.prototype.toString', () => {
58-
it('should return the name of the exception with the message, if stack is undefined', () => {
59-
expect(
60-
BaseException.prototype.toString.call({
61-
message: 'An error occurred',
62-
name: 'TestException'
63-
})
64-
).toBe('TestException: An error occurred');
65-
});
66-
it('should return the stack if it defined', () => {
67-
expect(BaseException.prototype.toString.call({ stack: '__STACK__' })).toContain('__STACK__');
68-
});
69-
});
70-
7157
describe('ExceptionBuilder', () => {
7258
it('should return never for the build method if no name is specified', () => {
7359
const fn = (): never => new ExceptionBuilder().build();
@@ -131,22 +117,52 @@ describe('ExceptionBuilder', () => {
131117
});
132118

133119
describe('ValueException', () => {
134-
it('should have the correct prototype', () => {
135-
expect(Object.getPrototypeOf(ValueException)).toBe(BaseException);
136-
});
137-
it('should have the asErr static method', () => {
138-
expect(ValueException.asErr()).toBeInstanceOf(Err);
120+
describe('static', () => {
121+
it('should have the correct prototype', () => {
122+
expect(Object.getPrototypeOf(ValueException)).toBe(BaseException);
123+
});
124+
it('should have the asErr static method', () => {
125+
expect(ValueException.asErr()).toBeInstanceOf(Err);
126+
});
127+
it('should have the asAsyncErr static method', async () => {
128+
expect(await ValueException.asAsyncErr()).toBeInstanceOf(Err);
129+
});
139130
});
140-
it('should have the asAsyncErr static method', async () => {
141-
expect(await ValueException.asAsyncErr()).toBeInstanceOf(Err);
131+
describe('toErr', () => {
132+
it('should return an Err instance', () => {
133+
const exception = new ValueException();
134+
expect(exception.toErr()).toBeInstanceOf(Err);
135+
});
142136
});
143-
it('should have the toErr method', () => {
144-
const exception = new ValueException();
145-
expect(exception.toErr()).toBeInstanceOf(Err);
137+
describe('toAsyncErr', () => {
138+
it('should return an Err instance', async () => {
139+
const exception = new ValueException();
140+
expect(await exception.toAsyncErr()).toBeInstanceOf(Err);
141+
});
146142
});
147-
it('should have the asAsyncErr static method', async () => {
148-
const exception = new ValueException();
149-
expect(await exception.toAsyncErr()).toBeInstanceOf(Err);
143+
describe('toString', () => {
144+
const value = new ValueException('An error occurred', {
145+
cause: new Error('Cause 1', {
146+
cause: new Error('Cause 2')
147+
}),
148+
details: {
149+
expected: 'number',
150+
received: 'string'
151+
}
152+
}).toString();
153+
it('should include the exception name and message', () => {
154+
expect(value).toContain('ValueException: An error occurred');
155+
});
156+
it('should include the causes in reverse order', () => {
157+
const explanations = value
158+
.split('The above exception was the cause of the following exception:')
159+
.map((s) => s.trim());
160+
expect(explanations[0]).toMatch(/^Error: Cause 2/);
161+
expect(explanations[1]).toMatch(/^Error: Cause 1/);
162+
});
163+
it('should include the details', () => {
164+
expect(value).toMatch(/details:\s*\{\s*expected:\s*'number',\s*received:\s*'string'\s*\}/);
165+
});
150166
});
151167
});
152168

src/exception.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ abstract class BaseException<TParams extends ExceptionParams, TOptions extends E
7777
const result: string[] = [];
7878
this.extractCauses(this).forEach((error) => {
7979
result.push(this.formatError(error));
80+
result.push('\nThe above exception was the cause of the following exception:\n');
8081
});
81-
result.push('\nThe above exception was the cause of the following exception:\n');
8282
result.push(this.formatError(this));
8383
return result.join('\n');
8484
}

0 commit comments

Comments
 (0)