From 1ae0a3976f1124dac17c5ca13d7f85608b15d64d Mon Sep 17 00:00:00 2001 From: eiabea Date: Sun, 18 Oct 2020 19:49:12 +0200 Subject: [PATCH 1/3] Started implementing typescript Started with cache controller and all the tests --- .gitignore | 5 +- .mocharc.yml | 7 + .nycrc | 23 +++- app.js => app.ts | 29 ++-- controller/cache.controller.js | 117 ---------------- controller/cache.controller.ts | 127 ++++++++++++++++++ index.js => index.ts | 2 +- package-lock.json | 73 +++++++++- package.json | 13 +- ...er.test.js => calendar.controller.test.ts} | 23 ++-- ...ller.test.js => google.controller.test.ts} | 0 ...r.test.js => nextcloud.controller.test.ts} | 0 ...er.test.js => database.controller.test.ts} | 20 +-- ...roller.test.js => heat.controller.test.ts} | 0 ...oller.test.js => relay.controller.test.ts} | 14 +- ...er.test.js => schedule.controller.test.ts} | 0 ...oller.test.js => slave.controller.test.ts} | 11 +- ...roller.test.js => temp.controller.test.ts} | 10 +- ...tus.route.test.js => status.route.test.ts} | 2 +- ...tus.route.test.js => status.route.test.ts} | 0 ...unit.test.js => status.route.unit.test.ts} | 7 +- tsconfig.json | 12 ++ 22 files changed, 316 insertions(+), 179 deletions(-) create mode 100644 .mocharc.yml rename app.js => app.ts (88%) delete mode 100644 controller/cache.controller.js create mode 100644 controller/cache.controller.ts rename index.js => index.ts (51%) rename test/controller/{calendar.controller.test.js => calendar.controller.test.ts} (91%) rename test/controller/calendear/{google.controller.test.js => google.controller.test.ts} (100%) rename test/controller/calendear/{nextcloud.controller.test.js => nextcloud.controller.test.ts} (100%) rename test/controller/{database.controller.test.js => database.controller.test.ts} (86%) rename test/controller/{heat.controller.test.js => heat.controller.test.ts} (100%) rename test/controller/{relay.controller.test.js => relay.controller.test.ts} (92%) rename test/controller/{schedule.controller.test.js => schedule.controller.test.ts} (100%) rename test/controller/{slave.controller.test.js => slave.controller.test.ts} (86%) rename test/controller/{temp.controller.test.js => temp.controller.test.ts} (86%) rename test/routes/master/{status.route.test.js => status.route.test.ts} (99%) rename test/routes/slave/{status.route.test.js => status.route.test.ts} (100%) rename test/routes/slave/{status.route.unit.test.js => status.route.unit.test.ts} (88%) create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore index 5b1670d..a628b5b 100644 --- a/.gitignore +++ b/.gitignore @@ -155,4 +155,7 @@ crashlytics-build.properties !/stack/node/yarn.lock # Google -/secrets \ No newline at end of file +/secrets + +# TypeScript +dist \ No newline at end of file diff --git a/.mocharc.yml b/.mocharc.yml new file mode 100644 index 0000000..727fbb9 --- /dev/null +++ b/.mocharc.yml @@ -0,0 +1,7 @@ +require: + - ts-node/register + - source-map-support/register +recursive: true +exit: true +slow: 500 +timeout: 5000 \ No newline at end of file diff --git a/.nycrc b/.nycrc index 7ce210c..4c9d7e3 100644 --- a/.nycrc +++ b/.nycrc @@ -1,15 +1,26 @@ { + "extension": [ + ".ts", + ".tsx" + ], "exclude": [ - "**/*.apidoc.js", + "typings", "coverage", - "apidoc", - "test", - "**/*test.js", - "index.js" + "doc", + "dist", + "interfaces", + "types", + "index.ts", + "**/*test.ts", + ".eslintrc.js" ], "reporter": [ + "lcov", "text", "html" ], - "all": true + "require": [ + "ts-node/register" + ], + "all": true } \ No newline at end of file diff --git a/app.js b/app.ts similarity index 88% rename from app.js rename to app.ts index d1135db..d94c7a7 100644 --- a/app.js +++ b/app.ts @@ -2,10 +2,10 @@ const express = require('express'); const bodyParser = require('body-parser'); const cors = require('cors'); const helmet = require('helmet'); -const bunyan = require('bunyan'); +import * as bunyan from 'bunyan'; +import { CacheController } from './controller/cache.controller'; // Controller -const Cache = require('./controller/cache.controller'); const Calendar = require('./controller/calendar.controller'); const Database = require('./controller/database.controller'); const Heat = require('./controller/heat.controller'); @@ -17,25 +17,34 @@ const Temp = require('./controller/temp.controller'); // Routes const StatusRoute = require('./routes/v1/status.route'); -const EXPRESS_PORT = parseInt(process.env.EXPRESS_PORT, 10) || 3000; -const IS_MASTER = process.env.TEMPEA_SLAVE !== 'true'; -const SLAVE_ENABLED = process.env.SLAVE_ENABLED === 'true'; +const EXPRESS_PORT: Number = parseInt(process.env.EXPRESS_PORT, 10) || 3000; +const IS_MASTER: Boolean = process.env.TEMPEA_SLAVE !== 'true'; +const SLAVE_ENABLED: Boolean = process.env.SLAVE_ENABLED === 'true'; module.exports = (loglevel) => { - const log = bunyan.createLogger({ + const log: bunyan = bunyan.createLogger({ name: 'tempea', level: loglevel, serializers: bunyan.stdSerializers, - }); + } as bunyan.LoggerOptions); - let heating = false; + let heating: Boolean = false; let server; let app; - const controller = {}; + const controller = { + cache: null, + temp: null, + calendar: null, + database: null, + heat: null, + relay: null, + schedule: null, + slave: null, + }; const initControllers = async () => { log.trace('Initializing general controller'); - controller.cache = Cache(log.child({ controller: 'cache' })); + controller.cache = new CacheController(log.child({ controller: 'cache' })); controller.temp = Temp(log.child({ controller: 'temp' }), controller.cache); if (IS_MASTER) { log.trace('Initializing master controller'); diff --git a/controller/cache.controller.js b/controller/cache.controller.js deleted file mode 100644 index 30f8d57..0000000 --- a/controller/cache.controller.js +++ /dev/null @@ -1,117 +0,0 @@ -module.exports = (log) => { - log.info('Creating cache controller'); - // TODO: using redis? - let cache = { - master: {}, - }; - - const updateRelayState = async (state) => { - log.trace({ state }, 'Updating relay state'); - cache.master.updated = Date.now(); - cache.master.relay = state; - return true; - }; - - const getRelayState = async () => { - log.trace('Getting relay state'); - if (cache.master.relay !== undefined) { - return cache.master.relay; - } - - throw Error('No cached value available'); - }; - - const updateDesiredObject = async (desired) => { - const desiredTagged = Object.assign(desired, { updated: Date.now() }); - log.trace({ desiredTagged }, 'Updating desired temperature'); - cache.desired = desiredTagged; - return true; - }; - - const getDesiredObject = async () => { - log.trace('Getting desired temperature'); - if (cache.desired) { - return cache.desired; - } - - throw Error('No cached value available'); - }; - - const updateCurrentTemperature = async (current) => { - log.trace({ current }, 'Updating current temperature'); - cache.master.updated = Date.now(); - cache.master.current = current; - return true; - }; - - const getCurrentTemperature = async () => { - log.trace('Getting current temperature'); - if (cache.master.current) { - return cache.master.current; - } - - throw Error('No cached value available'); - }; - - const updateSlaveData = async (data) => { - log.trace({ data }, 'Updating slave data'); - const slaveTagged = Object.assign(data, { updated: Date.now() }); - cache.slave = slaveTagged; - return true; - }; - - const getSlaveData = async () => { - log.trace('Getting slave data'); - if (cache.slave) { - return cache.slave; - } - - throw Error('No cached value available'); - }; - - const updateMqttData = async (data) => { - // Do not override updated, already present from influx - log.trace({ data }, 'Updating mqtt data'); - cache.mqtt = data; - return true; - }; - - const getMqttData = async () => { - log.trace('Getting mqtt data'); - if (cache.mqtt) { - return cache.mqtt; - } - - throw Error('No cached value available'); - }; - - const getMasterUpdated = async () => { - log.trace('Getting master updated data'); - if (cache.master.updated) { - return cache.master.updated; - } - - throw Error('No cached value available'); - }; - - const invalidate = async () => { - cache = { - master: {}, - }; - }; - - return { - invalidate, - updateDesiredObject, - getDesiredObject, - updateRelayState, - getRelayState, - updateCurrentTemperature, - getCurrentTemperature, - updateSlaveData, - getSlaveData, - getMqttData, - updateMqttData, - getMasterUpdated, - }; -}; diff --git a/controller/cache.controller.ts b/controller/cache.controller.ts new file mode 100644 index 0000000..286869b --- /dev/null +++ b/controller/cache.controller.ts @@ -0,0 +1,127 @@ +import * as bunyan from 'bunyan'; + +interface Cache { + master: { + updated?: Number + relay?: Number + current?: Number + }, + // TODO Use data classes + desired: any + slave: any, + mqtt: any +} + +export class CacheController { + private log: bunyan; + + private cache: Cache = { + master: {}, + desired: undefined, + slave: undefined, + mqtt: undefined + } + + constructor(log: bunyan) { + this.log = log; + this.log.info('Creating cache controller'); + } + + public async invalidate(): Promise { + this.cache = { + master: {}, + desired: undefined, + slave: undefined, + mqtt: undefined + }; + }; + + public async updateRelayState(state: Number): Promise { + this.log.trace({ state }, 'Updating relay state'); + this.cache.master.updated = Date.now(); + this.cache.master.relay = state; + return true; + }; + + public async getRelayState(): Promise { + this.log.trace('Getting relay state'); + if (this.cache.master.relay !== undefined) { + return this.cache.master.relay; + } + + throw Error('No cached value available'); + }; + + public async updateDesiredObject(desired): Promise { + const desiredTagged = Object.assign(desired, { updated: Date.now() }); + this.log.trace({ desiredTagged }, 'Updating desired temperature'); + this.cache.desired = desiredTagged; + return true; + }; + + public async getDesiredObject(): Promise { + this.log.trace('Getting desired temperature'); + if (this.cache.desired) { + return this.cache.desired; + } + + throw Error('No cached value available'); + }; + + public async updateCurrentTemperature(current): Promise { + this.log.trace({ current }, 'Updating current temperature'); + this.cache.master.updated = Date.now(); + this.cache.master.current = current; + return true; + }; + + public async getCurrentTemperature(): Promise { + this.log.trace('Getting current temperature'); + if (this.cache.master.current) { + return this.cache.master.current; + } + + throw Error('No cached value available'); + }; + + public async updateSlaveData(data: any): Promise { + this.log.trace({ data }, 'Updating slave data'); + const slaveTagged = Object.assign(data, { updated: Date.now() }); + this.cache.slave = slaveTagged; + return true; + }; + + public async getSlaveData(): Promise { + this.log.trace('Getting slave data'); + if (this.cache.slave) { + return this.cache.slave; + } + + throw Error('No cached value available'); + }; + + public async updateMqttData(data: any): Promise { + // Do not override updated, already present from influx + this.log.trace({ data }, 'Updating mqtt data'); + this.cache.mqtt = data; + return true; + }; + + public async getMqttData(): Promise { + this.log.trace('Getting mqtt data'); + if (this.cache.mqtt) { + return this.cache.mqtt; + } + + throw Error('No cached value available'); + }; + + public async getMasterUpdated(): Promise { + this.log.trace('Getting master updated data'); + if (this.cache.master.updated) { + return this.cache.master.updated; + } + + throw Error('No cached value available'); + }; +} diff --git a/index.js b/index.ts similarity index 51% rename from index.js rename to index.ts index f8466c9..bcd09aa 100644 --- a/index.js +++ b/index.ts @@ -1,6 +1,6 @@ const App = require('./app'); (async () => { - const TEMPEA_LOG_LEVEL = parseInt(process.env.TEMPEA_LOG_LEVEL, 10) || 50; + const TEMPEA_LOG_LEVEL: Number = parseInt(process.env.TEMPEA_LOG_LEVEL, 10) || 50; await App(TEMPEA_LOG_LEVEL).start(); })(); diff --git a/package-lock.json b/package-lock.json index 39763bf..8517549 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "tempea", - "version": "1.3.0", + "version": "1.4.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -487,6 +487,15 @@ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", "dev": true }, + "@types/bunyan": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@types/bunyan/-/bunyan-1.8.6.tgz", + "integrity": "sha512-YiozPOOsS6bIuz31ilYqR5SlLif4TBWsousN2aCWLi5233nZSX19tFbcQUPdR7xJ8ypPyxkCGNxg0CIV5n9qxQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/chai": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.3.tgz", @@ -511,6 +520,12 @@ "integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=", "dev": true }, + "@types/mocha": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.0.3.tgz", + "integrity": "sha512-vyxR57nv8NfcU0GZu8EUXZLTbCMupIUwy95LJ6lllN+JRPG25CwMHoB1q5xKh8YKhQnHYRAn4yW2yuHbf/5xgg==", + "dev": true + }, "@types/node": { "version": "12.11.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.11.1.tgz", @@ -667,6 +682,11 @@ "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", "dev": true }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, "argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -955,6 +975,11 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" + }, "bunyan": { "version": "1.8.14", "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.14.tgz", @@ -1511,8 +1536,7 @@ "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" }, "doctrine": { "version": "3.0.0", @@ -3627,6 +3651,11 @@ } } }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -5111,6 +5140,22 @@ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + } + } + }, "spawn-wrap": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", @@ -5466,6 +5511,18 @@ "punycode": "^2.1.1" } }, + "ts-node": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.0.0.tgz", + "integrity": "sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg==", + "requires": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + } + }, "tsconfig-paths": { "version": "3.9.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz", @@ -5534,6 +5591,11 @@ "is-typedarray": "^1.0.0" } }, + "typescript": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.3.tgz", + "integrity": "sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg==" + }, "undefsafe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", @@ -6053,6 +6115,11 @@ } } } + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" } } } diff --git a/package.json b/package.json index bddbe08..cd05e5e 100644 --- a/package.json +++ b/package.json @@ -10,9 +10,10 @@ "start:dev": "${NODE_PATH:-node_modules}/.bin/nodemon index.js", "start:dev:pretty": "${NODE_PATH:-node_modules}/.bin/nodemon index.js | ${NODE_PATH:-node_modules}/.bin/bunyan -o short", "lint": "${NODE_PATH:-node_modules}/.bin/eslint --fix .", - "test": "CI=true ${NODE_PATH:-node_modules}/.bin/nyc ${NODE_PATH:-node_modules}/.bin/_mocha --recursive --color --exit test", - "test:dev": "CI=true ${NODE_PATH:-node_modules}/.bin/_mocha --recursive --color --exit test", - "codecov": "${NODE_PATH:-node_modules}/.bin/nyc report --reporter=text-lcov > coverage.lcov && ${NODE_PATH:-node_modules}/.bin/codecov" + "test": "TS_NODE_FILES=true TS_NODE_TRANSPILE_ONLY=true ${NODE_PATH:-node_modules}/.bin/nyc ${NODE_PATH:-node_modules}/.bin/mocha test ./test/**/*.test.ts ./test/**/**/*.test.ts", + "test:dev": "TS_NODE_FILES=true TS_NODE_TRANSPILE_ONLY=true ${NODE_PATH:-node_modules}/.bin/mocha test", + "codecov": "${NODE_PATH:-node_modules}/.bin/nyc report --reporter=text-lcov > coverage.lcov && ${NODE_PATH:-node_modules}/.bin/codecov", + "build": "./node_modules/.bin/tsc -b tsconfig.json" }, "repository": { "type": "git", @@ -42,9 +43,13 @@ "moment": "^2.27.0", "moment-timezone": "^0.5.31", "node-ical": "^0.11.4", - "onoff": "^6.0.0" + "onoff": "^6.0.0", + "ts-node": "^9.0.0", + "typescript": "^4.0.3" }, "devDependencies": { + "@types/bunyan": "^1.8.6", + "@types/mocha": "^8.0.3", "chai-http": "^4.3.0", "codecov": "^3.7.2", "eslint": "^7.8.1", diff --git a/test/controller/calendar.controller.test.js b/test/controller/calendar.controller.test.ts similarity index 91% rename from test/controller/calendar.controller.test.js rename to test/controller/calendar.controller.test.ts index 4a39da1..5061f43 100644 --- a/test/controller/calendar.controller.test.js +++ b/test/controller/calendar.controller.test.ts @@ -4,7 +4,10 @@ const log = require('null-logger'); const sinon = require('sinon'); const proxyquire = require('proxyquire'); -const CacheController = require('../../controller/cache.controller')(log); +import { CacheController } from '../../controller/cache.controller'; + +const cacheController = new CacheController(log); + // Preload files require('../../controller/calendar.controller'); @@ -27,7 +30,7 @@ describe('Calendar Controller', () => { const CC = proxyquire('../../controller/calendar.controller', {}); - const desiredObj = await CC(log, CacheController) + const desiredObj = await CC(log, cacheController) .getDesiredObject(); expect(desiredObj.temp).to.equal(15); @@ -49,7 +52,7 @@ describe('Calendar Controller', () => { }), }); - const desiredObj = await CC(log, CacheController) + const desiredObj = await CC(log, cacheController) .getDesiredObject(); expect(desiredObj.temp).to.equal(15); @@ -72,7 +75,7 @@ describe('Calendar Controller', () => { }), }); - const desiredObj = await CC(log, CacheController) + const desiredObj = await CC(log, cacheController) .getDesiredObject(); expect(desiredObj.temp).to.equal(15); @@ -100,7 +103,7 @@ describe('Calendar Controller', () => { }), }); - const desiredObj = await CC(log, CacheController) + const desiredObj = await CC(log, cacheController) .getDesiredObject(); expect(desiredObj.temp).to.equal(21); @@ -129,7 +132,7 @@ describe('Calendar Controller', () => { }), }); - const desiredObj = await CC(log, CacheController) + const desiredObj = await CC(log, cacheController) .getDesiredObject(); expect(desiredObj.temp).to.equal(21); @@ -158,7 +161,7 @@ describe('Calendar Controller', () => { }), }); - const desiredObj = await CC(log, CacheController) + const desiredObj = await CC(log, cacheController) .getDesiredObject(); expect(desiredObj.temp).to.equal(15); @@ -187,7 +190,7 @@ describe('Calendar Controller', () => { }), }); - const desiredObj = await CC(log, CacheController) + const desiredObj = await CC(log, cacheController) .getDesiredObject(); expect(desiredObj.temp).to.equal(27); @@ -213,7 +216,7 @@ describe('Calendar Controller', () => { }), }); - const desiredObj = await CC(log, CacheController) + const desiredObj = await CC(log, cacheController) .getDesiredObject(); expect(desiredObj.temp).to.equal(21); @@ -239,7 +242,7 @@ describe('Calendar Controller', () => { }), }); - const desiredObj = await CC(log, CacheController) + const desiredObj = await CC(log, cacheController) .getDesiredObject(); expect(desiredObj.temp).to.equal(21); diff --git a/test/controller/calendear/google.controller.test.js b/test/controller/calendear/google.controller.test.ts similarity index 100% rename from test/controller/calendear/google.controller.test.js rename to test/controller/calendear/google.controller.test.ts diff --git a/test/controller/calendear/nextcloud.controller.test.js b/test/controller/calendear/nextcloud.controller.test.ts similarity index 100% rename from test/controller/calendear/nextcloud.controller.test.js rename to test/controller/calendear/nextcloud.controller.test.ts diff --git a/test/controller/database.controller.test.js b/test/controller/database.controller.test.ts similarity index 86% rename from test/controller/database.controller.test.js rename to test/controller/database.controller.test.ts index 93eed8e..99b222b 100644 --- a/test/controller/database.controller.test.js +++ b/test/controller/database.controller.test.ts @@ -9,7 +9,9 @@ const proxyquire = require('proxyquire'); const INFLUX_HOST = process.env.INFLUX_HOST || 'influx'; const INFLUX_PORT = process.env.INFLUX_PORT || 8086; -const CacheController = require('../../controller/cache.controller')(log); +import { CacheController } from '../../controller/cache.controller'; + +const cacheController = new CacheController(log); const DatabaseController = require('../../controller/database.controller'); @@ -30,7 +32,7 @@ describe('Database Controller', () => { }, }); - await DBC(log, CacheController); + await DBC(log, cacheController); }); it('should fallback to default values if no env is set', async () => { @@ -49,7 +51,7 @@ describe('Database Controller', () => { }, }); - await DBC(log, CacheController); + await DBC(log, cacheController); restore(); }); @@ -63,7 +65,7 @@ describe('Database Controller', () => { hum: 50, }; - const instance = await DatabaseController(log, CacheController); + const instance = await DatabaseController(log, cacheController); await instance.writeMeasurement(currentTemp, desiredTemp, heating, slaveData); }); @@ -77,7 +79,7 @@ describe('Database Controller', () => { hum: 50, }; - const instance = await DatabaseController(log, CacheController); + const instance = await DatabaseController(log, cacheController); await instance.writeMeasurement(currentTemp, desiredTemp, heating, slaveData); }); @@ -87,7 +89,7 @@ describe('Database Controller', () => { const desiredTemp = 21; const heating = false; - const instance = await DatabaseController(log, CacheController); + const instance = await DatabaseController(log, cacheController); await instance.writeMeasurement(currentTemp, desiredTemp, heating); }); @@ -97,7 +99,7 @@ describe('Database Controller', () => { const desiredTemp = 21; const heating = true; - const instance = await DatabaseController(log, CacheController); + const instance = await DatabaseController(log, cacheController); await instance.writeMeasurement(currentTemp, desiredTemp, heating); }); @@ -128,7 +130,7 @@ describe('Database Controller', () => { }, ], }); - const instance = await DatabaseController(log, CacheController); + const instance = await DatabaseController(log, cacheController); const latestEntry = await instance.getLatestMqttEntry(); expect(latestEntry.updated).to.eq(1550586338221); @@ -141,7 +143,7 @@ describe('Database Controller', () => { .reply(200, { results: [], }); - const instance = await DatabaseController(log, CacheController); + const instance = await DatabaseController(log, cacheController); try { await instance.getLatestMqttEntry(); diff --git a/test/controller/heat.controller.test.js b/test/controller/heat.controller.test.ts similarity index 100% rename from test/controller/heat.controller.test.js rename to test/controller/heat.controller.test.ts diff --git a/test/controller/relay.controller.test.js b/test/controller/relay.controller.test.ts similarity index 92% rename from test/controller/relay.controller.test.js rename to test/controller/relay.controller.test.ts index caf24fc..a1350ac 100644 --- a/test/controller/relay.controller.test.js +++ b/test/controller/relay.controller.test.ts @@ -3,7 +3,9 @@ const { assert, expect } = require('chai'); const log = require('null-logger'); const sinon = require('sinon'); const proxyquire = require('proxyquire').noPreserveCache(); -const CacheController = require('../../controller/cache.controller')(log); +import { CacheController } from '../../controller/cache.controller'; + +const cacheController = new CacheController(log); describe('Relay Controller', () => { let restore; @@ -31,7 +33,7 @@ describe('Relay Controller', () => { }; }, }, - })(log, CacheController); + })(log, cacheController); const initialState = await instance.getRelay(); @@ -57,7 +59,7 @@ describe('Relay Controller', () => { }; }, }, - })(log, CacheController); + })(log, cacheController); await instance.setRelay(1); const newState = await instance.getRelay(); @@ -84,7 +86,7 @@ describe('Relay Controller', () => { }; }, }, - })(log, CacheController); + })(log, cacheController); try { await instance.setRelay(1); @@ -106,7 +108,7 @@ describe('Relay Controller', () => { }; }, }, - })(log, CacheController); + })(log, cacheController); try { await instance.setRelay(1); @@ -129,7 +131,7 @@ describe('Relay Controller', () => { }; }, }, - })(log, CacheController); + })(log, cacheController); try { await instance.getRelay(); diff --git a/test/controller/schedule.controller.test.js b/test/controller/schedule.controller.test.ts similarity index 100% rename from test/controller/schedule.controller.test.js rename to test/controller/schedule.controller.test.ts diff --git a/test/controller/slave.controller.test.js b/test/controller/slave.controller.test.ts similarity index 86% rename from test/controller/slave.controller.test.js rename to test/controller/slave.controller.test.ts index b297c99..2d64ebb 100644 --- a/test/controller/slave.controller.test.js +++ b/test/controller/slave.controller.test.ts @@ -9,7 +9,10 @@ const SLAVE_HOST = 'mocked.tempea.com'; const SLAVE_PORT = '80'; const SLAVE_ENDPOINT = '/mocked'; -const CacheController = require('../../controller/cache.controller')(log); +import { CacheController } from '../../controller/cache.controller'; + +const cacheController = new CacheController(log); + // Preload files require('../../controller/slave.controller'); @@ -42,7 +45,7 @@ describe('Slave Controller', () => { const SC = proxyquire('../../controller/slave.controller', {}); - const slaveData = await SC(log, CacheController).getData(); + const slaveData = await SC(log, cacheController).getData(); expect(slaveData.temp).to.eq(mockedSlaveResponse.data.temp); expect(slaveData.hum).to.eq(mockedSlaveResponse.data.hum); @@ -57,7 +60,7 @@ describe('Slave Controller', () => { const SC = proxyquire('../../controller/slave.controller', {}); - const slaveController = await SC(log, CacheController); + const slaveController = await SC(log, cacheController); try { await slaveController.getData(); @@ -80,7 +83,7 @@ describe('Slave Controller', () => { const SC = proxyquire('../../controller/slave.controller', {}); - const slaveController = await SC(log, CacheController); + const slaveController = await SC(log, cacheController); try { await slaveController.getData(); diff --git a/test/controller/temp.controller.test.js b/test/controller/temp.controller.test.ts similarity index 86% rename from test/controller/temp.controller.test.js rename to test/controller/temp.controller.test.ts index 0c5f052..2e31666 100644 --- a/test/controller/temp.controller.test.js +++ b/test/controller/temp.controller.test.ts @@ -3,7 +3,9 @@ const log = require('null-logger'); const sinon = require('sinon'); const proxyquire = require('proxyquire').noPreserveCache(); -const CacheController = require('../../controller/cache.controller')(log); +import { CacheController } from '../../controller/cache.controller'; + +const cacheController = new CacheController(log); describe('Temp Controller', () => { it('should get current temperature', async () => { @@ -13,7 +15,7 @@ describe('Temp Controller', () => { ds18b20: { temperature: stub, }, - })(log, CacheController); + })(log, cacheController); const temp = await instance.getCurrentTemp(); @@ -27,7 +29,7 @@ describe('Temp Controller', () => { ds18b20: { temperature: stub, }, - })(log, CacheController); + })(log, cacheController); const temp = await instance.getCurrentTemp(); @@ -43,7 +45,7 @@ describe('Temp Controller', () => { ds18b20: { temperature: stub, }, - })(log, CacheController); + })(log, cacheController); try { await instance.getCurrentTemp(); diff --git a/test/routes/master/status.route.test.js b/test/routes/master/status.route.test.ts similarity index 99% rename from test/routes/master/status.route.test.js rename to test/routes/master/status.route.test.ts index 12c130b..13ce894 100644 --- a/test/routes/master/status.route.test.js +++ b/test/routes/master/status.route.test.ts @@ -125,7 +125,7 @@ describe('Status Route (Master)', () => { statement_id: 0, series: [ { - // default name set by telegraf + // default name set by telegraf name: 'mqtt_consumer', columns: [ 'time', diff --git a/test/routes/slave/status.route.test.js b/test/routes/slave/status.route.test.ts similarity index 100% rename from test/routes/slave/status.route.test.js rename to test/routes/slave/status.route.test.ts diff --git a/test/routes/slave/status.route.unit.test.js b/test/routes/slave/status.route.unit.test.ts similarity index 88% rename from test/routes/slave/status.route.unit.test.js rename to test/routes/slave/status.route.unit.test.ts index 40d7e3e..c1ffb98 100644 --- a/test/routes/slave/status.route.unit.test.js +++ b/test/routes/slave/status.route.unit.test.ts @@ -1,3 +1,4 @@ +import { CacheController } from '../../../controller/cache.controller'; const mockedEnv = require('mocked-env'); const express = require('express'); const chai = require('chai'); @@ -7,6 +8,7 @@ const log = require('null-logger'); const { assert } = chai; const chaiHttp = require('chai-http'); + chai.use(chaiHttp); describe('Status Route Unit', () => { @@ -27,14 +29,13 @@ describe('Status Route Unit', () => { delete require.cache[require.resolve('../../../controller/cache.controller')]; delete require.cache[require.resolve('../../../routes/v1/status.route')]; delete require.cache[require.resolve('../../../controller/temp.controller')]; - // eslint-disable-next-line global-require - const CacheController = require('../../../controller/cache.controller')(log); + const cacheController = new CacheController(log); // eslint-disable-next-line global-require const StatusRoute = require('../../../routes/v1/status.route'); // eslint-disable-next-line global-require const TempController = require('../../../controller/temp.controller'); - const tempController = TempController(log, CacheController); + const tempController = TempController(log, cacheController); const stub = sinon.stub(tempController, 'getCurrentTemp') .rejects(new Error('Mocked error')); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..9737d86 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "outDir": "./dist", + "allowJs": true, + "target": "es6" + }, + "esModuleInterop": true, + "exclude": [ + "./dist", + "./coverage/*" + ], +} \ No newline at end of file From 563c10ed73c32a99ac3c3dad653337f37cc812f4 Mon Sep 17 00:00:00 2001 From: eiabea Date: Mon, 26 Oct 2020 21:22:00 +0100 Subject: [PATCH 2/3] Refactored temp controller --- app.ts | 4 +- controller/index.ts | 2 + controller/temp.controller.js | 38 ----------------- controller/temp.controller.ts | 45 +++++++++++++++++++++ package-lock.json | 24 ++++++++--- package.json | 7 +++- test/controller/temp.controller.test.ts | 39 ++++++++---------- test/routes/slave/status.route.unit.test.ts | 5 +-- tsconfig.json | 3 +- 9 files changed, 92 insertions(+), 75 deletions(-) create mode 100644 controller/index.ts delete mode 100644 controller/temp.controller.js create mode 100644 controller/temp.controller.ts diff --git a/app.ts b/app.ts index d94c7a7..90e4ad4 100644 --- a/app.ts +++ b/app.ts @@ -4,6 +4,7 @@ const cors = require('cors'); const helmet = require('helmet'); import * as bunyan from 'bunyan'; import { CacheController } from './controller/cache.controller'; +import { TempController } from './controller/temp.controller'; // Controller const Calendar = require('./controller/calendar.controller'); @@ -12,7 +13,6 @@ const Heat = require('./controller/heat.controller'); const Relay = require('./controller/relay.controller'); const Schedule = require('./controller/schedule.controller'); const Slave = require('./controller/slave.controller'); -const Temp = require('./controller/temp.controller'); // Routes const StatusRoute = require('./routes/v1/status.route'); @@ -45,7 +45,7 @@ module.exports = (loglevel) => { const initControllers = async () => { log.trace('Initializing general controller'); controller.cache = new CacheController(log.child({ controller: 'cache' })); - controller.temp = Temp(log.child({ controller: 'temp' }), controller.cache); + controller.temp = new TempController(log.child({ controller: 'temp' }), controller.cache); if (IS_MASTER) { log.trace('Initializing master controller'); controller.calendar = Calendar(log.child({ controller: 'calendar' }), controller.cache); diff --git a/controller/index.ts b/controller/index.ts new file mode 100644 index 0000000..bae0e9c --- /dev/null +++ b/controller/index.ts @@ -0,0 +1,2 @@ +export { CacheController } from './cache.controller'; +export { TempController } from './temp.controller'; \ No newline at end of file diff --git a/controller/temp.controller.js b/controller/temp.controller.js deleted file mode 100644 index 52bf476..0000000 --- a/controller/temp.controller.js +++ /dev/null @@ -1,38 +0,0 @@ -const ds18b20 = require('ds18b20'); - -const SENSOR_ID = process.env.SENSOR_ID || '10-0008032d5234'; - -module.exports = (log, cache) => { - let prevValue = 20.0; - - const getCurrentTemp = async () => { - log.trace({ SENSOR_ID }, 'Getting current temperature'); - return new Promise((resolve, reject) => { - ds18b20.temperature(SENSOR_ID, async (err, value) => { - if (err) { - log.error({ err }, 'Error getting current temperature'); - return reject(err); - } - - let returnValue = value; - - // ignore the reset value of the sensor - if (value === 85.0) { - log.debug(`Sensor returned reset value 85, using previous value ${prevValue}`); - returnValue = prevValue; - } - - log.trace({ - value: returnValue, - }, 'Successfully got current temperature'); - prevValue = returnValue; - await cache.updateCurrentTemperature(returnValue); - return resolve(returnValue); - }); - }); - }; - - return { - getCurrentTemp, - }; -}; diff --git a/controller/temp.controller.ts b/controller/temp.controller.ts new file mode 100644 index 0000000..8e1dc4f --- /dev/null +++ b/controller/temp.controller.ts @@ -0,0 +1,45 @@ +// const ds18b20 = require('ds18b20'); +import * as bunyan from 'bunyan'; +import * as ds18b20 from 'ds18b20'; +import { CacheController } from './cache.controller'; + +const SENSOR_ID = process.env.SENSOR_ID || '10-0008032d5234'; + +export class TempController { + private cache: CacheController; + private log: bunyan; + private prevValue: Number = 20.0; + + constructor(log: bunyan, cache: CacheController) { + this.log = log; + this.log.info('Creating cache controller'); + this.cache = cache; + } + + public async getCurrentTemp() { + this.log.trace({ SENSOR_ID }, 'Getting current temperature'); + return new Promise((resolve, reject) => { + ds18b20.temperature(SENSOR_ID, async (err, value) => { + if (err) { + this.log.error({ err }, 'Error getting current temperature'); + return reject(err); + } + + let returnValue: Number = value; + + // ignore the reset value of the sensor + if (value === 85.0) { + this.log.debug(`Sensor returned reset value 85, using previous value ${this.prevValue}`); + returnValue = this.prevValue; + } + + this.log.trace({ + value: returnValue, + }, 'Successfully got current temperature'); + this.prevValue = returnValue; + await this.cache.updateCurrentTemperature(returnValue); + return resolve(returnValue); + }); + }); + }; +} diff --git a/package-lock.json b/package-lock.json index 8517549..2cdd429 100644 --- a/package-lock.json +++ b/package-lock.json @@ -497,10 +497,9 @@ } }, "@types/chai": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.3.tgz", - "integrity": "sha512-VRw2xEGbll3ZiTQ4J02/hUjNqZoue1bMhoo2dgM2LXjDdyaq4q80HgBDHwpI0/VKlo4Eg+BavyQMv/NYgTetzA==", - "dev": true + "version": "4.2.14", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.14.tgz", + "integrity": "sha512-G+ITQPXkwTrslfG5L/BksmbLUA0M1iybEsmCWPqzSxsRRhJZimBKJkoMi8fr/CPygPTj4zO5pJH7I2/cm9M7SQ==" }, "@types/color-name": { "version": "1.1.1", @@ -514,6 +513,14 @@ "integrity": "sha512-aRnpPa7ysx3aNW60hTiCtLHlQaIFsXFCgQlpakNgDNVFzbtusSY8PwjAQgRWfSk0ekNoBjO51eQRB6upA9uuyw==", "dev": true }, + "@types/ds18b20": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@types/ds18b20/-/ds18b20-0.1.0.tgz", + "integrity": "sha512-nhk9EXyN5MYN4HZnplwbNFDeMqNr1mfx+URTg2AtfhfDJyW0hanDVkCLtTNE4rbwbRBUNa+AjDostVWABoAfYA==", + "requires": { + "@types/node": "*" + } + }, "@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -529,8 +536,7 @@ "@types/node": { "version": "12.11.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-12.11.1.tgz", - "integrity": "sha512-TJtwsqZ39pqcljJpajeoofYRfeZ7/I/OMUQ5pR4q5wOKf2ocrUvBAZUMhWsOvKx3dVc/aaV5GluBivt0sWqA5A==", - "dev": true + "integrity": "sha512-TJtwsqZ39pqcljJpajeoofYRfeZ7/I/OMUQ5pR4q5wOKf2ocrUvBAZUMhWsOvKx3dVc/aaV5GluBivt0sWqA5A==" }, "@types/parse-json": { "version": "4.0.0", @@ -5511,6 +5517,12 @@ "punycode": "^2.1.1" } }, + "ts-mock-imports": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-mock-imports/-/ts-mock-imports-1.3.0.tgz", + "integrity": "sha512-cCrVcRYsp84eDvPict0ZZD/D7ppQ0/JSx4ve6aEU8DjlsaWRJWV6ADMovp2sCuh6pZcduLFoIYhKTDU2LARo7Q==", + "dev": true + }, "ts-node": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.0.0.tgz", diff --git a/package.json b/package.json index cd05e5e..f8b98be 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,8 @@ "url": "https://github.com/eiabea/tempea-api" }, "dependencies": { + "@types/chai": "^4.2.14", + "@types/ds18b20": "^0.1.0", "axios": "^0.20.0", "body-parser": "^1.19.0", "bunyan": "^1.8.14", @@ -66,6 +68,7 @@ "null-logger": "^1.0.0", "nyc": "^15.1.0", "proxyquire": "^2.1.3", - "sinon": "^9.0.3" + "sinon": "^9.0.3", + "ts-mock-imports": "^1.3.0" } -} \ No newline at end of file +} diff --git a/test/controller/temp.controller.test.ts b/test/controller/temp.controller.test.ts index 2e31666..26f477c 100644 --- a/test/controller/temp.controller.test.ts +++ b/test/controller/temp.controller.test.ts @@ -1,21 +1,20 @@ -const { assert, expect } = require('chai'); -const log = require('null-logger'); -const sinon = require('sinon'); -const proxyquire = require('proxyquire').noPreserveCache(); +import { assert, expect } from "chai"; +import * as log from 'null-logger'; -import { CacheController } from '../../controller/cache.controller'; +import { CacheController, TempController } from '../../controller'; + +import { ImportMock } from 'ts-mock-imports'; +import * as ds18b20 from 'ds18b20'; const cacheController = new CacheController(log); describe('Temp Controller', () => { + beforeEach(ImportMock.restore) it('should get current temperature', async () => { - const stub = sinon.stub().callsArgWith(1, null, 21); + const stub = ImportMock.mockFunction(ds18b20, 'temperature'); + stub.callsArgWith(1, null, 21) - const instance = proxyquire('../../controller/temp.controller', { - ds18b20: { - temperature: stub, - }, - })(log, cacheController); + const instance = new TempController(log, cacheController); const temp = await instance.getCurrentTemp(); @@ -23,13 +22,10 @@ describe('Temp Controller', () => { }); it('should get previous temperature', async () => { - const stub = sinon.stub().callsArgWith(1, null, 85); + const stub = ImportMock.mockFunction(ds18b20, 'temperature'); + stub.callsArgWith(1, null, 85); - const instance = proxyquire('../../controller/temp.controller', { - ds18b20: { - temperature: stub, - }, - })(log, cacheController); + const instance = new TempController(log, cacheController); const temp = await instance.getCurrentTemp(); @@ -39,13 +35,10 @@ describe('Temp Controller', () => { }); it('should fail to get temperature', async () => { - const stub = sinon.stub().callsArgWith(1, new Error('Mocked temp error')); + const stub = ImportMock.mockFunction(ds18b20, 'temperature'); + stub.callsArgWith(1, new Error('Mocked temp error')); - const instance = proxyquire('../../controller/temp.controller', { - ds18b20: { - temperature: stub, - }, - })(log, cacheController); + const instance = new TempController(log, cacheController); try { await instance.getCurrentTemp(); diff --git a/test/routes/slave/status.route.unit.test.ts b/test/routes/slave/status.route.unit.test.ts index c1ffb98..273017a 100644 --- a/test/routes/slave/status.route.unit.test.ts +++ b/test/routes/slave/status.route.unit.test.ts @@ -1,4 +1,5 @@ import { CacheController } from '../../../controller/cache.controller'; +import { TempController } from '../../../controller/temp.controller'; const mockedEnv = require('mocked-env'); const express = require('express'); const chai = require('chai'); @@ -32,10 +33,8 @@ describe('Status Route Unit', () => { const cacheController = new CacheController(log); // eslint-disable-next-line global-require const StatusRoute = require('../../../routes/v1/status.route'); - // eslint-disable-next-line global-require - const TempController = require('../../../controller/temp.controller'); - const tempController = TempController(log, cacheController); + const tempController = new TempController(log, cacheController); const stub = sinon.stub(tempController, 'getCurrentTemp') .rejects(new Error('Mocked error')); diff --git a/tsconfig.json b/tsconfig.json index 9737d86..0e5380d 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,8 @@ "compilerOptions": { "outDir": "./dist", "allowJs": true, - "target": "es6" + "target": "es6", + "moduleResolution": "node" }, "esModuleInterop": true, "exclude": [ From 47f53c0805d9f264366847539a4c62419ab0925a Mon Sep 17 00:00:00 2001 From: eiabea Date: Mon, 26 Oct 2020 21:38:23 +0100 Subject: [PATCH 3/3] Refactored secondary controller --- controller/index.ts | 3 +- controller/slave.controller.js | 33 -------------------- controller/slave.controller.ts | 39 ++++++++++++++++++++++++ controller/temp.controller.ts | 5 ++- test/controller/slave.controller.test.ts | 32 ++++++++----------- 5 files changed, 55 insertions(+), 57 deletions(-) delete mode 100644 controller/slave.controller.js create mode 100644 controller/slave.controller.ts diff --git a/controller/index.ts b/controller/index.ts index bae0e9c..41149c8 100644 --- a/controller/index.ts +++ b/controller/index.ts @@ -1,2 +1,3 @@ export { CacheController } from './cache.controller'; -export { TempController } from './temp.controller'; \ No newline at end of file +export { TempController } from './temp.controller'; +export { SlaveController } from './slave.controller'; \ No newline at end of file diff --git a/controller/slave.controller.js b/controller/slave.controller.js deleted file mode 100644 index 392815a..0000000 --- a/controller/slave.controller.js +++ /dev/null @@ -1,33 +0,0 @@ -const request = require('request'); -const axios = require('axios'); -const { assert } = require('chai'); - -module.exports = (log, cache) => { - const getData = async () => { - - const { - SLAVE_HOST, SLAVE_PORT, SLAVE_ENDPOINT, - } = process.env; - - log.trace({ SLAVE_HOST, SLAVE_PORT, SLAVE_ENDPOINT }, 'Getting data from slave'); - try { - const response = await axios.get(`http://${SLAVE_HOST}:${SLAVE_PORT}${SLAVE_ENDPOINT}`); - - const { data } = response; - - assert.isTrue(data.success); - assert.isDefined(data.data); - assert.isNumber(data.data.temp); - - await cache.updateSlaveData(data.data); - return data.data; - } catch (error) { - log.error({ error }, `Error getting data from slave ${SLAVE_HOST}`); - throw error; - } - } - - return { - getData, - }; -}; diff --git a/controller/slave.controller.ts b/controller/slave.controller.ts new file mode 100644 index 0000000..cc54ac6 --- /dev/null +++ b/controller/slave.controller.ts @@ -0,0 +1,39 @@ +import { assert } from 'chai'; +import axios from 'axios'; +import * as bunyan from 'bunyan'; + +import { CacheController } from './'; + +export class SlaveController { + private cache: CacheController; + private log: bunyan; + + constructor(log: bunyan, cache: CacheController) { + this.log = log; + this.log.info('Creating slave controller'); + this.cache = cache; + } + + public async getData() { + const { + SLAVE_HOST, SLAVE_PORT, SLAVE_ENDPOINT, + } = process.env; + + this.log.trace({ SLAVE_HOST, SLAVE_PORT, SLAVE_ENDPOINT }, 'Getting data from slave'); + try { + const response = await axios.get(`http://${SLAVE_HOST}:${SLAVE_PORT}${SLAVE_ENDPOINT}`); + + const { data } = response; + + assert.isTrue(data.success); + assert.isDefined(data.data); + assert.isNumber(data.data.temp); + + await this.cache.updateSlaveData(data.data); + return data.data; + } catch (error) { + this.log.error({ error }, `Error getting data from slave ${SLAVE_HOST}`); + throw error; + } + } +} \ No newline at end of file diff --git a/controller/temp.controller.ts b/controller/temp.controller.ts index 8e1dc4f..691b439 100644 --- a/controller/temp.controller.ts +++ b/controller/temp.controller.ts @@ -1,7 +1,6 @@ -// const ds18b20 = require('ds18b20'); import * as bunyan from 'bunyan'; import * as ds18b20 from 'ds18b20'; -import { CacheController } from './cache.controller'; +import { CacheController } from './'; const SENSOR_ID = process.env.SENSOR_ID || '10-0008032d5234'; @@ -12,7 +11,7 @@ export class TempController { constructor(log: bunyan, cache: CacheController) { this.log = log; - this.log.info('Creating cache controller'); + this.log.info('Creating temp controller'); this.cache = cache; } diff --git a/test/controller/slave.controller.test.ts b/test/controller/slave.controller.test.ts index 2d64ebb..f97fb97 100644 --- a/test/controller/slave.controller.test.ts +++ b/test/controller/slave.controller.test.ts @@ -1,22 +1,18 @@ -const mockedEnv = require('mocked-env'); +import mockedEnv from 'mocked-env'; -const { expect } = require('chai'); -const log = require('null-logger'); -const nock = require('nock'); -const proxyquire = require('proxyquire'); +import { expect } from 'chai'; +import * as log from 'null-logger'; +import * as nock from 'nock'; const SLAVE_HOST = 'mocked.tempea.com'; const SLAVE_PORT = '80'; const SLAVE_ENDPOINT = '/mocked'; -import { CacheController } from '../../controller/cache.controller'; +import { SlaveController, CacheController } from '../../controller'; const cacheController = new CacheController(log); -// Preload files -require('../../controller/slave.controller'); - -describe('Slave Controller', () => { +describe.only('Slave Controller', () => { const mockedSlaveResponse = { success: true, data: { @@ -43,9 +39,9 @@ describe('Slave Controller', () => { .get(SLAVE_ENDPOINT) .reply(200, mockedSlaveResponse); - const SC = proxyquire('../../controller/slave.controller', {}); + const instance = new SlaveController(log, cacheController); - const slaveData = await SC(log, cacheController).getData(); + const slaveData = await instance.getData(); expect(slaveData.temp).to.eq(mockedSlaveResponse.data.temp); expect(slaveData.hum).to.eq(mockedSlaveResponse.data.hum); @@ -58,12 +54,10 @@ describe('Slave Controller', () => { SLAVE_ENDPOINT: '/mocked', }); - const SC = proxyquire('../../controller/slave.controller', {}); - - const slaveController = await SC(log, cacheController); + const instance = new SlaveController(log, cacheController); try { - await slaveController.getData(); + await instance.getData(); } catch (err) { expect(err).to.be.instanceof(Error); expect(err.code).to.equal('ECONNREFUSED'); @@ -81,12 +75,10 @@ describe('Slave Controller', () => { .get(`${SLAVE_ENDPOINT}_invalid_json`) .reply(200, '{"success":false'); - const SC = proxyquire('../../controller/slave.controller', {}); - - const slaveController = await SC(log, cacheController); + const instance = new SlaveController(log, cacheController); try { - await slaveController.getData(); + await instance.getData(); } catch (err) { expect(err).to.be.instanceof(Error); }