diff --git a/README.md b/README.md index 7242ee3..8f158b7 100644 --- a/README.md +++ b/README.md @@ -137,10 +137,11 @@ DeviceHive module | [options.accessToken] | string | Access token | | [options.refreshToken] | string | Refresh token | | [options.login] | string | Login | -| [options.password] | string | Paaword | +| [options.password] | string | Password | | options.mainServiceURL | string | Main Service URL | | [options.authServiceURL] | string | Auth Service URL (required only for http) | -| [options.pluginServiceURL] | string | Alug inServi ceURL (required only for http) | +| [options.pluginServiceURL] | string | Plugin Service URL (required only for http) | +| [options.autoUpdateSession] | boolean | Flag to enable/disable autoupdating session. Default: true | @@ -2552,7 +2553,7 @@ Creates Plugin Update Query model | [options.returnCommands] | boolean | Checks if commands should be returned | | [options.returnUpdatedCommands] | boolean | Checks if updated commands should be returned | | [options.returnNotifications] | boolean | Checks if commands should be returned | -| [options.status] | string | Plugin status - active or disabled (ACTIVE | DISABLED | CREATED) | +| [options.status] | string | Plugin status - active or disabled (ACTIVE | INACTIVE | CREATED) | | [options.name] | string | Plugin name | | [options.description] | string | Plugin description | | [options.parameters] | string | Plugin parameters | @@ -2621,12 +2622,3 @@ Creates User List Query ### userListQuery.toObject() ⇒ Object Returns instance as a plain JS object - - - -## License - -[DeviceHive] is developed by [DataArt] Apps and distributed under Open Source -[Apache 2.0 license](https://en.wikipedia.org/wiki/Apache_License). - -© Copyright 2018 [DataArt] Apps © All Rights Reservedstrong text \ No newline at end of file diff --git a/example/node/index.js b/example/node/index.js index 31dc98d..9503faf 100644 --- a/example/node/index.js +++ b/example/node/index.js @@ -1,5 +1,6 @@ const DeviceHive = require(`../../index`); + const httpDeviceHive = new DeviceHive({ login: `dhadmin`, password: `dhadmin_#911`, @@ -11,7 +12,8 @@ const httpDeviceHive = new DeviceHive({ const wsDeviceHive = new DeviceHive({ login: `dhadmin`, password: `dhadmin_#911`, - mainServiceURL: 'ws://localhost:8080/dh/websocket' + mainServiceURL: 'ws://localhost:8080/dh/websocket', + autoUpdateSession: true }); const DeviceListQuery = DeviceHive.models.query.DeviceListQuery; @@ -48,7 +50,10 @@ void async function start () { console.log(await wsDeviceHive.network.list(networkListQuery)); console.log(await wsDeviceHive.token.refresh(refreshToken)); } + } catch (error) { console.warn(error); } + + process.exit(1); }(); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 8112900..50c6c3e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -687,6 +687,11 @@ "integrity": "sha1-FziZ0//Rx9k4PkR5Ul2+J4yrXys=", "dev": true }, + "array-uniq": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.2.tgz", + "integrity": "sha1-X8w3OSB3VyPP1k1lxkvvU7+eum0=" + }, "array-unique": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", @@ -851,9 +856,9 @@ } }, "babel-loader": { - "version": "8.0.0-beta.0", - "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.0-beta.0.tgz", - "integrity": "sha512-qVXXyIqTrLBH3Ki2VCJog1fUd6qzKUk9lHS34WJPW93Bh0BUvXTFSD5ZkG3a5+Uxxje+RgCk8Y7RyB6zyK9rWw==", + "version": "8.0.0-beta.2", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.0.0-beta.2.tgz", + "integrity": "sha512-P1zch1DvQy3RGmp/1CH78uPg5gTPQQ01S9r6ipCOWVamO0UIC8gnrx7m7LsUsXa470yB6IOZxhtEEwIUclRLNw==", "dev": true, "requires": { "find-cache-dir": "1.0.0", @@ -2267,7 +2272,7 @@ "dev": true, "requires": { "commondir": "1.0.1", - "make-dir": "1.1.0", + "make-dir": "1.2.0", "pkg-dir": "2.0.0" } }, @@ -2714,6 +2719,11 @@ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, + "jwt-decode": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-2.2.0.tgz", + "integrity": "sha1-fYa9VmefWM5qhHBKZX3TkruoGnk=" + }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -2813,20 +2823,12 @@ } }, "make-dir": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.1.0.tgz", - "integrity": "sha512-0Pkui4wLJ7rxvmfUvs87skoEaxmu0hCUApF8nonzpl7q//FWp9zu8W61Scz4sd/kUiqDxvUhtoam2efDyiBzcA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.2.0.tgz", + "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", "dev": true, "requires": { "pify": "3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } } }, "md5.js": { @@ -3282,6 +3284,12 @@ "sha.js": "2.4.10" } }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, "pkg-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", @@ -3422,6 +3430,14 @@ "safe-buffer": "5.1.1" } }, + "randomstring": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/randomstring/-/randomstring-1.1.5.tgz", + "integrity": "sha1-bfBij3XL1ZMpMNn+OrTpVqGFGMM=", + "requires": { + "array-uniq": "1.0.2" + } + }, "read-only-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-only-stream/-/read-only-stream-2.0.0.tgz", @@ -4109,14 +4125,13 @@ "dev": true }, "ws": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-4.0.0.tgz", - "integrity": "sha512-QYslsH44bH8O7/W2815u5DpnCpXWpEK44FmaHffNwgJI4JMaSZONgPBTOfrxJ29mXKbXak+LsJ2uAkDTYq2ptQ==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-4.1.0.tgz", + "integrity": "sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA==", "dev": true, "requires": { "async-limiter": "1.0.0", - "safe-buffer": "5.1.1", - "ultron": "1.1.1" + "safe-buffer": "5.1.1" } }, "xtend": { diff --git a/package.json b/package.json index ef7f6da..b55b983 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,9 @@ "main": "index.js", "scripts": { "build": "node build.js", - "test": "node_modules/.bin/mocha test/unit/**/**.spec.js --exit" + "test": "npm run unitTest & npm run integrationTest", + "unitTest": "node_modules/.bin/mocha test/unit/**/**.spec.js --exit", + "integrationTest": "node_modules/.bin/mocha test/integration/**/**.spec.js --timeout 10000 --exit" }, "repository": { "type": "git", @@ -15,7 +17,9 @@ "license": "Apache-2.0", "dependencies": { "isomorphic-fetch": "^2.2.1", + "jwt-decode": "^2.2.0", "query-string": "^5.1.0", + "randomstring": "^1.1.5", "string-template": "^1.0.0", "universal-websocket-client": "^1.0.1" }, @@ -23,13 +27,13 @@ "@babel/core": "^7.0.0-beta.40", "@babel/preset-env": "^7.0.0-beta.40", "babel-core": "^6.26.0", - "babel-loader": "^8.0.0-beta.0", + "babel-loader": "^8.0.0-beta.2", "babelify": "^8.0.0", "browserify": "^15.2.0", "chai": "^4.1.2", "exorcist": "^1.0.1", "mocha": "^5.0.1", "tinyify": "^2.4.0", - "ws": "^4.0.0" + "ws": "^4.1.0" } } diff --git a/src/ApiStrategy.js b/src/ApiStrategy.js index ec8db4e..4940406 100644 --- a/src/ApiStrategy.js +++ b/src/ApiStrategy.js @@ -20,9 +20,9 @@ class ApiStrategy extends EventEmitter { static getType(url) { let result; - if (url.startsWith('http') || url.startsWith('https')) { + if (url.startsWith(HTTP.TYPE)) { result = HTTP; - } else if (url.startsWith('ws') || url.startsWith('wss')) { + } else if (url.startsWith(WS.TYPE)) { result = WS; } else { throw new UnsupportedTransportError(); @@ -40,6 +40,8 @@ class ApiStrategy extends EventEmitter { const me = this; + me.reconnectionHandler = null; + me.urlsMap = new Map(); me.urlsMap.set(API.MAIN_BASE, mainServiceURL); @@ -48,7 +50,20 @@ class ApiStrategy extends EventEmitter { me.strategy = new (ApiStrategy.getType(mainServiceURL))({ mainServiceURL, authServiceURL, pluginServiceURL }); - me.strategy.on(`message`, (message) => { me.emit(`message`, message) }); + me.strategy.on(`message`, (message) => { + switch (me.strategy.type) { + case HTTP.TYPE: + me.emit(`message`, message); + break; + case WS.TYPE: + if (message.subscriptionId && message.action) { + me.emit(`message`, message[message.action.split(`/`)[0]]); + } else { + me.emit(`message`, message); + } + break; + } + }); } @@ -83,7 +98,25 @@ class ApiStrategy extends EventEmitter { } return me.strategy.send(sendData) - .then((response) => API.normalizeResponse(me.strategy.type, key, response)); + .then((response) => API.normalizeResponse(me.strategy.type, key, response)) + .catch(error => { + if (error === Utils.TOKEN_EXPIRED_MARK && me.reconnectionHandler) { + return me.reconnectionHandler() + .then(() => me.strategy.send(sendData)) + .then((response) => API.normalizeResponse(me.strategy.type, key, response)); + } else { + throw error; + } + }); + } + + /** + * Disconnects transport + */ + disconnect() { + const me = this; + + me.strategy.disconnect(); } } diff --git a/src/DeviceHive.js b/src/DeviceHive.js index 7cabbf2..82e3c5a 100644 --- a/src/DeviceHive.js +++ b/src/DeviceHive.js @@ -1,3 +1,4 @@ +const Utils = require(`./utils/Utils`); const EventEmitter = require('events'); const APIStrategy = require('./ApiStrategy'); const InfoAPI = require('./controllers/ServerInfoAPI'); @@ -98,7 +99,7 @@ class DeviceHive extends EventEmitter { * @param {string} [options.authServiceURL] - Auth Service URL (required only for http) * @param {string} [options.pluginServiceURL] - Alug inServi ceURL (required only for http) */ - constructor({ accessToken, refreshToken, login, password, mainServiceURL, authServiceURL, pluginServiceURL }) { + constructor({ mainServiceURL, authServiceURL, pluginServiceURL, accessToken, refreshToken, login, password, autoUpdateSession = true }) { super(); const me = this; @@ -107,6 +108,7 @@ class DeviceHive extends EventEmitter { me.refreshToken = refreshToken; me.login = login; me.password = password; + me.autoUpdateSession = autoUpdateSession; me.strategy = new APIStrategy({ mainServiceURL, authServiceURL, pluginServiceURL }); @@ -130,22 +132,48 @@ class DeviceHive extends EventEmitter { * Connect to the DeviceHive service * @returns {Promise} */ - async connect() { + async connect({ accessToken, refreshToken, login, password } = {}) { const me = this; - if (me.accessToken || me.refreshToken || (me.login && me.password)) { + if (!accessToken && !refreshToken && !(login && password)) { + accessToken = accessToken || me.accessToken; + refreshToken = refreshToken || me.refreshToken; + login = login || me.login; + password = password || me.password; + } + + if (accessToken || refreshToken || (login && password)) { try { - if (me.accessToken) { - await me.strategy.authorize(me.accessToken); - } else if (me.refreshToken) { - const accessToken = await me.token.refresh(me.refreshToken); + if (login && password) { + const { accessToken, refreshToken } = await me.token.login(login, password); + await me.strategy.authorize(accessToken); - } else if (me.login && me.password) { - const { accessToken } = await me.token.login(me.login, me.password); + + me.accessToken = accessToken; + me.refreshToken = refreshToken; + } else if (refreshToken) { + const { accessToken } = await me.token.refresh(refreshToken); + await me.strategy.authorize(accessToken); + + me.accessToken = accessToken; + me.refreshToken = refreshToken; + } else if (accessToken) { + await me.strategy.authorize(accessToken); + + me.accessToken = accessToken; + } + + if (me.autoUpdateSession === true) { + const userTokens = await me.token.createUserToken( + Utils.createUserTokenFromJWT(me.accessToken)); + + me.accessToken = userTokens.accessToken; + me.refreshToken = userTokens.refreshToken; + me.strategy.reconnectionHandler = () => me.connect({ refreshToken: me.refreshToken }); } } catch (error) { - throw new InvalidCredentialsError(); + throw new InvalidCredentialsError(error); } } else { throw new NoAuthCredentialsError(); @@ -153,6 +181,16 @@ class DeviceHive extends EventEmitter { return me; } + + /** + * Disconnects from DeviceHive server + * @returns {*|void} + */ + disconnect() { + const me = this; + + return me.strategy.disconnect(); + } } diff --git a/src/controllers/transportResolvers/ApiMap.js b/src/controllers/transportResolvers/ApiMap.js index 56138d1..25bf7f5 100644 --- a/src/controllers/transportResolvers/ApiMap.js +++ b/src/controllers/transportResolvers/ApiMap.js @@ -156,15 +156,15 @@ class ApiMap { } -apiMap.set(ApiMap.login, { http: { method: 'POST', uri: '/token', base: ApiMap.AUTH_BASE }, ws: { action: 'token', response: [`accessToken`, `refreshToken`] } }); +apiMap.set(ApiMap.login, { http: { method: 'POST', uri: '/token', base: ApiMap.AUTH_BASE, noAuth: true }, ws: { action: 'token', response: [`accessToken`, `refreshToken`] } }); apiMap.set(ApiMap.createUserToken, { http: { method: 'POST', uri: '/token/create', base: ApiMap.AUTH_BASE }, ws: { action: 'token/create', bodyKey: 'payload', response: [`accessToken`, `refreshToken`] } }); apiMap.set(ApiMap.createPluginToken, { http: { method: 'POST', uri: '/token/plugin/create', base: ApiMap.AUTH_BASE } }); -apiMap.set(ApiMap.refreshToken, { http: { method: 'POST', uri: '/token/refresh', base: ApiMap.AUTH_BASE }, ws: { action: 'token/refresh', response: [`accessToken`] } }); +apiMap.set(ApiMap.refreshToken, { http: { method: 'POST', uri: '/token/refresh', base: ApiMap.AUTH_BASE, noAuth: true }, ws: { action: 'token/refresh', response: [`accessToken`] } }); apiMap.set(ApiMap.authenticatePlugin, { http: { method: 'GET', uri: '/token/plugin/authenticate', base: ApiMap.AUTH_BASE } }); -apiMap.set(ApiMap.getServerInfo, { http: { method: 'GET', uri: '/info', base: ApiMap.MAIN_BASE }, ws: { action: 'server/info', response: { bodyKey: `info` } } }); -apiMap.set(ApiMap.getCacheInfo, { http: { method: 'GET', uri: '/info/cache', base: ApiMap.MAIN_BASE } }); -apiMap.set(ApiMap.getClusterInfo, { http: { method: 'GET', uri: '/info/config/cluster', base: ApiMap.MAIN_BASE }, ws: { action: 'cluster/info', response: { bodyKey: `clusterInfo` } } }); +apiMap.set(ApiMap.getServerInfo, { http: { method: 'GET', uri: '/info', base: ApiMap.MAIN_BASE, noAuth: true }, ws: { action: 'server/info', response: { bodyKey: `info` } } }); +apiMap.set(ApiMap.getCacheInfo, { http: { method: 'GET', uri: '/info/cache', base: ApiMap.MAIN_BASE, noAuth: true } }); +apiMap.set(ApiMap.getClusterInfo, { http: { method: 'GET', uri: '/info/config/cluster', base: ApiMap.MAIN_BASE, noAuth: true }, ws: { action: 'cluster/info', response: { bodyKey: `clusterInfo` } } }); apiMap.set(ApiMap.getConfiguration, { http: { method: 'GET', uri: '/configuration/{name}', base: ApiMap.MAIN_BASE }, ws: { action: 'configuration/get', response: { bodyKey: `configuration` } } }); apiMap.set(ApiMap.putConfiguration, { http: { method: 'PUT', uri: '/configuration/{name}', base: ApiMap.MAIN_BASE }, ws: { action: 'configuration/put', response: { bodyKey: `configuration` } } }); diff --git a/src/controllers/transportResolvers/HttpApiResolver.js b/src/controllers/transportResolvers/HttpApiResolver.js index c91e02a..26c1213 100644 --- a/src/controllers/transportResolvers/HttpApiResolver.js +++ b/src/controllers/transportResolvers/HttpApiResolver.js @@ -13,9 +13,22 @@ class HttpApiResolver { * @param {object} parameters - URI parameters * @returns {string} */ - static buildUrl(base, parameters) { - const stringParameters = queryString.stringify(parameters); - const url = format(base, parameters); + static buildUrl(base, parameters = {}) { + // console.log(base, parameters); + const pathRegex = /[^{}]+(?=\})/g; + const pathParameterKeys = pathRegex.test(base) ? base.match(pathRegex) : []; + const pathParameters = {}; + const queryParameters = {}; + Object.keys(parameters).forEach(key => { + if (pathParameterKeys.includes(key)) { + pathParameters[key] = parameters[key]; + } else { + queryParameters[key] = parameters[key]; + } + }); + + const stringParameters = queryString.stringify(queryParameters); + const url = format(base, pathParameters); return stringParameters ? `${url}?${stringParameters}` : url; } @@ -41,7 +54,7 @@ class HttpApiResolver { * @param {boolean} options.subscription * @param {boolean} options.unsubscription */ - constructor({ method, uri, base, subscription, unsubscription }) { + constructor({ method, uri, base, subscription, unsubscription, noAuth }) { const me = this; me.method = method; @@ -49,6 +62,7 @@ class HttpApiResolver { me.base = base; me.subscription = subscription; me.unsubscription = unsubscription; + me.noAuth = noAuth; } /** @@ -63,6 +77,7 @@ class HttpApiResolver { if (me.unsubscription === true) { result = { + noAuth: me.noAuth, unsubscription: me.unsubscription, body: { subscriptionId: parameters.subscriptionId @@ -70,6 +85,7 @@ class HttpApiResolver { }; } else { result = { + noAuth: me.noAuth, method: me.method, endpoint: HttpApiResolver.buildUrl(me.uri, parameters), base: me.base, diff --git a/src/error/InvalidCredentialsError.js b/src/error/InvalidCredentialsError.js index d0fd1d6..a93f4a6 100644 --- a/src/error/InvalidCredentialsError.js +++ b/src/error/InvalidCredentialsError.js @@ -6,10 +6,10 @@ class InvalidCredentialsError extends Error { /** * Creates new InvalidCredentialsError */ - constructor() { + constructor(message) { super(); - this.message = `Invalid credentials error during attempt to authenticate.`; + this.message = `Invalid credentials error during attempt to authenticate. Error: ${message}`; } } diff --git a/src/models/Configuration.js b/src/models/Configuration.js index fb67d27..fd124b7 100644 --- a/src/models/Configuration.js +++ b/src/models/Configuration.js @@ -11,14 +11,12 @@ class Configuration extends BaseModel { * @param {Object} options - model options object * @param {string} options.name - Configuration parameter name. * @param {string} options.value - Configuration parameter value. - * @param {number} options.entityVersion - Specifies the version field or property of an entity class. */ constructor({ name, value, entityVersion } = {}) { super(); this.name = name; this.value = value; - this.entityVersion = entityVersion; } get name() { @@ -37,14 +35,6 @@ class Configuration extends BaseModel { this._value = value; } - get entityVersion() { - return this._entityVersion; - } - - set entityVersion(value) { - this._entityVersion = value; - } - /** * Returns instance as a plain JS object * @returns {Object} diff --git a/src/models/Device.js b/src/models/Device.js index f9eb193..0d29a94 100644 --- a/src/models/Device.js +++ b/src/models/Device.js @@ -14,9 +14,9 @@ class Device extends BaseModel { * @param {object} options.data - Device data, a JSON object with an arbitrary structure * @param {number} options.networkId - Associated network id * @param {number} options.deviceTypeId - Associated deviceType id - * @param {boolean} options.blocked - Indicates whether device is blocked + * @param {boolean} options.isBlocked - Indicates whether device is isBlocked */ - constructor({ id, name, data, networkId, deviceTypeId, blocked } = {}) { + constructor({ id, name, data, networkId, deviceTypeId, isBlocked } = {}) { super(); this.id = id; @@ -24,7 +24,7 @@ class Device extends BaseModel { this.data = data; this.networkId = networkId; this.deviceTypeId = deviceTypeId; - this.blocked = blocked; + this.isBlocked = isBlocked; } get id() { @@ -67,12 +67,12 @@ class Device extends BaseModel { this._deviceTypeId = value; } - get blocked() { - return this._blocked; + get isBlocked() { + return this._isBlocked; } - set blocked(value) { - this._blocked = value; + set isBlocked(value) { + this._isBlocked = value; } /** @@ -86,7 +86,7 @@ class Device extends BaseModel { data: this.data, networkId: this.networkId, deviceTypeId: this.deviceTypeId, - blocked: this.blocked + isBlocked: this.isBlocked }; } } diff --git a/src/models/query/NotificationListQuery.js b/src/models/query/NotificationListQuery.js index 8fdc3ba..01ac544 100644 --- a/src/models/query/NotificationListQuery.js +++ b/src/models/query/NotificationListQuery.js @@ -13,20 +13,18 @@ class NotificationListQuery extends BaseModel { * @param {string} options.start - Start timestamp * @param {string} options.end - End timestamp * @param {string} options.notification - Notification name - * @param {string} options.status - Command status * @param {string} options.sortField - Sort field * @param {string} options.sortOrder - Sort order * @param {number} options.take - Limit param * @param {number} options.skip - Skip param */ - constructor({ deviceId, start, end, notification, status, sortField, sortOrder, take, skip } = {}) { + constructor({ deviceId, start, end, notification, sortField, sortOrder, take, skip } = {}) { super(); this.deviceId = deviceId; this.start = start; this.end = end; this.notification = notification; - this.status = status; this.sortField = sortField; this.sortOrder = sortOrder; this.take = take; @@ -65,14 +63,6 @@ class NotificationListQuery extends BaseModel { this._notification = value; } - get status() { - return this._status; - } - - set status(value) { - this._status = value; - } - get sortField() { return this._sortField; } @@ -115,7 +105,6 @@ class NotificationListQuery extends BaseModel { start: this.start, end: this.end, notification: this.notification, - status: this.status, sortField: this.sortField, sortOrder: this.sortOrder, take: this.take, diff --git a/src/models/query/PluginRegisterQuery.js b/src/models/query/PluginRegisterQuery.js index a485b62..29c5b59 100644 --- a/src/models/query/PluginRegisterQuery.js +++ b/src/models/query/PluginRegisterQuery.js @@ -17,9 +17,8 @@ class PluginRegisterQuery extends BaseModel { * @param {boolean} [options.returnUpdatedCommands] - Checks if updated commands should be returned * @param {boolean} [options.returnNotifications] - Checks if commands should be returned */ - constructor({ deviceId, networkIds, deviceTypeIds, names, returnCommands, returnUpdatedCommands, returnNotifications } = {}) { + constructor({ deviceId, networkIds, deviceTypeIds, names, returnCommands = true, returnUpdatedCommands = false, returnNotifications = false } = {}) { super(); - this.deviceId = deviceId; this.networkIds = networkIds; this.deviceTypeIds = deviceTypeIds; diff --git a/src/transports/HTTP.js b/src/transports/HTTP.js index 058c55d..cba6109 100644 --- a/src/transports/HTTP.js +++ b/src/transports/HTTP.js @@ -37,7 +37,7 @@ class HTTP extends Transport { /** * Rest API send method */ - send({ endpoint, method, body, subscription, unsubscription }) { + send({ endpoint, method, body, subscription, unsubscription, noAuth }) { const me = this; if (subscription === true) { @@ -62,7 +62,7 @@ class HTTP extends Transport { return Promise.resolve({ status: `No such subscription` }) } } else { - return fetch(endpoint, { headers: me._getHeaders(), method: method, body: JSON.stringify(body) }) + return fetch(endpoint, { headers: me._getHeaders(noAuth), method: method, body: JSON.stringify(body) }) .then(response => response.text()) .then(responseText => { return responseText ? JSON.parse(responseText) : responseText @@ -110,19 +110,28 @@ class HTTP extends Transport { * @returns {Object} * @private */ - _getHeaders() { + _getHeaders(noAuth = false) { const me = this; const headers = { "Content-type": `application/json`, "Accept": `application/json` }; - if (me.token) { - headers[`Authorization`] = `Bearer ${me.token}`; + if (me.token && !noAuth) { + headers.Authorization = `Bearer ${me.token}`; } return headers; } + + /** + * Disconnects HTTP transport + */ + disconnect() { + const me = this; + + me.token= ``; + } } diff --git a/src/transports/WS.js b/src/transports/WS.js index 2e88f24..4c6b792 100644 --- a/src/transports/WS.js +++ b/src/transports/WS.js @@ -98,6 +98,15 @@ class WS extends Transport { }); }); } + + /** + * Disconnects WS transport + */ + disconnect() { + const me = this; + + me.socket.close(); + } } diff --git a/src/transports/base/Transport.js b/src/transports/base/Transport.js index 0d832af..1e06051 100644 --- a/src/transports/base/Transport.js +++ b/src/transports/base/Transport.js @@ -20,6 +20,13 @@ class Transport extends EventEmitter { send() { console.warn(`Method "send" should be implemented in nested classes`); } + + /** + * Disconnects transport + */ + disconnect() { + console.warn(`Method "disconnect" should be implemented in nested classes`); + } } diff --git a/src/utils/Utils.js b/src/utils/Utils.js index 7f99d1b..102e21c 100644 --- a/src/utils/Utils.js +++ b/src/utils/Utils.js @@ -1,8 +1,14 @@ +const jwtDecode = require(`jwt-decode`); +const UserToken = require(`../models/UserToken`); + + /** * Utils */ class Utils { + static get TOKEN_EXPIRED_MARK() { return `Token expired`; } + /** * Checks that object is empty * @returns {boolean} - Is object empty @@ -25,6 +31,22 @@ class Utils { return `${firstPart}${secondPart}`; } + + /** + * Creates UserToken from jwt + * @param jwtToken + * @returns {UserToken} + */ + static createUserTokenFromJWT(jwtToken) { + const tokenPayload = jwtDecode(jwtToken).payload; + + return new UserToken({ + userId: tokenPayload.u, + actions: tokenPayload.a, + networkIds: tokenPayload.n, + deviceTypeIds: tokenPayload.dt + }); + } } diff --git a/test/integration/config.json b/test/integration/config.json new file mode 100644 index 0000000..5711a14 --- /dev/null +++ b/test/integration/config.json @@ -0,0 +1,19 @@ +{ + "TEST_USER_ID": 1, + "TEST_USER_LOGIN": "dhadmin", + "TEST_USER_PASSWORD": "dhadmin_#911", + "server": { + "http": { + "login": "dhadmin", + "password": "dhadmin_#911", + "mainServiceURL": "http://localhost:8080/dh/rest", + "authServiceURL": "http://localhost:8090/dh/rest", + "pluginServiceURL": "http://localhost:8110/dh/rest" + }, + "ws": { + "login": "dhadmin", + "password": "dhadmin_#911", + "mainServiceURL": "ws://localhost:8080/dh/websocket" + } + } +} \ No newline at end of file diff --git a/test/integration/controllers/ConfigurationAPI.spec.js b/test/integration/controllers/ConfigurationAPI.spec.js new file mode 100644 index 0000000..2d9d7dc --- /dev/null +++ b/test/integration/controllers/ConfigurationAPI.spec.js @@ -0,0 +1,97 @@ +const chai = require(`chai`); +const assert = chai.assert; +const config = require('../config'); +const DeviceHive = require('../../../index'); +const Configuration = DeviceHive.models.Configuration; + +const httpDeviceHive = new DeviceHive(config.server.http); +const wsDeviceHive = new DeviceHive(config.server.ws); + + +const TEST_CONFIGURATIONS = { + HTTP: { + name: `myTestConfigurationName-HTTP}`, + value: `myTestConfigurationValue-HTTP}` + }, + WS: { + name: `myTestConfigurationName-WS}`, + value: `myTestConfigurationValue-WS}` + } +}; + +describe('ConfigurationAPI', () => { + + before(done => { + Promise.all([httpDeviceHive.connect(), wsDeviceHive.connect()]) + .then(() => done()); + }); + + it(`should add new configuration with name ${TEST_CONFIGURATIONS.HTTP.name} and value ${TEST_CONFIGURATIONS.HTTP.value} via HTTP`, (done) => { + const configurationModel = new Configuration(TEST_CONFIGURATIONS.HTTP); + + httpDeviceHive.configuration.put(configurationModel) + .then(() => done()) + .catch(done); + }); + + it(`should add new configuration with name ${TEST_CONFIGURATIONS.WS.name} and value ${TEST_CONFIGURATIONS.WS.value} via WS`, (done) => { + const configurationModel = new Configuration(TEST_CONFIGURATIONS.WS); + + wsDeviceHive.configuration.put(configurationModel) + .then(() => done()) + .catch(done); + }); + + it(`should get configuration with name ${TEST_CONFIGURATIONS.HTTP.name} and value ${TEST_CONFIGURATIONS.HTTP.value} via HTTP`, done => { + httpDeviceHive.configuration.get(TEST_CONFIGURATIONS.HTTP.name) + .then(configuration => { + assert.isObject(configuration); + assert.equal(configuration.name, TEST_CONFIGURATIONS.HTTP.name); + assert.equal(configuration.value, TEST_CONFIGURATIONS.HTTP.value); + }) + .then(() => done()) + .catch(done); + }); + + it(`should get configuration with name ${TEST_CONFIGURATIONS.WS.name} and value ${TEST_CONFIGURATIONS.WS.value} via WS`, done => { + wsDeviceHive.configuration.get(TEST_CONFIGURATIONS.WS.name) + .then(configuration => { + assert.isObject(configuration); + assert.equal(configuration.name, TEST_CONFIGURATIONS.WS.name); + assert.equal(configuration.value, TEST_CONFIGURATIONS.WS.value); + }) + .then(() => done()) + .catch(done); + }); + + it(`should delete configuration with name ${TEST_CONFIGURATIONS.HTTP.name} and value ${TEST_CONFIGURATIONS.HTTP.value} via HTTP`, done => { + httpDeviceHive.configuration.delete(TEST_CONFIGURATIONS.HTTP.name) + .then(() => done()) + .catch(done); + }); + + it(`should delete configuration with name ${TEST_CONFIGURATIONS.WS.name} and value ${TEST_CONFIGURATIONS.WS.value} via WS`, done => { + wsDeviceHive.configuration.delete(TEST_CONFIGURATIONS.WS.name) + .then(() => done()) + .catch(done); + }); + + it(`should not get configuration with name ${TEST_CONFIGURATIONS.HTTP.name} and value ${TEST_CONFIGURATIONS.HTTP.value} via HTTP`, done => { + httpDeviceHive.configuration.get(TEST_CONFIGURATIONS.HTTP.name) + .then(() => done(new Error(`Configuration exists after deletion`))) + .catch(() => done()); + }); + + it(`should not get configuration with name ${TEST_CONFIGURATIONS.WS.name} and value ${TEST_CONFIGURATIONS.WS.value} via WS`, done => { + wsDeviceHive.configuration.get(TEST_CONFIGURATIONS.WS.name) + .then(() => done(new Error(`Configuration exists after deletion`))) + .catch(() => done()); + }); + + after(done => { + httpDeviceHive.disconnect(); + wsDeviceHive.disconnect(); + + done(); + }); +}); \ No newline at end of file diff --git a/test/integration/controllers/Device.spec.js b/test/integration/controllers/Device.spec.js new file mode 100644 index 0000000..7f349f3 --- /dev/null +++ b/test/integration/controllers/Device.spec.js @@ -0,0 +1,142 @@ +const chai = require(`chai`); +const assert = chai.assert; +const config = require('../config'); +const DeviceHive = require('../../../index'); +const Device = DeviceHive.models.Device; +const DeviceListQuery = DeviceHive.models.query.DeviceListQuery; + +const httpDeviceHive = new DeviceHive(config.server.http); +const wsDeviceHive = new DeviceHive(config.server.ws); + + +const TEST_DEVICE_ID_PREFIX = `DH-JS-LIB-DEVICE-ID-`; +const TEST_DEVICE_NAME_PREFIX = `DH-JS-LIB-DEVICE-NAME-`; +const TEST_DEVICES = { + HTTP: { + id: `${TEST_DEVICE_ID_PREFIX}HTTP`, + name: `${TEST_DEVICE_NAME_PREFIX}HTTP`, + networkId: 1, + deviceTypeId: 1, + isBlocked: false, + data: {} + }, + WS: { + id: `${TEST_DEVICE_ID_PREFIX}WS`, + name: `${TEST_DEVICE_NAME_PREFIX}WS`, + networkId: 1, + deviceTypeId: 1, + isBlocked: false, + data: {} + } +}; + +describe('DeviceAPI', () => { + + before(done => { + Promise.all([httpDeviceHive.connect(), wsDeviceHive.connect()]) + .then(() => done()); + }); + + it(`should add new device with next configuration: ${JSON.stringify(TEST_DEVICES.HTTP)} via HTTP`, done => { + const deviceModel = new Device(TEST_DEVICES.HTTP); + + httpDeviceHive.device.add(deviceModel) + .then(() => done()) + .catch(done); + }); + + it(`should add new device with next configuration: ${JSON.stringify(TEST_DEVICES.WS)} via WS`, done => { + const deviceModel = new Device(TEST_DEVICES.WS); + + wsDeviceHive.device.add(deviceModel) + .then(() => done()) + .catch(done); + }); + + it(`should get device with next configuration: ${JSON.stringify(TEST_DEVICES.HTTP)} via HTTP`, done => { + httpDeviceHive.device.get(TEST_DEVICES.HTTP.id) + .then(device => { + assert.isObject(device); + assert.deepEqual(device, TEST_DEVICES.HTTP); + }) + .then(() => done()) + .catch(done); + }); + + it(`should get device with next configuration: ${JSON.stringify(TEST_DEVICES.WS)} via WS`, done => { + wsDeviceHive.device.get(TEST_DEVICES.WS.id) + .then(device => { + assert.isObject(device); + assert.deepEqual(device, TEST_DEVICES.WS); + }) + .then(() => done()) + .catch(done); + }); + + it(`should list all devices with the next name pattern "${TEST_DEVICE_NAME_PREFIX}%" via HTTP`, done => { + const deviceListQuery = new DeviceListQuery({ namePattern: `${TEST_DEVICE_NAME_PREFIX}%` }); + + httpDeviceHive.device.list(deviceListQuery) + .then(devices => { + assert.equal(devices.length, Object.keys(TEST_DEVICES).length); + }) + .then(() => done()) + .catch(done); + }); + + it(`should list all devices with the next name pattern "${TEST_DEVICE_NAME_PREFIX}%" via WS`, done => { + const deviceListQuery = new DeviceListQuery({ namePattern: `${TEST_DEVICE_NAME_PREFIX}%` }); + + wsDeviceHive.device.list(deviceListQuery) + .then(devices => { + assert.equal(devices.length, Object.keys(TEST_DEVICES).length); + }) + .then(() => done()) + .catch(done); + }); + + it(`should count devices with the next name pattern "${TEST_DEVICE_NAME_PREFIX}%" via HTTP`, done => { + const deviceListQuery = new DeviceListQuery({ namePattern: `${TEST_DEVICE_NAME_PREFIX}%` }); + + httpDeviceHive.device.count(deviceListQuery) + .then(response => { + assert.equal(response.count, Object.keys(TEST_DEVICES).length); + }) + .then(done) + .catch(done); + }); + + it(`should count devices with the next name pattern "${TEST_DEVICE_NAME_PREFIX}%" via WS`, done => { + const deviceListQuery = new DeviceListQuery({ namePattern: `${TEST_DEVICE_NAME_PREFIX}%` }); + + wsDeviceHive.device.count(deviceListQuery) + .then(response => { + assert.equal(response.count, Object.keys(TEST_DEVICES).length); + }) + .then(done) + .catch(done); + }); + + it(`should delete device with next configuration: ${JSON.stringify(TEST_DEVICES.HTTP)} via HTTP`, done => { + const deviceModel = new Device(TEST_DEVICES.HTTP); + + httpDeviceHive.device.delete(deviceModel.id) + .then(() => done()) + .catch(done); + }); + + it(`should delete device with next configuration: ${JSON.stringify(TEST_DEVICES.WS)} via WS`, done => { + const deviceModel = new Device(TEST_DEVICES.WS); + + wsDeviceHive.device.delete(deviceModel.id) + .then(() => done()) + .catch(done); + }); + + after(done => { + httpDeviceHive.disconnect(); + wsDeviceHive.disconnect(); + + done(); + }); +}); \ No newline at end of file diff --git a/test/integration/controllers/DeviceCommandAPI.spec.js b/test/integration/controllers/DeviceCommandAPI.spec.js new file mode 100644 index 0000000..6e5d353 --- /dev/null +++ b/test/integration/controllers/DeviceCommandAPI.spec.js @@ -0,0 +1,317 @@ +const randomString = require(`randomstring`); +const chai = require(`chai`); +const assert = chai.assert; +const config = require('../config'); +const DeviceHive = require('../../../index'); +const Device = DeviceHive.models.Device; +const Command = DeviceHive.models.Command; +const CommandListQuery = DeviceHive.models.query.CommandListQuery; +const CommandPollQuery = DeviceHive.models.query.CommandPollQuery; +const CommandPollManyQuery = DeviceHive.models.query.CommandPollManyQuery; +const CommandWaitQuery = DeviceHive.models.query.CommandWaitQuery; + +const httpDeviceHive = new DeviceHive(config.server.http); +const wsDeviceHive = new DeviceHive(config.server.ws); + + +const TIMESTAMP = new Date().toISOString(); +const DH_COMMANDS_TEST_DEVICE = { + id: randomString.generate(), + name: `DH_COMMANDS_TEST_DEVICE`, + networkId: 1, + deviceTypeId: 1, + isBlocked: false, + data: {} +}; +const TEST_DEVICE_COMMANDS = { + HTTP: { + deviceId: DH_COMMANDS_TEST_DEVICE.id, + command: `command-${randomString.generate()}`, + timestamp: TIMESTAMP, + userId: 1, + networkId: 1, + deviceTypeId: 1, + parameters: { + jsonString: 'jsonString' + }, + lifetime: 0, + status: 'status', + result: { + jsonString: 'jsonString' + } + }, + WS: { + deviceId: DH_COMMANDS_TEST_DEVICE.id, + command: `command-${randomString.generate()}`, + timestamp: TIMESTAMP, + userId: 1, + networkId: 1, + deviceTypeId: 1, + parameters: { + jsonString: 'jsonString' + }, + lifetime: 0, + status: 'status', + result: { + jsonString: 'jsonString' + } + } +}; + +describe('DeviceCommandAPI', () => { + + before(done => { + Promise.all([httpDeviceHive.connect(), wsDeviceHive.connect()]) + .then(() => httpDeviceHive.device.add(new Device(DH_COMMANDS_TEST_DEVICE))) + .then(() => done()) + .catch(done); + }); + + it(`should insert new command with name ${TEST_DEVICE_COMMANDS.HTTP.command} via HTTP`, done => { + const commandModel = new Command(TEST_DEVICE_COMMANDS.HTTP); + + httpDeviceHive.command.insert(DH_COMMANDS_TEST_DEVICE.id, commandModel) + .then((commandResponse) => { + TEST_DEVICE_COMMANDS.HTTP.id = commandResponse.id; + + done(); + }) + .catch(done); + }); + + it(`should insert new command with name ${TEST_DEVICE_COMMANDS.WS.command} via WS`, done => { + const commandModel = new Command(TEST_DEVICE_COMMANDS.WS); + + wsDeviceHive.command.insert(DH_COMMANDS_TEST_DEVICE.id, commandModel) + .then((commandResponse) => { + TEST_DEVICE_COMMANDS.WS.id = commandResponse.id; + + done(); + }) + .catch(done); + }); + + it(`should list all commands for device with id ${DH_COMMANDS_TEST_DEVICE.id} via HTTP`, done => { + const commandListQuery = new CommandListQuery({ + deviceId: DH_COMMANDS_TEST_DEVICE.id + }); + + httpDeviceHive.command.list(commandListQuery) + .then(commands => { + assert.equal(commands.length, Object.keys(TEST_DEVICE_COMMANDS).length); + }) + .then(() => done()) + .catch(done); + }); + + it(`should list all commands for device with id ${DH_COMMANDS_TEST_DEVICE.id} via WS`, done => { + const commandListQuery = new CommandListQuery({ + deviceId: DH_COMMANDS_TEST_DEVICE.id + }); + + wsDeviceHive.command.list(commandListQuery) + .then(commands => { + assert.equal(commands.length, Object.keys(TEST_DEVICE_COMMANDS).length); + }) + .then(() => done()) + .catch(done); + }); + + it(`should get command with id ${TEST_DEVICE_COMMANDS.HTTP.id} for device with id ${DH_COMMANDS_TEST_DEVICE.id} via HTTP`, done => { + httpDeviceHive.command.get(DH_COMMANDS_TEST_DEVICE.id, TEST_DEVICE_COMMANDS.HTTP.id) + .then(command => { + assert.equal(command.id, TEST_DEVICE_COMMANDS.HTTP.id); + }) + .then(done) + .catch(done); + }); + + it(`should get command with id ${TEST_DEVICE_COMMANDS.WS.id} for device with id ${DH_COMMANDS_TEST_DEVICE.id} via WS`, done => { + wsDeviceHive.command.get(DH_COMMANDS_TEST_DEVICE.id, TEST_DEVICE_COMMANDS.WS.id) + .then(command => { + assert.equal(command.id, TEST_DEVICE_COMMANDS.WS.id); + }) + .then(done) + .catch(done); + }); + + it(`should update command with id ${TEST_DEVICE_COMMANDS.HTTP.id} for device with id ${DH_COMMANDS_TEST_DEVICE.id} via HTTP`, done => { + TEST_DEVICE_COMMANDS.HTTP.status = `status-${randomString.generate()}`; + + const commandModel = new Command(TEST_DEVICE_COMMANDS.HTTP); + + httpDeviceHive.command.update(commandModel) + .then(() => httpDeviceHive.command.get(DH_COMMANDS_TEST_DEVICE.id, TEST_DEVICE_COMMANDS.HTTP.id)) + .then((command) => { + assert.equal(command.status, TEST_DEVICE_COMMANDS.HTTP.status); + + done(); + }) + .catch(done); + }); + + it(`should update command with id ${TEST_DEVICE_COMMANDS.HTTP.id} for device with id ${DH_COMMANDS_TEST_DEVICE.id} via WS`, done => { + TEST_DEVICE_COMMANDS.WS.status = `status-${randomString.generate()}`; + + const commandModel = new Command(TEST_DEVICE_COMMANDS.WS); + + wsDeviceHive.command.update(commandModel) + .then(() => wsDeviceHive.command.get(DH_COMMANDS_TEST_DEVICE.id, TEST_DEVICE_COMMANDS.WS.id)) + .then((command) => { + assert.equal(command.status, TEST_DEVICE_COMMANDS.WS.status); + + done(); + }) + .catch(done); + }); + + it(`should poll new command for device with id ${DH_COMMANDS_TEST_DEVICE.id} via HTTP`, done => { + const commandPollQuery = new CommandPollQuery({ + deviceId: DH_COMMANDS_TEST_DEVICE.id, + waitTimeout: 1 + }); + + httpDeviceHive.command.poll(commandPollQuery) + .then((commands) => { + assert.equal(commands.length, 1); + assert.equal(commands[0].command, TEST_DEVICE_COMMANDS.HTTP.command); + + TEST_DEVICE_COMMANDS.HTTP.id = commands[0].id; + done(); + }) + .catch(done); + + setTimeout(() => { + TEST_DEVICE_COMMANDS.HTTP.command = `command-${randomString.generate()}`; + httpDeviceHive.command.insert(DH_COMMANDS_TEST_DEVICE.id, new Command(TEST_DEVICE_COMMANDS.HTTP)); + }, 100); + }); + + it(`should poll command update for device with id ${DH_COMMANDS_TEST_DEVICE.id} via HTTP`, done => { + const commandPollQuery = new CommandPollQuery({ + deviceId: DH_COMMANDS_TEST_DEVICE.id, + returnUpdatedCommands: true, + waitTimeout: 1 + }); + + httpDeviceHive.command.poll(commandPollQuery) + .then((commands) => { + assert.equal(commands.length, 1); + assert.equal(commands[0].command, TEST_DEVICE_COMMANDS.HTTP.command); + assert.equal(commands[0].status, TEST_DEVICE_COMMANDS.HTTP.status); + + TEST_DEVICE_COMMANDS.HTTP.id = commands[0].id; + done(); + }) + .catch(done); + + setTimeout(() => { + TEST_DEVICE_COMMANDS.HTTP.status = `status-${randomString.generate()}`; + httpDeviceHive.command.update(new Command(TEST_DEVICE_COMMANDS.HTTP)); + }, 100); + }); + + it(`should poll new command for network with id ${DH_COMMANDS_TEST_DEVICE.networkId} via HTTP`, done => { + const commandPollManyQuery = new CommandPollManyQuery({ + networkIds: [ DH_COMMANDS_TEST_DEVICE.networkId ], + waitTimeout: 1 + }); + + httpDeviceHive.command.pollMany(commandPollManyQuery) + .then((commands) => { + assert.equal(commands.length, 1); + assert.equal(commands[0].command, TEST_DEVICE_COMMANDS.HTTP.command); + + done(); + }) + .catch(done); + + setTimeout(() => { + TEST_DEVICE_COMMANDS.HTTP.command = `command-${randomString.generate()}`; + httpDeviceHive.command.insert(DH_COMMANDS_TEST_DEVICE.id, new Command(TEST_DEVICE_COMMANDS.HTTP)); + }, 100); + }); + + it(`should wait while command will be processed by device with id ${DH_COMMANDS_TEST_DEVICE.id}`, done => { + const commandWaitQuery = new CommandWaitQuery({ waitTimeout: 1 }); + + httpDeviceHive.command.wait(DH_COMMANDS_TEST_DEVICE.id, TEST_DEVICE_COMMANDS.HTTP.id, commandWaitQuery) + .then((command) => { + assert.equal(command.status, TEST_DEVICE_COMMANDS.HTTP.status); + + done() + }) + .catch(done); + + setTimeout(() => { + TEST_DEVICE_COMMANDS.HTTP.command = `command-${randomString.generate()}`; + + httpDeviceHive.command.insert(DH_COMMANDS_TEST_DEVICE.id, new Command(TEST_DEVICE_COMMANDS.HTTP)) + .then(() => { + TEST_DEVICE_COMMANDS.HTTP.status = `status-${randomString.generate()}`; + + httpDeviceHive.command.update(new Command(TEST_DEVICE_COMMANDS.HTTP)); + }); + }, 100); + }); + + it(`should subscribe for command insertion notifications on device with id ${DH_COMMANDS_TEST_DEVICE.id} via HTTP`, done => { + const commandPollQuery = new CommandPollQuery({ deviceId: DH_COMMANDS_TEST_DEVICE.id }); + let subscriptionId; + + httpDeviceHive.command.subscribe(commandPollQuery) + .then((response) => { + subscriptionId = response.subscriptionId; + + setTimeout(() => { + httpDeviceHive.on(`message`, (command) => { + assert.equal(command.command, TEST_DEVICE_COMMANDS.HTTP.command); + httpDeviceHive.command.unsubscribe(subscriptionId) + .then(() => done()) + .catch(done); + }); + }, 300); + + setTimeout(() => { + TEST_DEVICE_COMMANDS.HTTP.command = `command-${randomString.generate()}`; + httpDeviceHive.command.insert(DH_COMMANDS_TEST_DEVICE.id, new Command(TEST_DEVICE_COMMANDS.HTTP)); + }, 500); + }) + .catch(done); + }); + + it(`should subscribe for command insertion notifications on device with id ${DH_COMMANDS_TEST_DEVICE.id} via WS`, done => { + const commandPollQuery = new CommandPollQuery({ deviceId: DH_COMMANDS_TEST_DEVICE.id }); + let subscriptionId; + + wsDeviceHive.command.subscribe(commandPollQuery) + .then((response) => { + subscriptionId = response.subscriptionId; + + setTimeout(() => { + wsDeviceHive.on(`message`, (command) => { + assert.equal(command.command, TEST_DEVICE_COMMANDS.WS.command); + wsDeviceHive.command.unsubscribe(subscriptionId) + .then(() => done()) + .catch(done); + }); + }, 300); + + setTimeout(() => { + TEST_DEVICE_COMMANDS.WS.command = `command-${randomString.generate()}`; + wsDeviceHive.command.insert(DH_COMMANDS_TEST_DEVICE.id, new Command(TEST_DEVICE_COMMANDS.WS)); + }, 500); + }) + .catch(done); + }); + + after(done => { + httpDeviceHive.device.delete(DH_COMMANDS_TEST_DEVICE.id) + .then(() => { + httpDeviceHive.disconnect(); + wsDeviceHive.disconnect(); + + done(); + }); + }); +}); \ No newline at end of file diff --git a/test/integration/controllers/DeviceNotificationAPI.spec.js b/test/integration/controllers/DeviceNotificationAPI.spec.js new file mode 100644 index 0000000..f58124c --- /dev/null +++ b/test/integration/controllers/DeviceNotificationAPI.spec.js @@ -0,0 +1,227 @@ +const randomString = require(`randomstring`); +const chai = require(`chai`); +const assert = chai.assert; +const config = require('../config'); +const DeviceHive = require('../../../index'); +const Device = DeviceHive.models.Device; +const Notification = DeviceHive.models.Notification; +const NotificationListQuery = DeviceHive.models.query.NotificationListQuery; +const NotificationPollQuery = DeviceHive.models.query.NotificationPollQuery; +const NotificationPollManyQuery = DeviceHive.models.query.NotificationPollManyQuery; + +const httpDeviceHive = new DeviceHive(config.server.http); +const wsDeviceHive = new DeviceHive(config.server.ws); + + +const TIMESTAMP = new Date().toISOString(); +const DH_NOTIFICATIONS_TEST_DEVICE = { + id: randomString.generate(), + name: `DH_COMMANDS_TEST_DEVICE`, + networkId: 1, + deviceTypeId: 1, + isBlocked: false, + data: {} +}; +const TEST_DEVICE_NOTIFICATIONS = { + HTTP: { + deviceId: DH_NOTIFICATIONS_TEST_DEVICE.id, + notification: `notification-${randomString.generate()}`, + timestamp: TIMESTAMP, + parameters: { + jsonString: 'jsonString' + } + }, + WS: { + deviceId: DH_NOTIFICATIONS_TEST_DEVICE.id, + notification: `notification-${randomString.generate()}`, + timestamp: TIMESTAMP, + parameters: { + jsonString: 'jsonString' + } + } +}; + +describe('NotificationAPI', () => { + + before(done => { + Promise.all([httpDeviceHive.connect(), wsDeviceHive.connect()]) + .then(() => httpDeviceHive.device.add(new Device(DH_NOTIFICATIONS_TEST_DEVICE))) + .then(() => done()) + .catch(done); + }); + + it(`should insert new notification with name ${TEST_DEVICE_NOTIFICATIONS.HTTP.notification} via HTTP`, done => { + const notificationModel = new Notification(TEST_DEVICE_NOTIFICATIONS.HTTP); + + httpDeviceHive.notification.insert(DH_NOTIFICATIONS_TEST_DEVICE.id, notificationModel) + .then((notification) => { + TEST_DEVICE_NOTIFICATIONS.HTTP.id = notification.id; + + done(); + }) + .catch(done); + }); + + it(`should insert new notification with name ${TEST_DEVICE_NOTIFICATIONS.WS.notification} via WS`, done => { + const notificationModel = new Notification(TEST_DEVICE_NOTIFICATIONS.WS); + + wsDeviceHive.notification.insert(DH_NOTIFICATIONS_TEST_DEVICE.id, notificationModel) + .then((notification) => { + TEST_DEVICE_NOTIFICATIONS.WS.id = notification.id; + + done(); + }) + .catch(done); + }); + + it(`should list all notifications for device with id ${DH_NOTIFICATIONS_TEST_DEVICE.id} via HTTP`, done => { + const notificationListQuery = new NotificationListQuery({ + deviceId: DH_NOTIFICATIONS_TEST_DEVICE.id, + notification: TEST_DEVICE_NOTIFICATIONS.HTTP.notification + }); + + setTimeout(() => { + httpDeviceHive.notification.list(notificationListQuery) + .then(notifications => { + assert.equal(notifications[0].notification, TEST_DEVICE_NOTIFICATIONS.HTTP.notification); + }) + .then(() => done()) + .catch(done); + }, 200); + }); + + it(`should list all notifications for device with id ${DH_NOTIFICATIONS_TEST_DEVICE.id} via WS`, done => { + const notificationListQuery = new NotificationListQuery({ + deviceId: DH_NOTIFICATIONS_TEST_DEVICE.id, + notification: TEST_DEVICE_NOTIFICATIONS.WS.notification + }); + + setTimeout(() => { + wsDeviceHive.notification.list(notificationListQuery) + .then(notifications => { + assert.equal(notifications[0].notification, TEST_DEVICE_NOTIFICATIONS.WS.notification); + }) + .then(() => done()) + .catch(done); + }, 200); + }); + + it(`should get notification with id ${TEST_DEVICE_NOTIFICATIONS.HTTP.id} for device with id ${DH_NOTIFICATIONS_TEST_DEVICE.id} via HTTP`, done => { + httpDeviceHive.notification.get(DH_NOTIFICATIONS_TEST_DEVICE.id, TEST_DEVICE_NOTIFICATIONS.HTTP.id) + .then(notification => { + assert.equal(notification.id, TEST_DEVICE_NOTIFICATIONS.HTTP.id); + }) + .then(() => done()) + .catch(done); + }); + + it(`should get notification with id ${TEST_DEVICE_NOTIFICATIONS.WS.id} for device with id ${DH_NOTIFICATIONS_TEST_DEVICE.id} via WS`, done => { + wsDeviceHive.notification.get(DH_NOTIFICATIONS_TEST_DEVICE.id, TEST_DEVICE_NOTIFICATIONS.WS.id) + .then(command => { + assert.equal(command.id, TEST_DEVICE_NOTIFICATIONS.WS.id); + }) + .then(() => done()) + .catch(done); + }); + + it(`should poll new notification for device with id ${DH_NOTIFICATIONS_TEST_DEVICE.id} via HTTP`, done => { + const notificationPollQuery = new NotificationPollQuery({ + deviceId: DH_NOTIFICATIONS_TEST_DEVICE.id, + waitTimeout: 1 + }); + + httpDeviceHive.notification.poll(notificationPollQuery) + .then((notifications) => { + assert.equal(notifications.length, 1); + assert.equal(notifications[0].notification, TEST_DEVICE_NOTIFICATIONS.HTTP.notification); + + TEST_DEVICE_NOTIFICATIONS.HTTP.id = notifications[0].id; + done(); + }) + .catch(done); + + setTimeout(() => { + TEST_DEVICE_NOTIFICATIONS.HTTP.notification = `notification-${randomString.generate()}`; + httpDeviceHive.notification.insert(DH_NOTIFICATIONS_TEST_DEVICE.id, new Notification(TEST_DEVICE_NOTIFICATIONS.HTTP)); + }, 100); + }); + + it(`should poll new notification for network with id ${DH_NOTIFICATIONS_TEST_DEVICE.networkId} via HTTP`, done => { + const notificationPollManyQuery = new NotificationPollManyQuery({ + networkIds: [ DH_NOTIFICATIONS_TEST_DEVICE.networkId ], + waitTimeout: 1 + }); + + httpDeviceHive.notification.pollMany(notificationPollManyQuery) + .then((notifications) => { + assert.equal(notifications.length, 1); + assert.equal(notifications[0].notification, TEST_DEVICE_NOTIFICATIONS.HTTP.notification); + + done(); + }) + .catch(done); + + setTimeout(() => { + TEST_DEVICE_NOTIFICATIONS.HTTP.notification = `notification-${randomString.generate()}`; + httpDeviceHive.notification.insert(DH_NOTIFICATIONS_TEST_DEVICE.id, new Notification(TEST_DEVICE_NOTIFICATIONS.HTTP)); + }, 100); + }); + + it(`should subscribe for notification insertion notifications on device with id ${DH_NOTIFICATIONS_TEST_DEVICE.id} via HTTP`, done => { + const notificationPollQuery = new NotificationPollQuery({ deviceId: DH_NOTIFICATIONS_TEST_DEVICE.id }); + let subscriptionId; + + httpDeviceHive.notification.subscribe(notificationPollQuery) + .then((response) => { + subscriptionId = response.subscriptionId; + + httpDeviceHive.on(`message`, (command) => { + assert.equal(command.notification, TEST_DEVICE_NOTIFICATIONS.HTTP.notification); + httpDeviceHive.notification.unsubscribe(subscriptionId) + .then(() => done()) + .catch(done); + }); + + setTimeout(() => { + TEST_DEVICE_NOTIFICATIONS.HTTP.notification = `command-${randomString.generate()}`; + httpDeviceHive.notification.insert(DH_NOTIFICATIONS_TEST_DEVICE.id, new Notification(TEST_DEVICE_NOTIFICATIONS.HTTP)); + }, 100); + }) + .catch(done); + }); + + it(`should subscribe for notification insertion notifications on device with id ${DH_NOTIFICATIONS_TEST_DEVICE.id} via WS`, done => { + const notificationPollQuery = new NotificationPollQuery({ deviceId: DH_NOTIFICATIONS_TEST_DEVICE.id }); + let subscriptionId; + + wsDeviceHive.notification.subscribe(notificationPollQuery) + .then((response) => { + subscriptionId = response.subscriptionId; + + setTimeout(() => { + wsDeviceHive.on(`message`, (command) => { + assert.equal(command.notification, TEST_DEVICE_NOTIFICATIONS.WS.notification); + wsDeviceHive.notification.unsubscribe(subscriptionId) + .then(() => done()) + .catch(done); + }); + }, 200); + + setTimeout(() => { + TEST_DEVICE_NOTIFICATIONS.WS.notification = `command-${randomString.generate()}`; + wsDeviceHive.notification.insert(DH_NOTIFICATIONS_TEST_DEVICE.id, new Notification(TEST_DEVICE_NOTIFICATIONS.WS)); + }, 300); + }) + .catch(done); + }); + + after(done => { + httpDeviceHive.device.delete(DH_NOTIFICATIONS_TEST_DEVICE.id) + .then(() => { + httpDeviceHive.disconnect(); + wsDeviceHive.disconnect(); + + done(); + }); + }); +}); \ No newline at end of file diff --git a/test/integration/controllers/DeviceTypeAPI.spec.js b/test/integration/controllers/DeviceTypeAPI.spec.js new file mode 100644 index 0000000..211a86c --- /dev/null +++ b/test/integration/controllers/DeviceTypeAPI.spec.js @@ -0,0 +1,167 @@ +const randomString = require(`randomstring`); +const chai = require(`chai`); +const assert = chai.assert; +const config = require('../config'); +const DeviceHive = require('../../../index'); +const DeviceType = DeviceHive.models.DeviceType; +const DeviceTypeListQuery = DeviceHive.models.query.DeviceTypeListQuery; +const DeviceTypeCountQuery = DeviceHive.models.query.DeviceTypeCountQuery; + +const httpDeviceHive = new DeviceHive(config.server.http); +const wsDeviceHive = new DeviceHive(config.server.ws); + + +const TEST_DEVICE_TYPE_NAME_PREFIX = `DH-JS-LIB-DEVICE-TYPE-NAME-`; +const TEST_DEVICE_TYPE_DESCRIPTION_PREFIX = `DH-JS-LIB-DEVICE-TYPE-NAME-`; +const TEST_DEVICE_TYPES = { + HTTP: { + name: `${TEST_DEVICE_TYPE_NAME_PREFIX}${randomString.generate()}`, + description: `${TEST_DEVICE_TYPE_DESCRIPTION_PREFIX}${randomString.generate()}` + }, + WS: { + name: `${TEST_DEVICE_TYPE_NAME_PREFIX}${randomString.generate()}`, + description: `${TEST_DEVICE_TYPE_DESCRIPTION_PREFIX}${randomString.generate()}` + } +}; + +describe('DeviceTypeAPI', () => { + + before(done => { + Promise.all([httpDeviceHive.connect(), wsDeviceHive.connect()]) + .then(() => done()); + }); + + it(`should insert new device type with next configuration: ${JSON.stringify(TEST_DEVICE_TYPES.HTTP)} via HTTP`, done => { + const deviceTypeModel = new DeviceType(TEST_DEVICE_TYPES.HTTP); + + httpDeviceHive.deviceType.insert(deviceTypeModel) + .then(({ id }) => { + TEST_DEVICE_TYPES.HTTP.id = id; + done(); + }) + .catch(done); + }); + + it(`should insert new device type with next configuration: ${JSON.stringify(TEST_DEVICE_TYPES.WS)} via WS`, done => { + const deviceTypeModel = new DeviceType(TEST_DEVICE_TYPES.WS); + + wsDeviceHive.deviceType.insert(deviceTypeModel) + .then(({ id }) => { + TEST_DEVICE_TYPES.WS.id = id; + done(); + }) + .catch(done); + }); + + it(`should list all device types with the next name pattern: ${TEST_DEVICE_TYPE_NAME_PREFIX}% via HTTP`, done => { + const deviceTypeListQuery = new DeviceTypeListQuery({ namePattern: `${TEST_DEVICE_TYPE_NAME_PREFIX}%` }); + + httpDeviceHive.deviceType.list(deviceTypeListQuery) + .then(deviceTypes => { + assert(deviceTypes.length, Object.keys(TEST_DEVICE_TYPES).length); + }) + .then(() => done()) + .catch(done); + }); + + it(`should list all device types with the next name pattern: ${TEST_DEVICE_TYPE_NAME_PREFIX}% via WS`, done => { + const deviceTypeListQuery = new DeviceTypeListQuery({ namePattern: `${TEST_DEVICE_TYPE_NAME_PREFIX}%` }); + + wsDeviceHive.deviceType.list(deviceTypeListQuery) + .then(deviceTypes => { + assert(deviceTypes.length, Object.keys(TEST_DEVICE_TYPES).length); + }) + .then(() => done()) + .catch(done); + }); + + it(`should get device type with name: ${TEST_DEVICE_TYPES.HTTP.name} via HTTP`, done => { + httpDeviceHive.deviceType.get(TEST_DEVICE_TYPES.HTTP.id) + .then(deviceType => { + assert.equal(deviceType.id, TEST_DEVICE_TYPES.HTTP.id); + assert.equal(deviceType.name, TEST_DEVICE_TYPES.HTTP.name); + }) + .then(() => done()) + .catch(done); + }); + + it(`should get device type with name: ${TEST_DEVICE_TYPES.WS.name} via WS`, done => { + wsDeviceHive.deviceType.get(TEST_DEVICE_TYPES.WS.id) + .then(deviceType => { + assert.equal(deviceType.id, TEST_DEVICE_TYPES.WS.id); + assert.equal(deviceType.name, TEST_DEVICE_TYPES.WS.name); + }) + .then(() => done()) + .catch(done); + }); + + it(`should update device type with name: ${TEST_DEVICE_TYPES.HTTP.name} via HTTP`, done => { + TEST_DEVICE_TYPES.HTTP.description = `${TEST_DEVICE_TYPE_DESCRIPTION_PREFIX}-${randomString.generate()}`; + + const deviceTypeModel = new DeviceType(TEST_DEVICE_TYPES.HTTP); + + httpDeviceHive.deviceType.update(deviceTypeModel) + .then(() => httpDeviceHive.deviceType.get(TEST_DEVICE_TYPES.HTTP.id)) + .then((deviceType) => { + assert.equal(deviceType.description, TEST_DEVICE_TYPES.HTTP.description); + }) + .then(() => done()) + .catch(done); + + }); + + it(`should update device type with name: ${TEST_DEVICE_TYPES.WS.name} via WS`, done => { + TEST_DEVICE_TYPES.WS.description = `${TEST_DEVICE_TYPE_DESCRIPTION_PREFIX}-${randomString.generate()}`; + + const deviceTypeModel = new DeviceType(TEST_DEVICE_TYPES.WS); + + wsDeviceHive.deviceType.update(deviceTypeModel) + .then(() => wsDeviceHive.deviceType.get(TEST_DEVICE_TYPES.WS.id)) + .then((deviceType) => { + assert.equal(deviceType.description, TEST_DEVICE_TYPES.WS.description); + }) + .then(() => done()) + .catch(done); + }); + + it(`should count device types with the next name pattern: ${TEST_DEVICE_TYPE_NAME_PREFIX}% via HTTP`, done => { + const deviceTypeCountQuery = new DeviceTypeCountQuery({ namePattern: `${TEST_DEVICE_TYPE_NAME_PREFIX}%` }); + + httpDeviceHive.deviceType.count(deviceTypeCountQuery) + .then(({ count }) => { + assert.equal(count, Object.keys(TEST_DEVICE_TYPES).length); + }) + .then(() => done()) + .catch(done); + }); + + it(`should count device types with the next name pattern: ${TEST_DEVICE_TYPE_NAME_PREFIX}% via WS`, done => { + const deviceTypeCountQuery = new DeviceTypeCountQuery({ namePattern: `${TEST_DEVICE_TYPE_NAME_PREFIX}%` }); + + wsDeviceHive.deviceType.count(deviceTypeCountQuery) + .then(({ count }) => { + assert.equal(count, Object.keys(TEST_DEVICE_TYPES).length); + }) + .then(() => done()) + .catch(done); + }); + + it(`should delete device type with name: ${TEST_DEVICE_TYPES.HTTP.name} via HTTP`, done => { + httpDeviceHive.deviceType.delete(TEST_DEVICE_TYPES.HTTP.id) + .then(() => done()) + .catch(done); + }); + + it(`should delete device type with name: ${TEST_DEVICE_TYPES.WS.name} via WS`, done => { + wsDeviceHive.deviceType.delete(TEST_DEVICE_TYPES.WS.id) + .then(() => done()) + .catch(done); + }); + + after(done => { + httpDeviceHive.disconnect(); + wsDeviceHive.disconnect(); + + done(); + }); +}); \ No newline at end of file diff --git a/test/integration/controllers/NetworkAPI.spec.js b/test/integration/controllers/NetworkAPI.spec.js new file mode 100644 index 0000000..cab6b77 --- /dev/null +++ b/test/integration/controllers/NetworkAPI.spec.js @@ -0,0 +1,167 @@ +const randomString = require(`randomstring`); +const chai = require(`chai`); +const assert = chai.assert; +const config = require('../config'); +const DeviceHive = require('../../../index'); +const Network = DeviceHive.models.Network; +const NetworkListQuery = DeviceHive.models.query.NetworkListQuery; +const NetworkCountQuery = DeviceHive.models.query.NetworkCountQuery; + +const httpDeviceHive = new DeviceHive(config.server.http); +const wsDeviceHive = new DeviceHive(config.server.ws); + + +const TEST_NETWORK_NAME_PREFIX = `DH-JS-LIB-NETWORK-NAME-`; +const TEST_NETWORK_DESCRIPTION_PREFIX = `DH-JS-LIB-NETWORK-NAME-`; +const TEST_NETWORKS = { + HTTP: { + name: `${TEST_NETWORK_NAME_PREFIX}${randomString.generate()}`, + description: `${TEST_NETWORK_DESCRIPTION_PREFIX}${randomString.generate()}` + }, + WS: { + name: `${TEST_NETWORK_NAME_PREFIX}${randomString.generate()}`, + description: `${TEST_NETWORK_DESCRIPTION_PREFIX}${randomString.generate()}` + } +}; + +describe('NetworkAPI', () => { + + before(done => { + Promise.all([httpDeviceHive.connect(), wsDeviceHive.connect()]) + .then(() => done()); + }); + + it(`should insert new network with next configuration: ${JSON.stringify(TEST_NETWORKS.HTTP)} via HTTP`, done => { + const networkModel = new Network(TEST_NETWORKS.HTTP); + + httpDeviceHive.network.insert(networkModel) + .then(({ id }) => { + TEST_NETWORKS.HTTP.id = id; + done(); + }) + .catch(done); + }); + + it(`should insert new network with next configuration: ${JSON.stringify(TEST_NETWORKS.WS)} via WS`, done => { + const networkModel = new Network(TEST_NETWORKS.WS); + + wsDeviceHive.network.insert(networkModel) + .then(({ id }) => { + TEST_NETWORKS.WS.id = id; + done(); + }) + .catch(done); + }); + + it(`should list all device types with the next name pattern: ${TEST_NETWORK_NAME_PREFIX}% via HTTP`, done => { + const networkListQuery = new NetworkListQuery({ namePattern: `${TEST_NETWORK_NAME_PREFIX}%` }); + + httpDeviceHive.network.list(networkListQuery) + .then(networks => { + assert(networks.length, Object.keys(TEST_NETWORKS).length); + }) + .then(() => done()) + .catch(done); + }); + + it(`should list all device types with the next name pattern: ${TEST_NETWORK_NAME_PREFIX}% via WS`, done => { + const networkListQuery = new NetworkListQuery({ namePattern: `${TEST_NETWORK_NAME_PREFIX}%` }); + + wsDeviceHive.network.list(networkListQuery) + .then(networks => { + assert(networks.length, Object.keys(TEST_NETWORKS).length); + }) + .then(() => done()) + .catch(done); + }); + + it(`should get network with name: ${TEST_NETWORKS.HTTP.name} via HTTP`, done => { + httpDeviceHive.network.get(TEST_NETWORKS.HTTP.id) + .then(network => { + assert.equal(network.id, TEST_NETWORKS.HTTP.id); + assert.equal(network.name, TEST_NETWORKS.HTTP.name); + }) + .then(() => done()) + .catch(done); + }); + + it(`should get network with name: ${TEST_NETWORKS.WS.name} via WS`, done => { + wsDeviceHive.network.get(TEST_NETWORKS.WS.id) + .then(network => { + assert.equal(network.id, TEST_NETWORKS.WS.id); + assert.equal(network.name, TEST_NETWORKS.WS.name); + }) + .then(() => done()) + .catch(done); + }); + + it(`should update network with name: ${TEST_NETWORKS.HTTP.name} via HTTP`, done => { + TEST_NETWORKS.HTTP.description = `${TEST_NETWORK_DESCRIPTION_PREFIX}-${randomString.generate()}`; + + const networkModel = new Network(TEST_NETWORKS.HTTP); + + httpDeviceHive.network.update(networkModel) + .then(() => httpDeviceHive.network.get(TEST_NETWORKS.HTTP.id)) + .then((network) => { + assert.equal(network.description, TEST_NETWORKS.HTTP.description); + }) + .then(() => done()) + .catch(done); + + }); + + it(`should update network with name: ${TEST_NETWORKS.WS.name} via WS`, done => { + TEST_NETWORKS.WS.description = `${TEST_NETWORK_DESCRIPTION_PREFIX}-${randomString.generate()}`; + + const networkModel = new Network(TEST_NETWORKS.WS); + + wsDeviceHive.network.update(networkModel) + .then(() => wsDeviceHive.network.get(TEST_NETWORKS.WS.id)) + .then((network) => { + assert.equal(network.description, TEST_NETWORKS.WS.description); + }) + .then(() => done()) + .catch(done); + }); + + it(`should count device types with the next name pattern: ${TEST_NETWORK_NAME_PREFIX}% via HTTP`, done => { + const networkCountQuery = new NetworkCountQuery({ namePattern: `${TEST_NETWORK_NAME_PREFIX}%` }); + + httpDeviceHive.network.count(networkCountQuery) + .then(({ count }) => { + assert.equal(count, Object.keys(TEST_NETWORKS).length); + }) + .then(() => done()) + .catch(done); + }); + + it(`should count device types with the next name pattern: ${TEST_NETWORK_NAME_PREFIX}% via WS`, done => { + const networkCountQuery = new NetworkCountQuery({ namePattern: `${TEST_NETWORK_NAME_PREFIX}%` }); + + wsDeviceHive.network.count(networkCountQuery) + .then(({ count }) => { + assert.equal(count, Object.keys(TEST_NETWORKS).length); + }) + .then(() => done()) + .catch(done); + }); + + it(`should delete network with name: ${TEST_NETWORKS.HTTP.name} via HTTP`, done => { + httpDeviceHive.network.delete(TEST_NETWORKS.HTTP.id) + .then(() => done()) + .catch(done); + }); + + it(`should delete network with name: ${TEST_NETWORKS.WS.name} via WS`, done => { + wsDeviceHive.network.delete(TEST_NETWORKS.WS.id) + .then(() => done()) + .catch(done); + }); + + after(done => { + httpDeviceHive.disconnect(); + wsDeviceHive.disconnect(); + + done(); + }); +}); \ No newline at end of file diff --git a/test/integration/controllers/PluginAPI.spec.js b/test/integration/controllers/PluginAPI.spec.js new file mode 100644 index 0000000..088654d --- /dev/null +++ b/test/integration/controllers/PluginAPI.spec.js @@ -0,0 +1,110 @@ +const randomString = require(`randomstring`); +const chai = require(`chai`); +const assert = chai.assert; +const config = require(`../config`); +const DeviceHive = require(`../../../index`); +const Plugin = DeviceHive.models.Plugin; +const PluginRegisterQuery = DeviceHive.models.query.PluginRegisterQuery; + +const httpDeviceHive = new DeviceHive(config.server.http); +const wsDeviceHive = new DeviceHive(config.server.ws); + + +const TEST_PLUGIN = { + HTTP: { + name: `plugin-${randomString.generate()}`, + description: `description`, + parameters: { + jsonString: `string` + } + } +}; + +describe(`PluginAPI`, () => { + + before(done => { + Promise.all([httpDeviceHive.connect(), wsDeviceHive.connect()]) + .then(() => done()); + }); + + it(`should register plugin with name: ${TEST_PLUGIN.HTTP.name} via HTTP`, done => { + const plugin = new Plugin(TEST_PLUGIN.HTTP); + const pluginQuery = new PluginRegisterQuery({ + returnCommands: true, + returnUpdatedCommands: false, + returnNotifications: false + }); + + httpDeviceHive.plugin.register(plugin, pluginQuery) + .then(({ accessToken, refreshToken, topicName }) => { + assert.exists(accessToken); + assert.exists(refreshToken); + assert.exists(topicName); + + TEST_PLUGIN.HTTP.accessToken = accessToken; + TEST_PLUGIN.HTTP.refreshToken = refreshToken; + TEST_PLUGIN.HTTP.topicName = topicName; + }) + .then(() => done()) + .catch(done); + }); + + it(`should get plugin with name: ${TEST_PLUGIN.HTTP.name} via HTTP`, done => { + const pluginListQuery = new DeviceHive.models.query.PluginListQuery({ + name: TEST_PLUGIN.HTTP.name + }); + + httpDeviceHive.plugin.list(pluginListQuery) + .then(plugins => { + assert.equal(plugins[0].name, TEST_PLUGIN.HTTP.name); + }) + .then(() => done()) + .catch(done); + }); + + it(`should update plugin with name: ${TEST_PLUGIN.HTTP.name} via HTTP`, done => { + TEST_PLUGIN.HTTP.name = `plugin-${randomString.generate()}`; + + const pluginUpdateQuery = new DeviceHive.models.query.PluginUpdateQuery({ + topicName: TEST_PLUGIN.HTTP.topicName, + name: TEST_PLUGIN.HTTP.name + }); + const pluginListQuery = new DeviceHive.models.query.PluginListQuery({ + name: TEST_PLUGIN.HTTP.name + }); + + httpDeviceHive.plugin.update(pluginUpdateQuery) + .then(() => httpDeviceHive.plugin.list(pluginListQuery)) + .then(plugins => { + assert.equal(plugins[0].name, TEST_PLUGIN.HTTP.name); + }) + .then(() => done()) + .catch(done); + }); + + it(`should count plugin with name: ${TEST_PLUGIN.HTTP.name} via HTTP`, done => { + const pluginCountQuery = new DeviceHive.models.query.PluginCountQuery({ + name: TEST_PLUGIN.HTTP.name + }); + + httpDeviceHive.plugin.count(pluginCountQuery) + .then(({ count }) => { + assert.equal(count, 1); + }) + .then(() => done()) + .catch(done); + }); + + it(`should delete plugin with name: ${TEST_PLUGIN.HTTP.name}`, done => { + httpDeviceHive.plugin.delete(TEST_PLUGIN.HTTP.topicName) + .then(() => done()) + .catch(done); + }); + + after(done => { + httpDeviceHive.disconnect(); + wsDeviceHive.disconnect(); + + done(); + }); +}); \ No newline at end of file diff --git a/test/integration/controllers/ServerInfoAPI.spec.js b/test/integration/controllers/ServerInfoAPI.spec.js new file mode 100644 index 0000000..ecc5138 --- /dev/null +++ b/test/integration/controllers/ServerInfoAPI.spec.js @@ -0,0 +1,68 @@ +const chai = require(`chai`); +const assert = chai.assert; +const config = require('../config'); +const DeviceHive = require('../../../index'); + +const httpDeviceHive = new DeviceHive(config.server.http); +const wsDeviceHive = new DeviceHive(config.server.ws); + + +describe('ServerInfoAPI', () => { + + before(done => { + Promise.all([httpDeviceHive.connect(), wsDeviceHive.connect()]) + .then(() => done()); + }); + + it('should get server info via HTTP', done => { + httpDeviceHive.info.getServerInfo() + .then(serverInfo => { + assert.exists(serverInfo); + }) + .then(() => done()) + .catch(done); + }); + + it('should get server info via WS', done => { + wsDeviceHive.info.getServerInfo() + .then(serverInfo => { + assert.exists(serverInfo); + }) + .then(() => done()) + .catch(done); + }); + + it('should get cache info via HTTP', done => { + httpDeviceHive.info.getCacheInfo() + .then(cacheInfo => { + assert.exists(cacheInfo); + }) + .then(() => done()) + .catch(done); + }); + + it('should get cluster info via HTTP', done => { + httpDeviceHive.info.getClusterInfo() + .then(clusterInfo => { + assert.exists(clusterInfo); + }) + .then(() => done()) + .catch(done); + }); + + it('should get cluster info via WS', done => { + wsDeviceHive.info.getClusterInfo() + .then(clusterInfo => { + assert.exists(clusterInfo); + }) + .then(() => done()) + .catch(done); + }); + + after(done => { + httpDeviceHive.disconnect(); + wsDeviceHive.disconnect(); + + done(); + }); +}); \ No newline at end of file diff --git a/test/integration/controllers/TokenAPI.spec.js b/test/integration/controllers/TokenAPI.spec.js new file mode 100644 index 0000000..afd799f --- /dev/null +++ b/test/integration/controllers/TokenAPI.spec.js @@ -0,0 +1,169 @@ +const randomString = require(`randomstring`); +const chai = require(`chai`); +const assert = chai.assert; +const config = require(`../config`); +const DeviceHive = require(`../../../index`); +const UserToken = DeviceHive.models.UserToken; +const Plugin = DeviceHive.models.Plugin; +const PluginRegisterQuery = DeviceHive.models.query.PluginRegisterQuery; + +const httpDeviceHive = new DeviceHive(config.server.http); +const wsDeviceHive = new DeviceHive(config.server.ws); + + +const TEST_TOKENS = { + HTTP: {}, + WS: {} +}; +const TEST_PLUGIN = { + HTTP: { + name: `plugin-${randomString.generate()}`, + description: `description`, + parameters: { + jsonString: `string` + } + } +}; + +describe(`TokenAPI`, () => { + + before(done => { + const plugin = new Plugin(TEST_PLUGIN.HTTP); + const pluginQuery = new PluginRegisterQuery({ + returnCommands: true, + returnUpdatedCommands: false, + returnNotifications: false + }); + + Promise.all([httpDeviceHive.connect(), wsDeviceHive.connect()]) + .then(() => httpDeviceHive.plugin.register(plugin, pluginQuery)) + .then(({ accessToken, refreshToken, topicName }) => { + TEST_PLUGIN.HTTP.accessToken = accessToken; + TEST_PLUGIN.HTTP.refreshToken = refreshToken; + TEST_PLUGIN.HTTP.topicName = topicName; + }) + .then(() => done()); + }); + + it(`should create token for user via HTTP`, done => { + const token = new UserToken({ + userId: config.TEST_USER_ID, + actions: [`*`], + networkIds: [`*`], + deviceTypeIds: [`*`], + expiration: `2050-02-09T10:09:03.033Z` + }); + + httpDeviceHive.token.createUserToken(token) + .then(({ accessToken, refreshToken }) => { + assert.exists(accessToken); + assert.exists(refreshToken); + + TEST_TOKENS.HTTP.accessToken = accessToken; + TEST_TOKENS.HTTP.refreshToken = refreshToken; + }) + .then(() => done()) + .catch(done); + }); + + it(`should create token for user via WS`, done => { + const token = new UserToken({ + userId: config.TEST_USER_ID, + actions: [`*`], + networkIds: [`*`], + deviceTypeIds: [`*`], + expiration: `2050-02-09T10:09:03.033Z` + }); + + wsDeviceHive.token.createUserToken(token) + .then(({ accessToken, refreshToken }) => { + assert.exists(accessToken); + assert.exists(refreshToken); + + TEST_TOKENS.WS.accessToken = accessToken; + TEST_TOKENS.WS.refreshToken = refreshToken; + }) + .then(() => done()) + .catch(done); + }); + + it(`should refresh user access token via HTTP`, done => { + httpDeviceHive.token.refresh(TEST_TOKENS.HTTP.refreshToken) + .then(({ accessToken }) => { + assert.exists(accessToken); + + TEST_TOKENS.WS.accessToken = accessToken; + }) + .then(() => done()) + .catch(done); + }); + + it(`should refresh user access token via WS`, done => { + wsDeviceHive.token.refresh(TEST_TOKENS.WS.refreshToken) + .then(({ accessToken }) => { + assert.exists(accessToken); + + TEST_TOKENS.WS.accessToken = accessToken; + }) + .then(() => done()) + .catch(done); + }); + + it(`should log in user with given credentials: login ${config.TEST_USER_LOGIN}, password ${config.TEST_USER_PASSWORD} via HTTP`, done => { + httpDeviceHive.token.login(config.TEST_USER_LOGIN, config.TEST_USER_PASSWORD) + .then(({ accessToken, refreshToken }) => { + assert.exists(accessToken); + assert.exists(refreshToken); + }) + .then(() => done()) + .catch(done) + }); + + it(`should log in user with given credentials: login ${config.TEST_USER_LOGIN}, password ${config.TEST_USER_PASSWORD} via WS`, done => { + wsDeviceHive.token.login(config.TEST_USER_LOGIN, config.TEST_USER_PASSWORD) + .then(({ accessToken, refreshToken }) => { + assert.exists(accessToken); + assert.exists(refreshToken); + }) + .then(() => done()) + .catch(done) + }); + + it(`should create plugin token for plugin with name: ${TEST_PLUGIN.HTTP.name} via HTTP`, done => { + const token = new DeviceHive.models.PluginToken({ + actions: [], + expiration: `2030-02-09T10:09:03.033Z`, + topicName: TEST_PLUGIN.HTTP.topicName + }); + + httpDeviceHive.token.createPluginToken(token) + .then(({ accessToken, refreshToken }) => { + assert.exists(accessToken); + assert.exists(refreshToken); + }) + .then(() => done()) + .catch(done); + }); + + it(`should authenticate plugin with name: ${TEST_PLUGIN.HTTP.name} via HTTP`, done => { + httpDeviceHive.token.authPlugin(TEST_PLUGIN.HTTP.accessToken) + .then(({ tpc, a, e, t }) => { + assert.exists(tpc); + assert.exists(a); + assert.exists(e); + assert.exists(t); + }) + .then(done) + .catch(done); + }); + + after(done => { + httpDeviceHive.plugin.delete(TEST_PLUGIN.HTTP.topicName) + .then(() => { + httpDeviceHive.disconnect(); + wsDeviceHive.disconnect(); + + done(); + }); + }); +}); \ No newline at end of file diff --git a/test/integration/controllers/UserAPI.spec.js b/test/integration/controllers/UserAPI.spec.js new file mode 100644 index 0000000..41e760e --- /dev/null +++ b/test/integration/controllers/UserAPI.spec.js @@ -0,0 +1,346 @@ +const randomString = require(`randomstring`); +const chai = require(`chai`); +const assert = chai.assert; +const expect = chai.expect; +const config = require(`../config`); +const DeviceHive = require(`../../../index`); +const User = DeviceHive.models.User; +const DeviceType = DeviceHive.models.DeviceType; +const Network = DeviceHive.models.Network; +const UserListQuery = DeviceHive.models.query.UserListQuery; +const UserCountQuery = DeviceHive.models.query.UserCountQuery; + +const httpDeviceHive = new DeviceHive(config.server.http); +const wsDeviceHive = new DeviceHive(config.server.ws); + + +const TEST_USER_LOGIN_PREFIX = `DH-JS-LIB-USER-LOGIN-`; +const TEST_USERS = { + HTTP: { + login: `${TEST_USER_LOGIN_PREFIX}${randomString.generate()}`, + role: 1, + status: 0, + password: `password`, + data: { + jsonString: `jsonString` + } + }, + WS: { + login: `${TEST_USER_LOGIN_PREFIX}${randomString.generate()}`, + role: 1, + status: 0, + password: `password`, + data: { + jsonString: `jsonString` + } + } +}; +const TEST_DEVICE_TYPE_NAME_PREFIX = `DH-JS-LIB-DEVICE-TYPE-NAME-`; +const TEST_DEVICE_TYPE_DESCRIPTION_PREFIX = `DH-JS-LIB-DEVICE-TYPE-NAME-`; +const TEST_DEVICE_TYPE = { + name: `${TEST_DEVICE_TYPE_NAME_PREFIX}${randomString.generate()}`, + description: `${TEST_DEVICE_TYPE_DESCRIPTION_PREFIX}${randomString.generate()}` +}; +const TEST_NETWORK_NAME_PREFIX = `DH-JS-LIB-NETWORK-NAME-`; +const TEST_NETWORK_DESCRIPTION_PREFIX = `DH-JS-LIB-NETWORK-NAME-`; +const TEST_NETWORK = { + name: `${TEST_NETWORK_NAME_PREFIX}${randomString.generate()}`, + description: `${TEST_NETWORK_DESCRIPTION_PREFIX}${randomString.generate()}` +}; + +describe(`UserAPI`, () => { + const deviceTypeModel = new DeviceType(TEST_DEVICE_TYPE); + const networkModel = new Network(TEST_NETWORK); + + before(done => { + Promise.all([httpDeviceHive.connect(), wsDeviceHive.connect()]) + .then(() => httpDeviceHive.deviceType.insert(deviceTypeModel)) + .then(({ id }) => TEST_DEVICE_TYPE.id = id) + .then(() => httpDeviceHive.network.insert(networkModel)) + .then(({ id }) => TEST_NETWORK.id = id) + .then(() => done()); + }); + + it(`should add new user with login ${TEST_USERS.HTTP.login} via HTTP`, done => { + const userModel = new User(TEST_USERS.HTTP); + + httpDeviceHive.user.insert(userModel) + .then(({ id }) => { + assert.exists(id); + + TEST_USERS.HTTP.id = id; + }) + .then(() => done()) + .catch(done); + }); + + it(`should add new user with login ${TEST_USERS.WS.login} via WS`, done => { + const userModel = new User(TEST_USERS.WS); + + wsDeviceHive.user.insert(userModel) + .then(({ id }) => { + assert.exists(id); + + TEST_USERS.WS.id = id; + }) + .then(() => done()) + .catch(done); + }); + + it(`should list users with the next login pattern: ${TEST_USER_LOGIN_PREFIX}% via HTTP`, done => { + const userListQuery = new UserListQuery({ loginPattern: `${TEST_USER_LOGIN_PREFIX}%` }); + + httpDeviceHive.user.list(userListQuery) + .then(users => { + assert.equal(users.length, Object.keys(TEST_USERS).length); + }) + .then(() => done()) + .catch(done); + }); + + it(`should list users with the next login pattern: ${TEST_USER_LOGIN_PREFIX}% via HTTP`, done => { + const userListQuery = new UserListQuery({ loginPattern: `${TEST_USER_LOGIN_PREFIX}%` }); + + wsDeviceHive.user.list(userListQuery) + .then(users => { + assert.equal(users.length, Object.keys(TEST_USERS).length); + }) + .then(() => done()) + .catch(done); + }); + + it(`should get user with login: ${TEST_USERS.HTTP.login} via HTTP`, done => { + httpDeviceHive.user.get(TEST_USERS.HTTP.id) + .then(user => { + assert.equal(user.login, TEST_USERS.HTTP.login); + }) + .then(() => done()) + .catch(done); + }); + + it(`should get user with login: ${TEST_USERS.WS.login} via WS`, done => { + wsDeviceHive.user.get(TEST_USERS.WS.id) + .then(user => { + assert.equal(user.login, TEST_USERS.WS.login); + }) + .then(() => done()) + .catch(done); + }); + + it(`should get current user: login ${config.TEST_USER_LOGIN}, password ${config.TEST_USER_PASSWORD} via HTTP`, done => { + httpDeviceHive.user.getCurrent() + .then(user => { + assert.equal(user.login, config.TEST_USER_LOGIN); + }) + .then(() => done()) + .catch(done); + }); + + it(`should get current user: login ${config.TEST_USER_LOGIN}, password ${config.TEST_USER_PASSWORD} via WS`, done => { + wsDeviceHive.user.getCurrent() + .then(user => { + assert.equal(user.login, config.TEST_USER_LOGIN); + }) + .then(() => done()) + .catch(done); + }); + + it(`should update user with login: ${TEST_USERS.HTTP.login} via HTTP`, done => { + TEST_USERS.HTTP.data = { update: true }; + + const userModel = new User(TEST_USERS.HTTP); + + httpDeviceHive.user.update(userModel) + .then(() => httpDeviceHive.user.get(TEST_USERS.HTTP.id)) + .then((user) => { + assert.deepEqual(user.data, TEST_USERS.HTTP.data); + }) + .then(() => done()) + .catch(done); + }); + + it(`should update user with login: ${TEST_USERS.WS.login} via WS`, done => { + TEST_USERS.WS.data = { update: true }; + + const userModel = new User(TEST_USERS.WS); + + wsDeviceHive.user.update(userModel) + .then(() => wsDeviceHive.user.get(TEST_USERS.WS.id)) + .then((user) => { + assert.deepEqual(user.data, TEST_USERS.WS.data); + }) + .then(() => done()) + .catch(done); + }); + + it(`should update current user with login ${config.TEST_USER_LOGIN} via HTTP`, done => { + const userModel = new User({ data: { update: true } }); + + httpDeviceHive.user.updateCurrent(userModel) + .then(() => httpDeviceHive.user.getCurrent()) + .then(user => { + assert.deepEqual(user.data, userModel.data); + }) + .then(() => done()) + .catch(done); + }); + + it(`should update current user with login ${config.TEST_USER_LOGIN} via WS`, done => { + const userModel = new User({ data: { update: true } }); + + wsDeviceHive.user.updateCurrent(userModel) + .then(() => wsDeviceHive.user.getCurrent()) + .then(user => { + assert.deepEqual(user.data, userModel.data); + }) + .then(() => done()) + .catch(done); + }); + + it(`should count users with the next login pattern ${TEST_USER_LOGIN_PREFIX}% via HTTP`, done => { + const userListQuery = new UserCountQuery({ loginPattern: `${TEST_USER_LOGIN_PREFIX}%` }); + + httpDeviceHive.user.count(userListQuery) + .then(({ count }) => { + assert.equal(count, Object.keys(TEST_USERS).length); + }) + .then(() => done()) + .catch(done); + }); + + it(`should count users with the next login pattern ${TEST_USER_LOGIN_PREFIX}% via WS`, done => { + const userListQuery = new UserCountQuery({ loginPattern: `${TEST_USER_LOGIN_PREFIX}%` }); + + wsDeviceHive.user.count(userListQuery) + .then(({ count }) => { + assert.equal(count, Object.keys(TEST_USERS).length); + }) + .then(() => done()) + .catch(done); + }); + + it(`should get user's deviceTypes via HTTP`, done => { + httpDeviceHive.user.getDeviceTypes(TEST_USERS.HTTP.id) + .then(deviceTypes => { + assert.exists(deviceTypes); + expect(deviceTypes).to.be.an('array'); + }) + .then(() => done()) + .catch(done); + }); + + it(`should unassign all device types from user with login: ${TEST_USERS.HTTP.login} via HTTP`, done => { + httpDeviceHive.user.unassignAllDeviceTypes(TEST_USERS.HTTP.id) + .then(() => httpDeviceHive.user.getDeviceTypes(TEST_USERS.HTTP.id)) + .then((deviceTypes) => { + assert.exists(deviceTypes); + expect(deviceTypes).to.be.an('array').that.is.empty; + }) + .then(() => done()) + .catch(done); + }); + + it(`should assign all device types to user with login: ${TEST_USERS.HTTP.login} via HTTP`, done => { + httpDeviceHive.user.assignAllDeviceTypes(TEST_USERS.HTTP.id) + .then(() => httpDeviceHive.user.getDeviceTypes(TEST_USERS.HTTP.id)) + .then((deviceTypes) => { + assert.exists(deviceTypes); + expect(deviceTypes).to.be.an('array').that.is.not.empty; + }) + .then(() => done()) + .catch(done); + }); + + it(`should assign device type with name: ${TEST_DEVICE_TYPE.name} to user with login: ${TEST_USERS.HTTP.login} via HTTP`, done => { + httpDeviceHive.user.unassignAllDeviceTypes(TEST_USERS.HTTP.id) + .then(() => httpDeviceHive.user.assignDeviceType(TEST_USERS.HTTP.id, TEST_DEVICE_TYPE.id)) + .then(() => done()) + .catch(done); + }); + + it(`should get users device type with name: ${TEST_DEVICE_TYPE.name} via HTTP`, done => { + httpDeviceHive.user.getDeviceType(TEST_USERS.HTTP.id, TEST_DEVICE_TYPE.id) + .then(({ deviceType }) => { + assert.exists(deviceType); + assert.equal(deviceType.name, TEST_DEVICE_TYPE.name); + }) + .then(() => done()) + .catch(done); + }); + + it(`should unassign device type with name: ${TEST_DEVICE_TYPE.name} from user with login: ${TEST_USERS.HTTP.login} via HTTP`, done => { + httpDeviceHive.user.unassignDeviceType(TEST_USERS.HTTP.id, TEST_DEVICE_TYPE.id) + .then(() => httpDeviceHive.user.getDeviceType(TEST_USERS.HTTP.id, TEST_DEVICE_TYPE.id)) + .then(() => done(new Error(`Device type with id ${TEST_DEVICE_TYPE.id} for user with id ${TEST_USERS.HTTP.id} should not be found`))) + .catch(() => done()); + }); + + it(`should assign network with name: ${TEST_NETWORK.name} to user with login: ${TEST_USERS.HTTP.login} via HTTP`, done => { + httpDeviceHive.user.assignNetwork(TEST_USERS.HTTP.id, TEST_NETWORK.id) + .then(() => done()) + .catch(done); + }); + + it(`should get users network with name: ${TEST_NETWORK.name} via HTTP`, done => { + httpDeviceHive.user.getNetwork(TEST_USERS.HTTP.id, TEST_NETWORK.id) + .then(({ network }) => { + assert.exists(network); + assert.equal(network.name, TEST_NETWORK.name); + }) + .then(() => done()) + .catch(done); + }); + + it(`should unassign network with name: ${TEST_NETWORK.name} from user with login: ${TEST_USERS.HTTP.login} via HTTP`, done => { + httpDeviceHive.user.unassignNetwork(TEST_USERS.HTTP.id, TEST_NETWORK.id) + .then(() => httpDeviceHive.user.getNetwork(TEST_USERS.HTTP.id, TEST_NETWORK.id)) + .then(() => done(new Error(`Network with id ${TEST_NETWORK.id} for user with id ${TEST_USERS.HTTP.id} should not be found`))) + .catch(() => done()); + }); + + it(`should assign network with name: ${TEST_NETWORK.name} to user with login: ${TEST_USERS.WS.login} via WS`, done => { + wsDeviceHive.user.assignNetwork(TEST_USERS.WS.id, TEST_NETWORK.id) + .then(() => done()) + .catch(done); + }); + + it(`should get users network with name: ${TEST_NETWORK.name} via WS`, done => { + wsDeviceHive.user.getNetwork(TEST_USERS.WS.id, TEST_NETWORK.id) + .then(({ network }) => { + assert.exists(network); + assert.equal(network.name, TEST_NETWORK.name); + }) + .then(() => done()) + .catch(done); + }); + + it(`should unassign network with name: ${TEST_NETWORK.name} from user with login: ${TEST_USERS.WS.login} via WS`, done => { + wsDeviceHive.user.unassignNetwork(TEST_USERS.WS.id, TEST_NETWORK.id) + .then(() => wsDeviceHive.user.getNetwork(TEST_USERS.WS.id, TEST_NETWORK.id)) + .then(() => done(new Error(`Network with id ${TEST_NETWORK.id} for user with id ${TEST_USERS.WS.id} should not be found`))) + .catch(() => done()); + }); + + it(`should delete user with login: ${TEST_USERS.HTTP.login} via HTTP`, done => { + httpDeviceHive.user.delete(TEST_USERS.HTTP.id) + .then(() => done()) + .catch(done); + }); + + it(`should delete user with login: ${TEST_USERS.WS.login} via WS`, done => { + wsDeviceHive.user.delete(TEST_USERS.WS.id) + .then(() => done()) + .catch(done); + }); + + after(done => { + httpDeviceHive.deviceType.delete(TEST_DEVICE_TYPE.id) + .then(() => httpDeviceHive.network.delete(TEST_NETWORK.id)) + .then(() => { + httpDeviceHive.disconnect(); + wsDeviceHive.disconnect(); + + done(); + }); + }); +}); \ No newline at end of file diff --git a/test/unit/controllers/ConfigurationAPI.http.spec.js b/test/unit/controllers/ConfigurationAPI.http.spec.js index 69474d2..e99c46d 100644 --- a/test/unit/controllers/ConfigurationAPI.http.spec.js +++ b/test/unit/controllers/ConfigurationAPI.http.spec.js @@ -50,7 +50,8 @@ describe('ConfigurationAPI HTTP', () => { login: `dhadmin`, password: `dhadmin_#911`, mainServiceURL: 'http://localhost:3390', - authServiceURL: 'http://localhost:3391' + authServiceURL: 'http://localhost:3391', + autoUpdateSession: false }); deviceHive.connect() @@ -84,8 +85,7 @@ describe('ConfigurationAPI HTTP', () => { // Configurating Configaration model const expectedBody = { name: 'myTestName', - value: 'string', - entityVersion: '1' + value: 'string' }; const configuration = new DeviceHive.models.Configuration(expectedBody); diff --git a/test/unit/controllers/ConfigurationAPI.ws.spec.js b/test/unit/controllers/ConfigurationAPI.ws.spec.js index 8cc4734..072afd1 100644 --- a/test/unit/controllers/ConfigurationAPI.ws.spec.js +++ b/test/unit/controllers/ConfigurationAPI.ws.spec.js @@ -40,7 +40,8 @@ describe('ConfigurationAPI WS', () => { deviceHive = new DeviceHive({ login: `dhadmin`, password: `dhadmin_#911`, - mainServiceURL: 'ws://localhost:4390' + mainServiceURL: 'ws://localhost:4390', + autoUpdateSession: false }); deviceHive.connect() diff --git a/test/unit/controllers/DeviceAPI.http.spec.js b/test/unit/controllers/DeviceAPI.http.spec.js index 4df0037..3ab1849 100644 --- a/test/unit/controllers/DeviceAPI.http.spec.js +++ b/test/unit/controllers/DeviceAPI.http.spec.js @@ -50,7 +50,8 @@ describe('DeviceAPI', () => { login: `dhadmin`, password: `dhadmin_#911`, mainServiceURL: 'http://localhost:3390', - authServiceURL: 'http://localhost:3391' + authServiceURL: 'http://localhost:3391', + autoUpdateSession: false }); deviceHive.connect() @@ -107,7 +108,7 @@ describe('DeviceAPI', () => { name: 'myTestName', networkId: 1, deviceTypeId: 1, - blocked: false + isBlocked: false }; const device = new DeviceHive.models.Device(expectedBody); diff --git a/test/unit/controllers/DeviceAPI.ws.spec.js b/test/unit/controllers/DeviceAPI.ws.spec.js index b3b8c03..33cff90 100644 --- a/test/unit/controllers/DeviceAPI.ws.spec.js +++ b/test/unit/controllers/DeviceAPI.ws.spec.js @@ -40,7 +40,8 @@ describe('DeviceAPI WS', () => { deviceHive = new DeviceHive({ login: `dhadmin`, password: `dhadmin_#911`, - mainServiceURL: 'ws://localhost:4390' + mainServiceURL: 'ws://localhost:4390', + autoUpdateSession: false }); deviceHive.connect() @@ -97,7 +98,7 @@ describe('DeviceAPI WS', () => { name: 'myTestName', networkId: 1, deviceTypeId: 1, - blocked: false + isBlocked: false }; const device = new DeviceHive.models.Device(expected); diff --git a/test/unit/controllers/DeviceCommandAPI.http.spec.js b/test/unit/controllers/DeviceCommandAPI.http.spec.js index 5bf0ede..4cf17a6 100644 --- a/test/unit/controllers/DeviceCommandAPI.http.spec.js +++ b/test/unit/controllers/DeviceCommandAPI.http.spec.js @@ -50,7 +50,8 @@ describe('DeviceCommandAPI HTTP', () => { login: `dhadmin`, password: `dhadmin_#911`, mainServiceURL: 'http://localhost:3390', - authServiceURL: 'http://localhost:3391' + authServiceURL: 'http://localhost:3391', + autoUpdateSession: false }); deviceHive.connect() @@ -79,7 +80,7 @@ describe('DeviceCommandAPI HTTP', () => { it('DeviceCommandAPI.list()', done => { - const expectedQuery = { + const source = { deviceId: 'deviceId', start: '2018-02-09T10:09:03.033Z', end: '2018-02-09T10:09:03.033Z', @@ -91,16 +92,27 @@ describe('DeviceCommandAPI HTTP', () => { skip: '1' }; + const expected = { + start: '2018-02-09T10:09:03.033Z', + end: '2018-02-09T10:09:03.033Z', + command: 'command', + status: 'status', + sortField: 'sortField', + sortOrder: 'sortOrder', + take: '1', + skip: '1' + }; + // Configurating Device List query - const commandListQuery = new DeviceHive.models.query.CommandListQuery(expectedQuery); + const commandListQuery = new DeviceHive.models.query.CommandListQuery(source); deviceHive.command.list(commandListQuery); // sent data events.once('request', data => { assert.equal(data.method, 'GET', 'Not correct method'); - assert.equal(data.url.pathname, `/device/${expectedQuery.deviceId}/command`, 'Not correct URL'); - assert.deepEqual(data.url.parameters, expectedQuery, 'Not correct query'); + assert.equal(data.url.pathname, `/device/${source.deviceId}/command`, 'Not correct URL'); + assert.deepEqual(data.url.parameters, expected, 'Not correct query'); done(); }); @@ -180,7 +192,7 @@ describe('DeviceCommandAPI HTTP', () => { it('DeviceCommandAPI.poll()', done => { - const expectedQuery = { + const source = { deviceId: 'deviceId', names: 'names', timestamp: '2018-02-09T10:09:03.033Z', @@ -189,16 +201,24 @@ describe('DeviceCommandAPI HTTP', () => { limit: '1', }; + const expected = { + names: 'names', + timestamp: '2018-02-09T10:09:03.033Z', + returnUpdatedCommands: 'returnUpdatedCommands', + waitTimeout: '10', + limit: '1', + }; + // Configurating Command List query - const commandPollQuery = new DeviceHive.models.query.CommandPollQuery(expectedQuery); + const commandPollQuery = new DeviceHive.models.query.CommandPollQuery(source); deviceHive.command.poll(commandPollQuery); // sent data events.once('request', data => { assert.equal(data.method, 'GET', 'Not correct method'); - assert.equal(data.url.pathname, `/device/${expectedQuery.deviceId}/command/poll`, 'Not correct URL'); - assert.deepEqual(data.url.parameters, expectedQuery, 'Not correct query'); + assert.equal(data.url.pathname, `/device/${source.deviceId}/command/poll`, 'Not correct URL'); + assert.deepEqual(data.url.parameters, expected, 'Not correct query'); done(); }); @@ -233,22 +253,26 @@ describe('DeviceCommandAPI HTTP', () => { it('DeviceCommandAPI.wait()', done => { - const expectedQuery = { + const source = { deviceId: '1', commandId: '1', waitTimeout: '1' }; + const expected = { + waitTimeout: '1' + }; + // Configurating Command List query - const commandWaitQuery = new DeviceHive.models.query.CommandWaitQuery(expectedQuery); + const commandWaitQuery = new DeviceHive.models.query.CommandWaitQuery(source); - deviceHive.command.wait(expectedQuery.deviceId, expectedQuery.commandId, commandWaitQuery); + deviceHive.command.wait(source.deviceId, source.commandId, commandWaitQuery); // sent data events.once('request', data => { assert.equal(data.method, 'GET', 'Not correct method'); - assert.equal(data.url.pathname, `/device/${expectedQuery.deviceId}/command/${expectedQuery.commandId}/poll`, 'Not correct URL'); - assert.deepEqual(data.url.parameters, expectedQuery, 'Not correct query'); + assert.equal(data.url.pathname, `/device/${source.deviceId}/command/${source.commandId}/poll`, 'Not correct URL'); + assert.deepEqual(data.url.parameters, expected, 'Not correct query'); done(); }); diff --git a/test/unit/controllers/DeviceCommandAPI.ws.spec.js b/test/unit/controllers/DeviceCommandAPI.ws.spec.js index 364e317..a690828 100644 --- a/test/unit/controllers/DeviceCommandAPI.ws.spec.js +++ b/test/unit/controllers/DeviceCommandAPI.ws.spec.js @@ -40,7 +40,8 @@ describe('DeviceCommandAPI WS', () => { deviceHive = new DeviceHive({ login: `dhadmin`, password: `dhadmin_#911`, - mainServiceURL: 'ws://localhost:4390' + mainServiceURL: 'ws://localhost:4390', + autoUpdateSession: false }); deviceHive.connect() diff --git a/test/unit/controllers/NotificationAPI.http.spec.js b/test/unit/controllers/DeviceNotificationAPI.http.spec.js similarity index 83% rename from test/unit/controllers/NotificationAPI.http.spec.js rename to test/unit/controllers/DeviceNotificationAPI.http.spec.js index fa2fd51..260cc1a 100644 --- a/test/unit/controllers/NotificationAPI.http.spec.js +++ b/test/unit/controllers/DeviceNotificationAPI.http.spec.js @@ -11,7 +11,7 @@ const DeviceHive = require('../../../index'); let authService, mainService, deviceHive; -describe('NotificationAPI WS', () => { +describe('NotificationAPI HTTP', () => { before(done => { // authService @@ -50,7 +50,8 @@ describe('NotificationAPI WS', () => { login: `dhadmin`, password: `dhadmin_#911`, mainServiceURL: 'http://localhost:3390', - authServiceURL: 'http://localhost:3391' + authServiceURL: 'http://localhost:3391', + autoUpdateSession: false }); deviceHive.connect() @@ -79,7 +80,7 @@ describe('NotificationAPI WS', () => { it('NotificationAPI.list()', done => { - const expectedQuery = { + const source = { deviceId: 'deviceId', start: '2018-02-09T10:09:03.033Z', end: '2018-02-09T10:09:03.033Z', @@ -91,16 +92,26 @@ describe('NotificationAPI WS', () => { skip: '1' }; + const expected = { + start: '2018-02-09T10:09:03.033Z', + end: '2018-02-09T10:09:03.033Z', + notification: 'notification', + sortField: 'sortField', + sortOrder: 'sortOrder', + take: '1', + skip: '1' + }; + // Configurating Notification List query - const notificationListQuery = new DeviceHive.models.query.NotificationListQuery(expectedQuery); + const notificationListQuery = new DeviceHive.models.query.NotificationListQuery(source); deviceHive.notification.list(notificationListQuery); // sent data events.once('request', data => { assert.equal(data.method, 'GET', 'Not correct method'); - assert.equal(data.url.pathname, `/device/${expectedQuery.deviceId}/notification`, 'Not correct URL'); - assert.deepEqual(data.url.parameters, expectedQuery, 'Not correct query'); + assert.equal(data.url.pathname, `/device/${source.deviceId}/notification`, 'Not correct URL'); + assert.deepEqual(data.url.parameters, expected, 'Not correct query'); done(); }); @@ -136,23 +147,29 @@ describe('NotificationAPI WS', () => { it('NotificationAPI.poll()', done => { - const expectedQuery = { + const source = { deviceId: 'deviceId', names: 'names', timestamp: '2018-02-09T10:09:03.033Z', waitTimeout: '10' }; + const expected = { + names: 'names', + timestamp: '2018-02-09T10:09:03.033Z', + waitTimeout: '10' + }; + // Configurating Notification List query - const notificationPollQuery = new DeviceHive.models.query.NotificationPollQuery(expectedQuery); + const notificationPollQuery = new DeviceHive.models.query.NotificationPollQuery(source); deviceHive.notification.poll(notificationPollQuery); // sent data events.once('request', data => { assert.equal(data.method, 'GET', 'Not correct method'); - assert.equal(data.url.pathname, `/device/${expectedQuery.deviceId}/notification/poll`, 'Not correct URL'); - assert.deepEqual(data.url.parameters, expectedQuery, 'Not correct query'); + assert.equal(data.url.pathname, `/device/${source.deviceId}/notification/poll`, 'Not correct URL'); + assert.deepEqual(data.url.parameters, expected, 'Not correct query'); done(); }); diff --git a/test/unit/controllers/NotificationAPI.ws.spec.js b/test/unit/controllers/DeviceNotificationAPI.ws.spec.js similarity index 98% rename from test/unit/controllers/NotificationAPI.ws.spec.js rename to test/unit/controllers/DeviceNotificationAPI.ws.spec.js index 52558b3..fc3facd 100644 --- a/test/unit/controllers/NotificationAPI.ws.spec.js +++ b/test/unit/controllers/DeviceNotificationAPI.ws.spec.js @@ -40,7 +40,8 @@ describe('NotificationAPI WS', () => { deviceHive = new DeviceHive({ login: `dhadmin`, password: `dhadmin_#911`, - mainServiceURL: 'ws://localhost:4390' + mainServiceURL: 'ws://localhost:4390', + autoUpdateSession: false }); deviceHive.connect() @@ -75,7 +76,6 @@ describe('NotificationAPI WS', () => { start: '2018-02-09T10:09:03.033Z', end: '2018-02-09T10:09:03.033Z', notification: 'notification', - status: 'status', sortField: 'sortField', sortOrder: 'sortOrder', take: '1', diff --git a/test/unit/controllers/DeviceTypeAPI.http.spec.js b/test/unit/controllers/DeviceTypeAPI.http.spec.js index ca56fa0..89c44da 100644 --- a/test/unit/controllers/DeviceTypeAPI.http.spec.js +++ b/test/unit/controllers/DeviceTypeAPI.http.spec.js @@ -50,7 +50,8 @@ describe('DeviceTypeAPI HTTP', () => { login: `dhadmin`, password: `dhadmin_#911`, mainServiceURL: 'http://localhost:3390', - authServiceURL: 'http://localhost:3391' + authServiceURL: 'http://localhost:3391', + autoUpdateSession: false }); deviceHive.connect() diff --git a/test/unit/controllers/DeviceTypeAPI.ws.spec.js b/test/unit/controllers/DeviceTypeAPI.ws.spec.js index 9d67940..f041ff2 100644 --- a/test/unit/controllers/DeviceTypeAPI.ws.spec.js +++ b/test/unit/controllers/DeviceTypeAPI.ws.spec.js @@ -40,7 +40,8 @@ describe('DeviceTypeAPI WS', () => { deviceHive = new DeviceHive({ login: `dhadmin`, password: `dhadmin_#911`, - mainServiceURL: 'ws://localhost:4390' + mainServiceURL: 'ws://localhost:4390', + autoUpdateSession: false }); deviceHive.connect() diff --git a/test/unit/controllers/NetworkAPI.http.spec.js b/test/unit/controllers/NetworkAPI.http.spec.js index a60633e..b654370 100644 --- a/test/unit/controllers/NetworkAPI.http.spec.js +++ b/test/unit/controllers/NetworkAPI.http.spec.js @@ -50,7 +50,8 @@ describe('NetworkAPI', () => { login: `dhadmin`, password: `dhadmin_#911`, mainServiceURL: 'http://localhost:3390', - authServiceURL: 'http://localhost:3391' + authServiceURL: 'http://localhost:3391', + autoUpdateSession: false }); deviceHive.connect() diff --git a/test/unit/controllers/NetworkAPI.ws.spec.js b/test/unit/controllers/NetworkAPI.ws.spec.js index 73f3e8e..a330a88 100644 --- a/test/unit/controllers/NetworkAPI.ws.spec.js +++ b/test/unit/controllers/NetworkAPI.ws.spec.js @@ -40,7 +40,8 @@ describe('NetworkAPI WS', () => { deviceHive = new DeviceHive({ login: `dhadmin`, password: `dhadmin_#911`, - mainServiceURL: 'ws://localhost:4390' + mainServiceURL: 'ws://localhost:4390', + autoUpdateSession: false }); deviceHive.connect() diff --git a/test/unit/controllers/PluginAPI.http.spec.js b/test/unit/controllers/PluginAPI.http.spec.js index a7f8a39..fda4d71 100644 --- a/test/unit/controllers/PluginAPI.http.spec.js +++ b/test/unit/controllers/PluginAPI.http.spec.js @@ -73,6 +73,7 @@ describe('PluginAPI HTTP', () => { mainServiceURL: 'http://localhost:3390', authServiceURL: 'http://localhost:3391', pluginServiceURL: 'http://localhost:3392', + autoUpdateSession: false }); deviceHive.connect() diff --git a/test/unit/controllers/ServerInfoAPI.http.spec.js b/test/unit/controllers/ServerInfoAPI.http.spec.js index 152ab7b..0f9a048 100644 --- a/test/unit/controllers/ServerInfoAPI.http.spec.js +++ b/test/unit/controllers/ServerInfoAPI.http.spec.js @@ -50,7 +50,8 @@ describe('InfoAPI HTTP', () => { login: `dhadmin`, password: `dhadmin_#911`, mainServiceURL: 'http://localhost:3390', - authServiceURL: 'http://localhost:3391' + authServiceURL: 'http://localhost:3391', + autoUpdateSession: false }); deviceHive.connect() diff --git a/test/unit/controllers/ServerInfoAPI.ws.spec.js b/test/unit/controllers/ServerInfoAPI.ws.spec.js index 5f61a50..d41e76f 100644 --- a/test/unit/controllers/ServerInfoAPI.ws.spec.js +++ b/test/unit/controllers/ServerInfoAPI.ws.spec.js @@ -40,7 +40,8 @@ describe('InfoAPI WS', () => { deviceHive = new DeviceHive({ login: `dhadmin`, password: `dhadmin_#911`, - mainServiceURL: 'ws://localhost:4390' + mainServiceURL: 'ws://localhost:4390', + autoUpdateSession: false }); deviceHive.connect() diff --git a/test/unit/controllers/TokenAPI.http.spec.js b/test/unit/controllers/TokenAPI.http.spec.js index 438f02d..e75fb20 100644 --- a/test/unit/controllers/TokenAPI.http.spec.js +++ b/test/unit/controllers/TokenAPI.http.spec.js @@ -11,7 +11,7 @@ const DeviceHive = require('../../../index'); let authService, mainService, deviceHive; -describe('TokenAPI', () => { +describe('TokenAPI HTTP', () => { before(done => { // authService @@ -51,7 +51,8 @@ describe('TokenAPI', () => { login: `dhadmin`, password: `dhadmin_#911`, mainServiceURL: 'http://localhost:3390', - authServiceURL: 'http://localhost:3391' + authServiceURL: 'http://localhost:3391', + autoUpdateSession: false }); deviceHive.connect() diff --git a/test/unit/controllers/TokenAPI.ws.spec.js b/test/unit/controllers/TokenAPI.ws.spec.js index de64cca..a1a455a 100644 --- a/test/unit/controllers/TokenAPI.ws.spec.js +++ b/test/unit/controllers/TokenAPI.ws.spec.js @@ -40,7 +40,8 @@ describe('TokenAPI WS', () => { deviceHive = new DeviceHive({ login: `dhadmin`, password: `dhadmin_#911`, - mainServiceURL: 'ws://localhost:4390' + mainServiceURL: 'ws://localhost:4390', + autoUpdateSession: false }); deviceHive.connect() diff --git a/test/unit/controllers/UserAPI.http.spec.js b/test/unit/controllers/UserAPI.http.spec.js index 7c105b6..a69244a 100644 --- a/test/unit/controllers/UserAPI.http.spec.js +++ b/test/unit/controllers/UserAPI.http.spec.js @@ -11,7 +11,7 @@ const DeviceHive = require('../../../index'); let authService, mainService, deviceHive; -describe('UserAPI', () => { +describe('UserAPI HTTP', () => { before(done => { // authService @@ -50,7 +50,8 @@ describe('UserAPI', () => { login: `dhadmin`, password: `dhadmin_#911`, mainServiceURL: 'http://localhost:3390', - authServiceURL: 'http://localhost:3391' + authServiceURL: 'http://localhost:3391', + autoUpdateSession: false }); deviceHive.connect() diff --git a/test/unit/controllers/UserAPI.ws.spec.js b/test/unit/controllers/UserAPI.ws.spec.js index ec91fb6..0b33f0b 100644 --- a/test/unit/controllers/UserAPI.ws.spec.js +++ b/test/unit/controllers/UserAPI.ws.spec.js @@ -40,7 +40,8 @@ describe('NetworkAPI WS', () => { deviceHive = new DeviceHive({ login: `dhadmin`, password: `dhadmin_#911`, - mainServiceURL: 'ws://localhost:4390' + mainServiceURL: 'ws://localhost:4390', + autoUpdateSession: false }); deviceHive.connect() diff --git a/test/unit/models/Configuration.spec.js b/test/unit/models/Configuration.spec.js index 38b92b9..e9d606d 100644 --- a/test/unit/models/Configuration.spec.js +++ b/test/unit/models/Configuration.spec.js @@ -6,8 +6,7 @@ describe('Configuration', () => { const expected = { name: 'string', - value: 'string', - entityVersion: 0 + value: 'string' }; diff --git a/test/unit/models/Device.spec.js b/test/unit/models/Device.spec.js index 6921455..ab37321 100644 --- a/test/unit/models/Device.spec.js +++ b/test/unit/models/Device.spec.js @@ -11,7 +11,7 @@ describe('Device', () => { }, networkId: 0, deviceTypeId: 0, - blocked: false + isBlocked: false }; diff --git a/test/unit/modelsQuery/NotificationListQuery.spec.js b/test/unit/modelsQuery/NotificationListQuery.spec.js index 96c0a05..90ba20b 100644 --- a/test/unit/modelsQuery/NotificationListQuery.spec.js +++ b/test/unit/modelsQuery/NotificationListQuery.spec.js @@ -9,7 +9,6 @@ describe('NotificationListQuery', () => { start: '2018-02-09T10:09:03.033Z', end: '2018-02-09T10:09:03.033Z', notification: 'string', - status: 'string', sortField: 'string', sortOrder: 'string', take: 1,