homehub/packages/homehub_core/tests/lib/websocket.spec.js

269 lines
7.5 KiB
JavaScript
Raw Normal View History

2021-08-26 10:33:15 +00:00
import * as WebSocketLib from 'src/lib/websocket';
describe('src/lib/websocket', () => {
describe('HomeHubWebSocket', () => {
const settings = {
url: '/websocket',
};
it('includes the subscribable mixin', () => {
// Given
const webSocket = new WebSocketLib.HomeHubWebSocket(false, settings);
// Then
expect(webSocket.__mixins__).toContain('SubscribableMixin');
});
it('includes the event source mixin', () => {
// Given
const webSocket = new WebSocketLib.HomeHubWebSocket(false, settings);
// Then
expect(webSocket.__mixins__).toContain('EventSourceMixin');
});
describe('constructor', () => {
it('initializes the instance', () => {
// Given
const webSocket = new WebSocketLib.HomeHubWebSocket(false, settings);
// Then
expect(webSocket.debug).toBe(false);
expect(webSocket.settings).toEqual(settings);
expect(webSocket.socket).toBe(null);
expect(webSocket.reconnectTimeout).toBe(null);
expect(webSocket.reconnectCounter).toEqual(0);
});
});
describe('logDebug', () => {
beforeEach(() => {
spyOn(console, 'log');
});
it('logs a message if debug is true', () => {
// Given
const webSocket = new WebSocketLib.HomeHubWebSocket(true, settings);
// When
webSocket.logDebug('Testing');
// Then
expect(console.log).toHaveBeenCalledWith('Testing'); // eslint-disable-line no-console
});
it('does not log a message if debug is false', () => {
// Given
const webSocket = new WebSocketLib.HomeHubWebSocket(false, settings);
// When
webSocket.logDebug('Testing');
// Then
expect(console.log).not.toHaveBeenCalled(); // eslint-disable-line no-console
});
});
describe('stopReconnect', () => {
beforeEach(() => {
spyOn(window, 'clearTimeout');
});
it('stops the reconnect process', () => {
// Given
const webSocket = new WebSocketLib.HomeHubWebSocket(false, settings);
webSocket.reconnectTimeout = 123;
webSocket.reconnectCounter = 5;
// When
webSocket.stopReconnect();
// Then
expect(webSocket.reconnectTimeout).toBe(null);
expect(webSocket.reconnectCounter).toEqual(0);
expect(window.clearTimeout).toHaveBeenCalledWith(123);
});
});
describe('startReconnect', () => {
beforeEach(() => {
spyOn(window, 'setTimeout').and.returnValue(123);
});
it('starts the reconnect process', () => {
// Given
const webSocket = new WebSocketLib.HomeHubWebSocket(false, settings);
webSocket.reconnectCounter = 5;
// When
webSocket.startReconnect();
// Then
expect(webSocket.reconnectCounter).toEqual(6);
expect(webSocket.reconnectTimeout).toEqual(123);
expect(window.setTimeout).toHaveBeenCalledWith(webSocket.start, 1000);
});
it('breaks the reconnect process when retry count reaches limit', () => {
// Given
const webSocket = new WebSocketLib.HomeHubWebSocket(false, settings);
webSocket.reconnectCounter = 30;
spyOn(webSocket, 'stopReconnect');
// When
let error = null;
try {
webSocket.startReconnect();
} catch (exc) {
error = exc;
}
// Then
expect(error).toBeInstanceOf(Error);
expect(webSocket.stopReconnect).toHaveBeenCalled();
});
});
describe('start', () => {
let fakeWebSocket = null;
beforeEach(() => {
fakeWebSocket = jasmine.createSpyObj(['addEventListener', 'close']);
spyOn(window, 'WebSocket').and.returnValue(fakeWebSocket);
});
it('configures and opens the websocket connection', () => {
// Given
let fullSettings = {
...settings,
protocols: ['spam', 'eggs'],
};
const webSocket = new WebSocketLib.HomeHubWebSocket(
false, fullSettings
);
// When
webSocket.start();
// Then
expect(window.WebSocket).toHaveBeenCalledWith(
fullSettings.url, fullSettings.protocols
);
expect(fakeWebSocket.addEventListener).toHaveBeenCalledWith(
'open', webSocket.onSocketOpen
);
expect(fakeWebSocket.addEventListener).toHaveBeenCalledWith(
'close', webSocket.onSocketClose
);
expect(fakeWebSocket.addEventListener).toHaveBeenCalledWith(
'message', webSocket.onSocketMessage
);
});
});
describe('stop', () => {
let fakeWebSocket = null;
beforeEach(() => {
fakeWebSocket = jasmine.createSpyObj(['addEventListener', 'close']);
});
it('closes the websocket connection', () => {
// Given
const webSocket = new WebSocketLib.HomeHubWebSocket(false, settings);
webSocket.socket = fakeWebSocket;
// When
webSocket.stop();
// Then
expect(fakeWebSocket.close).toHaveBeenCalled();
});
});
describe('onSocketOpen', () => {
let fakeWebSocket = null;
beforeEach(() => {
fakeWebSocket = jasmine.createSpyObj(['addEventListener', 'close']);
fakeWebSocket.readyState = 1;
});
it('handles the open websocket event', () => {
// Given
const webSocket = new WebSocketLib.HomeHubWebSocket(false, settings);
webSocket.socket = fakeWebSocket;
spyOn(webSocket, 'logDebug');
spyOn(webSocket, 'stopReconnect');
spyOn(webSocket, 'fireEvent');
// When
webSocket.onSocketOpen();
// Then
expect(webSocket.logDebug).toHaveBeenCalled();
expect(webSocket.stopReconnect).toHaveBeenCalled();
expect(webSocket.fireEvent).toHaveBeenCalledWith('start');
});
});
describe('onSocketClose', () => {
it('handles the open websocket event', () => {
// Given
const webSocket = new WebSocketLib.HomeHubWebSocket(false, settings);
spyOn(webSocket, 'logDebug');
spyOn(webSocket, 'startReconnect');
spyOn(webSocket, 'fireEvent');
// When
webSocket.onSocketClose({code: 1000});
// Then
expect(webSocket.logDebug).toHaveBeenCalled();
expect(webSocket.startReconnect).toHaveBeenCalled();
expect(webSocket.fireEvent).toHaveBeenCalledWith('stop');
});
});
describe('onSocketMessage', () => {
beforeEach(() => {
spyOn(console, 'error');
});
it('gracefully handles JSON parse error', () => {
// Given
const webSocket = new WebSocketLib.HomeHubWebSocket(false, settings);
spyOn(webSocket, 'notify');
// When
webSocket.onSocketMessage({data: 'spam'});
// Then
expect(console.error).toHaveBeenCalledWith(
jasmine.any(String), jasmine.any(Error)
);
expect(webSocket.notify).not.toHaveBeenCalled();
});
it('parses the event data and notifies the subscribers', () => {
// Given
const webSocket = new WebSocketLib.HomeHubWebSocket(false, settings);
spyOn(webSocket, 'notify');
const message = {
type: 'TESTING',
data: {
spam: true,
},
};
// When
webSocket.onSocketMessage({data: JSON.stringify(message)});
// Then
expect(webSocket.notify).toHaveBeenCalledWith(message);
});
});
});
});