From 01d86aa6ddb9c19bad09e706c18afe7b350dd289 Mon Sep 17 00:00:00 2001 From: Bartek Fabiszewski Date: Thu, 19 Dec 2019 23:03:23 +0100 Subject: [PATCH] Add config class --- js/src/config.js | 127 +++++++++++++++++++++++++++++++ js/test/config.test.js | 168 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 295 insertions(+) create mode 100644 js/src/config.js create mode 100644 js/test/config.test.js diff --git a/js/src/config.js b/js/src/config.js new file mode 100644 index 0000000..d1cdf49 --- /dev/null +++ b/js/src/config.js @@ -0,0 +1,127 @@ +/* + * μlogger + * + * Copyright(C) 2019 Bartek Fabiszewski (www.fabiszewski.net) + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +import uObserve from './observe.js'; + +/** + * @class uConfig + * @property {number} interval; + * @property {string} units + * @property {string} mapApi + * @property {?string} gkey + * @property {Object} olLayers + * @property {number} initLatitude + * @property {number} initLongitude + * @property {RegExp} passRegex + * @property {number} strokeWeight + * @property {string} strokeColor + * @property {number} strokeOpacity + * @property {boolean} showLatest + * @property {string} colorNormal + * @property {string} colorStart + * @property {string} colorStop + * @property {string} colorExtra + * @property {string} colorHilite + */ +export default class uConfig { + + constructor() { + this.initialize(); + } + + initialize() { + this.interval = 10; + this.units = 'metric'; + this.lang = 'en'; + this.mapApi = 'openlayers'; + this.gkey = null; + this.olLayers = {}; + this.initLatitude = 52.23; + this.initLongitude = 21.01; + this.passRegex = new RegExp('(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.{12,})'); + this.strokeWeight = 2; + this.strokeColor = '#ff0000'; + this.strokeOpacity = 1; + // marker colors + this.colorNormal = '#fff'; + this.colorStart = '#55b500'; + this.colorStop = '#ff6a00'; + this.colorExtra = '#ccc'; + this.colorHilite = '#feff6a'; + this.initUnits(); + } + + initUnits() { + if (this.units === 'imperial') { + this.factorSpeed = 0.62; // to mph + this.unitSpeed = 'unitmph'; + this.factorDistance = 3.28; // to feet + this.unitDistance = 'unitft'; + this.factorDistanceMajor = 0.62; // to miles + this.unitDistanceMajor = 'unitmi'; + } else if (this.units === 'nautical') { + this.factorSpeed = 0.54; // to knots + this.unitSpeed = 'unitkt'; + this.factorDistance = 1; // meters + this.unitDistance = 'unitm'; + this.factorDistanceMajor = 0.54; // to nautical miles + this.unitDistanceMajor = 'unitnm'; + } else { + this.factorSpeed = 1; + this.unitSpeed = 'unitkmh'; + this.factorDistance = 1; + this.unitDistance = 'unitm'; + this.factorDistanceMajor = 1; + this.unitDistanceMajor = 'unitkm'; + } + this.unitDay = 'unitday'; + } + + /** + * Load config values from data object + * @param {Object} data + */ + load(data) { + if (data) { + for (const property in data) { + if (data.hasOwnProperty(property) && this.hasOwnProperty(property)) { + this[property] = data[property]; + } + } + if (data.passRegex) { + const re = data.passRegex; + this.passRegex = new RegExp(re.substr(1, re.length - 2)); + } + this.initUnits(); + } + } + + reinitialize() { + uObserve.unobserveAll(this); + this.initialize(); + } + + /** + * @param {string} property + * @param {ObserveCallback} callback + */ + onChanged(property, callback) { + uObserve.observe(this, property, callback); + } +} diff --git a/js/test/config.test.js b/js/test/config.test.js new file mode 100644 index 0000000..6896a52 --- /dev/null +++ b/js/test/config.test.js @@ -0,0 +1,168 @@ +/* + * μlogger + * + * Copyright(C) 2019 Bartek Fabiszewski (www.fabiszewski.net) + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +import uConfig from '../src/config.js'; +import uObserve from '../src/observe.js'; + +describe('Config tests', () => { + + let config; + beforeEach(() => { + config = new uConfig(); + }); + + it('should create instance', () => { + expect(config.interval).toBeDefined(); + expect(config.interval).toBeDefined(); + expect(config.units).toBeDefined(); + expect(config.lang).toBeDefined(); + expect(config.mapApi).toBeDefined(); + expect(config.gkey).toBeDefined(); + expect(config.olLayers).toBeDefined(); + expect(config.initLatitude).toBeDefined(); + expect(config.initLongitude).toBeDefined(); + expect(config.passRegex).toBeDefined(); + expect(config.strokeWeight).toBeDefined(); + expect(config.strokeColor).toBeDefined(); + expect(config.strokeOpacity).toBeDefined(); + expect(config.colorNormal).toBeDefined(); + expect(config.colorStart).toBeDefined(); + expect(config.colorStop).toBeDefined(); + expect(config.colorExtra).toBeDefined(); + expect(config.colorHilite).toBeDefined(); + expect(config.factorSpeed).toBeDefined(); + expect(config.unitSpeed).toBeDefined(); + expect(config.factorDistance).toBeDefined(); + expect(config.unitDistance).toBeDefined(); + expect(config.factorDistanceMajor).toBeDefined(); + expect(config.unitDistanceMajor).toBeDefined(); + expect(config.unitDay).toBeDefined(); + }); + + it('should set units to imperial', () => { + // when + config.units = 'imperial'; + config.initUnits(); + // then + expect(config.factorSpeed).toBe(0.62); // to mph + expect(config.unitSpeed).toBe('unitmph'); + expect(config.factorDistance).toBe(3.28); // to feet + expect(config.unitDistance).toBe('unitft'); + expect(config.factorDistanceMajor).toBe(0.62); // to miles + expect(config.unitDistanceMajor).toBe('unitmi'); + }); + + it('should set units to nautical', () => { + // when + config.units = 'nautical'; + config.initUnits(); + // then + expect(config.factorSpeed).toBe(0.54); // to knots + expect(config.unitSpeed).toBe('unitkt'); + expect(config.factorDistance).toBe(1); // meters + expect(config.unitDistance).toBe('unitm'); + expect(config.factorDistanceMajor).toBe(0.54); // to nautical miles + expect(config.unitDistanceMajor).toBe('unitnm'); + }); + + it('should set units to metric', () => { + // when + config.units = 'metric'; + config.initUnits(); + // then + expect(config.factorSpeed).toBe(1); + expect(config.unitSpeed).toBe('unitkmh'); + expect(config.factorDistance).toBe(1); + expect(config.unitDistance).toBe('unitm'); + expect(config.factorDistanceMajor).toBe(1); + expect(config.unitDistanceMajor).toBe('unitkm'); + }); + + it('should load property from data', () => { + // given + config.interval = 1; + const data = { + interval: 2 + }; + // when + config.load(data); + // then + expect(config.interval).toBe(data.interval); + }); + + it('should skip unknown propery loaded from data', () => { + // given + const data = { + unknownProperty: 2 + }; + // when + config.load(data); + // then + expect(config.unknownProperty).not.toBeDefined(); + }); + + it('should update units after loading data', () => { + // given + const data = { + units: 'imperial' + }; + // when + config.load(data); + // then + expect(config.factorSpeed).toBe(0.62); + }); + + it('should parse regex if present in data', () => { + // given + const data = { + passRegex: '/(?=.{5,})/' + }; + // when + config.load(data); + // then + expect(config.passRegex).toEqual(jasmine.any(RegExp)); + }); + + it('should reinitialize config and remove any observers', () => { + // given + const data = { + interval: 10000 + }; + config.load(data); + uObserve.observe(config, 'interval', () => {/* ignored */}); + // when + config.reinitialize(); + // then + expect(config.interval).not.toBe(data.interval); + expect(uObserve.isObserved(config, 'interval')).toBe(false); + }); + + it('should notify observer on changed config value', (done) => { + // given + const newInterval = 10000; + // when + config.onChanged('interval', (interval) => { + // then + expect(interval).toBe(newInterval); + done(); + }); + config.interval = newInterval; + }); + +});