aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/connect/package.json2
-rw-r--r--packages/connect/src/orderbook_channel_factory.ts14
-rw-r--r--packages/connect/src/types.ts2
-rw-r--r--packages/connect/test/orderbook_channel_factory_test.ts34
-rw-r--r--packages/connect/test/ws_orderbook_channel_test.ts26
5 files changed, 54 insertions, 24 deletions
diff --git a/packages/connect/package.json b/packages/connect/package.json
index 78cb3e71d..cc68d34f4 100644
--- a/packages/connect/package.json
+++ b/packages/connect/package.json
@@ -59,6 +59,7 @@
"isomorphic-fetch": "^2.2.1",
"lodash": "^4.17.4",
"query-string": "^5.0.1",
+ "sinon": "^4.0.0",
"websocket": "^1.0.25"
},
"devDependencies": {
@@ -68,6 +69,7 @@
"@types/lodash": "4.14.104",
"@types/mocha": "^2.2.42",
"@types/query-string": "^5.0.1",
+ "@types/sinon": "^2.2.2",
"@types/websocket": "^0.0.39",
"async-child-process": "^1.1.1",
"chai": "^4.0.1",
diff --git a/packages/connect/src/orderbook_channel_factory.ts b/packages/connect/src/orderbook_channel_factory.ts
index 1b5625840..5134af323 100644
--- a/packages/connect/src/orderbook_channel_factory.ts
+++ b/packages/connect/src/orderbook_channel_factory.ts
@@ -1,21 +1,27 @@
import * as WebSocket from 'websocket';
-import { OrderbookChannel } from './types';
+import { OrderbookChannel, OrderbookChannelHandler } from './types';
import { assert } from './utils/assert';
import { WebSocketOrderbookChannel } from './ws_orderbook_channel';
export const orderbookChannelFactory = {
/**
* Instantiates a new WebSocketOrderbookChannel instance
- * @param url The relayer API base WS url you would like to interact with
+ * @param url The relayer API base WS url you would like to interact with
+ * @param handler An OrderbookChannelHandler instance that responds to various
+ * channel updates
* @return An OrderbookChannel Promise
*/
- async createWebSocketOrderbookChannelAsync(url: string): Promise<OrderbookChannel> {
+ async createWebSocketOrderbookChannelAsync(
+ url: string,
+ handler: OrderbookChannelHandler,
+ ): Promise<OrderbookChannel> {
assert.isUri('url', url);
+ assert.isOrderbookChannelHandler('handler', handler);
return new Promise<OrderbookChannel>((resolve, reject) => {
const client = new WebSocket.w3cwebsocket(url);
client.onopen = () => {
- const orderbookChannel = new WebSocketOrderbookChannel(client);
+ const orderbookChannel = new WebSocketOrderbookChannel(client, handler);
resolve(orderbookChannel);
};
client.onerror = err => {
diff --git a/packages/connect/src/types.ts b/packages/connect/src/types.ts
index d7d7a96d0..7347beb0b 100644
--- a/packages/connect/src/types.ts
+++ b/packages/connect/src/types.ts
@@ -11,7 +11,7 @@ export interface Client {
}
export interface OrderbookChannel {
- subscribe: (subscriptionOpts: OrderbookChannelSubscriptionOpts, handler: OrderbookChannelHandler) => void;
+ subscribe: (subscriptionOpts: OrderbookChannelSubscriptionOpts) => void;
close: () => void;
}
diff --git a/packages/connect/test/orderbook_channel_factory_test.ts b/packages/connect/test/orderbook_channel_factory_test.ts
index fd84332cc..d2140bfa6 100644
--- a/packages/connect/test/orderbook_channel_factory_test.ts
+++ b/packages/connect/test/orderbook_channel_factory_test.ts
@@ -9,18 +9,38 @@ import { orderbookChannelFactory } from '../src/orderbook_channel_factory';
chai.config.includeStack = true;
chai.use(dirtyChai);
const expect = chai.expect;
+const emptyOrderbookChannelHandler = {
+ onSnapshot: () => {
+ _.noop();
+ },
+ onUpdate: () => {
+ _.noop();
+ },
+ onError: () => {
+ _.noop();
+ },
+ onClose: () => {
+ _.noop();
+ },
+};
describe('orderbookChannelFactory', () => {
const websocketUrl = 'ws://localhost:8080';
-
describe('#createWebSocketOrderbookChannelAsync', () => {
it('throws when input is not a url', () => {
- const badInput = 54;
- const badSubscribeCall = orderbookChannelFactory.createWebSocketOrderbookChannelAsync.bind(
- orderbookChannelFactory,
- badInput,
- );
- expect(orderbookChannelFactory.createWebSocketOrderbookChannelAsync(badInput as any)).to.be.rejected();
+ const badUrlInput = 54;
+ expect(
+ orderbookChannelFactory.createWebSocketOrderbookChannelAsync(
+ badUrlInput as any,
+ emptyOrderbookChannelHandler,
+ ),
+ ).to.be.rejected();
+ });
+ it('throws when handler has the incorrect members', () => {
+ const badHandlerInput = {};
+ expect(
+ orderbookChannelFactory.createWebSocketOrderbookChannelAsync(websocketUrl, badHandlerInput as any),
+ ).to.be.rejected();
});
});
});
diff --git a/packages/connect/test/ws_orderbook_channel_test.ts b/packages/connect/test/ws_orderbook_channel_test.ts
index f4ad67ba3..fed4f2217 100644
--- a/packages/connect/test/ws_orderbook_channel_test.ts
+++ b/packages/connect/test/ws_orderbook_channel_test.ts
@@ -2,6 +2,7 @@ import * as chai from 'chai';
import * as dirtyChai from 'dirty-chai';
import * as _ from 'lodash';
import 'mocha';
+import * as Sinon from 'sinon';
import * as WebSocket from 'websocket';
import { WebSocketOrderbookChannel } from '../src/ws_orderbook_channel';
@@ -26,8 +27,10 @@ const emptyOrderbookChannelHandler = {
describe('WebSocketOrderbookChannel', () => {
const websocketUrl = 'ws://localhost:8080';
- const client = new WebSocket.w3cwebsocket(websocketUrl);
- const orderbookChannel = new WebSocketOrderbookChannel(client, emptyOrderbookChannelHandler);
+ const openClient = new WebSocket.w3cwebsocket(websocketUrl);
+ Sinon.stub(openClient, 'readyState').get(() => WebSocket.w3cwebsocket.OPEN);
+ Sinon.stub(openClient, 'send').callsFake(_.noop);
+ const openOrderbookChannel = new WebSocketOrderbookChannel(openClient, emptyOrderbookChannelHandler);
const subscriptionOpts = {
baseTokenAddress: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
quoteTokenAddress: '0xef7fff64389b814a946f3e92105513705ca6b990',
@@ -36,22 +39,21 @@ describe('WebSocketOrderbookChannel', () => {
};
describe('#subscribe', () => {
it('throws when subscriptionOpts does not conform to schema', () => {
- const badSubscribeCall = orderbookChannel.subscribe.bind(
- orderbookChannel,
- {},
- emptyOrderbookChannelHandler,
- );
+ const badSubscribeCall = openOrderbookChannel.subscribe.bind(openOrderbookChannel, {});
expect(badSubscribeCall).throws(
'Expected subscriptionOpts to conform to schema /RelayerApiOrderbookChannelSubscribePayload\nEncountered: {}\nValidation errors: instance requires property "baseTokenAddress", instance requires property "quoteTokenAddress"',
);
});
it('does not throw when inputs are of correct types', () => {
- const goodSubscribeCall = orderbookChannel.subscribe.bind(
- orderbookChannel,
- subscriptionOpts,
- emptyOrderbookChannelHandler,
- );
+ const goodSubscribeCall = openOrderbookChannel.subscribe.bind(openOrderbookChannel, subscriptionOpts);
expect(goodSubscribeCall).to.not.throw();
});
+ it('throws when client is closed', () => {
+ const closedClient = new WebSocket.w3cwebsocket(websocketUrl);
+ Sinon.stub(closedClient, 'readyState').get(() => WebSocket.w3cwebsocket.CLOSED);
+ const closedOrderbookChannel = new WebSocketOrderbookChannel(closedClient, emptyOrderbookChannelHandler);
+ const badSubscribeCall = closedOrderbookChannel.subscribe.bind(closedOrderbookChannel, subscriptionOpts);
+ expect(badSubscribeCall).throws('WebSocket connection is closed');
+ });
});
});