Merge branch 'develop' into update_templates

This commit is contained in:
Karsten Hassel 2021-07-20 22:33:02 +02:00 committed by GitHub
commit df9bd2b0f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 255 additions and 224 deletions

View File

@ -23,7 +23,6 @@
}, },
"rules": { "rules": {
"prettier/prettier": "error", "prettier/prettier": "error",
"eqeqeq": "error",
"no-prototype-builtins": "off", "no-prototype-builtins": "off",
"no-unused-vars": "off" "no-unused-vars": "off"
} }

View File

@ -16,6 +16,7 @@ _This release is scheduled to be released on 2021-10-01._
- Bump electron to v13 (and spectron to v15) and update other dependencies in package.json. - Bump electron to v13 (and spectron to v15) and update other dependencies in package.json.
- Refactor test configs, use default test config for all tests. - Refactor test configs, use default test config for all tests.
- Updated github templates. - Updated github templates.
- Actually test all js and css files when lint script is run.
### Fixed ### Fixed

View File

@ -16,7 +16,7 @@
<!-- custom.css is loaded by the loader.js to make sure it's loaded after the module css files. --> <!-- custom.css is loaded by the loader.js to make sure it's loaded after the module css files. -->
<script type="text/javascript"> <script type="text/javascript">
var version = "#VERSION#"; window.mmVersion = "#VERSION#";
</script> </script>
</head> </head>
<body> <body>

View File

