Skip to content

Commit

Permalink
Merge pull request #6 from zabertech/9901--better-errors
Browse files Browse the repository at this point in the history
9901 - better errors
  • Loading branch information
zaberSatnam authored Jun 15, 2022
2 parents e17fc70 + 3a197b9 commit 3a59387
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 23 deletions.
12 changes: 11 additions & 1 deletion src/errors.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
export class SwampyerError extends Error {}
export class SwampyerError {
constructor(public readonly message?: string) {}

toString() {
return this.message;
}
}

export class SwampyerOperationError extends SwampyerError {
constructor(
Expand All @@ -9,6 +15,10 @@ export class SwampyerOperationError extends SwampyerError {
) {
super(reason);
}

toString() {
return `${this.message}\n\n${this.args?.join('\n\n')}`;
}
}

export class TimeoutError extends SwampyerError {
Expand Down
44 changes: 22 additions & 22 deletions src/swampyer.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-floating-promises */
import { TransportError, AbortError, ConnectionOpenError, SwampyerOperationError, ConnectionClosedError } from './errors';
import { TransportError, AbortError, ConnectionOpenError, SwampyerOperationError, ConnectionClosedError, SwampyerError } from './errors';
import { Swampyer } from './swampyer';
import { Transport, TransportProvider } from './transports/transport';
import { CloseDetails, CloseReason, MessageData, MessageTypes, OpenOptions } from './types';
Expand Down Expand Up @@ -174,9 +174,9 @@ describe(`${Swampyer.prototype.open.name}()`, () => {
const openPromise = wamp.open(transportProvider, { realm });
await waitUntilPass(() => expect(transportProvider.isOpen).toBe(true));
transportProvider.transport.close();
await expect(openPromise).rejects.toThrow(TransportError);
await expect(openPromise).rejects.toBeInstanceOf(TransportError);
expect(onClose).toBeCalledTimes(1);
expect(onClose).toBeCalledWith<[CloseReason, CloseDetails]>('open_error', { error: expect.any(Error) });
expect(onClose).toBeCalledWith<[CloseReason, CloseDetails]>('open_error', { error: expect.any(SwampyerError) });
});

it('throws an error if the WAMP server sends an ABORT message. The close event is emiited', async () => {
Expand All @@ -187,9 +187,9 @@ describe(`${Swampyer.prototype.open.name}()`, () => {
await waitUntilPass(() => expect(transportProvider.isOpen).toBe(true));
expect(await transportProvider.transport.read()).toEqual([MessageTypes.Hello, realm, expect.any(Object)]);
transportProvider.sendToLib(MessageTypes.Abort, ['some.error.happened', 'no reason at all']);
await expect(openPromise).rejects.toThrow(AbortError);
await expect(openPromise).rejects.toBeInstanceOf(AbortError);
expect(onClose).toBeCalledTimes(1);
expect(onClose).toBeCalledWith<[CloseReason, CloseDetails]>('open_error', { error: expect.any(Error) });
expect(onClose).toBeCalledWith<[CloseReason, CloseDetails]>('open_error', { error: expect.any(SwampyerError) });
});

it('throws an error if the "auth.onChallenge" function has an error. The close event is emiited', async () => {
Expand All @@ -209,30 +209,30 @@ describe(`${Swampyer.prototype.open.name}()`, () => {
transportProvider.sendToLib(MessageTypes.Challenge, ['ticket', {}]);
expect(await transportProvider.transport.read()).toEqual([MessageTypes.Abort, expect.any(Object), 'wamp.error.cannot_authenticate']);

await expect(openPromise).rejects.toThrow(AbortError);
await expect(openPromise).rejects.toBeInstanceOf(AbortError);
expect(onClose).toBeCalledTimes(1);
expect(onClose).toBeCalledWith<[CloseReason, CloseDetails]>('open_error', { error: expect.any(Error) });
expect(onClose).toBeCalledWith<[CloseReason, CloseDetails]>('open_error', { error: expect.any(SwampyerError) });
});

it('throws an error if we try to call "open()" again while the connection is already open. The transport is not opened', async () => {
await openWamp();
const newTransportProvider = new MockTransportProvider();
await expect(wamp.open(newTransportProvider, { realm })).rejects.toThrow(ConnectionOpenError);
await expect(wamp.open(newTransportProvider, { realm })).rejects.toBeInstanceOf(ConnectionOpenError);
expect(newTransportProvider.isOpen).toBe(false);
});

it('throws an error if we call "open()" while a previous call to "open()" is in progress. The transport is not opened', async () => {
wamp.open(transportProvider, { realm });
const newTransportProvider = new MockTransportProvider();
await expect(wamp.open(newTransportProvider, { realm })).rejects.toThrow(ConnectionOpenError);
await expect(wamp.open(newTransportProvider, { realm })).rejects.toBeInstanceOf(ConnectionOpenError);
expect(newTransportProvider.isOpen).toBe(false);
});

it('closes the transport if any errors occur', async () => {
const openPromise = wamp.open(transportProvider, { realm });
await waitUntilPass(() => expect(transportProvider.isOpen).toBe(true));
transportProvider.transport.close();
await expect(openPromise).rejects.toThrow(TransportError);
await expect(openPromise).rejects.toBeInstanceOf(TransportError);
expect(transportProvider.transport.isClosed).toBe(true);
});
});
Expand Down Expand Up @@ -577,7 +577,7 @@ describe(`${Swampyer.prototype.register.name}()`, () => {
const regRequest = await transportProvider.transport.read();
transportProvider.sendToLib(MessageTypes.Error, [MessageTypes.Register, regRequest[1] as number, {}, 'something bad', [], {}]);

await expect(regPromise).rejects.toThrow(SwampyerOperationError);
await expect(regPromise).rejects.toBeInstanceOf(SwampyerOperationError);
});

it('throws an error if a GOODBYE message is received while registering', async () => {
Expand All @@ -586,7 +586,7 @@ describe(`${Swampyer.prototype.register.name}()`, () => {
await transportProvider.transport.read();
transportProvider.sendToLib(MessageTypes.Goodbye, [{}, 'com.some.reason']);

await expect(regPromise).rejects.toThrow(ConnectionClosedError);
await expect(regPromise).rejects.toBeInstanceOf(ConnectionClosedError);
});

it('handles errors thrown by registration callbacks and returns the error to the caller', async () => {
Expand Down Expand Up @@ -625,15 +625,15 @@ describe(`${Swampyer.prototype.call.name}()`, () => {
const request = await transportProvider.transport.read();
expect(request).toEqual([MessageTypes.Call, expect.any(Number), {}, 'com.test.something', args, kwargs]);
transportProvider.sendToLib(MessageTypes.Error, [MessageTypes.Call, request[1] as number, {}, 'something bad', [], {}]);
await expect(promise).rejects.toThrow(SwampyerOperationError);
await expect(promise).rejects.toBeInstanceOf(SwampyerOperationError);
});

it('throws an error if a GOODBYE message is received before the call can be finished', async () => {
const promise = wamp.call('com.test.something', args, kwargs);
const request = await transportProvider.transport.read();
expect(request).toEqual([MessageTypes.Call, expect.any(Number), {}, 'com.test.something', args, kwargs]);
transportProvider.sendToLib(MessageTypes.Goodbye, [{}, 'com.some.reason']);
await expect(promise).rejects.toThrow(ConnectionClosedError);
await expect(promise).rejects.toBeInstanceOf(ConnectionClosedError);
});
});

Expand Down Expand Up @@ -669,15 +669,15 @@ describe(`${Swampyer.prototype.unregister.name}()`, () => {
const request = await transportProvider.transport.read();
expect(request).toEqual([MessageTypes.Unregister, expect.any(Number), regId]);
transportProvider.sendToLib(MessageTypes.Error, [MessageTypes.Unregister, request[1] as number, {}, 'something bad', [], {}]);
await expect(promise).rejects.toThrow(SwampyerOperationError);
await expect(promise).rejects.toBeInstanceOf(SwampyerOperationError);
});

it('throws an error if a GOODBYE event occurs while unregistering', async () => {
const promise = wamp.unregister(regId);
const request = await transportProvider.transport.read();
expect(request).toEqual([MessageTypes.Unregister, expect.any(Number), regId]);
transportProvider.sendToLib(MessageTypes.Goodbye, [{}, 'com.some.reason']);
await expect(promise).rejects.toThrow(ConnectionClosedError);
await expect(promise).rejects.toBeInstanceOf(ConnectionClosedError);
});
});

Expand Down Expand Up @@ -727,15 +727,15 @@ describe(`${Swampyer.prototype.subscribe.name}()`, () => {
const promise = wamp.subscribe('com.some.uri', subHandler);
const request = await transportProvider.transport.read();
transportProvider.sendToLib(MessageTypes.Error, [MessageTypes.Subscribe, request[1] as number, {}, 'something bad', [], {}]);
await expect(promise).rejects.toThrow(SwampyerOperationError);
await expect(promise).rejects.toBeInstanceOf(SwampyerOperationError);
});

it('throws an error if GOODBYE event occurs before subscribe operation finishes', async () => {
const subHandler = jest.fn();
const promise = wamp.subscribe('com.some.uri', subHandler);
await transportProvider.transport.read();
transportProvider.sendToLib(MessageTypes.Goodbye, [{}, 'com.some.reason']);
await expect(promise).rejects.toThrow(ConnectionClosedError);
await expect(promise).rejects.toBeInstanceOf(ConnectionClosedError);
});

it('does nothing if subscription handler throws an error', async () => {
Expand Down Expand Up @@ -777,14 +777,14 @@ describe(`${Swampyer.prototype.publish.name}()`, () => {
const promise = wamp.publish('com.some.uri', ['something'], { something: 'else' }, { acknowledge: true });
const request = await transportProvider.transport.read();
transportProvider.sendToLib(MessageTypes.Error, [MessageTypes.Publish, request[1] as number, {}, 'something bad', [], {}]);
await expect(promise).rejects.toThrow(SwampyerOperationError);
await expect(promise).rejects.toBeInstanceOf(SwampyerOperationError);
});

it('throws an error if a GOODBYE message is received before publish acknowledgement is received', async () => {
const promise = wamp.publish('com.some.uri', ['something'], { something: 'else' }, { acknowledge: true });
await transportProvider.transport.read();
transportProvider.sendToLib(MessageTypes.Goodbye, [{}, 'com.some.reason']);
await expect(promise).rejects.toThrow(ConnectionClosedError);
await expect(promise).rejects.toBeInstanceOf(ConnectionClosedError);
});
});

Expand Down Expand Up @@ -816,15 +816,15 @@ describe(`${Swampyer.prototype.unsubscribe.name}()`, () => {
const request = await transportProvider.transport.read();
expect(request).toEqual([MessageTypes.Unsubscribe, expect.any(Number), subId]);
transportProvider.sendToLib(MessageTypes.Error, [MessageTypes.Unsubscribe, request[1] as number, {}, 'something bad', [], {}]);
await expect(promise).rejects.toThrow(SwampyerOperationError);
await expect(promise).rejects.toBeInstanceOf(SwampyerOperationError);
});

it('throws an error if a GOODBYE message is received before unsubscribe operation finishes', async () => {
const promise = wamp.unsubscribe(subId);
const request = await transportProvider.transport.read();
expect(request).toEqual([MessageTypes.Unsubscribe, expect.any(Number), subId]);
transportProvider.sendToLib(MessageTypes.Goodbye, [{}, 'com.some.reason']);
await expect(promise).rejects.toThrow(ConnectionClosedError);
await expect(promise).rejects.toBeInstanceOf(ConnectionClosedError);
});
});

Expand Down

0 comments on commit 3a59387

Please sign in to comment.