diff --git a/dist/lib/client.js b/dist/lib/client.js index 1802783..2daa43f 100644 --- a/dist/lib/client.js +++ b/dist/lib/client.js @@ -371,7 +371,7 @@ class Client extends _eventemitter.default { } this.api.notifications().then(result => { - this.notifications = _objectSpread({}, this.notifications, {}, flattenTree(result)); + this.notifications = _objectSpread(_objectSpread({}, this.notifications), flattenTree(result)); Object.keys(this.notifications).forEach(path => { const notification = _objectSpread({ path diff --git a/dist/lib/connection.js b/dist/lib/connection.js index e489975..04a11df 100644 --- a/dist/lib/connection.js +++ b/dist/lib/connection.js @@ -383,7 +383,7 @@ class Connection extends _eventemitter.default { } if (this._authenticated === true && !path.includes('auth/login')) { - opts.headers = _objectSpread({}, opts.headers, { + opts.headers = _objectSpread(_objectSpread({}, opts.headers), {}, { Authorization: "".concat(this._token.kind, " ").concat(this._token.token) }); opts.credentials = 'same-origin'; diff --git a/dist/lib/discovery.js b/dist/lib/discovery.js index 8759883..44d5b41 100644 --- a/dist/lib/discovery.js +++ b/dist/lib/discovery.js @@ -4,6 +4,8 @@ require("core-js/modules/es.string.includes"); require("core-js/modules/es.string.split"); +require("core-js/modules/es.string.starts-with"); + require("core-js/modules/es.string.trim"); Object.defineProperty(exports, "__esModule", { @@ -62,7 +64,7 @@ class SKServer { createClient() { let opts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - return new _client.default(_objectSpread({}, opts, { + return new _client.default(_objectSpread(_objectSpread({}, opts), {}, { hostname: this._hostname, port: this._port })); @@ -73,55 +75,57 @@ class SKServer { exports.SKServer = SKServer; class Discovery extends _eventemitter.default { - constructor(bonjour) { + constructor(bonjourOrMdns) { let timeout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 60000; super(); - const props = ['_server', '_registry'].join(','); + this.found = []; - if (!bonjour || typeof bonjour !== 'object' || Object.keys(bonjour).join(',') !== props) { - throw new Error('Invalid mDNS provider'); + if (!bonjourOrMdns || typeof bonjourOrMdns !== 'object') { + throw new Error('No mDNS provider given'); } - this.found = []; - const browser = bonjour.find({ - type: 'signalk-http' - }); - browser.on('up', ad => { - const service = _objectSpread({}, ad.txt, { - name: ad.name || '', - hostname: ad.host || '', - port: parseInt(ad.port, 10) - }); - - if (service.hasOwnProperty('roles') && typeof service.roles === 'string' && service.roles.includes(',')) { - service.roles = service.roles.split(',').map(role => role.trim().toLowerCase()); - } - - if (service.hasOwnProperty('roles') && typeof service.roles === 'string' && !service.roles.includes(',')) { - service.roles = [service.roles].map(role => role.trim().toLowerCase()); - } + const bonjourProps = ['_server', '_registry'].join(','); + const mdnsProps = ['dns_sd', 'Advertisement', 'createAdvertisement', 'Browser'].join(','); - let ipv4 = service.hostname; + if (Object.keys(bonjourOrMdns).join(',').startsWith(bonjourProps)) { + return this.discoverWithBonjour(bonjourOrMdns, timeout); + } - if (Array.isArray(ad.addresses)) { - ipv4 = ad.addresses.reduce((found, address) => { - if (address && typeof address === 'string' && address.includes('.')) { - found = address; - } + if (Object.keys(bonjourOrMdns).join(',').startsWith(mdnsProps)) { + return this.discoverWithMdns(bonjourOrMdns, timeout); + } - return found; - }, service.hostname); - } + throw new Error('Unrecognized mDNS provider given'); + } - if (ipv4.trim() !== '') { - service.hostname = ipv4; + discoverWithBonjour(bonjour, timeout) { + const browser = bonjour.find({ + type: 'signalk-http' + }); + browser.on('up', ad => this.handleDiscoveredService(ad, _objectSpread(_objectSpread({}, ad.txt), {}, { + name: ad.name || '', + hostname: ad.host || '', + port: parseInt(ad.port, 10), + provider: 'bonjour' + }))); + setTimeout(() => { + if (this.found.length === 0) { + this.emit('timeout'); } - const server = new SKServer(service); - this.found.push(server); - this.emit('found', server); - }); + browser.stop(); + }, timeout); browser.start(); + } + + discoverWithMdns(mDNS, timeout) { + const browser = mDNS.createBrowser(mDNS.tcp('_signalk-http')); + browser.on('serviceUp', ad => this.handleDiscoveredService(ad, _objectSpread(_objectSpread({}, ad.txtRecord), {}, { + hostname: ad.host || '', + port: parseInt(ad.port, 10), + provider: 'mdns' + }))); + browser.on('error', err => this.handleDiscoveryError(err)); setTimeout(() => { if (this.found.length === 0) { this.emit('timeout'); @@ -129,6 +133,38 @@ class Discovery extends _eventemitter.default { browser.stop(); }, timeout); + browser.start(); + } + + handleDiscoveryError(err) { + console.error("Error during discovery: ".concat(err.message)); + } + + handleDiscoveredService(ad, service) { + if (typeof service.roles === 'string') { + service.roles = service.roles.split(',').map(role => role.trim().toLowerCase()); + } + + service.roles = Array.isArray(service.roles) ? service.roles : []; + let ipv4 = service.hostname; + + if (Array.isArray(ad.addresses)) { + ipv4 = ad.addresses.reduce((found, address) => { + if (address && typeof address === 'string' && address.includes('.')) { + found = address; + } + + return found; + }, service.hostname); + } + + if (ipv4.trim() !== '') { + service.hostname = ipv4; + } + + const server = new SKServer(service); + this.found.push(server); + this.emit('found', server); } } diff --git a/dist/lib/request.js b/dist/lib/request.js index 217b207..2ba5805 100644 --- a/dist/lib/request.js +++ b/dist/lib/request.js @@ -66,7 +66,7 @@ class Request extends _eventemitter.default { response, receivedAt }); - this.emit('response', _objectSpread({}, response, { + this.emit('response', _objectSpread(_objectSpread({}, response), {}, { request: { receivedAt, name: this.name, diff --git a/package.json b/package.json index 7f827f2..d02eb22 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "casper-chai": "^0.3.0", "chai": "^4.1.0", "freeport-promise": "^1.1.0", + "mdns": "^2.5.1", "mocha": "^6.0.2", "signalk-server": "^1.28.0" }, diff --git a/src/lib/discovery.js b/src/lib/discovery.js index 468fd27..a90755e 100644 --- a/src/lib/discovery.js +++ b/src/lib/discovery.js @@ -11,7 +11,7 @@ import EventEmitter from 'eventemitter3' import Client from './client' export class SKServer { - constructor (service) { + constructor(service) { this._roles = service.roles || ['master', 'main'] this._self = service.self || '' this._version = service.version || '0.0.0' @@ -19,100 +19,144 @@ export class SKServer { this._port = service.port } - get roles () { + get roles() { return this._roles } - get self () { + get self() { return this._self } - get version () { + get version() { return this._version } - get hostname () { + get hostname() { return this._hostname } - get port () { + get port() { return this._port } - isMain () { + isMain() { return this._roles.includes('main') } - isMaster () { + isMaster() { return this._roles.includes('master') } - createClient (opts = {}) { + createClient(opts = {}) { return new Client({ ...opts, hostname: this._hostname, - port: this._port + port: this._port, }) } } export default class Discovery extends EventEmitter { - constructor (bonjour, timeout = 60000) { + constructor(bonjourOrMdns, timeout = 60000) { super() - const props = [ '_server', '_registry' ].join(',') + this.found = [] - if (!bonjour || typeof bonjour !== 'object' || Object.keys(bonjour).join(',') !== props) { - throw new Error('Invalid mDNS provider') + if (!bonjourOrMdns || typeof bonjourOrMdns !== 'object') { + throw new Error('No mDNS provider given') } - this.found = [] + const bonjourProps = ['_server', '_registry'].join(',') + const mdnsProps = ['dns_sd', 'Advertisement', 'createAdvertisement', 'Browser'].join(',') + + if (Object.keys(bonjourOrMdns).join(',').startsWith(bonjourProps)) { + return this.discoverWithBonjour(bonjourOrMdns, timeout) + } + + if (Object.keys(bonjourOrMdns).join(',').startsWith(mdnsProps)) { + return this.discoverWithMdns(bonjourOrMdns, timeout) + } + + throw new Error('Unrecognized mDNS provider given') + } + + discoverWithBonjour(bonjour, timeout) { const browser = bonjour.find({ type: 'signalk-http' }) - browser.on('up', ad => { - const service = { + browser.on('up', (ad) => + this.handleDiscoveredService(ad, { ...ad.txt, name: ad.name || '', hostname: ad.host || '', - port: parseInt(ad.port, 10) - } + port: parseInt(ad.port, 10), + provider: 'bonjour', + }) + ) - if (service.hasOwnProperty('roles') && typeof service.roles === 'string' && service.roles.includes(',')) { - service.roles = service.roles.split(',').map(role => role.trim().toLowerCase()) + setTimeout(() => { + if (this.found.length === 0) { + this.emit('timeout') } - if (service.hasOwnProperty('roles') && typeof service.roles === 'string' && !service.roles.includes(',')) { - service.roles = [ service.roles ].map(role => role.trim().toLowerCase()) - } + browser.stop() + }, timeout) - let ipv4 = service.hostname + browser.start() + } - if (Array.isArray(ad.addresses)) { - ipv4 = ad.addresses.reduce((found, address) => { - if (address && typeof address === 'string' && address.includes('.')) { - found = address - } - return found - }, service.hostname) - } + discoverWithMdns(mDNS, timeout) { + const browser = mDNS.createBrowser(mDNS.tcp('_signalk-http')) - if (ipv4.trim() !== '') { - service.hostname = ipv4 - } + browser.on('serviceUp', (ad) => + this.handleDiscoveredService(ad, { + ...ad.txtRecord, + hostname: ad.host || '', + port: parseInt(ad.port, 10), + provider: 'mdns', + }) + ) - const server = new SKServer(service) - this.found.push(server) - this.emit('found', server) - }) - - browser.start() + browser.on('error', (err) => this.handleDiscoveryError(err)) setTimeout(() => { if (this.found.length === 0) { this.emit('timeout') } - + browser.stop() }, timeout) + + browser.start() + } + + handleDiscoveryError(err) { + console.error(`Error during discovery: ${err.message}`) + } + + handleDiscoveredService(ad, service) { + if (typeof service.roles === 'string') { + service.roles = service.roles.split(',').map((role) => role.trim().toLowerCase()) + } + + service.roles = Array.isArray(service.roles) ? service.roles : [] + + let ipv4 = service.hostname + + if (Array.isArray(ad.addresses)) { + ipv4 = ad.addresses.reduce((found, address) => { + if (address && typeof address === 'string' && address.includes('.')) { + found = address + } + return found + }, service.hostname) + } + + if (ipv4.trim() !== '') { + service.hostname = ipv4 + } + + const server = new SKServer(service) + this.found.push(server) + this.emit('found', server) } } diff --git a/test/index.js b/test/index.js index 4baf48f..c89916a 100644 --- a/test/index.js +++ b/test/index.js @@ -6,13 +6,10 @@ * @module @signalk/signalk-js-sdk */ -import Client, { - Discovery, - Client as NamedClient, - PERMISSIONS_READONLY -} from '../src' +import Client, { Discovery, Client as NamedClient, PERMISSIONS_READONLY } from '../src' import Bonjour from 'bonjour' +import mdns from 'mdns' import { assert } from 'chai' import { v4 as uuid } from 'uuid' import Server from 'signalk-server' @@ -42,9 +39,9 @@ const getPathsFromDelta = (delta, paths = []) => { return paths } - delta.updates.forEach(update => { + delta.updates.forEach((update) => { if (update && typeof update === 'object' && Array.isArray(update.values)) { - update.values.forEach(mut => { + update.values.forEach((mut) => { if (!paths.includes(mut.path)) { paths.push(mut.path) } @@ -66,20 +63,23 @@ let serverApp const securityConfig = { allow_readonly: false, expiration: '1d', - secretKey: '3c2eddf95ece9080518eb777b26c0fa6285f107cccb5ff9d5bdd7776eeb82c8afaf0dffa7d9312936882351ec6b1d5535203b4a2b806ab130cdbcd917f46f2a69e7ff4548ca3644c97a98185284041de46518cdb026f85430532fa4482882e4cfd08cc0256dca88d0ca2577b91d6a435a832e6c600b2db13f794d087e5e3a181d9566c1e61a14f984dbc643a7f6ab6a60cafafff34c93475d442475136cf7f0bfb62c59b050a9be572bc26993c46ef05fa748dc8395277eaa07519d79a7bc12502a2429b2f89b78796f6dcf3f474a5c5e276ecbb59dcdceaa8df8f1b1f98ec23a4c36cc1334e07e06a8c8cd6671fee599e578d24aabd187d1a2903ae6facb090', - users: [{ - username: 'sdk', - type: 'admin', - password: '$2a$10$JyzSM5PMD3PCyivdtSN61OfwmjfgdISVtJ1l5KIC8/R1sUHPseMU2' - }], + secretKey: + '3c2eddf95ece9080518eb777b26c0fa6285f107cccb5ff9d5bdd7776eeb82c8afaf0dffa7d9312936882351ec6b1d5535203b4a2b806ab130cdbcd917f46f2a69e7ff4548ca3644c97a98185284041de46518cdb026f85430532fa4482882e4cfd08cc0256dca88d0ca2577b91d6a435a832e6c600b2db13f794d087e5e3a181d9566c1e61a14f984dbc643a7f6ab6a60cafafff34c93475d442475136cf7f0bfb62c59b050a9be572bc26993c46ef05fa748dc8395277eaa07519d79a7bc12502a2429b2f89b78796f6dcf3f474a5c5e276ecbb59dcdceaa8df8f1b1f98ec23a4c36cc1334e07e06a8c8cd6671fee599e578d24aabd187d1a2903ae6facb090', + users: [ + { + username: 'sdk', + type: 'admin', + password: '$2a$10$JyzSM5PMD3PCyivdtSN61OfwmjfgdISVtJ1l5KIC8/R1sUHPseMU2', + }, + ], devices: [], immutableConfig: false, acls: [], allowDeviceAccessRequests: true, - allowNewUserRegistration: true + allowNewUserRegistration: true, } -function startServer (done = () => {}) { +function startServer(done = () => {}) { TEST_SERVER_HOSTNAME = 'localhost' let promise @@ -90,27 +90,27 @@ function startServer (done = () => {}) { promise = Promise.resolve(TEST_SERVER_PORT) } - promise.then(port => { + promise.then((port) => { TEST_SERVER_PORT = port serverApp = new Server({ config: { settings: { port, interfaces: { - plugins: false + plugins: false, }, security: { - strategy: './tokensecurity' - } - } + strategy: './tokensecurity', + }, + }, }, - securityConfig: securityConfig + securityConfig: securityConfig, }) serverApp.start().then(() => done()) }) } -function killServer (done = () => {}) { +function killServer(done = () => {}) { if (!serverApp) { return done() } @@ -119,7 +119,7 @@ function killServer (done = () => {}) { } describe('Signal K SDK', () => { - before(done => { + before((done) => { if (TEST_SERVER_HOSTNAME) { done() } else { @@ -132,7 +132,7 @@ describe('Signal K SDK', () => { // @TODO requesting access should be expanded into a small class to manage the entire flow (including polling) describe('Device access requests', () => { - it('... successfully requests device access', done => { + it('... successfully requests device access', (done) => { const clientId = uuid() const client = new Client({ hostname: TEST_SERVER_HOSTNAME, @@ -143,13 +143,13 @@ describe('Signal K SDK', () => { password: PASSWORD, reconnect: false, notifications: true, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) client.on('connect', () => { client .requestDeviceAccess('Top Secret Client', clientId) - .then(result => { + .then((result) => { client.disconnect() assert( isObject(result, 'response', true) && @@ -159,7 +159,7 @@ describe('Signal K SDK', () => { ) done() }) - .catch(err => done(err)) + .catch((err) => done(err)) }) client.connect() @@ -204,10 +204,10 @@ describe('Signal K SDK', () => { // */ // I don't understand why this suddenly doesn't work anymore. Is this buggy in server? - it.skip('... FIXME: can respond to the access request notification sent by server', done => { + it.skip('... FIXME: can respond to the access request notification sent by server', (done) => { let sent = false let connected = false - + const clientId = uuid() const client = new Client({ hostname: TEST_SERVER_HOSTNAME, @@ -218,14 +218,14 @@ describe('Signal K SDK', () => { password: PASSWORD, reconnect: false, notifications: true, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) client.on('connect', () => { connected = true }) - client.on('notification', notification => { + client.on('notification', (notification) => { if ( sent === false && notification.path.includes('security.accessRequest') && @@ -234,42 +234,38 @@ describe('Signal K SDK', () => { sent = true client .respondToAccessRequest(clientId, PERMISSIONS_READONLY) - .then(result => { - assert( - String(result).toLowerCase().includes('request updated') === true - ) // TODO: node server returns incorrect response here + .then((result) => { + assert(String(result).toLowerCase().includes('request updated') === true) // TODO: node server returns incorrect response here done() }) - .catch(err => done(err)) + .catch((err) => done(err)) } }) client.on('connect', () => { setTimeout(() => { - client - .requestDeviceAccess('Top Secret Client', clientId) - .catch(err => done(err)) + client.requestDeviceAccess('Top Secret Client', clientId).catch((err) => done(err)) }, 1500) }) client.connect() }).timeout(30000) }) - + describe('Authentication over WebSockets, using seperate mechanism', () => { - it('... sends an authentication request with incorrect password, and receives the proper error code', done => { + it('... sends an authentication request with incorrect password, and receives the proper error code', (done) => { const client = new Client({ hostname: TEST_SERVER_HOSTNAME, port: TEST_SERVER_PORT, useTLS: false, reconnect: false, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) client.on('connect', () => { client.authenticate(USER, 'wrong!') - client.once('error', err => { + client.once('error', (err) => { assert(err.message.includes('401')) done() }) @@ -278,22 +274,20 @@ describe('Signal K SDK', () => { client.connect() }).timeout(15000) - it('... sends an authentication request and receives a well-formed response including token', done => { + it('... sends an authentication request and receives a well-formed response including token', (done) => { const client = new Client({ hostname: TEST_SERVER_HOSTNAME, port: TEST_SERVER_PORT, useTLS: false, reconnect: false, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) client.on('connect', () => { client.authenticate(USER, PASSWORD) - client.once('authenticated', data => { - assert( - data && typeof data === 'object' && data.hasOwnProperty('token') - ) + client.once('authenticated', (data) => { + assert(data && typeof data === 'object' && data.hasOwnProperty('token')) done() }) }) @@ -301,27 +295,27 @@ describe('Signal K SDK', () => { client.connect() }).timeout(15000) - it('... successfully authenticates, and then can access resources via the REST API', done => { + it('... successfully authenticates, and then can access resources via the REST API', (done) => { const client = new Client({ hostname: TEST_SERVER_HOSTNAME, port: TEST_SERVER_PORT, useTLS: false, reconnect: false, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) client.on('connect', () => { client.authenticate(USER, PASSWORD) - client.once('authenticated', data => { + client.once('authenticated', (data) => { client .API() - .then(api => api.self()) - .then(result => { + .then((api) => api.self()) + .then((result) => { assert(result && typeof result === 'object') done() }) - .catch(err => done(err)) + .catch((err) => done(err)) }) }) @@ -330,7 +324,7 @@ describe('Signal K SDK', () => { }) describe('Request/response mechanics', () => { - it('... sends a request and receives a well-formed response', done => { + it('... sends a request and receives a well-formed response', (done) => { const client = new Client({ hostname: TEST_SERVER_HOSTNAME, port: TEST_SERVER_PORT, @@ -340,26 +334,25 @@ describe('Signal K SDK', () => { password: PASSWORD, reconnect: false, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) client.on('connect', () => { const request = client.request('PUT', { put: { path: 'electrical.switches.anchorLight.state', - value: 1 - } + value: 1, + }, }) - request.once('response', response => { + request.once('response', (response) => { assert( response && typeof response === 'object' && response.hasOwnProperty('requestId') && response.hasOwnProperty('state') && response.hasOwnProperty('statusCode') && - (response.state === 'PENDING' || - response.state === 'COMPLETED') && + (response.state === 'PENDING' || response.state === 'COMPLETED') && response.requestId === request.getRequestId() ) done() @@ -372,84 +365,113 @@ describe('Signal K SDK', () => { }).timeout(15000) // TODO: not yet implemented by Signal K node.js server, so this this would always fail - it.skip('... TODO: sends a query for a request and receives a well-formed response (not yet implemented in Node server)', done => { - const client = new Client({ - hostname: TEST_SERVER_HOSTNAME, - port: TEST_SERVER_PORT, - useTLS: false, - reconnect: false, - notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX - }) + it.skip( + '... TODO: sends a query for a request and receives a well-formed response (not yet implemented in Node server)', + (done) => { + const client = new Client({ + hostname: TEST_SERVER_HOSTNAME, + port: TEST_SERVER_PORT, + useTLS: false, + reconnect: false, + notifications: false, + bearerTokenPrefix: BEARER_TOKEN_PREFIX, + }) - let received = 0 + let received = 0 - client.on('connect', () => { - const request = client.request('LOGIN', { - login: { - username: USER, - password: PASSWORD - } - }) + client.on('connect', () => { + const request = client.request('LOGIN', { + login: { + username: USER, + password: PASSWORD, + }, + }) - request.on('response', response => { - received += 1 + request.on('response', (response) => { + received += 1 - if (received === 1) { - // Send query after initial response... - request.query() - } + if (received === 1) { + // Send query after initial response... + request.query() + } - if (received > 1) { - assert( - response && - typeof response === 'object' && - response.hasOwnProperty('requestId') && - response.hasOwnProperty('state') && - response.hasOwnProperty('statusCode') && - (response.state === 'PENDING' || response.state === 'COMPLETED') && - response.requestId === request.getRequestId() - ) - done() - } - }) + if (received > 1) { + assert( + response && + typeof response === 'object' && + response.hasOwnProperty('requestId') && + response.hasOwnProperty('state') && + response.hasOwnProperty('statusCode') && + (response.state === 'PENDING' || response.state === 'COMPLETED') && + response.requestId === request.getRequestId() + ) + done() + } + }) - request.send() - }) + request.send() + }) - client.connect() - }).timeout(15000) + client.connect() + } + ).timeout(15000) }) describe('mDNS server discovery', () => { - !process.env.TRAVIS && it('... Emits an event when a Signal K host is found', done => { - let found = 0 - const bonjour = Bonjour() - const discovery = new Discovery(bonjour, 10000) + !process.env.TRAVIS && + it('... Emits an event when a Signal K host is found, using mDNS', (done) => { + let found = 0 + const discovery = new Discovery(mdns, 10000) - discovery.once('found', server => { - found += 1 - assert( - typeof server.hostname === 'string' && - server.hostname !== '' && - typeof server.port === 'number' && - typeof server.createClient === 'function' && - Array.isArray(server.roles) && - server.createClient() instanceof Client - ) - done() - }) + discovery.once('found', (server) => { + found += 1 + assert( + typeof server.hostname === 'string' && + server.hostname !== '' && + typeof server.port === 'number' && + typeof server.createClient === 'function' && + Array.isArray(server.roles) && + server.createClient() instanceof Client + ) + done() + }) - discovery.on('timeout', () => { - if (found === 0) { + discovery.on('timeout', () => { + if (found === 0) { + done() + } + }) + }).timeout(15000) + + !process.env.TRAVIS && + it('... Emits an event when a Signal K host is found, using Bonjour', (done) => { + let found = 0 + const bonjour = Bonjour() + const discovery = new Discovery(bonjour, 10000) + + discovery.once('found', (server) => { + found += 1 + assert( + typeof server.hostname === 'string' && + server.hostname !== '' && + typeof server.port === 'number' && + typeof server.createClient === 'function' && + Array.isArray(server.roles) && + server.createClient() instanceof Client + ) done() - } - }) - }).timeout(15000) + }) + + discovery.on('timeout', () => { + if (found === 0) { + done() + } + }) + }).timeout(15000) }) - + describe('Delta stream behaviour & subscriptions', () => { - it('... Streams own vessel (self) data when the behaviour is set to "null"', done => { + it('... Streams own vessel (self) data when the behaviour is set to "null"', (done) => { const client = new Client({ hostname: 'demo.signalk.org', port: 80, @@ -457,32 +479,30 @@ describe('Signal K SDK', () => { reconnect: false, notifications: false, bearerTokenPrefix: BEARER_TOKEN_PREFIX, - deltaStreamBehaviour: null + deltaStreamBehaviour: null, }) let count = 0 - client.on('delta', data => { + client.on('delta', (data) => { count += 1 if (count < 5) { assert( data && - typeof data === 'object' && - data.hasOwnProperty('updates') && - data.hasOwnProperty('context') && - data.context === client.self + typeof data === 'object' && + data.hasOwnProperty('updates') && + data.hasOwnProperty('context') && + data.context === client.self ) } else if (count === 5) { done() } }) - client - .connect() - .catch(err => done(err)) + client.connect().catch((err) => done(err)) }).timeout(20000) - it('... Streams own vessel (self) data when the behaviour is set to "self"', done => { + it('... Streams own vessel (self) data when the behaviour is set to "self"', (done) => { const client = new Client({ hostname: 'demo.signalk.org', port: 80, @@ -490,32 +510,30 @@ describe('Signal K SDK', () => { reconnect: false, notifications: false, bearerTokenPrefix: BEARER_TOKEN_PREFIX, - deltaStreamBehaviour: 'self' + deltaStreamBehaviour: 'self', }) let count = 0 - client.on('delta', data => { + client.on('delta', (data) => { count += 1 if (count < 5) { assert( data && - typeof data === 'object' && - data.hasOwnProperty('updates') && - data.hasOwnProperty('context') && - data.context === client.self + typeof data === 'object' && + data.hasOwnProperty('updates') && + data.hasOwnProperty('context') && + data.context === client.self ) } else if (count === 5) { done() } }) - client - .connect() - .catch(err => done(err)) + client.connect().catch((err) => done(err)) }).timeout(20000) - it('... Streams data from multiple vessels when the behaviour is set to "all"', done => { + it('... Streams data from multiple vessels when the behaviour is set to "all"', (done) => { const client = new Client({ hostname: 'demo.wilhelmsk.com', port: 3000, @@ -523,7 +541,7 @@ describe('Signal K SDK', () => { reconnect: false, notifications: false, bearerTokenPrefix: BEARER_TOKEN_PREFIX, - deltaStreamBehaviour: 'all' + deltaStreamBehaviour: 'all', }) let contexes = [] @@ -533,18 +551,16 @@ describe('Signal K SDK', () => { done() }, 5000) - client.on('delta', data => { + client.on('delta', (data) => { if (!contexes.includes(data.context)) { contexes.push(data.context) } }) - client - .connect() - .catch(err => done(err)) + client.connect().catch((err) => done(err)) }).timeout(30000) - it('... Creates a subscription for navigation data from own vessel', done => { + it('... Creates a subscription for navigation data from own vessel', (done) => { const client = new Client({ hostname: 'demo.signalk.org', port: 80, @@ -552,20 +568,22 @@ describe('Signal K SDK', () => { reconnect: false, notifications: false, bearerTokenPrefix: BEARER_TOKEN_PREFIX, - subscriptions: [{ - context: 'vessels.self', - subscribe: [ - { - path: 'navigation.position', - policy: 'instant' - } - ] - }] + subscriptions: [ + { + context: 'vessels.self', + subscribe: [ + { + path: 'navigation.position', + policy: 'instant', + }, + ], + }, + ], }) - + let count = 0 - client.on('delta', data => { + client.on('delta', (data) => { count += 1 if (count < 5) { @@ -574,8 +592,8 @@ describe('Signal K SDK', () => { return false } - const found = update.values.find(mut => (mut.path === 'navigation.position')) - return (found && typeof found === 'object') + const found = update.values.find((mut) => mut.path === 'navigation.position') + return found && typeof found === 'object' } let hasPath = false @@ -589,23 +607,21 @@ describe('Signal K SDK', () => { assert( data && - typeof data === 'object' && - data.hasOwnProperty('updates') && - data.hasOwnProperty('context') && - hasPath && - data.context === client.self + typeof data === 'object' && + data.hasOwnProperty('updates') && + data.hasOwnProperty('context') && + hasPath && + data.context === client.self ) } else if (count === 5) { done() } }) - client - .connect() - .catch(err => done(err)) + client.connect().catch((err) => done(err)) }).timeout(30000) - it('... Creates multiple subscriptions when notifications = true and the subscription pertains multiple vessels', done => { + it('... Creates multiple subscriptions when notifications = true and the subscription pertains multiple vessels', (done) => { const client = new Client({ hostname: 'demo.signalk.org', port: 80, @@ -613,21 +629,23 @@ describe('Signal K SDK', () => { reconnect: false, notifications: true, bearerTokenPrefix: BEARER_TOKEN_PREFIX, - subscriptions: [{ - context: 'vessels.*', - subscribe: [ - { - path: 'navigation.position', - policy: 'instant' - } - ] - }] + subscriptions: [ + { + context: 'vessels.*', + subscribe: [ + { + path: 'navigation.position', + policy: 'instant', + }, + ], + }, + ], }) - + const pathsFound = [] let isDone = false - client.on('delta', data => { + client.on('delta', (data) => { if (isDone === true) { return } @@ -635,7 +653,7 @@ describe('Signal K SDK', () => { if (pathsFound.includes('notifications.*') && pathsFound.includes('navigation.position')) { assert( pathsFound.includes('notifications.*') === true && - pathsFound.includes('navigation.position') === true + pathsFound.includes('navigation.position') === true ) isDone = true @@ -643,8 +661,8 @@ describe('Signal K SDK', () => { } if (data && typeof data === 'object' && Array.isArray(data.updates)) { - data.updates.forEach(update => { - update.values.forEach(mut => { + data.updates.forEach((update) => { + update.values.forEach((mut) => { if (pathsFound.includes(mut.path)) { return } @@ -653,7 +671,11 @@ describe('Signal K SDK', () => { pathsFound.push(mut.path) } - if (mut.path.includes('notifications.') && data.context === client.self && !pathsFound.includes('notifications.*')) { + if ( + mut.path.includes('notifications.') && + data.context === client.self && + !pathsFound.includes('notifications.*') + ) { pathsFound.push('notifications.*') } }) @@ -662,27 +684,25 @@ describe('Signal K SDK', () => { }) client.on('connect', () => { - client.requestDeviceAccess('Top Secret Client', uuid()).catch(err => done(err)) + client.requestDeviceAccess('Top Secret Client', uuid()).catch((err) => done(err)) }) - client - .connect() - .catch(err => done(err)) + client.connect().catch((err) => done(err)) }).timeout(30000) - it('... Modifies the delta stream subscription after initialisation', done => { + it('... Modifies the delta stream subscription after initialisation', (done) => { const client = new Client({ hostname: 'demo.signalk.org', port: 80, useTLS: false, reconnect: false, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) - + let count = 0 - client.on('delta', data => { + client.on('delta', (data) => { count += 1 if (count < 5) { @@ -691,8 +711,8 @@ describe('Signal K SDK', () => { return false } - const found = update.values.find(mut => (mut.path === 'navigation.position')) - return (found && typeof found === 'object') + const found = update.values.find((mut) => mut.path === 'navigation.position') + return found && typeof found === 'object' } let hasPath = false @@ -706,11 +726,11 @@ describe('Signal K SDK', () => { assert( data && - typeof data === 'object' && - data.hasOwnProperty('updates') && - data.hasOwnProperty('context') && - hasPath && - data.context === client.self + typeof data === 'object' && + data.hasOwnProperty('updates') && + data.hasOwnProperty('context') && + hasPath && + data.context === client.self ) } else if (count === 5) { done() @@ -723,36 +743,35 @@ describe('Signal K SDK', () => { subscribe: [ { path: 'navigation.position', - policy: 'instant' - } - ] + policy: 'instant', + }, + ], }) }) - client - .connect() - .catch(err => done(err)) + client.connect().catch((err) => done(err)) }).timeout(30000) - it('... Handles multiple subscribe calls correctly', done => { + it('... Handles multiple subscribe calls correctly', (done) => { const client = new Client({ hostname: 'demo.signalk.org', port: 80, useTLS: false, reconnect: false, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) - + const paths = [] let isDone = false - client.on('delta', delta => { + client.on('delta', (delta) => { if (isDone === true) { return } - isDone = paths.includes('navigation.position') && paths.includes('environment.wind.angleApparent') + isDone = + paths.includes('navigation.position') && paths.includes('environment.wind.angleApparent') if (isDone === true) { assert(isDone === true) @@ -768,9 +787,9 @@ describe('Signal K SDK', () => { subscribe: [ { path: 'navigation.position', - policy: 'instant' - } - ] + policy: 'instant', + }, + ], }) client.subscribe({ @@ -778,42 +797,40 @@ describe('Signal K SDK', () => { subscribe: [ { path: 'environment.wind.angleApparent', - policy: 'instant' - } - ] + policy: 'instant', + }, + ], }) }) - client - .connect() - .catch(err => done(err)) + client.connect().catch((err) => done(err)) }).timeout(30000) - it('... Handles subscribes, then unsubscribes', done => { + it('... Handles subscribes, then unsubscribes', (done) => { const client = new Client({ hostname: 'demo.signalk.org', port: 80, useTLS: false, reconnect: false, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) - + const paths = [] let isDone = false let countAtUnsubscribe = -1 - client.on('delta', delta => { + client.on('delta', (delta) => { if (isDone === true) { return } - + getPathsFromDelta(delta, paths) if (countAtUnsubscribe === -1 && paths.length > 0) { client.unsubscribe() countAtUnsubscribe = paths.length - + setTimeout(() => { isDone = true assert(countAtUnsubscribe === paths.length) @@ -828,57 +845,59 @@ describe('Signal K SDK', () => { subscribe: [ { path: 'navigation.position', - policy: 'instant' - } - ] + policy: 'instant', + }, + ], }) }) - client - .connect() - .catch(err => done(err)) + client.connect().catch((err) => done(err)) }).timeout(30000) - it.skip('... @TODO: Unsubscribes, after subscribing using a behaviour modifier (not supported by server)', done => { - const client = new Client({ - hostname: 'demo.signalk.org', - port: 80, - useTLS: false, - reconnect: false, - notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX, - deltaStreamBehaviour: null - }) - - const paths = [] - let isDone = false - let countAtUnsubscribe = -1 + it.skip( + '... @TODO: Unsubscribes, after subscribing using a behaviour modifier (not supported by server)', + (done) => { + const client = new Client({ + hostname: 'demo.signalk.org', + port: 80, + useTLS: false, + reconnect: false, + notifications: false, + bearerTokenPrefix: BEARER_TOKEN_PREFIX, + deltaStreamBehaviour: null, + }) - client.on('delta', delta => { - if (isDone === true) { - return - } - - getPathsFromDelta(delta, paths) + const paths = [] + let isDone = false + let countAtUnsubscribe = -1 - if (countAtUnsubscribe === -1 && paths.length > 0) { - client.unsubscribe() - countAtUnsubscribe = paths.length - - setTimeout(() => { - isDone = true - assert(countAtUnsubscribe === paths.length, `No. of recorded paths (${paths.length}) doesn't match count when unsubscribe() was called (${countAtUnsubscribe})`) - done() - }, 1500) - } - }) + client.on('delta', (delta) => { + if (isDone === true) { + return + } - client - .connect() - .catch(err => done(err)) - }).timeout(30000) + getPathsFromDelta(delta, paths) - it('... Streams no data when the behaviour is set to "none"', done => { + if (countAtUnsubscribe === -1 && paths.length > 0) { + client.unsubscribe() + countAtUnsubscribe = paths.length + + setTimeout(() => { + isDone = true + assert( + countAtUnsubscribe === paths.length, + `No. of recorded paths (${paths.length}) doesn't match count when unsubscribe() was called (${countAtUnsubscribe})` + ) + done() + }, 1500) + } + }) + + client.connect().catch((err) => done(err)) + } + ).timeout(30000) + + it('... Streams no data when the behaviour is set to "none"', (done) => { const client = new Client({ hostname: 'demo.signalk.org', port: 80, @@ -886,7 +905,7 @@ describe('Signal K SDK', () => { reconnect: false, notifications: false, bearerTokenPrefix: BEARER_TOKEN_PREFIX, - deltaStreamBehaviour: 'none' + deltaStreamBehaviour: 'none', }) let count = 0 @@ -901,7 +920,7 @@ describe('Signal K SDK', () => { done() }, 10000) - client.on('delta', data => { + client.on('delta', (data) => { if (isDone === false) { count += 1 } @@ -914,14 +933,12 @@ describe('Signal K SDK', () => { } }) - client - .connect() - .catch(err => done(err)) + client.connect().catch((err) => done(err)) }).timeout(20000) }) describe('Notifications', () => { - it('... Connects and receives notifications', done => { + it('... Connects and receives notifications', (done) => { const clientId = uuid() const client = new Client({ hostname: TEST_SERVER_HOSTNAME, @@ -932,10 +949,10 @@ describe('Signal K SDK', () => { useAuthentication: true, username: USER, password: PASSWORD, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) - client.once('notification', notification => { + client.once('notification', (notification) => { assert( notification && typeof notification === 'object' && @@ -947,15 +964,13 @@ describe('Signal K SDK', () => { client.on('connect', () => { setTimeout(() => { - // Force the sending of a notification - client - .requestDeviceAccess('Top Secret Client', clientId) - .catch(err => { - console.log('ERROR', err.message) - console.log(err.stack) + // Force the sending of a notification + client.requestDeviceAccess('Top Secret Client', clientId).catch((err) => { + console.log('ERROR', err.message) + console.log(err.stack) - done(err) - }) + done(err) + }) }, 500) }) @@ -977,7 +992,7 @@ describe('Signal K SDK', () => { reconnect: false, autoConnect: true, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) }) @@ -993,19 +1008,19 @@ describe('Signal K SDK', () => { 'sails', 'sensors', 'steering', - 'tanks' + 'tanks', ] - groups.forEach(group => { - it(`... Fetches "self/${group}" successfully`, done => { + groups.forEach((group) => { + it(`... Fetches "self/${group}" successfully`, (done) => { client .API() - .then(api => api[group]()) - .then(result => { + .then((api) => api[group]()) + .then((result) => { assert(result && typeof result === 'object') done() }) - .catch(err => { + .catch((err) => { // 404 means successful request, but the data isn't present on the vessel if (err.message.includes('404')) { return done() @@ -1016,37 +1031,37 @@ describe('Signal K SDK', () => { }) }) - it.skip('... @FIXME Successfully completes a PUT request for a given path', done => { + it.skip('... @FIXME Successfully completes a PUT request for a given path', (done) => { client .API() - .then(api => api.put('/vessels/self/environment/depth/belowTransducer', { value: 100 })) - .then(result => { + .then((api) => api.put('/vessels/self/environment/depth/belowTransducer', { value: 100 })) + .then((result) => { console.log(result) done() }) - .catch(err => done(err)) + .catch((err) => done(err)) }) - it.skip('... @FIXME Fails to complete a PUT request for an unknown path', done => { + it.skip('... @FIXME Fails to complete a PUT request for an unknown path', (done) => { client .API() - .then(api => api.put('/vessels/self/environment/depth/belowTransducer', { value: 100 })) - .then(result => { + .then((api) => api.put('/vessels/self/environment/depth/belowTransducer', { value: 100 })) + .then((result) => { console.log(result) done() }) - .catch(err => done(err)) + .catch((err) => done(err)) }) - it('... Fetches meta data by path successfully', done => { + it('... Fetches meta data by path successfully', (done) => { client .API() - .then(api => api.getMeta('vessels.self.navigation.position')) - .then(result => { + .then((api) => api.getMeta('vessels.self.navigation.position')) + .then((result) => { assert(result && typeof result === 'object') done() }) - .catch(err => { + .catch((err) => { // 404 means successful request, but the data isn't present on the vessel if (err.message.includes('404')) { return done() @@ -1056,15 +1071,15 @@ describe('Signal K SDK', () => { }) }) - it('... Fetches position data by path successfully, using dot notation', done => { + it('... Fetches position data by path successfully, using dot notation', (done) => { client .API() - .then(api => api.get('vessels.self.navigation.position')) - .then(result => { + .then((api) => api.get('vessels.self.navigation.position')) + .then((result) => { assert(result && typeof result === 'object') done() }) - .catch(err => { + .catch((err) => { // 404 means successful request, but the data isn't present on the vessel if (err.message.includes('404')) { return done() @@ -1074,15 +1089,15 @@ describe('Signal K SDK', () => { }) }) - it('... Fetches position data by path successfully, using forward slashes', done => { + it('... Fetches position data by path successfully, using forward slashes', (done) => { client .API() - .then(api => api.get('/vessels/self/navigation/position')) - .then(result => { + .then((api) => api.get('/vessels/self/navigation/position')) + .then((result) => { assert(result && typeof result === 'object') done() }) - .catch(err => { + .catch((err) => { // 404 means successful request, but the data isn't present on the vessel if (err.message.includes('404')) { return done() @@ -1092,15 +1107,15 @@ describe('Signal K SDK', () => { }) }) - it('... Fetches server version successfully', done => { + it('... Fetches server version successfully', (done) => { client .API() - .then(api => api.version()) - .then(result => { + .then((api) => api.version()) + .then((result) => { assert(typeof result === 'string') done() }) - .catch(err => { + .catch((err) => { // 404 means successful request, but the data isn't present on the vessel if (err.message.includes('404')) { return done() @@ -1110,15 +1125,15 @@ describe('Signal K SDK', () => { }) }) - it('... Fetches the vessels\' "name" successfully', done => { + it('... Fetches the vessels\' "name" successfully', (done) => { client .API() - .then(api => api.name()) - .then(result => { + .then((api) => api.name()) + .then((result) => { assert(typeof result === 'string') done() }) - .catch(err => { + .catch((err) => { // 404 means successful request, but the data isn't present on the vessel if (err.message.includes('404')) { return done() @@ -1128,15 +1143,15 @@ describe('Signal K SDK', () => { }) }) - it('... Fetches "self" successfully', done => { + it('... Fetches "self" successfully', (done) => { client .API() - .then(api => api.self()) - .then(result => { + .then((api) => api.self()) + .then((result) => { assert(result && typeof result === 'object') done() }) - .catch(err => { + .catch((err) => { // 404 means successful request, but the data isn't present on the vessel if (err.message.includes('404')) { return done() @@ -1146,15 +1161,15 @@ describe('Signal K SDK', () => { }) }) - it('... Fetches "vessels" successfully', done => { + it('... Fetches "vessels" successfully', (done) => { client .API() - .then(api => api.vessels()) - .then(result => { + .then((api) => api.vessels()) + .then((result) => { assert(result && typeof result === 'object') done() }) - .catch(err => { + .catch((err) => { // 404 means successful request, but the data isn't present on the vessel if (err.message.includes('404')) { return done() @@ -1164,15 +1179,15 @@ describe('Signal K SDK', () => { }) }) - it('... Fetches "aircraft" successfully', done => { + it('... Fetches "aircraft" successfully', (done) => { client .API() - .then(api => api.aircraft()) - .then(result => { + .then((api) => api.aircraft()) + .then((result) => { assert(result && typeof result === 'object') done() }) - .catch(err => { + .catch((err) => { // 404 means successful request, but the data isn't present on the vessel if (err.message.includes('404')) { return done() @@ -1182,15 +1197,15 @@ describe('Signal K SDK', () => { }) }) - it('... Fetches "aton" successfully', done => { + it('... Fetches "aton" successfully', (done) => { client .API() - .then(api => api.aton()) - .then(result => { + .then((api) => api.aton()) + .then((result) => { assert(result && typeof result === 'object') done() }) - .catch(err => { + .catch((err) => { // 404 means successful request, but the data isn't present on the vessel if (err.message.includes('404')) { return done() @@ -1200,15 +1215,15 @@ describe('Signal K SDK', () => { }) }) - it('... Fetches "sar" successfully', done => { + it('... Fetches "sar" successfully', (done) => { client .API() - .then(api => api.sar()) - .then(result => { + .then((api) => api.sar()) + .then((result) => { assert(result && typeof result === 'object') done() }) - .catch(err => { + .catch((err) => { // 404 means successful request, but the data isn't present on the vessel if (err.message.includes('404')) { return done() @@ -1218,15 +1233,15 @@ describe('Signal K SDK', () => { }) }) - it('... Fetches the vessel MRN successfully', done => { + it('... Fetches the vessel MRN successfully', (done) => { client .API() - .then(api => api.mrn()) - .then(result => { + .then((api) => api.mrn()) + .then((result) => { assert(typeof result === 'string') done() }) - .catch(err => { + .catch((err) => { // 404 means successful request, but the data isn't present on the vessel if (err.message.includes('404')) { return done() @@ -1236,15 +1251,15 @@ describe('Signal K SDK', () => { }) }) - it('... Fetches "sources" successfully', done => { + it('... Fetches "sources" successfully', (done) => { client .API() - .then(api => api.sources()) - .then(result => { + .then((api) => api.sources()) + .then((result) => { assert(result && typeof result === 'object') done() }) - .catch(err => { + .catch((err) => { // 404 means successful request, but the data isn't present on the vessel if (err.message.includes('404')) { return done() @@ -1254,15 +1269,15 @@ describe('Signal K SDK', () => { }) }) - it('... Fetches "resources" successfully', done => { + it('... Fetches "resources" successfully', (done) => { client .API() - .then(api => api.resources()) - .then(result => { + .then((api) => api.resources()) + .then((result) => { assert(result && typeof result === 'object') done() }) - .catch(err => { + .catch((err) => { // 404 means successful request, but the data isn't present on the vessel if (err.message.includes('404')) { return done() @@ -1274,12 +1289,12 @@ describe('Signal K SDK', () => { }) describe('Module API', () => { - it('... exports a Signal K Client as a named constant and the default export', done => { + it('... exports a Signal K Client as a named constant and the default export', (done) => { assert(Client === NamedClient) done() }) - it('... successfully instantiates a Client with default options', done => { + it('... successfully instantiates a Client with default options', (done) => { const client = new Client() assert(client.options.hostname === 'localhost') assert(client.options.port === 3000) @@ -1289,13 +1304,13 @@ describe('Signal K SDK', () => { done() }) - it('... instantiates a Client with custom options', done => { + it('... instantiates a Client with custom options', (done) => { const client = new Client({ hostname: 'signalk.org' }) assert(client.options.hostname === 'signalk.org') done() }) - it('... Client is an EventEmitter', done => { + it('... Client is an EventEmitter', (done) => { const client = new Client() assert(typeof client.on === 'function') done() @@ -1303,14 +1318,14 @@ describe('Signal K SDK', () => { }) describe('Connection', () => { - it('... Successfully closes the connection and any connection attempts when "disconnect" is called', done => { + it('... Successfully closes the connection and any connection attempts when "disconnect" is called', (done) => { let client = new Client({ hostname: TEST_SERVER_HOSTNAME, port: TEST_SERVER_PORT, useTLS: false, autoConnect: true, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) client.on('connect', () => { @@ -1323,14 +1338,14 @@ describe('Signal K SDK', () => { }) }) - it('... Reconnects after a connection failure until (odd) maxRetries is reached, at which point an event is emitted', done => { + it('... Reconnects after a connection failure until (odd) maxRetries is reached, at which point an event is emitted', (done) => { const client = new Client({ hostname: 'poo.signalk.org', port: 80, useTLS: false, maxRetries: 11, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) client.on('hitMaxRetries', () => { @@ -1341,14 +1356,14 @@ describe('Signal K SDK', () => { client.connect().catch(() => {}) }).timeout(60000) - it('... Reconnects after a connection failure until (even) maxRetries is reached, at which point an event is emitted', done => { + it('... Reconnects after a connection failure until (even) maxRetries is reached, at which point an event is emitted', (done) => { const client = new Client({ hostname: 'poo.signalk.org', port: 80, useTLS: false, maxRetries: 10, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) client.on('hitMaxRetries', () => { @@ -1359,14 +1374,14 @@ describe('Signal K SDK', () => { client.connect().catch(() => {}) }).timeout(60000) - it('... Emits an "error" event after a failed connection attempt', done => { + it('... Emits an "error" event after a failed connection attempt', (done) => { const client = new Client({ hostname: 'poo.signalk.org', port: 80, useTLS: false, reconnect: false, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) client.on('error', () => { @@ -1377,14 +1392,14 @@ describe('Signal K SDK', () => { client.connect().catch(() => {}) }).timeout(30000) - it('... Emits a "connect" event after successful connection to demo.signalk.org', done => { + it('... Emits a "connect" event after successful connection to demo.signalk.org', (done) => { const client = new Client({ hostname: 'demo.signalk.org', port: 80, useTLS: false, reconnect: false, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) client.on('connect', () => { @@ -1395,14 +1410,14 @@ describe('Signal K SDK', () => { client.connect() }).timeout(30000) - it('... Rejects the connect Promise after a failed connection attempt', done => { + it('... Rejects the connect Promise after a failed connection attempt', (done) => { const client = new Client({ hostname: 'poo.signalk.org', port: 80, useTLS: false, reconnect: false, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) client.connect().catch(() => { @@ -1411,14 +1426,14 @@ describe('Signal K SDK', () => { }) }).timeout(30000) - it('... Resolves the connect Promise after successful connection to demo.signalk.org', done => { + it('... Resolves the connect Promise after successful connection to demo.signalk.org', (done) => { const client = new Client({ hostname: 'demo.signalk.org', port: 80, useTLS: false, reconnect: false, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) client.connect().then(() => { @@ -1427,14 +1442,14 @@ describe('Signal K SDK', () => { }) }).timeout(30000) - it('... Gets server connection info after successful connection to demo.signalk.org', done => { + it('... Gets server connection info after successful connection to demo.signalk.org', (done) => { const client = new Client({ hostname: 'demo.signalk.org', port: 80, useTLS: false, reconnect: false, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) client.on('connectionInfo', () => { @@ -1445,50 +1460,43 @@ describe('Signal K SDK', () => { client.connect() }).timeout(15000) - it('... Gets vessel "self" MRN after successful connection to demo.signalk.org', done => { + it('... Gets vessel "self" MRN after successful connection to demo.signalk.org', (done) => { const client = new Client({ hostname: 'demo.signalk.org', port: 80, useTLS: false, reconnect: false, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) - client.on('self', self => { - assert( - self === - 'vessels.urn:mrn:signalk:uuid:c0d79334-4e25-4245-8892-54e8ccc8021d' - ) + client.on('self', (self) => { + assert(self === 'vessels.urn:mrn:signalk:uuid:c0d79334-4e25-4245-8892-54e8ccc8021d') done() }) client.connect() }).timeout(15000) - it('... Fails to get vessel in case of unauthenticated connection', done => { + it('... Fails to get vessel in case of unauthenticated connection', (done) => { const client = new Client({ hostname: TEST_SERVER_HOSTNAME, port: TEST_SERVER_PORT, useTLS: false, reconnect: false, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) client.on('connect', () => { client .API() - .then(api => api.self()) - .then(result => { - assert( - result && - typeof result === 'object' && - result.hasOwnProperty('uuid') - ) + .then((api) => api.self()) + .then((result) => { + assert(result && typeof result === 'object' && result.hasOwnProperty('uuid')) done(new Error("Got data when we shouldn't be authenticated")) }) - .catch(err => { + .catch((err) => { assert( err && typeof err === 'object' && @@ -1502,7 +1510,7 @@ describe('Signal K SDK', () => { client.connect() }).timeout(15000) - it('... Successfully authenticates with correct username/password', done => { + it('... Successfully authenticates with correct username/password', (done) => { const client = new Client({ hostname: TEST_SERVER_HOSTNAME, port: TEST_SERVER_PORT, @@ -1512,29 +1520,25 @@ describe('Signal K SDK', () => { password: PASSWORD, reconnect: false, notifications: false, - bearerTokenPrefix: BEARER_TOKEN_PREFIX + bearerTokenPrefix: BEARER_TOKEN_PREFIX, }) client.on('connect', () => { client .API() - .then(api => api.self()) - .then(result => { - assert( - result && - typeof result === 'object' && - result.hasOwnProperty('uuid') - ) + .then((api) => api.self()) + .then((result) => { + assert(result && typeof result === 'object' && result.hasOwnProperty('uuid')) done() }) - .catch(err => done(err)) + .catch((err) => done(err)) }) client.connect() }).timeout(15000) // */ - it('... Successfully re-connects after the remote server is restarted', done => { + it('... Successfully re-connects after the remote server is restarted', (done) => { const client = new Client({ hostname: TEST_SERVER_HOSTNAME, port: TEST_SERVER_PORT, @@ -1545,7 +1549,7 @@ describe('Signal K SDK', () => { reconnect: true, notifications: false, bearerTokenPrefix: BEARER_TOKEN_PREFIX, - maxRetries: Infinity + maxRetries: Infinity, }) let connectionCount = 0 @@ -1553,9 +1557,11 @@ describe('Signal K SDK', () => { client.on('connect', () => { connectionCount += 1 if (connectionCount === 1) { - killServer(() => setTimeout(() => { - startServer() - }, 100)) + killServer(() => + setTimeout(() => { + startServer() + }, 100) + ) } if (connectionCount === 2) { @@ -1565,7 +1571,7 @@ describe('Signal K SDK', () => { client.connect() }).timeout(15000) - + /* // @NOTE: // this test requires a manual restart of the test server,