@ -8,8 +8,8 @@
* MIT Licensed. * MIT Licensed.
*/ */
(function () { (function () {
var initializing = false; let initializing = false;
var fnTest = /xyz/.test(function () { const fnTest = /xyz/.test(function () {
xyz; xyz;
}) })
? /\b_super\b/ ? /\b_super\b/
@ -20,27 +20,27 @@
// Create a new Class that inherits from this class // Create a new Class that inherits from this class
Class.extend = function (prop) { Class.extend = function (prop) {
var _super = this.prototype; let _super = this.prototype;
// Instantiate a base class (but only create the instance, // Instantiate a base class (but only create the instance,
// don't run the init constructor) // don't run the init constructor)
initializing = true; initializing = true;
var prototype = new this(); const prototype = new this();
initializing = false; initializing = false;
// Make a copy of all prototype properties, to prevent reference issues. // Make a copy of all prototype properties, to prevent reference issues.
for (var p in prototype) { for (const p in prototype) {
prototype[p] = cloneObject(prototype[p]); prototype[p] = cloneObject(prototype[p]);
} }
// Copy the properties over onto the new prototype // Copy the properties over onto the new prototype
for (var name in prop) { for (const name in prop) {
// Check if we're overwriting an existing function // Check if we're overwriting an existing function
prototype[name] = prototype[name] =
typeof prop[name] === "function" && typeof _super[name] === "function" && fnTest.test(prop[name]) typeof prop[name] === "function" && typeof _super[name] === "function" && fnTest.test(prop[name])
? (function (name, fn) { ? (function (name, fn) {
return function () { return function () {
var tmp = this._super; const tmp = this._super;
// Add a new ._super() method that is the same method // Add a new ._super() method that is the same method
// but on the super-class // but on the super-class
@ -48,7 +48,7 @@
// The method only need to be bound temporarily, so we // The method only need to be bound temporarily, so we
// remove it when we're done executing // remove it when we're done executing
var ret = fn.apply(this, arguments); const ret = fn.apply(this, arguments);
this._super = tmp; this._super = tmp;
return ret; return ret;
@ -91,8 +91,8 @@ function cloneObject(obj) {
return obj; return obj;
} }
var temp = obj.constructor(); // give temp the original obj's constructor const temp = obj.constructor(); // give temp the original obj's constructor
for (var key in obj) { for (const key in obj) {
temp[key] = cloneObject(obj[key]); temp[key] = cloneObject(obj[key]);
if (key === "lockStrings") { if (key === "lockStrings") {

View File

@ -65,7 +65,7 @@ function createWindow() {
if (process.argv.includes("dev")) { if (process.argv.includes("dev")) {
if (process.env.JEST_WORKER_ID !== undefined) { if (process.env.JEST_WORKER_ID !== undefined) {
// if we are running with jest // if we are running with jest
var devtools = new BrowserWindow(electronOptions); const devtools = new BrowserWindow(electronOptions);
mainWindow.webContents.setDevToolsWebContents(devtools.webContents); mainWindow.webContents.setDevToolsWebContents(devtools.webContents);
} }
mainWindow.webContents.openDevTools(); mainWindow.webContents.openDevTools();

View File

@ -7,7 +7,7 @@
* By Michael Teeuw https://michaelteeuw.nl * By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed. * MIT Licensed.
*/ */
var Module = Class.extend({ const Module = Class.extend({
/********************************************************* /*********************************************************
* All methods (and properties) below can be subclassed. * * All methods (and properties) below can be subclassed. *
*********************************************************/ *********************************************************/
@ -498,8 +498,8 @@ Module.create = function (name) {
Module.register = function (name, moduleDefinition) { Module.register = function (name, moduleDefinition) {
if (moduleDefinition.requiresVersion) { if (moduleDefinition.requiresVersion) {
Log.log("Check MagicMirror version for module '" + name + "' - Minimum version: " + moduleDefinition.requiresVersion + " - Current version: " + window.version); Log.log("Check MagicMirror version for module '" + name + "' - Minimum version: " + moduleDefinition.requiresVersion + " - Current version: " + window.mmVersion);
if (cmpVersions(window.version, moduleDefinition.requiresVersion) >= 0) { if (cmpVersions(window.mmVersion, moduleDefinition.requiresVersion) >= 0) {
Log.log("Version is ok!"); Log.log("Version is ok!");
} else { } else {
Log.warn("Version is incorrect. Skip module: '" + name + "'"); Log.warn("Version is incorrect. Skip module: '" + name + "'");
@ -510,6 +510,8 @@ Module.register = function (name, moduleDefinition) {
Module.definitions[name] = moduleDefinition; Module.definitions[name] = moduleDefinition;
}; };
window.Module = Module;
/** /**
* Compare two semantic version numbers and return the difference. * Compare two semantic version numbers and return the difference.
* *

View File

@ -6,7 +6,7 @@
* By Christopher Fenner https://github.com/CFenner * By Christopher Fenner https://github.com/CFenner
* MIT Licensed. * MIT Licensed.
*/ */
var Translator = (function () { const Translator = (function () {
/** /**
* Load a JSON file via XHR. * Load a JSON file via XHR.
* *
@ -141,12 +141,7 @@ var Translator = (function () {
* The first language defined in translations.js will be used. * The first language defined in translations.js will be used.
*/ */
loadCoreTranslationsFallback: function () { loadCoreTranslationsFallback: function () {
// The variable `first` will contain the first let first = Object.keys(translations)[0];
// defined translation after the following line.
for (var first in translations) {
break;
}
if (first) { if (first) {
Log.log("Loading core translation fallback file: " + translations[first]); Log.log("Loading core translation fallback file: " + translations[first]);
loadJSON(translations[first], (translations) => { loadJSON(translations[first], (translations) => {
@ -156,3 +151,5 @@ var Translator = (function () {
} }
}; };
})(); })();
window.Translator = Translator;

View File

@ -1,3 +1,5 @@
/* eslint-disable */
/* Magic Mirror /* Magic Mirror
* Module: CurrentWeather * Module: CurrentWeather
* *

View File

@ -134,7 +134,7 @@ WeatherProvider.register("envcanada", {
// //
fetchData: function (url, method = "GET", data = null) { fetchData: function (url, method = "GET", data = null) {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
var request = new XMLHttpRequest(); const request = new XMLHttpRequest();
request.open(method, url, true); request.open(method, url, true);
request.onreadystatechange = function () { request.onreadystatechange = function () {
if (this.readyState === 4) { if (this.readyState === 4) {
@ -164,7 +164,7 @@ WeatherProvider.register("envcanada", {
// CORS errors when accessing EC // CORS errors when accessing EC
// //
getUrl() { getUrl() {
var path = "https://thingproxy.freeboard.io/fetch/https://dd.weather.gc.ca/citypage_weather/xml/" + this.config.provCode + "/" + this.config.siteCode + "_e.xml"; const path = "https://thingproxy.freeboard.io/fetch/https://dd.weather.gc.ca/citypage_weather/xml/" + this.config.provCode + "/" + this.config.siteCode + "_e.xml";
return path; return path;
}, },
@ -232,7 +232,7 @@ WeatherProvider.register("envcanada", {
// Capture the sunrise and sunset values from EC data // Capture the sunrise and sunset values from EC data
// //
var sunList = ECdoc.querySelectorAll("siteData riseSet dateTime"); const sunList = ECdoc.querySelectorAll("siteData riseSet dateTime");
currentWeather.sunrise = moment(sunList[1].querySelector("timeStamp").textContent, "YYYYMMDDhhmmss"); currentWeather.sunrise = moment(sunList[1].querySelector("timeStamp").textContent, "YYYYMMDDhhmmss");
currentWeather.sunset = moment(sunList[3].querySelector("timeStamp").textContent, "YYYYMMDDhhmmss"); currentWeather.sunset = moment(sunList[3].querySelector("timeStamp").textContent, "YYYYMMDDhhmmss");
@ -249,14 +249,14 @@ WeatherProvider.register("envcanada", {
const days = []; const days = [];
var weather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits); const weather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits);
var foreBaseDates = ECdoc.querySelectorAll("siteData forecastGroup dateTime"); const foreBaseDates = ECdoc.querySelectorAll("siteData forecastGroup dateTime");
var baseDate = foreBaseDates[1].querySelector("timeStamp").textContent; const baseDate = foreBaseDates[1].querySelector("timeStamp").textContent;
weather.date = moment(baseDate, "YYYYMMDDhhmmss"); weather.date = moment(baseDate, "YYYYMMDDhhmmss");
var foreGroup = ECdoc.querySelectorAll("siteData forecastGroup forecast"); const foreGroup = ECdoc.querySelectorAll("siteData forecastGroup forecast");
// For simplicity, we will only accumulate precipitation and will not try to break out // For simplicity, we will only accumulate precipitation and will not try to break out
// rain vs snow accumulations // rain vs snow accumulations
@ -288,9 +288,9 @@ WeatherProvider.register("envcanada", {
// where the next day's (aka Tomorrow's) forecast is located in the forecast array. // where the next day's (aka Tomorrow's) forecast is located in the forecast array.
// //
var nextDay = 0; let nextDay = 0;
var lastDay = 0; let lastDay = 0;
var currentTemp = ECdoc.querySelector("siteData currentConditions temperature").textContent; const currentTemp = ECdoc.querySelector("siteData currentConditions temperature").textContent;
// //
// If the first Element is Current Today, look at Current Today and Current Tonight for the current day. // If the first Element is Current Today, look at Current Today and Current Tonight for the current day.
@ -356,10 +356,10 @@ WeatherProvider.register("envcanada", {
// iteration looking at the current Element and the next Element. // iteration looking at the current Element and the next Element.
// //
var lastDate = moment(baseDate, "YYYYMMDDhhmmss"); let lastDate = moment(baseDate, "YYYYMMDDhhmmss");
for (var stepDay = nextDay; stepDay < lastDay; stepDay += 2) { for (let stepDay = nextDay; stepDay < lastDay; stepDay += 2) {
var weather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits); let weather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits);
// Add 1 to the date to reflect the current forecast day we are building // Add 1 to the date to reflect the current forecast day we are building
@ -402,23 +402,23 @@ WeatherProvider.register("envcanada", {
// Get local timezone UTC offset so that each hourly time can be calculated properly // Get local timezone UTC offset so that each hourly time can be calculated properly
var baseHours = ECdoc.querySelectorAll("siteData hourlyForecastGroup dateTime"); const baseHours = ECdoc.querySelectorAll("siteData hourlyForecastGroup dateTime");
var hourOffset = baseHours[1].getAttribute("UTCOffset"); const hourOffset = baseHours[1].getAttribute("UTCOffset");
// //
// The EC hourly forecast is held in a 24-element array - Elements 0 to 23 - with Element 0 holding // The EC hourly forecast is held in a 24-element array - Elements 0 to 23 - with Element 0 holding
// the forecast for the next 'on the hour' timeslot. This means the array is a rolling 24 hours. // the forecast for the next 'on the hour' timeslot. This means the array is a rolling 24 hours.
// //
var hourGroup = ECdoc.querySelectorAll("siteData hourlyForecastGroup hourlyForecast"); const hourGroup = ECdoc.querySelectorAll("siteData hourlyForecastGroup hourlyForecast");
for (var stepHour = 0; stepHour < 24; stepHour += 1) { for (let stepHour = 0; stepHour < 24; stepHour += 1) {
var weather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits); const weather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits);
// Determine local time by applying UTC offset to the forecast timestamp // Determine local time by applying UTC offset to the forecast timestamp
var foreTime = moment(hourGroup[stepHour].getAttribute("dateTimeUTC"), "YYYYMMDDhhmmss"); const foreTime = moment(hourGroup[stepHour].getAttribute("dateTimeUTC"), "YYYYMMDDhhmmss");
var currTime = foreTime.add(hourOffset, "hours"); const currTime = foreTime.add(hourOffset, "hours");
weather.date = moment(currTime, "X"); weather.date = moment(currTime, "X");
// Capture the temperature // Capture the temperature
@ -427,7 +427,7 @@ WeatherProvider.register("envcanada", {
// Capture Likelihood of Precipitation (LOP) and unit-of-measure values // Capture Likelihood of Precipitation (LOP) and unit-of-measure values
var precipLOP = hourGroup[stepHour].querySelector("lop").textContent * 1.0; const precipLOP = hourGroup[stepHour].querySelector("lop").textContent * 1.0;
if (precipLOP > 0) { if (precipLOP > 0) {
weather.precipitation = precipLOP; weather.precipitation = precipLOP;
@ -453,9 +453,9 @@ WeatherProvider.register("envcanada", {
// //
setMinMaxTemps(weather, foreGroup, today, fullDay, currentTemp) { setMinMaxTemps(weather, foreGroup, today, fullDay, currentTemp) {
var todayTemp = foreGroup[today].querySelector("temperatures temperature").textContent; const todayTemp = foreGroup[today].querySelector("temperatures temperature").textContent;
var todayClass = foreGroup[today].querySelector("temperatures temperature").getAttribute("class"); const todayClass = foreGroup[today].querySelector("temperatures temperature").getAttribute("class");
// //
// The following logic is largely aimed at accommodating the Current day's forecast whereby we // The following logic is largely aimed at accommodating the Current day's forecast whereby we
@ -500,9 +500,9 @@ WeatherProvider.register("envcanada", {
} }
} }
var nextTemp = foreGroup[today + 1].querySelector("temperatures temperature").textContent; const nextTemp = foreGroup[today + 1].querySelector("temperatures temperature").textContent;
var nextClass = foreGroup[today + 1].querySelector("temperatures temperature").getAttribute("class"); const nextClass = foreGroup[today + 1].querySelector("temperatures temperature").getAttribute("class");
if (fullDay === true) { if (fullDay === true) {
if (nextClass === "low") { if (nextClass === "low") {
@ -577,6 +577,7 @@ WeatherProvider.register("envcanada", {
return temp; return temp;
} }
}, },
// //
// Convert km/h to mph // Convert km/h to mph
// //

View File

@ -60,7 +60,7 @@ WeatherProvider.register("smhi", {
*/ */
setConfig(config) { setConfig(config) {
this.config = config; this.config = config;
if (!config.precipitationValue || ["pmin", "pmean", "pmedian", "pmax"].indexOf(config.precipitationValue) == -1) { if (!config.precipitationValue || ["pmin", "pmean", "pmedian", "pmax"].indexOf(config.precipitationValue) === -1) {
console.log("invalid or not set: " + config.precipitationValue); console.log("invalid or not set: " + config.precipitationValue);
config.precipitationValue = this.defaults.precipitationValue; config.precipitationValue = this.defaults.precipitationValue;
} }
@ -70,6 +70,7 @@ WeatherProvider.register("smhi", {
* Of all the times returned find out which one is closest to the current time, should be the first if the data isn't old. * Of all the times returned find out which one is closest to the current time, should be the first if the data isn't old.
* *
* @param times * @param times
* @returns {undefined}
*/ */
getClosestToCurrentTime(times) { getClosestToCurrentTime(times) {
let now = moment(); let now = moment();
@ -85,6 +86,8 @@ WeatherProvider.register("smhi", {
/** /**
* Get the forecast url for the configured coordinates * Get the forecast url for the configured coordinates
*
* @returns {string}
*/ */
getURL() { getURL() {
let lon = this.config.lon; let lon = this.config.lon;
@ -99,8 +102,7 @@ WeatherProvider.register("smhi", {
* *
* @param weatherData * @param weatherData
* @param coordinates * @param coordinates
* @param weatherData * @returns {WeatherObject}
* @param coordinates
*/ */
convertWeatherDataToObject(weatherData, coordinates) { convertWeatherDataToObject(weatherData, coordinates) {
let currentWeather = new WeatherObject("metric", "metric", "metric"); //Weather data is only for Sweden and nobody in Sweden would use imperial let currentWeather = new WeatherObject("metric", "metric", "metric"); //Weather data is only for Sweden and nobody in Sweden would use imperial
@ -145,8 +147,7 @@ WeatherProvider.register("smhi", {
* *
* @param allWeatherData * @param allWeatherData
* @param coordinates * @param coordinates
* @param allWeatherData * @returns {*[]}
* @param coordinates
*/ */
convertWeatherDataGroupedByDay(allWeatherData, coordinates) { convertWeatherDataGroupedByDay(allWeatherData, coordinates) {
let currentWeather; let currentWeather;
@ -194,6 +195,7 @@ WeatherProvider.register("smhi", {
* Resolve coordinates from the response data (probably preferably to use this if it's not matching the config values exactly) * Resolve coordinates from the response data (probably preferably to use this if it's not matching the config values exactly)
* *
* @param data * @param data
* @returns {{lon, lat}}
*/ */
resolveCoordinates(data) { resolveCoordinates(data) {
return { lat: data.geometry.coordinates[0][1], lon: data.geometry.coordinates[0][0] }; return { lat: data.geometry.coordinates[0][1], lon: data.geometry.coordinates[0][0] };
@ -203,6 +205,7 @@ WeatherProvider.register("smhi", {
* Checks if the weatherObject is at dayTime. * Checks if the weatherObject is at dayTime.
* *
* @param weatherObject * @param weatherObject
* @returns {boolean}
*/ */
isDayTime(weatherObject) { isDayTime(weatherObject) {
return weatherObject.date.isBetween(weatherObject.sunrise, weatherObject.sunset, undefined, "[]"); return weatherObject.date.isBetween(weatherObject.sunrise, weatherObject.sunset, undefined, "[]");
@ -213,15 +216,16 @@ WeatherProvider.register("smhi", {
* Find these gaps and fill them with the previous hours data to make the data returned a complete set. * Find these gaps and fill them with the previous hours data to make the data returned a complete set.
* *
* @param data * @param data
* @returns {*[]}
*/ */
fillInGaps(data) { fillInGaps(data) {
let result = []; let result = [];
for (const i = 1; i < data.length; i++) { for (let i = 1; i < data.length; i++) {
let to = moment(data[i].validTime); let to = moment(data[i].validTime);
let from = moment(data[i - 1].validTime); let from = moment(data[i - 1].validTime);
let hours = moment.duration(to.diff(from)).asHours(); let hours = moment.duration(to.diff(from)).asHours();
// For each hour add a datapoint but change the validTime // For each hour add a datapoint but change the validTime
for (const j = 0; j < hours; j++) { for (let j = 0; j < hours; j++) {
let current = Object.assign({}, data[i]); let current = Object.assign({}, data[i]);
current.validTime = from.clone().add(j, "hours").toISOString(); current.validTime = from.clone().add(j, "hours").toISOString();
result.push(current); result.push(current);
@ -236,11 +240,10 @@ WeatherProvider.register("smhi", {
* *
* @param currentWeatherData * @param currentWeatherData
* @param name * @param name
* @param currentWeatherData * @returns {unknown}
* @param name
*/ */
paramValue(currentWeatherData, name) { paramValue(currentWeatherData, name) {
return currentWeatherData.parameters.filter((p) => p.name == name).flatMap((p) => p.values)[0]; return currentWeatherData.parameters.filter((p) => p.name === name).flatMap((p) => p.values)[0];
}, },
/** /**
@ -250,8 +253,7 @@ WeatherProvider.register("smhi", {
* *
* @param input * @param input
* @param isDayTime * @param isDayTime
* @param input * @returns {string|string}
* @param isDayTime
*/ */
convertWeatherType(input, isDayTime) { convertWeatherType(input, isDayTime) {
switch (input) { switch (input) {

View File

@ -1,3 +1,5 @@
/* global WeatherProvider, WeatherObject, SunCalc */
/* Magic Mirror /* Magic Mirror
* Module: Weather * Module: Weather
* *
@ -91,7 +93,7 @@ WeatherProvider.register("ukmetofficedatahub", {
this.fetchWeather(this.getUrl("hourly"), this.getHeaders()) this.fetchWeather(this.getUrl("hourly"), this.getHeaders())
.then((data) => { .then((data) => {
// Check data is useable // Check data is useable
if (!data || !data.features || !data.features[0].properties || !data.features[0].properties.timeSeries || data.features[0].properties.timeSeries.length == 0) { if (!data || !data.features || !data.features[0].properties || !data.features[0].properties.timeSeries || data.features[0].properties.timeSeries.length === 0) {
// Did not receive usable new data. // Did not receive usable new data.
// Maybe this needs a better check? // Maybe this needs a better check?
Log.error("Possibly bad current/hourly data?"); Log.error("Possibly bad current/hourly data?");
@ -125,7 +127,7 @@ WeatherProvider.register("ukmetofficedatahub", {
let nowUtc = moment.utc(); let nowUtc = moment.utc();
// Find hour that contains the current time // Find hour that contains the current time
for (hour in forecastDataHours) { for (let hour in forecastDataHours) {
let forecastTime = moment.utc(forecastDataHours[hour].time); let forecastTime = moment.utc(forecastDataHours[hour].time);
if (nowUtc.isSameOrAfter(forecastTime) && nowUtc.isBefore(moment(forecastTime.add(1, "h")))) { if (nowUtc.isSameOrAfter(forecastTime) && nowUtc.isBefore(moment(forecastTime.add(1, "h")))) {
currentWeather.date = forecastTime; currentWeather.date = forecastTime;
@ -162,7 +164,7 @@ WeatherProvider.register("ukmetofficedatahub", {
this.fetchWeather(this.getUrl("daily"), this.getHeaders()) this.fetchWeather(this.getUrl("daily"), this.getHeaders())
.then((data) => { .then((data) => {
// Check data is useable // Check data is useable
if (!data || !data.features || !data.features[0].properties || !data.features[0].properties.timeSeries || data.features[0].properties.timeSeries.length == 0) { if (!data || !data.features || !data.features[0].properties || !data.features[0].properties.timeSeries || data.features[0].properties.timeSeries.length === 0) {
// Did not receive usable new data. // Did not receive usable new data.
// Maybe this needs a better check? // Maybe this needs a better check?
Log.error("Possibly bad forecast data?"); Log.error("Possibly bad forecast data?");
@ -196,7 +198,7 @@ WeatherProvider.register("ukmetofficedatahub", {
let today = moment.utc().startOf("date"); let today = moment.utc().startOf("date");
// Go through each day in the forecasts // Go through each day in the forecasts
for (day in forecastDataDays) { for (let day in forecastDataDays) {
const forecastWeather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits, this.config.useKmh); const forecastWeather = new WeatherObject(this.config.units, this.config.tempUnits, this.config.windUnits, this.config.useKmh);
// Get date of forecast // Get date of forecast
@ -258,11 +260,11 @@ WeatherProvider.register("ukmetofficedatahub", {
// To use kilometres per hour, use "kph" // To use kilometres per hour, use "kph"
// Else assumed imperial and the value is returned in miles per hour (a Met Office user is likely to be UK-based) // Else assumed imperial and the value is returned in miles per hour (a Met Office user is likely to be UK-based)
convertWindSpeed(windInMpS) { convertWindSpeed(windInMpS) {
if (this.config.windUnits == "mps") { if (this.config.windUnits === "mps") {
return windInMpS; return windInMpS;
} }
if (this.config.windUnits == "kph" || this.config.windUnits == "metric" || this.config.useKmh) { if (this.config.windUnits === "kph" || this.config.windUnits === "metric" || this.config.useKmh) {
return windInMpS * 3.6; return windInMpS * 3.6;
} }

View File

@ -1,3 +1,5 @@
/* eslint-disable */
/* Magic Mirror /* Magic Mirror
* Module: WeatherForecast * Module: WeatherForecast
* *

150
package-lock.json generated
View File

@ -11,7 +11,7 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"colors": "^1.4.0", "colors": "^1.4.0",
"console-stamp": "^3.0.2", "console-stamp": "^3.0.3",
"digest-fetch": "^1.2.0", "digest-fetch": "^1.2.0",
"eslint": "^7.30.0", "eslint": "^7.30.0",
"express": "^4.17.1", "express": "^4.17.1",
@ -23,17 +23,17 @@
"moment": "^2.29.1", "moment": "^2.29.1",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.1",
"node-ical": "^0.13.0", "node-ical": "^0.13.0",
"simple-git": "^2.40.0", "simple-git": "^2.41.1",
"socket.io": "^4.1.2" "socket.io": "^4.1.3"
}, },
"devDependencies": { "devDependencies": {
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-plugin-jest": "^24.3.6", "eslint-plugin-jest": "^24.3.6",
"eslint-plugin-jsdoc": "^35.4.1", "eslint-plugin-jsdoc": "^35.4.3",
"eslint-plugin-prettier": "^3.4.0", "eslint-plugin-prettier": "^3.4.0",
"express-basic-auth": "^1.2.0", "express-basic-auth": "^1.2.0",
"husky": "^7.0.0", "husky": "^7.0.1",
"jest": "27.0.6", "jest": "^27.0.6",
"jsdom": "^16.6.0", "jsdom": "^16.6.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"nyc": "^15.1.0", "nyc": "^15.1.0",
@ -50,7 +50,7 @@
"node": ">=12" "node": ">=12"
}, },
"optionalDependencies": { "optionalDependencies": {
"electron": "^13.1.5" "electron": "^13.1.6"
} }
}, },
"node_modules/@babel/code-frame": { "node_modules/@babel/code-frame": {
@ -703,17 +703,17 @@
} }
}, },
"node_modules/@es-joy/jsdoccomment": { "node_modules/@es-joy/jsdoccomment": {
"version": "0.8.0", "version": "0.9.0-alpha.1",
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.8.0.tgz", "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.9.0-alpha.1.tgz",
"integrity": "sha512-Xd3GzYsL2sz2pcdtYt5Q0Wz1ol/o9Nt2UQL4nFPDcaEomvPmwjJsbjkKx1SKhl2h3TgwazNBLdcNr2m0UiGiFA==", "integrity": "sha512-Clxxc0PwpISoYYBibA+1L2qFJ7gvFVhI2Hos87S06K+Q0cXdOhZQJNKWuaQGPAeHjZEuUB/YoWOfwjuF2wirqA==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"comment-parser": "^1.1.5", "comment-parser": "1.1.6-beta.0",
"esquery": "^1.4.0", "esquery": "^1.4.0",
"jsdoc-type-pratt-parser": "1.0.4" "jsdoc-type-pratt-parser": "1.0.4"
}, },
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=12.0.0"
} }
}, },
"node_modules/@eslint/eslintrc": { "node_modules/@eslint/eslintrc": {
@ -2600,9 +2600,9 @@
} }
}, },
"node_modules/comment-parser": { "node_modules/comment-parser": {
"version": "1.1.5", "version": "1.1.6-beta.0",
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.1.5.tgz", "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.1.6-beta.0.tgz",
"integrity": "sha512-RePCE4leIhBlmrqiYTvaqEeGYg7qpSl4etaIabKtdOQVi+mSTIBBklGUwIr79GXYnl3LpMwmDw4KeR2stNc6FA==", "integrity": "sha512-q3cA8TSMyqW7wcPSYWzbO/rMahnXgzs4SLG/UIWXdEsnXTFPZkEkWAdNgPiHig2OzxgpPLOh4WwsmClDxndwHw==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">= 10.0.0" "node": ">= 10.0.0"
@ -2679,11 +2679,11 @@
} }
}, },
"node_modules/console-stamp": { "node_modules/console-stamp": {
"version": "3.0.2", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/console-stamp/-/console-stamp-3.0.2.tgz", "resolved": "https://registry.npmjs.org/console-stamp/-/console-stamp-3.0.3.tgz",
"integrity": "sha512-nYIxVrp1Cau8wRy8RQJO1VNBTYQPnFcN7SrsLAStSavo38Y4+jcysh5n4nZNd/WkR2IOULgwr2+6qDxMUA7Hog==", "integrity": "sha512-6ltMcMEVDHb1bqb+qaVfCX7Vf3vEkfZEeKyReG1ny45Rv6YJynCcdv94j7whNVfxj/4/3Ji/QBHY6p4JI51Ucw==",
"dependencies": { "dependencies": {
"chalk": "^4.1.0", "chalk": "^4.1.1",
"dateformat": "^4.5.1" "dateformat": "^4.5.1"
}, },
"engines": { "engines": {
@ -3243,11 +3243,12 @@
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
}, },
"node_modules/electron": { "node_modules/electron": {
"version": "13.1.5", "version": "13.1.6",
"resolved": "https://registry.npmjs.org/electron/-/electron-13.1.5.tgz", "resolved": "https://registry.npmjs.org/electron/-/electron-13.1.6.tgz",
"integrity": "sha512-ZoMCcPQNs/zO/Zdb5hq5H+rwRaKrdI3/sfXEwBVMx7f5jwa9jPQB3dZ2+7t59uD9VcFAWsH/pozr8nPPlv0tyw==", "integrity": "sha512-XiB55/JTaQpDFQrD9pulYnOGwaWeMyRIub5ispvoE2bWBvM5zVMLptwMLb0m3KTMrfSkzhedZvOu7fwYvR7L7Q==",
"devOptional": true, "devOptional": true,
"hasInstallScript": true, "hasInstallScript": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@electron/get": "^1.0.1", "@electron/get": "^1.0.1",
"@types/node": "^14.6.2", "@types/node": "^14.6.2",
@ -3646,14 +3647,14 @@
} }
}, },
"node_modules/eslint-plugin-jsdoc": { "node_modules/eslint-plugin-jsdoc": {
"version": "35.4.1", "version": "35.4.3",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-35.4.1.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-35.4.3.tgz",
"integrity": "sha512-lnpu2Bj+ta2eAqwCWnb6f3Xjc78TWKo/oMCpDH5NfpPhYnePNtGZJzoAMgU5uo9BQqmXJ8pql8aiodOhg82ofw==", "integrity": "sha512-hBEn+VNjVX0IKoZ2OdZs0Z1fU8CqZkBSzLqD8ZpwZEamrdi2TUgKvujvETe8gXYQ/67hpRtbR5iPFTgmWpRevw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@es-joy/jsdoccomment": "^0.8.0", "@es-joy/jsdoccomment": "^0.9.0-alpha.1",
"comment-parser": "1.1.5", "comment-parser": "1.1.6-beta.0",
"debug": "^4.3.1", "debug": "^4.3.2",
"esquery": "^1.4.0", "esquery": "^1.4.0",
"jsdoc-type-pratt-parser": "^1.0.4", "jsdoc-type-pratt-parser": "^1.0.4",
"lodash": "^4.17.21", "lodash": "^4.17.21",
@ -4865,10 +4866,11 @@
} }
}, },
"node_modules/husky": { "node_modules/husky": {
"version": "7.0.0", "version": "7.0.1",
"resolved": "https://registry.npmjs.org/husky/-/husky-7.0.0.tgz", "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.1.tgz",
"integrity": "sha512-xK7lO0EtSzfFPiw+oQncQVy/XqV7UVVjxBByc+Iv5iK3yhW9boDoWgvZy3OGo48QKg/hUtZkzz0hi2HXa0kn7w==", "integrity": "sha512-gceRaITVZ+cJH9sNHqx5tFwbzlLCVxtVZcusME8JYQ8Edy5mpGDOqD8QBCdMhpyo9a+JXddnujQ4rpY2Ff9SJA==",
"dev": true, "dev": true,
"license": "MIT",
"bin": { "bin": {
"husky": "lib/bin.js" "husky": "lib/bin.js"
}, },
@ -8578,9 +8580,9 @@
"dev": true "dev": true
}, },
"node_modules/simple-git": { "node_modules/simple-git": {
"version": "2.40.0", "version": "2.41.1",
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-2.40.0.tgz", "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-2.41.1.tgz",
"integrity": "sha512-7IO/eQwrN5kvS38TTu9ljhG9tx2nn0BTqZOmqpPpp51TvE44YIvLA6fETqEVA8w/SeEfPaVv6mk7Tsk9Jns+ag==", "integrity": "sha512-n1STz1tfnemvYndzWakgKa0JB4s/LrUG4btXMetWB9N9ZoIAJQd0ZtWj9sBwWxIZ/X/tYdA/tq+KHfFNAGzZhQ==",
"dependencies": { "dependencies": {
"@kwsites/file-exists": "^1.1.1", "@kwsites/file-exists": "^1.1.1",
"@kwsites/promise-deferred": "^1.1.1", "@kwsites/promise-deferred": "^1.1.1",
@ -8637,19 +8639,19 @@
} }
}, },
"node_modules/socket.io": { "node_modules/socket.io": {
"version": "4.1.2", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.1.2.tgz", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.1.3.tgz",
"integrity": "sha512-xK0SD1C7hFrh9+bYoYCdVt+ncixkSLKtNLCax5aEy1o3r5PaO5yQhVb97exIe67cE7lAK+EpyMytXWTWmyZY8w==", "integrity": "sha512-tLkaY13RcO4nIRh1K2hT5iuotfTaIQw7cVIe0FUykN3SuQi0cm7ALxuyT5/CtDswOMWUzMGTibxYNx/gU7In+Q==",
"dependencies": { "dependencies": {
"@types/cookie": "^0.4.0", "@types/cookie": "^0.4.0",
"@types/cors": "^2.8.8", "@types/cors": "^2.8.10",
"@types/node": ">=10.0.0", "@types/node": ">=10.0.0",
"accepts": "~1.3.4", "accepts": "~1.3.4",
"base64id": "~2.0.0", "base64id": "~2.0.0",
"debug": "~4.3.1", "debug": "~4.3.1",
"engine.io": "~5.1.0", "engine.io": "~5.1.1",
"socket.io-adapter": "~2.3.0", "socket.io-adapter": "~2.3.1",
"socket.io-parser": "~4.0.3" "socket.io-parser": "~4.0.4"
}, },
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"
@ -10913,12 +10915,12 @@
"requires": {} "requires": {}
}, },
"@es-joy/jsdoccomment": { "@es-joy/jsdoccomment": {
"version": "0.8.0", "version": "0.9.0-alpha.1",
"resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.8.0.tgz", "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.9.0-alpha.1.tgz",
"integrity": "sha512-Xd3GzYsL2sz2pcdtYt5Q0Wz1ol/o9Nt2UQL4nFPDcaEomvPmwjJsbjkKx1SKhl2h3TgwazNBLdcNr2m0UiGiFA==", "integrity": "sha512-Clxxc0PwpISoYYBibA+1L2qFJ7gvFVhI2Hos87S06K+Q0cXdOhZQJNKWuaQGPAeHjZEuUB/YoWOfwjuF2wirqA==",
"dev": true, "dev": true,
"requires": { "requires": {
"comment-parser": "^1.1.5", "comment-parser": "1.1.6-beta.0",
"esquery": "^1.4.0", "esquery": "^1.4.0",
"jsdoc-type-pratt-parser": "1.0.4" "jsdoc-type-pratt-parser": "1.0.4"
} }
@ -12396,9 +12398,9 @@
} }
}, },
"comment-parser": { "comment-parser": {
"version": "1.1.5", "version": "1.1.6-beta.0",
"resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.1.5.tgz", "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.1.6-beta.0.tgz",
"integrity": "sha512-RePCE4leIhBlmrqiYTvaqEeGYg7qpSl4etaIabKtdOQVi+mSTIBBklGUwIr79GXYnl3LpMwmDw4KeR2stNc6FA==", "integrity": "sha512-q3cA8TSMyqW7wcPSYWzbO/rMahnXgzs4SLG/UIWXdEsnXTFPZkEkWAdNgPiHig2OzxgpPLOh4WwsmClDxndwHw==",
"dev": true "dev": true
}, },
"commondir": { "commondir": {
@ -12465,11 +12467,11 @@
} }
}, },
"console-stamp": { "console-stamp": {
"version": "3.0.2", "version": "3.0.3",
"resolved": "https://registry.npmjs.org/console-stamp/-/console-stamp-3.0.2.tgz", "resolved": "https://registry.npmjs.org/console-stamp/-/console-stamp-3.0.3.tgz",
"integrity": "sha512-nYIxVrp1Cau8wRy8RQJO1VNBTYQPnFcN7SrsLAStSavo38Y4+jcysh5n4nZNd/WkR2IOULgwr2+6qDxMUA7Hog==", "integrity": "sha512-6ltMcMEVDHb1bqb+qaVfCX7Vf3vEkfZEeKyReG1ny45Rv6YJynCcdv94j7whNVfxj/4/3Ji/QBHY6p4JI51Ucw==",
"requires": { "requires": {
"chalk": "^4.1.0", "chalk": "^4.1.1",
"dateformat": "^4.5.1" "dateformat": "^4.5.1"
} }
}, },
@ -12915,9 +12917,9 @@
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
}, },
"electron": { "electron": {
"version": "13.1.5", "version": "13.1.6",
"resolved": "https://registry.npmjs.org/electron/-/electron-13.1.5.tgz", "resolved": "https://registry.npmjs.org/electron/-/electron-13.1.6.tgz",
"integrity": "sha512-ZoMCcPQNs/zO/Zdb5hq5H+rwRaKrdI3/sfXEwBVMx7f5jwa9jPQB3dZ2+7t59uD9VcFAWsH/pozr8nPPlv0tyw==", "integrity": "sha512-XiB55/JTaQpDFQrD9pulYnOGwaWeMyRIub5ispvoE2bWBvM5zVMLptwMLb0m3KTMrfSkzhedZvOu7fwYvR7L7Q==",
"devOptional": true, "devOptional": true,
"requires": { "requires": {
"@electron/get": "^1.0.1", "@electron/get": "^1.0.1",
@ -13209,14 +13211,14 @@
} }
}, },
"eslint-plugin-jsdoc": { "eslint-plugin-jsdoc": {
"version": "35.4.1", "version": "35.4.3",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-35.4.1.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-35.4.3.tgz",
"integrity": "sha512-lnpu2Bj+ta2eAqwCWnb6f3Xjc78TWKo/oMCpDH5NfpPhYnePNtGZJzoAMgU5uo9BQqmXJ8pql8aiodOhg82ofw==", "integrity": "sha512-hBEn+VNjVX0IKoZ2OdZs0Z1fU8CqZkBSzLqD8ZpwZEamrdi2TUgKvujvETe8gXYQ/67hpRtbR5iPFTgmWpRevw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@es-joy/jsdoccomment": "^0.8.0", "@es-joy/jsdoccomment": "^0.9.0-alpha.1",
"comment-parser": "1.1.5", "comment-parser": "1.1.6-beta.0",
"debug": "^4.3.1", "debug": "^4.3.2",
"esquery": "^1.4.0", "esquery": "^1.4.0",
"jsdoc-type-pratt-parser": "^1.0.4", "jsdoc-type-pratt-parser": "^1.0.4",
"lodash": "^4.17.21", "lodash": "^4.17.21",
@ -14135,9 +14137,9 @@
"dev": true "dev": true
}, },
"husky": { "husky": {
"version": "7.0.0", "version": "7.0.1",
"resolved": "https://registry.npmjs.org/husky/-/husky-7.0.0.tgz", "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.1.tgz",
"integrity": "sha512-xK7lO0EtSzfFPiw+oQncQVy/XqV7UVVjxBByc+Iv5iK3yhW9boDoWgvZy3OGo48QKg/hUtZkzz0hi2HXa0kn7w==", "integrity": "sha512-gceRaITVZ+cJH9sNHqx5tFwbzlLCVxtVZcusME8JYQ8Edy5mpGDOqD8QBCdMhpyo9a+JXddnujQ4rpY2Ff9SJA==",
"dev": true "dev": true
}, },
"iconv-lite": { "iconv-lite": {
@ -16981,9 +16983,9 @@
"dev": true "dev": true
}, },
"simple-git": { "simple-git": {
"version": "2.40.0", "version": "2.41.1",
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-2.40.0.tgz", "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-2.41.1.tgz",
"integrity": "sha512-7IO/eQwrN5kvS38TTu9ljhG9tx2nn0BTqZOmqpPpp51TvE44YIvLA6fETqEVA8w/SeEfPaVv6mk7Tsk9Jns+ag==", "integrity": "sha512-n1STz1tfnemvYndzWakgKa0JB4s/LrUG4btXMetWB9N9ZoIAJQd0ZtWj9sBwWxIZ/X/tYdA/tq+KHfFNAGzZhQ==",
"requires": { "requires": {
"@kwsites/file-exists": "^1.1.1", "@kwsites/file-exists": "^1.1.1",
"@kwsites/promise-deferred": "^1.1.1", "@kwsites/promise-deferred": "^1.1.1",
@ -17027,19 +17029,19 @@
} }
}, },
"socket.io": { "socket.io": {
"version": "4.1.2", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.1.2.tgz", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.1.3.tgz",
"integrity": "sha512-xK0SD1C7hFrh9+bYoYCdVt+ncixkSLKtNLCax5aEy1o3r5PaO5yQhVb97exIe67cE7lAK+EpyMytXWTWmyZY8w==", "integrity": "sha512-tLkaY13RcO4nIRh1K2hT5iuotfTaIQw7cVIe0FUykN3SuQi0cm7ALxuyT5/CtDswOMWUzMGTibxYNx/gU7In+Q==",
"requires": { "requires": {
"@types/cookie": "^0.4.0", "@types/cookie": "^0.4.0",
"@types/cors": "^2.8.8", "@types/cors": "^2.8.10",
"@types/node": ">=10.0.0", "@types/node": ">=10.0.0",
"accepts": "~1.3.4", "accepts": "~1.3.4",
"base64id": "~2.0.0", "base64id": "~2.0.0",
"debug": "~4.3.1", "debug": "~4.3.1",
"engine.io": "~5.1.0", "engine.io": "~5.1.1",
"socket.io-adapter": "~2.3.0", "socket.io-adapter": "~2.3.1",
"socket.io-parser": "~4.0.3" "socket.io-parser": "~4.0.4"
} }
}, },
"socket.io-adapter": { "socket.io-adapter": {

View File

@ -15,13 +15,13 @@
"test:e2e": "NODE_ENV=test jest --selectProjects e2e -i --forceExit", "test:e2e": "NODE_ENV=test jest --selectProjects e2e -i --forceExit",
"test:unit": "NODE_ENV=test jest --selectProjects unit -i --forceExit", "test:unit": "NODE_ENV=test jest --selectProjects unit -i --forceExit",
"test:prettier": "prettier . --check", "test:prettier": "prettier . --check",
"test:js": "eslint js/**/*.js modules/default/**/*.js clientonly/*.js serveronly/*.js translations/*.js vendor/*.js tests/**/*.js config/* --config .eslintrc.json --quiet", "test:js": "eslint 'js/**/*.js' 'modules/default/**/*.js' 'clientonly/*.js' 'serveronly/*.js' 'translations/*.js' 'vendor/*.js' 'tests/**/*.js' 'config/*' --config .eslintrc.json --quiet",
"test:css": "stylelint css/main.css modules/default/**/*.css --config .stylelintrc.json", "test:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --config .stylelintrc.json",
"test:calendar": "node ./modules/default/calendar/debug.js", "test:calendar": "node ./modules/default/calendar/debug.js",
"config:check": "node js/check_config.js", "config:check": "node js/check_config.js",
"lint:prettier": "prettier . --write", "lint:prettier": "prettier . --write",
"lint:js": "eslint js/**/*.js modules/default/**/*.js clientonly/*.js serveronly/*.js translations/*.js vendor/*.js tests/**/*.js config/* --config .eslintrc.json --fix", "lint:js": "eslint 'js/**/*.js' 'modules/default/**/*.js' 'clientonly/*.js' 'serveronly/*.js' 'translations/*.js' 'vendor/*.js' 'tests/**/*.js' 'config/*' --config .eslintrc.json --fix",
"lint:css": "stylelint css/main.css modules/default/**/*.css --config .stylelintrc.json --fix", "lint:css": "stylelint 'css/main.css' 'fonts/*.css' 'modules/default/**/*.css' 'vendor/*.css' --config .stylelintrc.json --fix",
"lint:staged": "pretty-quick --staged", "lint:staged": "pretty-quick --staged",
"prepare": "[ -f node_modules/.bin/husky ] && husky install || echo no husky installed." "prepare": "[ -f node_modules/.bin/husky ] && husky install || echo no husky installed."
}, },
@ -46,12 +46,12 @@
"homepage": "https://magicmirror.builders", "homepage": "https://magicmirror.builders",
"devDependencies": { "devDependencies": {
"eslint-config-prettier": "^8.3.0", "eslint-config-prettier": "^8.3.0",
"eslint-plugin-jsdoc": "^35.4.1",
"eslint-plugin-prettier": "^3.4.0",
"eslint-plugin-jest": "^24.3.6", "eslint-plugin-jest": "^24.3.6",
"eslint-plugin-jsdoc": "^35.4.3",
"eslint-plugin-prettier": "^3.4.0",
"express-basic-auth": "^1.2.0", "express-basic-auth": "^1.2.0",
"husky": "^7.0.0", "husky": "^7.0.1",
"jest": "27.0.6", "jest": "^27.0.6",
"jsdom": "^16.6.0", "jsdom": "^16.6.0",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"nyc": "^15.1.0", "nyc": "^15.1.0",
@ -65,11 +65,11 @@
"stylelint-prettier": "^1.2.0" "stylelint-prettier": "^1.2.0"
}, },
"optionalDependencies": { "optionalDependencies": {
"electron": "^13.1.5" "electron": "^13.1.6"
}, },
"dependencies": { "dependencies": {
"colors": "^1.4.0", "colors": "^1.4.0",
"console-stamp": "^3.0.2", "console-stamp": "^3.0.3",
"digest-fetch": "^1.2.0", "digest-fetch": "^1.2.0",
"eslint": "^7.30.0", "eslint": "^7.30.0",
"express": "^4.17.1", "express": "^4.17.1",
@ -81,8 +81,8 @@
"moment": "^2.29.1", "moment": "^2.29.1",
"node-fetch": "^2.6.1", "node-fetch": "^2.6.1",
"node-ical": "^0.13.0", "node-ical": "^0.13.0",
"simple-git": "^2.40.0", "simple-git": "^2.41.1",
"socket.io": "^4.1.2" "socket.io": "^4.1.3"
}, },
"_moduleAliases": { "_moduleAliases": {
"node_helper": "js/node_helper.js", "node_helper": "js/node_helper.js",

View File

@ -5,7 +5,7 @@ describe("Clock set to spanish language module", function () {
let app = null; let app = null;
testMatch = async function (element, regex) { const testMatch = async function (element, regex) {
await app.client.waitUntilWindowLoaded(); await app.client.waitUntilWindowLoaded();
const elem = await app.client.$(element); const elem = await app.client.$(element);
const txt = await elem.getText(element); const txt = await elem.getText(element);

View File

@ -6,7 +6,7 @@ describe("Clock module", function () {
let app = null; let app = null;
testMatch = async function (element, regex) { const testMatch = async function (element, regex) {
await app.client.waitUntilWindowLoaded(); await app.client.waitUntilWindowLoaded();
const elem = await app.client.$(element); const elem = await app.client.$(element);
const txt = await elem.getText(element); const txt = await elem.getText(element);

View File

@ -1,5 +1,8 @@
const _ = require("lodash"); const _ = require("lodash");
/**
* @param extendedData
*/
function generateWeather(extendedData = {}) { function generateWeather(extendedData = {}) {
return JSON.stringify( return JSON.stringify(
_.merge( _.merge(

View File

@ -1,5 +1,8 @@
const _ = require("lodash"); const _ = require("lodash");
/**
* @param extendedData
*/
function generateWeatherForecast(extendedData = {}) { function generateWeatherForecast(extendedData = {}) {
return JSON.stringify( return JSON.stringify(
_.merge( _.merge(

View File

@ -12,6 +12,9 @@ describe("Weather module", function () {
helpers.setupTimeout(this); helpers.setupTimeout(this);
/**
* @param responses
*/
async function setup(responses) { async function setup(responses) {
app = await helpers.startApplication({ app = await helpers.startApplication({
args: ["js/electron.js"], args: ["js/electron.js"],
@ -23,10 +26,17 @@ describe("Weather module", function () {
app.client.setupStub(); app.client.setupStub();
} }
/**
* @param element
*/
async function getElement(element) { async function getElement(element) {
return await app.client.$(element); return await app.client.$(element);
} }
/**
* @param element
* @param result
*/
async function getText(element, result) { async function getText(element, result) {
const elem = await getElement(element); const elem = await getElement(element);
return await elem.getText(element).then(function (text) { return await elem.getText(element).then(function (text) {

View File

@ -1,9 +1,6 @@
const helpers = require("./global-setup"); const helpers = require("./global-setup");
const fetch = require("node-fetch"); const fetch = require("node-fetch");
const before = global.before;
const after = global.after;
describe("Vendors", function () { describe("Vendors", function () {
helpers.setupTimeout(this); helpers.setupTimeout(this);
@ -26,6 +23,7 @@ describe("Vendors", function () {
describe("Get list vendors", function () { describe("Get list vendors", function () {
const vendors = require(__dirname + "/../../vendor/vendor.js"); const vendors = require(__dirname + "/../../vendor/vendor.js");
Object.keys(vendors).forEach((vendor) => { Object.keys(vendors).forEach((vendor) => {
it(`should return 200 HTTP code for vendor "${vendor}"`, function (done) { it(`should return 200 HTTP code for vendor "${vendor}"`, function (done) {
const urlVendor = "http://localhost:8080/vendor/" + vendors[vendor]; const urlVendor = "http://localhost:8080/vendor/" + vendors[vendor];

View File

@ -67,6 +67,9 @@ describe("Translator", function () {
Fallback: "core fallback" Fallback: "core fallback"
}; };
/**
* @param Translator
*/
function setTranslations(Translator) { function setTranslations(Translator) {
Translator.translations = translations; Translator.translations = translations;
Translator.coreTranslations = coreTranslations; Translator.coreTranslations = coreTranslations;

View File

@ -4,39 +4,41 @@ const vm = require("vm");
const basedir = path.join(__dirname, "../../.."); const basedir = path.join(__dirname, "../../..");
beforeAll(function () {
const fileName = "js/app.js";
const filePath = path.join(basedir, fileName);
const code = fs.readFileSync(filePath);
sandbox = {
module: {},
__dirname: path.dirname(filePath),
global: {},
process: {
on: function () {},
env: {}
}
};
sandbox.require = function (filename) {
// This modifies the global slightly,
// but supplies vm with essential code
if (filename === "logger") {
return require("../mocks/logger.js");
} else {
try {
return require(filename);
} catch {
// ignore
}
}
};
vm.runInNewContext(code, sandbox, fileName);
});
describe("Default modules set in modules/default/defaultmodules.js", function () { describe("Default modules set in modules/default/defaultmodules.js", function () {
let sandbox = null;
beforeAll(function () {
const fileName = "js/app.js";
const filePath = path.join(basedir, fileName);
const code = fs.readFileSync(filePath);
sandbox = {
module: {},
__dirname: path.dirname(filePath),
global: {},
process: {
on: function () {},
env: {}
}
};
sandbox.require = function (filename) {
// This modifies the global slightly,
// but supplies vm with essential code
if (filename === "logger") {
return require("../mocks/logger.js");
} else {
try {
return require(filename);
} catch (ignore) {
// ignore
}
}
};
vm.runInNewContext(code, sandbox, fileName);
});
const expectedDefaultModules = require("../../../modules/default/defaultmodules"); const expectedDefaultModules = require("../../../modules/default/defaultmodules");
for (const defaultModule of expectedDefaultModules) { for (const defaultModule of expectedDefaultModules) {

View File

@ -2,41 +2,43 @@ const fs = require("fs");
const path = require("path"); const path = require("path");
const vm = require("vm"); const vm = require("vm");
beforeAll(function () {
const basedir = path.join(__dirname, "../../..");
const fileName = "js/app.js";
const filePath = path.join(basedir, fileName);
const code = fs.readFileSync(filePath);
sandbox = {
module: {},
__dirname: path.dirname(filePath),
global: {},
process: {
on: function () {},
env: {}
}
};
sandbox.require = function (filename) {
// This modifies the global slightly,
// but supplies vm with essential code
if (filename === "logger") {
return require("../mocks/logger.js");
} else {
try {
return require(filename);
} catch {
// ignore
}
}
};
vm.runInNewContext(code, sandbox, fileName);
});
describe("'global.root_path' set in js/app.js", function () { describe("'global.root_path' set in js/app.js", function () {
let sandbox = null;
beforeAll(function () {
const basedir = path.join(__dirname, "../../..");
const fileName = "js/app.js";
const filePath = path.join(basedir, fileName);
const code = fs.readFileSync(filePath);
sandbox = {
module: {},
__dirname: path.dirname(filePath),
global: {},
process: {
on: function () {},
env: {}
}
};
sandbox.require = function (filename) {
// This modifies the global slightly,
// but supplies vm with essential code
if (filename === "logger") {
return require("../mocks/logger.js");
} else {
try {
return require(filename);
} catch (ignore) {
// ignore
}
}
};
vm.runInNewContext(code, sandbox, fileName);
});
const expectedSubPaths = ["modules", "serveronly", "js", "js/app.js", "js/main.js", "js/electron.js", "config"]; const expectedSubPaths = ["modules", "serveronly", "js", "js/app.js", "js/main.js", "js/electron.js", "config"];
expectedSubPaths.forEach((subpath) => { expectedSubPaths.forEach((subpath) => {

View File

@ -5,7 +5,7 @@
* MIT Licensed. * MIT Licensed.
*/ */
var translations = { let translations = {
en: "translations/en.json", // English en: "translations/en.json", // English
nl: "translations/nl.json", // Dutch nl: "translations/nl.json", // Dutch
de: "translations/de.json", // German de: "translations/de.json", // German