diff options
Diffstat (limited to 'packages')
-rw-r--r-- | packages/connect/package.json | 2 | ||||
-rw-r--r-- | packages/connect/src/orderbook_channel_factory.ts | 14 | ||||
-rw-r--r-- | packages/connect/src/types.ts | 2 | ||||
-rw-r--r-- | packages/connect/test/orderbook_channel_factory_test.ts | 34 | ||||
-rw-r--r-- | packages/connect/test/ws_orderbook_channel_test.ts | 26 |
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'); + }); }); }); |