238 lines
4.9 KiB
JavaScript
238 lines
4.9 KiB
JavaScript
// ISC, Copyright 2017 Jaco Greeff
|
|
|
|
const { mockWs, TEST_WS_URL } = require('../../test/mockWs');
|
|
|
|
const Ws = require('./index');
|
|
|
|
let ws;
|
|
let mock;
|
|
let encodeSpy;
|
|
let decodeSpy;
|
|
|
|
function createWs (requests, autoConnect) {
|
|
mock = mockWs(requests);
|
|
ws = new Ws(TEST_WS_URL, autoConnect);
|
|
|
|
encodeSpy = jest.spyOn(ws, 'encodeObject');
|
|
decodeSpy = jest.spyOn(ws, 'decodeResponse');
|
|
|
|
return ws;
|
|
}
|
|
|
|
describe('Ws', () => {
|
|
afterEach(() => {
|
|
if (encodeSpy) {
|
|
encodeSpy.mockRestore();
|
|
encodeSpy = null;
|
|
}
|
|
|
|
if (decodeSpy) {
|
|
decodeSpy.mockRestore();
|
|
decodeSpy = null;
|
|
}
|
|
|
|
if (mock) {
|
|
mock.done();
|
|
mock = null;
|
|
}
|
|
});
|
|
|
|
it('requires an ws:// prefixed endpoint', () => {
|
|
expect(
|
|
() => new Ws('http://')
|
|
).toThrow(/with 'ws/);
|
|
});
|
|
|
|
describe('websocket', () => {
|
|
let errorSpy;
|
|
|
|
beforeEach(() => {
|
|
ws = createWs([]);
|
|
|
|
errorSpy = jest.spyOn(console, 'error');
|
|
});
|
|
|
|
afterEach(() => {
|
|
errorSpy.mockRestore();
|
|
});
|
|
|
|
it('sets up the on* handlers', () => {
|
|
expect(ws._websocket.onclose[0]).toEqual(ws._onClose);
|
|
expect(ws._websocket.onerror[0]).toEqual(ws._onError);
|
|
expect(ws._websocket.onmessage[0]).toEqual(ws._onMessage);
|
|
expect(ws._websocket.onopen[0]).toEqual(ws._onOpen);
|
|
});
|
|
|
|
describe('_onClose', () => {
|
|
beforeEach(() => {
|
|
jest.useFakeTimers();
|
|
});
|
|
|
|
afterEach(() => {
|
|
jest.useRealTimers();
|
|
});
|
|
|
|
it('reconnects after delay', () => {
|
|
ws.connect = jest.fn();
|
|
ws._onClose();
|
|
|
|
expect(ws.connect).not.toHaveBeenCalled();
|
|
|
|
jest.runAllTimers();
|
|
|
|
expect(ws.connect).toHaveBeenCalled();
|
|
});
|
|
|
|
it('sets isConnected false', () => {
|
|
expect(ws.isConnected).toEqual(false);
|
|
});
|
|
|
|
it('does not reconnect when autoConnect false', () => {
|
|
mock.done();
|
|
ws = createWs([], false);
|
|
|
|
ws.connect = jest.fn();
|
|
ws._onClose();
|
|
|
|
expect(ws.connect).not.toHaveBeenCalled();
|
|
|
|
jest.runAllTimers();
|
|
|
|
expect(ws.connect).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('_onError', () => {
|
|
it('logs the error', () => {
|
|
ws._onError('test error');
|
|
|
|
expect(errorSpy).toHaveBeenCalledWith('test error');
|
|
});
|
|
});
|
|
|
|
describe('_onMessage', () => {
|
|
it('fails with log when handler not found', () => {
|
|
ws._onMessage({ data: '{"id":2}' });
|
|
|
|
expect(errorSpy).toHaveBeenCalledWith('Unable to find handler for id=2');
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('send', () => {
|
|
it('handles internal errors', () => {
|
|
ws = createWs([]);
|
|
|
|
ws._isConnected = true;
|
|
ws._websocket = null;
|
|
|
|
return ws
|
|
.send('test_encoding', ['param'])
|
|
.catch((error) => {
|
|
expect(error).toBeDefined();
|
|
});
|
|
});
|
|
|
|
it('encodes requests', () => {
|
|
ws = createWs([{
|
|
id: 1,
|
|
method: 'test_encoding',
|
|
reply: {
|
|
result: 'ok'
|
|
}
|
|
}]);
|
|
|
|
return ws
|
|
.send('test_encoding', ['param'])
|
|
.then((result) => {
|
|
expect(encodeSpy).toHaveBeenCalledWith('test_encoding', ['param']);
|
|
});
|
|
});
|
|
|
|
it('decodes responses', () => {
|
|
ws = createWs([{
|
|
id: 1,
|
|
method: 'test_encoding',
|
|
reply: {
|
|
result: 'ok'
|
|
}
|
|
}]);
|
|
|
|
return ws
|
|
.send('test_encoding', ['param'])
|
|
.then((result) => {
|
|
expect(decodeSpy).toHaveBeenCalledWith({
|
|
id: 1,
|
|
jsonrpc: '2.0',
|
|
result: 'ok'
|
|
});
|
|
});
|
|
});
|
|
|
|
it('passes the body through correctly', () => {
|
|
ws = createWs([{
|
|
id: 1,
|
|
method: 'test_body',
|
|
reply: {
|
|
result: 'ok'
|
|
}
|
|
}]);
|
|
|
|
return ws
|
|
.send('test_body', ['param'])
|
|
.then((result) => {
|
|
expect(
|
|
mock.body['test_body']
|
|
).toEqual('{"id":1,"jsonrpc":"2.0","method":"test_body","params":["param"]}');
|
|
});
|
|
});
|
|
|
|
it('throws error when !response.ok', () => {
|
|
ws = createWs([{
|
|
id: 1,
|
|
error: {
|
|
code: 666,
|
|
message: 'error'
|
|
}
|
|
}]);
|
|
|
|
return ws
|
|
.send('test_error', [])
|
|
.catch((error) => {
|
|
expect(error.message).toMatch(/\[666\]: error/);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('queued', () => {
|
|
let sendPromise;
|
|
|
|
beforeEach(() => {
|
|
ws = createWs([{
|
|
id: 1,
|
|
method: 'test_queue',
|
|
reply: {
|
|
result: 'ok'
|
|
}
|
|
}], false);
|
|
sendPromise = ws.send('test_queue', []);
|
|
});
|
|
|
|
it('sends messages when connected', () => {
|
|
ws.connect();
|
|
|
|
return sendPromise.then((result) => {
|
|
expect(result).toEqual('ok');
|
|
});
|
|
});
|
|
|
|
it('sends messages when connected (errors)', () => {
|
|
ws.connect();
|
|
|
|
return sendPromise.then((result) => {
|
|
expect(result).toEqual('ok');
|
|
});
|
|
});
|
|
});
|
|
});
|