From 6e240c181f1c58c24b4ba27e0e001a20bfb3c4f9 Mon Sep 17 00:00:00 2001 From: Martin M Date: Fri, 29 Nov 2019 02:25:38 -0300 Subject: [PATCH] Release v1.10.0 (#38) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 100% coverage for mixins/user/regionMixin.js * check if websocket connection is valid json * removed unnecessary delays * added more test cases * move constants to json files * renamed login method to getCredentials * mixin renamed * don’t export internal methods * mixin renamed * keep socket connection opened * using new getCredentials method * reanmed login to credentials * version bump --- lib/data/devices-channel-length.json | 20 +++++ lib/data/devices-type-uuid.json | 55 ++++++++++++ lib/ewelink-helper.js | 87 ++----------------- ...{loginPayload.js => credentialsPayload.js} | 4 +- lib/payloads/index.js | 4 +- main.js | 58 ++----------- mixins/user/getCredentialsMixin.js | 59 +++++++++++++ .../{regionMixin.js => getRegionMixin.js} | 14 +-- mixins/websocket/openWebSocketMixin.js | 16 +++- package-lock.json | 2 +- package.json | 2 +- test/_setup/expectations.js | 4 +- test/env-node.spec.js | 14 ++- test/env-serverless.spec.js | 16 ++-- test/firmware.spec.js | 4 +- test/helpers.spec.js | 36 ++++++++ test/invalid-credentials.spec.js | 10 +-- test/power-usage.spec.js | 8 +- test/temperature-humidity.spec.js | 8 +- test/user.spec.js | 28 ++++-- test/valid-credentials.spec.js | 10 +-- 21 files changed, 264 insertions(+), 195 deletions(-) create mode 100644 lib/data/devices-channel-length.json create mode 100644 lib/data/devices-type-uuid.json rename lib/payloads/{loginPayload.js => credentialsPayload.js} (79%) create mode 100644 mixins/user/getCredentialsMixin.js rename mixins/user/{regionMixin.js => getRegionMixin.js} (52%) create mode 100644 test/helpers.spec.js diff --git a/lib/data/devices-channel-length.json b/lib/data/devices-channel-length.json new file mode 100644 index 0000000..10d7b22 --- /dev/null +++ b/lib/data/devices-channel-length.json @@ -0,0 +1,20 @@ +{ + "SOCKET": 1, + "SWITCH_CHANGE": 1, + "GSM_UNLIMIT_SOCKET": 1, + "SWITCH": 1, + "THERMOSTAT": 1, + "SOCKET_POWER": 1, + "GSM_SOCKET": 1, + "POWER_DETECTION_SOCKET": 1, + "SOCKET_2": 2, + "GSM_SOCKET_2": 2, + "SWITCH_2": 2, + "SOCKET_3": 3, + "GSM_SOCKET_3": 3, + "SWITCH_3": 3, + "SOCKET_4": 4, + "GSM_SOCKET_4": 4, + "SWITCH_4": 4, + "CUN_YOU_DOOR": 4 +} \ No newline at end of file diff --git a/lib/data/devices-type-uuid.json b/lib/data/devices-type-uuid.json new file mode 100644 index 0000000..ce23d23 --- /dev/null +++ b/lib/data/devices-type-uuid.json @@ -0,0 +1,55 @@ +{ + "1": "SOCKET", + "2": "SOCKET_2", + "3": "SOCKET_3", + "4": "SOCKET_4", + "6": "SWITCH", + "5": "SOCKET_POWER", + "7": "SWITCH_2", + "8": "SWITCH_3", + "9": "SWITCH_4", + "10": "OSPF", + "11": "CURTAIN", + "12": "EW-RE", + "13": "FIREPLACE", + "14": "SWITCH_CHANGE", + "15": "THERMOSTAT", + "16": "COLD_WARM_LED", + "17": "THREE_GEAR_FAN", + "18": "SENSORS_CENTER", + "19": "HUMIDIFIER", + "22": "RGB_BALL_LIGHT", + "23": "NEST_THERMOSTAT", + "24": "GSM_SOCKET", + "25": "AROMATHERAPY", + "26": "BJ_THERMOSTAT", + "27": "GSM_UNLIMIT_SOCKET", + "28": "RF_BRIDGE", + "29": "GSM_SOCKET_2", + "30": "GSM_SOCKET_3", + "31": "GSM_SOCKET_4", + "32": "POWER_DETECTION_SOCKET", + "33": "LIGHT_BELT", + "34": "FAN_LIGHT", + "35": "EZVIZ_CAMERA", + "36": "SINGLE_CHANNEL_DIMMER_SWITCH", + "38": "HOME_KIT_BRIDGE", + "40": "FUJIN_OPS", + "41": "CUN_YOU_DOOR", + "42": "SMART_BEDSIDE_AND_NEW_RGB_BALL_LIGHT", + "43": "", + "44": "", + "45": "DOWN_CEILING_LIGHT", + "46": "AIR_CLEANER", + "49": "MACHINE_BED", + "51": "COLD_WARM_DESK_LIGHT", + "52": "DOUBLE_COLOR_DEMO_LIGHT", + "53": "ELECTRIC_FAN_WITH_LAMP", + "55": "SWEEPING_ROBOT", + "56": "RGB_BALL_LIGHT_4", + "57": "MONOCHROMATIC_BALL_LIGHT", + "59": "MEARICAMERA", + "1001": "BLADELESS_FAN", + "1002": "NEW_HUMIDIFIER", + "1003": "WARM_AIR_BLOWER" +} \ No newline at end of file diff --git a/lib/ewelink-helper.js b/lib/ewelink-helper.js index 034ee2c..396f827 100644 --- a/lib/ewelink-helper.js +++ b/lib/ewelink-helper.js @@ -1,6 +1,9 @@ const crypto = require('crypto'); const random = require('random'); +const DEVICE_TYPE_UUID = require('./data/devices-type-uuid'); +const DEVICE_CHANNEL_LENGTH = require('./data/devices-channel-length'); + const makeFakeIMEI = () => { const num1 = random.int(1000, 9999); const num2 = random.int(1000, 9999); @@ -13,88 +16,10 @@ const makeAuthorizationSign = body => .update(JSON.stringify(body)) .digest('base64'); -const getDeviceTypeByUiid = uiid => { - const MAPPING = { - 1: 'SOCKET', - 2: 'SOCKET_2', - 3: 'SOCKET_3', - 4: 'SOCKET_4', - 5: 'SOCKET_POWER', - 6: 'SWITCH', - 7: 'SWITCH_2', - 8: 'SWITCH_3', - 9: 'SWITCH_4', - 10: 'OSPF', - 11: 'CURTAIN', - 12: 'EW-RE', - 13: 'FIREPLACE', - 14: 'SWITCH_CHANGE', - 15: 'THERMOSTAT', - 16: 'COLD_WARM_LED', - 17: 'THREE_GEAR_FAN', - 18: 'SENSORS_CENTER', - 19: 'HUMIDIFIER', - 22: 'RGB_BALL_LIGHT', - 23: 'NEST_THERMOSTAT', - 24: 'GSM_SOCKET', - 25: 'AROMATHERAPY', - 26: 'BJ_THERMOSTAT', - 27: 'GSM_UNLIMIT_SOCKET', - 28: 'RF_BRIDGE', - 29: 'GSM_SOCKET_2', - 30: 'GSM_SOCKET_3', - 31: 'GSM_SOCKET_4', - 32: 'POWER_DETECTION_SOCKET', - 33: 'LIGHT_BELT', - 34: 'FAN_LIGHT', - 35: 'EZVIZ_CAMERA', - 36: 'SINGLE_CHANNEL_DIMMER_SWITCH', - 38: 'HOME_KIT_BRIDGE', - 40: 'FUJIN_OPS', - 41: 'CUN_YOU_DOOR', - 42: 'SMART_BEDSIDE_AND_NEW_RGB_BALL_LIGHT', - 43: '', - 44: '', - 45: 'DOWN_CEILING_LIGHT', - 46: 'AIR_CLEANER', - 49: 'MACHINE_BED', - 51: 'COLD_WARM_DESK_LIGHT', - 52: 'DOUBLE_COLOR_DEMO_LIGHT', - 53: 'ELECTRIC_FAN_WITH_LAMP', - 55: 'SWEEPING_ROBOT', - 56: 'RGB_BALL_LIGHT_4', - 57: 'MONOCHROMATIC_BALL_LIGHT', - 59: 'MEARICAMERA', - 1001: 'BLADELESS_FAN', - 1002: 'NEW_HUMIDIFIER', - 1003: 'WARM_AIR_BLOWER', - }; - return MAPPING[uiid] || ''; -}; +const getDeviceTypeByUiid = uiid => DEVICE_TYPE_UUID[uiid] || ''; -const getDeviceChannelCountByType = deviceType => { - const DEVICE_CHANNEL_LENGTH = { - SOCKET: 1, - SWITCH_CHANGE: 1, - GSM_UNLIMIT_SOCKET: 1, - SWITCH: 1, - THERMOSTAT: 1, - SOCKET_POWER: 1, - GSM_SOCKET: 1, - POWER_DETECTION_SOCKET: 1, - SOCKET_2: 2, - GSM_SOCKET_2: 2, - SWITCH_2: 2, - SOCKET_3: 3, - GSM_SOCKET_3: 3, - SWITCH_3: 3, - SOCKET_4: 4, - GSM_SOCKET_4: 4, - SWITCH_4: 4, - CUN_YOU_DOOR: 4, - }; - return DEVICE_CHANNEL_LENGTH[deviceType] || 0; -}; +const getDeviceChannelCountByType = deviceType => + DEVICE_CHANNEL_LENGTH[deviceType] || 0; const getDeviceChannelCount = deviceUUID => { const deviceType = getDeviceTypeByUiid(deviceUUID); diff --git a/lib/payloads/loginPayload.js b/lib/payloads/credentialsPayload.js similarity index 79% rename from lib/payloads/loginPayload.js rename to lib/payloads/credentialsPayload.js index bccfc67..53ba099 100644 --- a/lib/payloads/loginPayload.js +++ b/lib/payloads/credentialsPayload.js @@ -2,7 +2,7 @@ const nonce = require('nonce')(); const { makeFakeIMEI } = require('../ewelink-helper'); -const loginPayload = ({ email, password }) => ({ +const credentialsPayload = ({ email, password }) => ({ email, password, version: 6, @@ -16,4 +16,4 @@ const loginPayload = ({ email, password }) => ({ appVersion: '3.5.3', }); -module.exports = loginPayload; +module.exports = credentialsPayload; diff --git a/lib/payloads/index.js b/lib/payloads/index.js index 9ec1a8f..98e52eb 100644 --- a/lib/payloads/index.js +++ b/lib/payloads/index.js @@ -1,11 +1,11 @@ const firmwareUpdate = require('./firmwareUpdate'); -const loginPayload = require('./loginPayload'); +const credentialsPayload = require('./credentialsPayload'); const wssLoginPayload = require('./wssLoginPayload'); const wssUpdatePayload = require('./wssUpdatePayload'); module.exports = { firmwareUpdate, - loginPayload, + credentialsPayload, wssLoginPayload, wssUpdatePayload, }; diff --git a/main.js b/main.js index 01e2069..9e98fa1 100644 --- a/main.js +++ b/main.js @@ -2,10 +2,6 @@ const rp = require('request-promise'); const { _get } = require('./lib/helpers'); -const { makeAuthorizationSign } = require('./lib/ewelink-helper'); - -const payloads = require('./lib/payloads'); - class eWeLink { constructor({ region = 'us', email, password, at, apiKey }) { if (!at && (!email && !password)) { @@ -60,7 +56,7 @@ class eWeLink { const { at } = this; if (!at) { - await this.login(); + await this.getCredentials(); } let apiUrl = this.getApiUrl(); @@ -85,49 +81,12 @@ class eWeLink { return response; } - - /** - * Helper to login into eWeLink API - * - * @returns {Promise<{msg: string, error: *}>} - */ - async login() { - const body = payloads.loginPayload({ - email: this.email, - password: this.password, - }); - - let response = await rp({ - method: 'POST', - uri: `${this.getApiUrl()}/user/login`, - headers: { Authorization: `Sign ${makeAuthorizationSign(body)}` }, - body, - json: true, - }); - - const error = _get(response, 'error', false); - const region = _get(response, 'region', false); - - if (error && [400, 401, 404].indexOf(parseInt(error)) !== -1) { - return { error, msg: 'Authentication error' }; - } - - if (error && parseInt(error) === 301 && region) { - if (this.region !== region) { - this.region = region; - response = await this.login(); - return response; - } - return { error, msg: 'Region does not exist' }; - } - - this.apiKey = _get(response, 'user.apikey', ''); - this.at = _get(response, 'at', ''); - return response; - } - } +/* LOAD MIXINS: user */ +const getCredentialsMixin = require('./mixins/user/getCredentialsMixin'); +const getRegionMixin = require('./mixins/user/getRegionMixin'); + /* LOAD MIXINS: power state */ const getDevicePowerStateMixin = require('./mixins/powerState/getDevicePowerStateMixin'); const setDevicePowerState = require('./mixins/powerState/setDevicePowerStateMixin'); @@ -150,12 +109,11 @@ const getFirmwareVersionMixin = require('./mixins/firmware/getFirmwareVersionMix const checkDeviceUpdateMixin = require('./mixins/firmware/checkDeviceUpdateMixin'); const checkDevicesUpdatesMixin = require('./mixins/firmware/checkDevicesUpdatesMixin'); -/* LOAD MIXINS: user */ -const regionMixin = require('./mixins/user/regionMixin'); - /* LOAD MIXINS: websocket */ const openWebSocketMixin = require('./mixins/websocket/openWebSocketMixin'); +Object.assign(eWeLink.prototype, getCredentialsMixin, getRegionMixin); + Object.assign( eWeLink.prototype, getDevicePowerStateMixin, @@ -185,8 +143,6 @@ Object.assign( checkDevicesUpdatesMixin ); -Object.assign(eWeLink.prototype, regionMixin); - Object.assign(eWeLink.prototype, openWebSocketMixin); module.exports = eWeLink; diff --git a/mixins/user/getCredentialsMixin.js b/mixins/user/getCredentialsMixin.js new file mode 100644 index 0000000..0b243e4 --- /dev/null +++ b/mixins/user/getCredentialsMixin.js @@ -0,0 +1,59 @@ +const rp = require('request-promise'); + +const { _get } = require('../../lib/helpers'); +const { credentialsPayload } = require('../../lib/payloads'); +const { makeAuthorizationSign } = require('../../lib/ewelink-helper'); + +const getCredentialsMixin = { + /** + * Returns user credentials information + * + * @returns {Promise<{msg: string, error: *}>} + */ + async getCredentials() { + const body = credentialsPayload({ + email: this.email, + password: this.password, + }); + + let response = await rp({ + method: 'POST', + uri: `${this.getApiUrl()}/user/login`, + headers: { Authorization: `Sign ${makeAuthorizationSign(body)}` }, + body, + json: true, + }); + + const error = _get(response, 'error', false); + const region = _get(response, 'region', false); + + if (error && [400, 401, 404].indexOf(parseInt(error)) !== -1) { + return { error, msg: 'Authentication error' }; + } + + if (error && parseInt(error) === 301 && region) { + if (this.region !== region) { + this.region = region; + response = await this.getCredentials(); + return response; + } + return { error, msg: 'Region does not exist' }; + } + + this.apiKey = _get(response, 'user.apikey', ''); + this.at = _get(response, 'at', ''); + return response; + }, + + /** + * DEPRECATED: keept for backward compatibility + * Will be removed on version 2.0 + * + * @returns {Promise<{msg: string, error: *}>} + */ + async login() { + return this.getCredentials(); + }, +}; + +module.exports = getCredentialsMixin; diff --git a/mixins/user/regionMixin.js b/mixins/user/getRegionMixin.js similarity index 52% rename from mixins/user/regionMixin.js rename to mixins/user/getRegionMixin.js index bea869b..c78ca6b 100644 --- a/mixins/user/regionMixin.js +++ b/mixins/user/getRegionMixin.js @@ -1,6 +1,6 @@ const { _get } = require('../../lib/helpers'); -const regionMixin = { +const getRegionMixin = { async getRegion() { if (!this.email || !this.password) { return { @@ -9,19 +9,19 @@ const regionMixin = { }; } - const login = await this.login(); + const credentials = await this.getCredentials(); - const error = _get(login, 'error', false); + const error = _get(credentials, 'error', false); if (error) { - return login; + return credentials; } return { - email: login.user.email, - region: login.region, + email: credentials.user.email, + region: credentials.region, }; }, }; -module.exports = regionMixin; +module.exports = getRegionMixin; diff --git a/mixins/websocket/openWebSocketMixin.js b/mixins/websocket/openWebSocketMixin.js index 3786be2..c420948 100644 --- a/mixins/websocket/openWebSocketMixin.js +++ b/mixins/websocket/openWebSocketMixin.js @@ -9,10 +9,10 @@ const openWebSocketMixin = { * and execute callback function with server message as argument * * @param callback - * + * @param heartbeat * @returns {Promise} */ - async openWebSocket(callback) { + async openWebSocket(callback, ...{ heartbeat = 120000 }) { const payloadLogin = payloads.wssLoginPayload({ at: this.at, apiKey: this.apiKey, @@ -23,13 +23,21 @@ const openWebSocketMixin = { }); wsp.onMessage.addListener(message => { - const data = JSON.parse(message); - callback(data); + try { + const data = JSON.parse(message); + callback(data); + } catch (error) { + callback(message); + } }); await wsp.open(); await wsp.send(payloadLogin); + setInterval(async () => { + await wsp.send('ping'); + }, heartbeat); + return wsp; }, }; diff --git a/package-lock.json b/package-lock.json index 9bfa371..9eba8cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "ewelink-api", - "version": "1.9.0", + "version": "1.10.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 47668be..2c02d11 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ewelink-api", - "version": "1.9.0", + "version": "1.10.0", "description": "eWeLink API for Node.js", "author": "Martín M.", "license": "MIT", diff --git a/test/_setup/expectations.js b/test/_setup/expectations.js index 16e8f6a..35c71a3 100644 --- a/test/_setup/expectations.js +++ b/test/_setup/expectations.js @@ -1,4 +1,4 @@ -const loginExpectations = { +const credentialsExpectations = { at: expect.any(String), user: { email: expect.any(String) }, region: expect.any(String), @@ -56,7 +56,7 @@ const regionExpectations = { }; module.exports = { - loginExpectations, + credentialsExpectations: credentialsExpectations, allDevicesExpectations, specificDeviceExpectations, rawPowerUsageExpectations, diff --git a/test/env-node.spec.js b/test/env-node.spec.js index 742c0aa..2291fc9 100644 --- a/test/env-node.spec.js +++ b/test/env-node.spec.js @@ -10,7 +10,7 @@ const { } = require('./_setup/credentials.json'); const { - loginExpectations, + credentialsExpectations, allDevicesExpectations, specificDeviceExpectations, } = require('./_setup/expectations'); @@ -26,10 +26,10 @@ describe('env: node script', () => { await delay(1000); }); - test('login into ewelink', async () => { - const login = await conn.login(); - expect(typeof login).toBe('object'); - expect(login).toMatchObject(loginExpectations); + test('get ewelink credentials', async () => { + const credentials = await conn.getCredentials(); + expect(typeof credentials).toBe('object'); + expect(credentials).toMatchObject(credentialsExpectations); }); test('get all devices', async () => { @@ -69,7 +69,6 @@ describe('env: node script', () => { test('set single channel device power state', async () => { jest.setTimeout(30000); - await delay(3000); const device = await conn.getDevice(singleChannelDeviceId); const currentState = device.params.switch; const newState = currentState === 'on' ? 'off' : 'on'; @@ -87,7 +86,6 @@ describe('env: node script', () => { test('set multi channel device power state', async () => { jest.setTimeout(30000); - await delay(3000); const channel = 3; const device = await conn.getDevice(fourChannelsDevice); const currentState = device.params.switches[channel - 1].switch; @@ -107,7 +105,6 @@ describe('env: node script', () => { test('toggle single channel device power state', async () => { jest.setTimeout(30000); - await delay(3000); const device = await conn.getDevice(singleChannelDeviceId); const currentState = device.params.switch; const newState = currentState === 'on' ? 'off' : 'on'; @@ -123,7 +120,6 @@ describe('env: node script', () => { test('toggle multi channel device power state', async () => { jest.setTimeout(30000); - await delay(3000); const channel = 3; const device = await conn.getDevice(fourChannelsDevice); const currentState = device.params.switches[channel - 1].switch; diff --git a/test/env-serverless.spec.js b/test/env-serverless.spec.js index bc24c5b..d586198 100644 --- a/test/env-serverless.spec.js +++ b/test/env-serverless.spec.js @@ -10,7 +10,7 @@ const { } = require('./_setup/credentials.json'); const { - loginExpectations, + credentialsExpectations, allDevicesExpectations, specificDeviceExpectations, } = require('./_setup/expectations'); @@ -23,13 +23,13 @@ describe('env: serverless', () => { await delay(1000); }); - test('login into ewelink', async () => { + test('get ewelink credentials', async () => { const conn = new ewelink({ email, password }); - const login = await conn.login(); - accessToken = login.at; - apiKey = login.user.apikey; - expect(typeof login).toBe('object'); - expect(login).toMatchObject(loginExpectations); + const credentials = await conn.getCredentials(); + accessToken = credentials.at; + apiKey = credentials.user.apikey; + expect(typeof credentials).toBe('object'); + expect(credentials).toMatchObject(credentialsExpectations); }); test('get all devices', async () => { @@ -59,7 +59,6 @@ describe('env: serverless', () => { test('set device power state', async () => { jest.setTimeout(30000); - await delay(3000); const conn = new ewelink({ at: accessToken, apiKey }); const device = await conn.getDevice(singleChannelDeviceId); const currentState = device.params.switch; @@ -78,7 +77,6 @@ describe('env: serverless', () => { test('toggle device power state', async () => { jest.setTimeout(30000); - await delay(3000); const conn = new ewelink({ at: accessToken, apiKey }); const device = await conn.getDevice(singleChannelDeviceId); const currentState = device.params.switch; diff --git a/test/firmware.spec.js b/test/firmware.spec.js index 3f9cc14..3bfc70e 100644 --- a/test/firmware.spec.js +++ b/test/firmware.spec.js @@ -27,8 +27,8 @@ describe.skip('firmware: get version methods', () => { }); test('get device firmware version should be right message', async () => { - const login = await connection.login(); - const accessToken = login.at; + const credentials = await connection.getCredentials(); + const accessToken = credentials.at; const conn = new ewelink({ at: accessToken }); const device = await conn.getDevice(singleChannelDeviceId); const currentVersion = device.params.fwVersion; diff --git a/test/helpers.spec.js b/test/helpers.spec.js new file mode 100644 index 0000000..5ebc2d1 --- /dev/null +++ b/test/helpers.spec.js @@ -0,0 +1,36 @@ +const ewelinkHelpers = require('../lib/ewelink-helper'); + +describe('check eWeLink helpers', () => { + test('should return fake imei', async () => { + const imei = ewelinkHelpers.makeFakeIMEI(); + expect(imei.length).toBe(36); + expect(imei.substr(0, 9)).toBe('DF7425A0-'); + expect(imei.substr(imei.length - 18, imei.length)).toBe( + '-9F5E-3BC9179E48FB' + ); + }); + + test('make authorization sign should return right string', async () => { + const auth = ewelinkHelpers.makeAuthorizationSign({ data: 'string' }); + expect(auth.length).toBe(44); + expect(auth).toBe('WtmdvaPxqhi3pd8ck1R/bvzfRzHgxDTwgnuOib33xx4='); + }); + + test('getDeviceChannelCount method should return right value', async () => { + const deviceA = ewelinkHelpers.getDeviceChannelCount(8); + expect(typeof deviceA).toBe('number'); + expect(deviceA).toBe(3); + const deviceB = ewelinkHelpers.getDeviceChannelCount(31); + expect(typeof deviceB).toBe('number'); + expect(deviceB).toBe(4); + const deviceC = ewelinkHelpers.getDeviceChannelCount(29); + expect(typeof deviceC).toBe('number'); + expect(deviceC).toBe(2); + const deviceD = ewelinkHelpers.getDeviceChannelCount(27); + expect(typeof deviceD).toBe('number'); + expect(deviceD).toBe(1); + const unknownDevice = ewelinkHelpers.getDeviceChannelCount(5000); + expect(typeof unknownDevice).toBe('number'); + expect(unknownDevice).toBe(0); + }); +}); diff --git a/test/invalid-credentials.spec.js b/test/invalid-credentials.spec.js index 96fdba7..2fac8c0 100644 --- a/test/invalid-credentials.spec.js +++ b/test/invalid-credentials.spec.js @@ -19,12 +19,12 @@ describe('invalid credentials', () => { expect(conn.error).toBe('No credentials provided'); }); - test('get error response on api login', async () => { + test('get error response on ewelink credentials', async () => { const conn = new ewelink({ email: 'invalid', password: 'credentials' }); - const login = await conn.login(); - expect(typeof login).toBe('object'); - expect(login.msg).toBe('Authentication error'); - expect(login.error).toBe(400); + const credentials = await conn.getCredentials(); + expect(typeof credentials).toBe('object'); + expect(credentials.msg).toBe('Authentication error'); + expect(credentials.error).toBe(400); }); test('get error response on all devices', async () => { diff --git a/test/power-usage.spec.js b/test/power-usage.spec.js index 2e2a810..ca18105 100644 --- a/test/power-usage.spec.js +++ b/test/power-usage.spec.js @@ -18,7 +18,7 @@ describe('power usage: node script', () => { beforeAll(async () => { conn = new ewelink({ email, password }); - await conn.login(); + await conn.getCredentials(); }); beforeEach(async () => { @@ -49,9 +49,9 @@ describe('power usage: serverless', () => { beforeAll(async () => { const conn = new ewelink({ email, password }); - const login = await conn.login(); - accessToken = login.at; - apiKey = login.user.apikey; + const credentials = await conn.getCredentials(); + accessToken = credentials.at; + apiKey = credentials.user.apikey; }); test('should return raw power usage', async () => { diff --git a/test/temperature-humidity.spec.js b/test/temperature-humidity.spec.js index 2d0ccdb..db66f4d 100644 --- a/test/temperature-humidity.spec.js +++ b/test/temperature-humidity.spec.js @@ -15,7 +15,7 @@ describe('current temperature and humidity: node script', () => { beforeAll(async () => { conn = new ewelink({ email, password }); - await conn.login(); + await conn.getCredentials(); }); beforeEach(async () => { @@ -57,9 +57,9 @@ describe('current temperature and humidity: serverless', () => { beforeAll(async () => { const conn = new ewelink({ email, password }); - const login = await conn.login(); - accessToken = login.at; - apiKey = login.user.apikey; + const credentials = await conn.getCredentials(); + accessToken = credentials.at; + apiKey = credentials.user.apikey; }); beforeEach(async () => { diff --git a/test/user.spec.js b/test/user.spec.js index 48ecd71..053427a 100644 --- a/test/user.spec.js +++ b/test/user.spec.js @@ -5,17 +5,33 @@ const { email, password, region } = require('./_setup/credentials.json'); const { regionExpectations } = require('./_setup/expectations'); describe('check user information', () => { - let connection; - - beforeAll(() => { - connection = new ewelink({ email, password }); - }); - test('region should be returned', async () => { + const connection = new ewelink({ email, password }); const response = await connection.getRegion(); expect(response).toMatchObject(regionExpectations); expect(typeof response).toBe('object'); expect(response.email).toBe(email); expect(response.region).toBe(region); }); + + test('invalid credentials should fail', async () => { + const connection = new ewelink({ + email: 'invalid', + password: 'credentials', + }); + const response = await connection.getRegion(); + expect(typeof response).toBe('object'); + expect(response.msg).toBe('Authentication error'); + expect(response.error).toBe(400); + }); + + test('invalid initialization should warn user', async () => { + const connection = new ewelink({ at: 'access token' }); + const response = await connection.getRegion(); + expect(typeof response).toBe('object'); + expect(response.msg).toBe( + 'Library needs to be initialized using email and password' + ); + expect(response.error).toBe(406); + }); }); diff --git a/test/valid-credentials.spec.js b/test/valid-credentials.spec.js index 07a5d3d..9da7d24 100644 --- a/test/valid-credentials.spec.js +++ b/test/valid-credentials.spec.js @@ -9,7 +9,7 @@ const { fourChannelsDevice, } = require('./_setup/credentials.json'); -const { loginExpectations } = require('./_setup/expectations'); +const { credentialsExpectations } = require('./_setup/expectations'); describe('valid credentials, invalid device', () => { beforeEach(async () => { @@ -99,10 +99,10 @@ describe('valid credentials, invalid device', () => { }); describe('valid credentials, wrong region', () => { - test('should login in the right region', async () => { + test('should get valid credentials in the right region', async () => { const conn = new ewelink({ email, password, region: 'eu' }); - const login = await conn.login(); - expect(typeof login).toBe('object'); - expect(login).toMatchObject(loginExpectations); + const credentials = await conn.getCredentials(); + expect(typeof credentials).toBe('object'); + expect(credentials).toMatchObject(credentialsExpectations); }); });