From 8a3e186f2d2182259dba0b56151690898e528f86 Mon Sep 17 00:00:00 2001 From: ka-vaNu Date: Tue, 24 Dec 2024 10:27:57 +0100 Subject: [PATCH 1/3] order deps --- package-lock.json | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index babd3ae..2c2aeed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,10 +33,10 @@ "chai": "^4.4.1", "chai-as-promised": "^7.1.1", "mocha": "^10.3.0", + "nodemon": "^3.1.9", "proxyquire": "^2.1.3", "sinon": "^17.0.1", - "sinon-chai": "^3.7.0", - "nodemon": "^3.1.9" + "sinon-chai": "^3.7.0" }, "engines": { "node": ">= 18" @@ -2030,6 +2030,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", @@ -2297,6 +2298,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2326,6 +2328,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -2579,6 +2582,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, "license": "MIT", "dependencies": { "anymatch": "~3.1.2", @@ -2603,6 +2607,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -2829,6 +2834,7 @@ "version": "4.4.0", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -3983,6 +3989,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -4113,6 +4120,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -4648,6 +4656,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true, "license": "ISC" }, "node_modules/import-fresh": { @@ -4788,6 +4797,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" @@ -4902,6 +4912,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -4955,6 +4966,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -4994,6 +5006,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -5947,6 +5960,7 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, "license": "MIT" }, "node_modules/natural-compare": { @@ -6027,6 +6041,7 @@ "version": "3.1.9", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.9.tgz", "integrity": "sha512-hdr1oIb2p6ZSxu3PB2JWWYS7ZQ0qvaZsc3hK8DR8f02kRzc8rjYmxAIvdz+aYC+8F2IjNaB7HMcSDg8nQpJxyg==", + "dev": true, "license": "MIT", "dependencies": { "chokidar": "^3.5.2", @@ -6055,6 +6070,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -6064,6 +6080,7 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "license": "MIT", "dependencies": { "has-flag": "^3.0.0" @@ -6101,6 +6118,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -6443,6 +6461,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -6662,6 +6681,7 @@ "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true, "license": "MIT" }, "node_modules/punycode": { @@ -6847,6 +6867,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, "license": "MIT", "dependencies": { "picomatch": "^2.2.1" @@ -7101,6 +7122,7 @@ "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -7269,6 +7291,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, "license": "MIT", "dependencies": { "semver": "^7.5.3" @@ -7681,6 +7704,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -7693,6 +7717,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", + "dev": true, "license": "ISC", "bin": { "nodetouch": "bin/nodetouch.js" @@ -7927,6 +7952,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true, "license": "MIT" }, "node_modules/underscore": { From 9952e190e5d86f296417d3a584cda74d26f636ef Mon Sep 17 00:00:00 2001 From: ka-vaNu Date: Thu, 26 Dec 2024 09:02:46 +0100 Subject: [PATCH 2/3] #233 add tool-tests --- lib/tools.js | 1 + lib/tools.test.js | 64 +++++++++++++++++++++++++++++++++++++++++++++-- main.test.js | 35 -------------------------- 3 files changed, 63 insertions(+), 37 deletions(-) delete mode 100644 main.test.js diff --git a/lib/tools.js b/lib/tools.js index b842272..6b91d37 100644 --- a/lib/tools.js +++ b/lib/tools.js @@ -65,6 +65,7 @@ async function simpleObjectUrlGetter(device, url) { } } catch (error) { iob.log.error(`simpleObjectUrlGetter: ${error}`); + states = {}; } return states; } diff --git a/lib/tools.test.js b/lib/tools.test.js index 7469d2e..7ffda5f 100644 --- a/lib/tools.test.js +++ b/lib/tools.test.js @@ -1,6 +1,8 @@ /* eslint-disable no-undef */ const expect = require('chai').expect; const tools = require('../lib/tools'); +const axios = require('axios'); +const sinon = require('sinon'); const datapoints = { 'gatebox#command.move': { @@ -17,10 +19,45 @@ const datapoints = { }, }; +const responseData = { + status: 'value1', + details: { + description: 'value3', + isActive: true, + additionalInfo: null, + }, + items: [ + { + id: 1, + name: 'Item 1', + }, + { + id: 2, + name: 'Item 2', + }, + ], + message: 'Ein einfacher String', + userId: 12345, + balance: 123.45, +}; + +const expectedResponse = + '{"status":"value1","details.description":"value3","details.isActive":true,"details.additionalInfo":null,"items[0].id":1,"items[0].name":"Item 1","items[1].id":2,"items[1].name":"Item 2","message":"Ein einfacher String","userId":12345,"balance":123.45}'; + +const device = { + dev_name: 'fakeName', + smart_name: 'fakeSmartName', + dev_ip: 'localhost', + dev_port: 3000, + dev_type: 'shutterbox', + polling: 60, + api_type: 'shutterbox', +}; + const fruits = []; fruits.push('banana', 'apple', 'peach'); -describe('Test isObject', function () { +describe('Test tools.isObject', function () { it('expect false', function () { expect(tools.isObject(null)).to.be.false; }); @@ -34,7 +71,7 @@ describe('Test isObject', function () { }); }); -describe('Test isArray', function () { +describe('Test tools.isArray', function () { it('expect true', function () { expect(tools.isArray(fruits)).to.be.true; }); @@ -47,3 +84,26 @@ describe('Test isArray', function () { expect(tools.isArray(datapoints)).to.be.false; }); }); + +describe('Test tools.simpleObjectUrlGetter', () => { + let axiosGetStub; + + beforeEach(() => { + axiosGetStub = sinon.stub(axios.default, 'get'); + }); + + afterEach(() => { + sinon.restore(); + }); + + it('should fetch data and return the dot-notated object', async () => { + const url = '/test'; + + axiosGetStub.resolves({ data: responseData }); + + const result = await tools.simpleObjectUrlGetter(device, url); + + expect(axiosGetStub).to.have.been.calledOnceWithExactly('http://localhost:3000/test'); + expect(JSON.stringify(result)).to.be.equal(expectedResponse); + }); +}); diff --git a/main.test.js b/main.test.js deleted file mode 100644 index b724d98..0000000 --- a/main.test.js +++ /dev/null @@ -1,35 +0,0 @@ -"use strict"; - -/** - * This is a dummy TypeScript test file using chai and mocha - * - * It's automatically excluded from npm and its build output is excluded from both git and npm. - * It is advised to test all your modules with accompanying *.test.js-files - */ - -// tslint:disable:no-unused-expression - -// @ts-ignore -const { expect } = require("chai"); -// import { functionToTest } from "./moduleToTest"; - -// @ts-ignore -// eslint-disable-next-line no-undef -describe("module to test => function to test", () => { - // initializing logic - const expected = 5; - - // @ts-ignore - // eslint-disable-next-line no-undef - it(`should return ${expected}`, () => { - const result = 5; - // assign result a value from functionToTest - expect(result).to.equal(expected); - // or using the should() syntax - // @ts-ignore - result.should.equal(expected); - }); - // ... more tests => it -}); - -// ... more test suites => describe From e926739aa0d7d2ca46e98e94f4ec9609e542e75e Mon Sep 17 00:00:00 2001 From: ka-vaNu Date: Thu, 26 Dec 2024 11:45:19 +0100 Subject: [PATCH 3/3] #233 search datapoints case-insensitive, fix case problems in API --- lib/gatebox.js | 2 +- lib/multisensor.js | 4 ++-- lib/shutterbox.js | 5 ----- lib/tools.js | 20 +++++++++++++++++++- lib/tools.test.js | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 54 insertions(+), 9 deletions(-) diff --git a/lib/gatebox.js b/lib/gatebox.js index 4c1eee5..8454e69 100644 --- a/lib/gatebox.js +++ b/lib/gatebox.js @@ -51,7 +51,7 @@ const datapoints = { type: 'state', common: { name: 'IP-Adress', type: 'string', role: 'text', read: true, write: false }, }, - 'gatebox#upTimeS': { + 'gatebox#uptimeS': { path: 'uptimeS', type: 'state', common: { name: 'Uptime in seconds', type: 'number', role: 'value', read: true, write: false }, diff --git a/lib/multisensor.js b/lib/multisensor.js index d81e3c6..28ef254 100644 --- a/lib/multisensor.js +++ b/lib/multisensor.js @@ -39,8 +39,8 @@ const datapoints = { type: 'state', common: { name: 'IP-Adress', type: 'string', role: 'text', read: true, write: false }, }, - 'multisensor#upTimeS': { - path: 'upTimeS', + 'multisensor#uptimeS': { + path: 'uptimeS', type: 'state', common: { name: 'Uptime in seconds', type: 'number', role: 'value', read: true, write: false }, }, diff --git a/lib/shutterbox.js b/lib/shutterbox.js index 0c30b7c..ce30a14 100644 --- a/lib/shutterbox.js +++ b/lib/shutterbox.js @@ -66,11 +66,6 @@ const datapoints = { type: 'state', common: { name: 'IP-Adress', type: 'string', role: 'text', read: true, write: false }, }, - 'shutterbox#upTimeS': { - path: 'uptimeS', - type: 'state', - common: { name: 'Uptime in seconds', type: 'number', role: 'value', read: true, write: false }, - }, 'shutterbox#uptimeS': { path: 'uptimeS', type: 'state', diff --git a/lib/tools.js b/lib/tools.js index 6b91d37..6f06acc 100644 --- a/lib/tools.js +++ b/lib/tools.js @@ -41,6 +41,22 @@ function isArray(it) { return Object.prototype.toString.call(it) === '[object Array]'; } +/** + * Finds a value in an object by a property name, case-insensitive. + * + * @param obj - The object to search in. + * @param prop - The property name to search for. + * @returns The value of the found property, or undefined if not found. + */ +function findVal(obj, prop) { + prop = `${prop}`.toLowerCase(); + for (let p in obj) { + if (Object.prototype.hasOwnProperty.call(obj, p) && prop == `${p}`.toLowerCase()) { + return obj[p]; + } + } +} + /** * * @param device object of the device to request data @@ -120,7 +136,8 @@ async function setIobStates(device, values) { } if (Object.prototype.hasOwnProperty.call(iob.datapoints[device.dev_name], search)) { const deviceDatapoints = iob.datapoints[device.dev_name]; - const path = deviceDatapoints[search].path; + const datapoint = findVal(deviceDatapoints, search); + const path = datapoint.path; if (iob.extLog) { iob.log.info(`setIobStates path: ${path}`); } @@ -179,6 +196,7 @@ async function initCommon(name, apiType) { module.exports = { isArray, isObject, + findVal, setIob, initCommon, getBleboxData, diff --git a/lib/tools.test.js b/lib/tools.test.js index 7ffda5f..d53434b 100644 --- a/lib/tools.test.js +++ b/lib/tools.test.js @@ -19,6 +19,12 @@ const datapoints = { }, }; +const objCaseInsensitive = { + testlower: 'lower', + TESTUPPER: 'upper', + TestMixed: 'mixed', +}; + const responseData = { status: 'value1', details: { @@ -85,6 +91,32 @@ describe('Test tools.isArray', function () { }); }); +describe('Test tools.findVal', function () { + it('search lower same case', function () { + expect(tools.findVal(objCaseInsensitive, 'testlower')).to.equal('lower'); + }); + + it('search lower different case', function () { + expect(tools.findVal(objCaseInsensitive, 'TESTLOWER')).to.equal('lower'); + }); + + it('search UPPER same case', function () { + expect(tools.findVal(objCaseInsensitive, 'TESTUPPER')).to.equal('upper'); + }); + + it('search UPPER different case', function () { + expect(tools.findVal(objCaseInsensitive, 'testupper')).to.equal('upper'); + }); + + it('search Mixed', function () { + expect(tools.findVal(objCaseInsensitive, 'testmixed')).to.equal('mixed'); + }); + + it('search not found', function () { + expect(tools.findVal(objCaseInsensitive, 'test')).to.be.undefined; + }); +}); + describe('Test tools.simpleObjectUrlGetter', () => { let axiosGetStub;