UNPKG

myojs

Version:

JavaScript/ES2015/ES6 client for the Thalmic Labs Myo

613 lines (609 loc) 22.6 kB
import {Server as WebSocketServer} from 'ws'; import BaseConnection from './../src/connection/BaseConnection.js'; import {assert} from 'chai'; const frameDump = '{ "frame" : { "id" : 43928, "timestamp" : "1423842951", "rssi" : 53, "event" : { "type" : "onConnect" }, "rotation" : [ -0.4093628, -0.1088257, 0.1548462, 0.8925171 ], "euler" : { "roll" : 1.34422, "pitch" : -1.428455, "yaw" : 2.271631 }, "pose" : { "type" : 5 }, "gyro" : [ 2.868652, -2.868652, 2.563476 ], "accel" : [ 0.04736328, -0.7241211, 0.6367188 ], "emg" : [ -6, 0, -1, 0, 40, 1, 2, -2 ] }}'; const frameDumpDeviceInfo = '{ "frame" : { "deviceInfo" : { "connected" : true }}}'; describe('BaseConnection', () => { describe('Constructor: Test with valid host and port', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection(); }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }); it('should return a Myo object', (done) => { assert.strictEqual(baseConnection.host, '127.0.0.1'); assert.strictEqual(baseConnection.port, 6450); done(); }); }); describe('Constructor: Test with empty object', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection({}); }); after((done) => { baseConnection = null; done(); }); it('should return a Myo object with default host and port', (done) => { assert.strictEqual(baseConnection.host, '127.0.0.1'); assert.strictEqual(baseConnection.port, 6450); done(); }); }); describe('Constructor: Test with empty host', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection({someProperty:'someString', port:6450}); }); after((done) => { baseConnection = null; done(); }); it('should return a Myo object with default host', (done) => { assert.strictEqual(baseConnection.host, '127.0.0.1'); assert.strictEqual(baseConnection.port, 6450); done(); }); }); describe('Constructor: Test with host of wrong type', () => { after((done) => { done(); }); it('should throw an error when host is of wrong type', (done) => { assert.throws(() => { new BaseConnection({host: 6450}); }, Error, 'Host needs to be of type string'); done(); }); }); describe('Constructor: Test with empty port', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection({host:'someString'}); }); after((done) => { baseConnection = null; done(); }); it('should return a Myo object with default port', (done) => { assert.strictEqual(baseConnection.host, 'someString'); assert.strictEqual(baseConnection.port, 6450); done(); }); }); describe('Constructor: Test with port of wrong type', () => { after((done) => { done(); }); it('should throw an error when port is of wrong type', (done) => { assert.throws(() => { new BaseConnection({host:'someString', port:'someOtherString'}); }, Error, 'Port needs to be of type integer'); done(); }); }); describe('Constructor: Test with passing a string as an argument', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection('someString'); }); after((done) => { baseConnection = null; done(); }); it('should return a Myo object with default host and port', (done) => { assert.strictEqual(baseConnection.host, '127.0.0.1'); assert.strictEqual(baseConnection.port, 6450); done(); }); }); describe('#send', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection(); }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }); it('should throw an error when parameter is invalid', (done) => { assert.throws(() => { baseConnection.send('abc'); }, Error, 'Parameter needs to be an object'); done(); }); }); describe('#getUrl', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection(); }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }); it('should return the correct url', (done) => { assert.strictEqual(baseConnection.getUrl(), 'ws://127.0.0.1:6450/'); done(); }); }); describe('#handleOpen', () => { let wss = null; let baseConnection = null; before(() => { baseConnection = new BaseConnection(); wss = new WebSocketServer({port: 6450}); }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; wss.close(); wss = null; done(); }); it('should call context to requestDeviceInfo', (done) => { let didRequestDeviceInfo = false; const errTimeout = setTimeout(() => { assert.strictEqual(false, '"requestDeviceInfo" never sent'); clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }, 1000); wss.on('connection', (ws) => { ws.on('message', (message) => { const data = JSON.parse(message); if(data.hasOwnProperty('command')) { if(data.command === 'requestDeviceInfo') { didRequestDeviceInfo = true; clearTimeout(errTimeout); assert.strictEqual(true, didRequestDeviceInfo); done(); } } }); }); baseConnection.connect(); }); }); describe('#handleOpen: when already connected', () => { let wss = null; let baseConnection = null; before(() => { baseConnection = new BaseConnection(); wss = new WebSocketServer({port: 6450}); }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; wss.close(); wss = null; done(); }); it('should return string "connected"', (done) => { baseConnection.connected = true; assert.strictEqual('connected', baseConnection.handleOpen()); done(); }); }); describe('#handleClose: when connected', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection(); }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }); it('should return "disconnecting"', (done) => { baseConnection.connected = true; assert.strictEqual('disconnecting', baseConnection.handleClose()); done(); }); }); describe('#handleClose: return "disconnected" if disconnected', () => { let wss = null; let baseConnection = null; before(() => { wss = new WebSocketServer({port: 6450}); baseConnection = new BaseConnection(); }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; wss.close(); wss = null; done(); }); it('should return "disconnecting" if connected', (done) => { const errTimeout = setTimeout(() => { assert.strictEqual(false, 'failed to connect or receive data'); clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }, 1000); wss.on('connection', (ws) => { ws.on('message', (message) => { const data = JSON.parse(message); if(data.hasOwnProperty('command')) { if(data.command === 'requestDeviceInfo') { clearTimeout(errTimeout); assert.strictEqual(baseConnection.handleClose(), 'disconnected'); done(); } } }); }); baseConnection.connect(); }); }); describe('#reconnect', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection(); }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }); it('should return "stopReconnection" when connected', (done) => { baseConnection.connected = true; assert.strictEqual(baseConnection.reconnect(), 'stopReconnection'); clearInterval(baseConnection.reconnectionTimer); done(); }); it('should return "connect" if not connected', (done) => { baseConnection.connected = false; assert.strictEqual(baseConnection.reconnect(), 'connect'); clearInterval(baseConnection.reconnectionTimer); done(); }); }); describe('#handleData: errors', () => { it('should throw an error when no data is sent', () => { assert.throws(() => { const baseConnection = new BaseConnection(); baseConnection.handleData(); }, Error, 'No data received'); }); it('should throw an error when JSON string is invalid', () => { assert.throws(() => { const baseConnection = new BaseConnection(); baseConnection.handleData('abc'); }, Error, 'Invalid JSON'); }); }); describe('#handleData: deviceInfo', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection(); }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }); it('should emit a deviceInfo event', (done) => { let didEmitDeviceInfo = false; const errTimeout = setTimeout(() => { assert.strictEqual(false, 'Event never fired'); done(); }, 10); baseConnection.on('deviceInfo', () => { didEmitDeviceInfo = true; clearTimeout(errTimeout); assert.strictEqual(true, didEmitDeviceInfo); done(); }); baseConnection.connected = false; baseConnection.handleData(frameDumpDeviceInfo); }); }); describe('#handleData: connect', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection(); }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }); it('should emit a "connect" event', (done) => { let didEmitConnect = false; const errTimeout = setTimeout(() => { assert.strictEqual(false, '"connect" event never fired'); done(); }, 10); baseConnection.on('connect', () => { didEmitConnect = true; clearTimeout(errTimeout); assert.strictEqual(true, didEmitConnect); done(); }); baseConnection.connected = false; baseConnection.handleData(frameDumpDeviceInfo); }); }); describe('#handleData: frame', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection(); }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }); it('should emit a "frame" event', (done) => { let didEmitFrame = false; baseConnection.connected = true; const errTimeout = setTimeout(() => { assert.strictEqual(false, '"frame" event never fired'); done(); }, 10); baseConnection.on('frame', () => { didEmitFrame = true; clearTimeout(errTimeout); assert.strictEqual(true, didEmitFrame); done(); }); baseConnection.handleData(frameDump); }); }); describe('#handleData: pose', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection(); }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }); it('should emit a "pose" event', (done) => { let didEmitPose = false; baseConnection.connected = true; const errTimeout = setTimeout(() => { assert.strictEqual(false, '"pose" event never fired'); done(); }, 10); baseConnection.on('pose', () => { didEmitPose = true; clearTimeout(errTimeout); assert.strictEqual(true, didEmitPose); done(); }); baseConnection.handleData(frameDump); }); }); describe('#handleData: event', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection(); }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }); it('should emit a "event" event', (done) => { let didEmitEvent = false; baseConnection.connected = true; const errTimeout = setTimeout(() => { assert.strictEqual(false, '"event" event never fired'); done(); }, 10); baseConnection.on('event', () => { didEmitEvent = true; clearTimeout(errTimeout); assert.strictEqual(true, didEmitEvent); done(); }); baseConnection.handleData(frameDump); }); }); describe('#startReconnection', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection(); }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }); it('should return "reconnecting" if no reconnectionTimer', (done) => { baseConnection.reconnectionTimer = null; assert.strictEqual(baseConnection.startReconnection(), 'reconnecting'); clearInterval(baseConnection.reconnectionTimer); done(); }); }); describe('#startReconnection: when already connected', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection(); }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }); it('should return "already reconnecting" if having reconnectionTimer', (done) => { baseConnection.reconnectionTimer = 1234; assert.strictEqual(baseConnection.startReconnection(), 'already reconnecting'); done(); }); }); describe('#stopReconnection', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection(); }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }); it('should clear reconnection timer', (done) => { baseConnection.reconnectionTimer = setInterval(() => {}, 1000); baseConnection.stopReconnection(); assert.isUndefined(baseConnection.reconnectionTimer); done(); }); }); describe('#connect', () => { let wss = null; let baseConnection = null; before(() => { wss = new WebSocketServer({port: 6450}); baseConnection = new BaseConnection(); }); after((done) => { wss.close(); wss = null; baseConnection.socket = null; clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }); it('should emit a "connect" event', (done) => { let didRequestDeviceInfo = false; wss.on('connection', (ws) => { ws.on('message', (message) => { const data = JSON.parse(message); if(data.hasOwnProperty('command')) { if(data.command === 'requestDeviceInfo') { didRequestDeviceInfo = true; ws.send(frameDumpDeviceInfo); } } }); }); const errTimeout = setTimeout(() => { assert.strictEqual(false, '"connect" event never fired'); done(); }, 1000); baseConnection.on('connect', () => { clearTimeout(errTimeout); assert.strictEqual(true, baseConnection.connected); assert.strictEqual(true, didRequestDeviceInfo); done(); }); baseConnection.connect(); }); }); describe('#connect: when already connected', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection(); }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }); it('should return "socket already created" when already created socket', (done) => { baseConnection.socket = {}; assert.strictEqual(baseConnection.connect(), 'socket already created'); done(); }); }); describe('#disconnect (connected)', () => { let didEmitDisconnect = false; let baseConnection = null; let didCloseSocket = null; before(() => { baseConnection = new BaseConnection(); baseConnection.socket = {}; baseConnection.socket.close = () => { didCloseSocket = true; }; }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }); it('should emit a "disconnect" event', (done) => { didCloseSocket = false; baseConnection.connected = true; const errTimeout = setTimeout(() => { assert.strictEqual(false, '"disconnect" event never fired'); done(); }, 10); baseConnection.on('disconnect', () => { didEmitDisconnect = true; clearTimeout(errTimeout); assert.strictEqual(true, didEmitDisconnect); done(); }); baseConnection.disconnect(); assert.strictEqual(true, didCloseSocket); }); }); describe('#disconnect (disconnected)', () => { let didEmitDisconnect = false; let baseConnection = null; let didCloseSocket = null; before(() => { baseConnection = new BaseConnection(); baseConnection.socket = {}; baseConnection.socket.close = () => { didCloseSocket = true; }; }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }); it('should not emit a "disconnect" event if disconnected', (done) => { didCloseSocket = false; const errTimeout = setTimeout(() => { assert.strictEqual(false, didEmitDisconnect); done(); }, 10); baseConnection.on('disconnect', () => { didEmitDisconnect = true; clearTimeout(errTimeout); assert.strictEqual(true, didEmitDisconnect); done(); }); baseConnection.disconnect(); assert.strictEqual(true, didCloseSocket); }); }); describe('#disconnect (stopReconnection)', () => { let baseConnection = null; before(() => { baseConnection = new BaseConnection(); baseConnection.socket = {}; baseConnection.socket.close = () => {}; }); after((done) => { clearInterval(baseConnection.reconnectionTimer); baseConnection = null; done(); }); it('should call "stopReconnection" if not allowing reconnections', (done) => { let didStopReconnection = false; baseConnection.stopReconnection = () => { didStopReconnection = true; }; baseConnection.disconnect(false); assert.isUndefined(baseConnection.reconnectionTimer); assert.strictEqual(true, didStopReconnection); done(); }); }); });