Merge pull request #2873 from MichMich/develop

v2.20.0
This commit is contained in:
Michael Teeuw 2022-07-02 13:07:02 +02:00 committed by GitHub
commit 30d5bfe59e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
43 changed files with 2472 additions and 3072 deletions

View File

@ -16,7 +16,7 @@
},
"parserOptions": {
"sourceType": "module",
"ecmaVersion": 2018,
"ecmaVersion": 2020,
"ecmaFeatures": {
"globalReturn": true
}

6
.github/dependabot.yaml vendored Normal file
View File

@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

View File

@ -9,16 +9,19 @@ on:
pull_request:
branches: [master, develop]
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
matrix:
node-version: [14.x, 16.x, 17.x]
node-version: [14.x, 16.x, 18.x]
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:

View File

@ -1,4 +1,5 @@
# This workflow runs the automated test and uploads the coverage results to codecov.io
# For more information see: https://github.com/codecov/codecov-action
name: "Run Codecov Tests"
@ -8,13 +9,16 @@ on:
pull_request:
branches: [master, develop]
permissions:
contents: read
jobs:
run-and-upload-coverage-report:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Install dependencies and run coverage
run: |
Xvfb :99 -screen 0 1024x768x16 &

View File

@ -1,4 +1,5 @@
# This workflow enforces the update of a changelog file on every pull request
# For more information see: https://github.com/dangoslen/changelog-enforcer
name: "Enforce Changelog"
@ -11,10 +12,8 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Enforce changelog
uses: dangoslen/changelog-enforcer@v2
uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: "CHANGELOG.md"
skipLabels: "Skip Changelog"

View File

@ -5,6 +5,28 @@ This project adheres to [Semantic Versioning](https://semver.org/).
❤️ **Donate:** Enjoying MagicMirror²? [Please consider a donation!](https://magicmirror.builders/donate) With your help we can continue to improve the MagicMirror².
## [2.20.0] - 2022-07-02
Special thanks to the following contributors: @eouia, @khassel, @kolbyjack, @KristjanESPERANTO, @nathannaveen, @naveensrinivasan, @rejas, @rohitdharavath and @sdetweil.
### Added
- Added a new config option `httpHeaders` used by helmet (see https://helmetjs.github.io/). You can now set own httpHeaders which will override the defaults in `js/defauls.js` which is useful e.g. if you want to embed MagicMirror into annother website (solves #2847).
- Show endDate for calendar events when dateHeader is enabled and showEnd is set to true (#2192).
- Added the notification emitting from the weather module on infromation updated.
- Use recommended file extention for YAML files (#2864).
### Updated
- Use latest node 18 when running tests on github actions.
- Update `electron` to v19 and other dependencies.
- Use internal fetch function of node instead external `node-fetch` library if used node version >= `v18`.
- Include duplicate events in broadcasts.
### Fixed
- Fix problems with non latin fonds caused by updating to fontsource (fixes #2835).
## [2.19.0] - 2022-04-01
Special thanks to the following contributors: @10bias, @CFenner, @JHWelch, @k1rd3rf, @khassel, @kolbyjack, @krekos, @KristjanESPERANTO, @Nerfzooka, @oraclesean, @oscarb, @philnagel, @rejas, @sdetweil, @shin10, @SiderealArt and @Tom-Hirschberger.
@ -12,9 +34,9 @@ Special thanks to the following contributors: @10bias, @CFenner, @JHWelch, @k1rd
### Added
- Added a config option under the weather module, `absoluteDates`, providing an option to format weather forecast date output with either absolute or relative dates.
- Added test for new weather forecast `absoluteDates` porperty.
- Added test for new weather forecast `absoluteDates` property.
- The modules get a class hidden added/removed if they get hidden/shown which will also toggle pointer-events.
- Added new config option `showTitleAsUrl` to newsfeed module. If set, the diplayed title is a link to the article which is useful when running in a browser and you want to read this article.
- Added new config option `showTitleAsUrl` to newsfeed module. If set, the displayed title is a link to the article which is useful when running in a browser and you want to read this article.
- Added internal cors proxy to get weather providers working without public proxies (fixes #2714). The new url `http(s)://address:port/cors?url=https://whatever-to-proxy` can be used in other modules too.
- Added a WeatherProvider for Weatherflow.
- Added new env var `ELECTRON_DISABLE_GPU` which disable gpu under electron if set (fixes #2831).
@ -39,6 +61,7 @@ Special thanks to the following contributors: @10bias, @CFenner, @JHWelch, @k1rd
- Don't adjust startDate for full day events if endDate is in the past.
- Fix windspeed conversion error in openweathermap provider. (#2812)
- Fix conflicting parms turning off showEnd for full day events. (#2629)
- Fix regression, calendar.maximumEntries not used to filter calendar level entries (#2868)
## [2.18.0] - 2022-01-01

View File

@ -7,31 +7,31 @@
"name": "magicmirror-fonts",
"license": "MIT",
"dependencies": {
"@fontsource/roboto": "^4.5.5",
"@fontsource/roboto-condensed": "^4.5.6"
"@fontsource/roboto": "^4.5.7",
"@fontsource/roboto-condensed": "^4.5.8"
}
},
"node_modules/@fontsource/roboto": {
"version": "4.5.5",
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.5.tgz",
"integrity": "sha512-Pe1p+gAO6K0aLxBXlLoJRHVx352tVc/v/7DOnvM3t+FYXb+KUga9aCD1NpnDfd0kKnWXqrZyAXguyyFWDDuphw=="
"version": "4.5.7",
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.7.tgz",
"integrity": "sha512-m57UMER23Mk6Drg9OjtHW1Y+0KPGyZfE5XJoPTOsLARLar6013kJj4X2HICt+iFLJqIgTahA/QAvSn9lwF1EEw=="
},
"node_modules/@fontsource/roboto-condensed": {
"version": "4.5.6",
"resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-4.5.6.tgz",
"integrity": "sha512-WDN0RlwXa3ADUDJxrB9HEIhrwYdJFLTNw4YemEYSeIPURU5DAHSx2VFXFv69PbM7kV8At5yMTp8bQkL5TBUP3w=="
"version": "4.5.8",
"resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-4.5.8.tgz",
"integrity": "sha512-HCuf1rVSOsXnl/KgHNRLCr8XS/Dunzn10BjhliJiEZ5qPynXCWH4RRBFupIODHamhj2Uyp/iZkSQp574luKp6A=="
}
},
"dependencies": {
"@fontsource/roboto": {
"version": "4.5.5",
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.5.tgz",
"integrity": "sha512-Pe1p+gAO6K0aLxBXlLoJRHVx352tVc/v/7DOnvM3t+FYXb+KUga9aCD1NpnDfd0kKnWXqrZyAXguyyFWDDuphw=="
"version": "4.5.7",
"resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-4.5.7.tgz",
"integrity": "sha512-m57UMER23Mk6Drg9OjtHW1Y+0KPGyZfE5XJoPTOsLARLar6013kJj4X2HICt+iFLJqIgTahA/QAvSn9lwF1EEw=="
},
"@fontsource/roboto-condensed": {
"version": "4.5.6",
"resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-4.5.6.tgz",
"integrity": "sha512-WDN0RlwXa3ADUDJxrB9HEIhrwYdJFLTNw4YemEYSeIPURU5DAHSx2VFXFv69PbM7kV8At5yMTp8bQkL5TBUP3w=="
"version": "4.5.8",
"resolved": "https://registry.npmjs.org/@fontsource/roboto-condensed/-/roboto-condensed-4.5.8.tgz",
"integrity": "sha512-HCuf1rVSOsXnl/KgHNRLCr8XS/Dunzn10BjhliJiEZ5qPynXCWH4RRBFupIODHamhj2Uyp/iZkSQp574luKp6A=="
}
}
}

View File

@ -10,7 +10,7 @@
"url": "https://github.com/MichMich/MagicMirror/issues"
},
"dependencies": {
"@fontsource/roboto": "^4.5.5",
"@fontsource/roboto-condensed": "^4.5.6"
"@fontsource/roboto": "^4.5.7",
"@fontsource/roboto-condensed": "^4.5.8"
}
}

View File

@ -2,57 +2,54 @@
font-family: Roboto;
font-style: normal;
font-weight: 100;
src: local("Roboto Thin"), local("Roboto-Thin"), url("node_modules/@fontsource/roboto/files/roboto-latin-100-normal.woff2") format("woff2"), url("node_modules/@fontsource/roboto/files/roboto-latin-100-normal.woff") format("woff");
src: local("Roboto Thin"), local("Roboto-Thin"), url("node_modules/@fontsource/roboto/files/roboto-all-100-normal.woff") format("woff");
}
@font-face {
font-family: "Roboto Condensed";
font-style: normal;
font-weight: 300;
src: local("Roboto Condensed Light"), local("RobotoCondensed-Light"), url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-300-normal.woff2") format("woff2"),
url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-300-normal.woff") format("woff");
src: local("Roboto Condensed Light"), local("RobotoCondensed-Light"), url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-all-300-normal.woff") format("woff");
}
@font-face {
font-family: "Roboto Condensed";
font-style: normal;
font-weight: 400;
src: local("Roboto Condensed"), local("RobotoCondensed-Regular"), url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-400-normal.woff2") format("woff2"),
url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-400-normal.woff") format("woff");
src: local("Roboto Condensed"), local("RobotoCondensed-Regular"), url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-all-400-normal.woff") format("woff");
}
@font-face {
font-family: "Roboto Condensed";
font-style: normal;
font-weight: 700;
src: local("Roboto Condensed Bold"), local("RobotoCondensed-Bold"), url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-700-normal.woff2") format("woff2"),
url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-latin-700-normal.woff") format("woff");
src: local("Roboto Condensed Bold"), local("RobotoCondensed-Bold"), url("node_modules/@fontsource/roboto-condensed/files/roboto-condensed-all-700-normal.woff") format("woff");
}
@font-face {
font-family: Roboto;
font-style: normal;
font-weight: 400;
src: local("Roboto"), local("Roboto-Regular"), url("node_modules/@fontsource/roboto/files/roboto-latin-400-normal.woff2") format("woff2"), url("node_modules/@fontsource/roboto/files/roboto-latin-400-normal.woff") format("woff");
src: local("Roboto"), local("Roboto-Regular"), url("node_modules/@fontsource/roboto/files/roboto-all-400-normal.woff") format("woff");
}
@font-face {
font-family: Roboto;
font-style: normal;
font-weight: 500;
src: local("Roboto Medium"), local("Roboto-Medium"), url("node_modules/@fontsource/roboto/files/roboto-latin-500-normal.woff2") format("woff2"), url("node_modules/@fontsource/roboto/files/roboto-latin-500-normal.woff") format("woff");
src: local("Roboto Medium"), local("Roboto-Medium"), url("node_modules/@fontsource/roboto/files/roboto-all-500-normal.woff") format("woff");
}
@font-face {
font-family: Roboto;
font-style: normal;
font-weight: 700;
src: local("Roboto Bold"), local("Roboto-Bold"), url("node_modules/@fontsource/roboto/files/roboto-latin-700-normal.woff2") format("woff2"), url("node_modules/@fontsource/roboto/files/roboto-latin-700-normal.woff") format("woff");
src: local("Roboto Bold"), local("Roboto-Bold"), url("node_modules/@fontsource/roboto/files/roboto-all-700-normal.woff") format("woff");
}
@font-face {
font-family: Roboto;
font-style: normal;
font-weight: 300;
src: local("Roboto Light"), local("Roboto-Light"), url("node_modules/@fontsource/roboto/files/roboto-latin-300-normal.woff2") format("woff2"), url("node_modules/@fontsource/roboto/files/roboto-latin-300-normal.woff") format("woff");
src: local("Roboto Light"), local("Roboto-Light"), url("node_modules/@fontsource/roboto/files/roboto-all-300-normal.woff") format("woff");
}

View File

@ -25,6 +25,9 @@ const defaults = {
units: "metric",
zoom: 1,
customCss: "css/custom.css",
// httpHeaders used by helmet, see https://helmetjs.github.io/. You can add other/more object values by overriding this in config.js,
// e.g. you need to add `frameguard: false` for embedding MagicMirror in another website, see https://github.com/MichMich/MagicMirror/issues/2847
httpHeaders: { contentSecurityPolicy: false, crossOriginOpenerPolicy: false, crossOriginEmbedderPolicy: false, crossOriginResourcePolicy: false, originAgentCluster: false },
modules: [
{

View File

@ -8,7 +8,7 @@ const Log = require("logger");
let config = process.env.config ? JSON.parse(process.env.config) : {};
// Module to control application life.
const app = electron.app;
// If ELECTRON_DISABLE_GPU is set electron is startet with --disable-gpu flag.
// If ELECTRON_DISABLE_GPU is set electron is started with --disable-gpu flag.
// See https://www.electronjs.org/docs/latest/tutorial/offscreen-rendering for more info.
if (process.env.ELECTRON_DISABLE_GPU !== undefined) {
app.disableHardwareAcceleration();

20
js/fetch.js Normal file
View File

@ -0,0 +1,20 @@
/**
* fetch
*
* @param {string} url to be fetched
* @param {object} options object e.g. for headers
* @class
*/
async function fetch(url, options) {
const nodeVersion = process.version.match(/^v(\d+)\.*/)[1];
if (nodeVersion >= 18) {
// node version >= 18
return global.fetch(url, options);
} else {
// node version < 18
const nodefetch = require("node-fetch");
return nodefetch(url, options);
}
}
module.exports = fetch;

View File

@ -10,7 +10,7 @@ const path = require("path");
const ipfilter = require("express-ipfilter").IpFilter;
const fs = require("fs");
const helmet = require("helmet");
const fetch = require("node-fetch");
const fetch = require("fetch");
const Log = require("logger");
const Utils = require("./utils.js");
@ -69,7 +69,7 @@ function Server(config, callback) {
res.status(403).send("This device is not allowed to access your mirror. <br> Please check your config.js or config.js.sample to change this.");
});
});
app.use(helmet({ contentSecurityPolicy: false, crossOriginOpenerPolicy: false, crossOriginEmbedderPolicy: false, crossOriginResourcePolicy: false, originAgentCluster: false }));
app.use(helmet(config.httpHeaders));
app.use("/js", express.static(__dirname));

View File

@ -305,6 +305,12 @@ Module.register("calendar", {
timeWrapper.className = "time light align-left " + this.timeClassForUrl(event.url);
timeWrapper.style.paddingLeft = "2px";
timeWrapper.innerHTML = moment(event.startDate, "x").format("LT");
// Add endDate to dataheaders if showEnd is enabled
if (this.config.showEnd) {
timeWrapper.innerHTML += " - " + moment(event.endDate, "x").format("LT");
}
eventWrapper.appendChild(timeWrapper);
titleWrapper.classList.add("align-right");
}
@ -490,23 +496,21 @@ Module.register("calendar", {
for (const e in calendar) {
const event = JSON.parse(JSON.stringify(calendar[e])); // clone object
if (event.endDate < now && limitNumberOfEntries) {
continue;
}
if (this.config.hidePrivate) {
if (event.class === "PRIVATE") {
if (this.config.hidePrivate && event.class === "PRIVATE") {
// do not add the current event, skip it
continue;
}
}
if (this.config.hideOngoing && limitNumberOfEntries) {
if (event.startDate < now) {
if (limitNumberOfEntries) {
if (event.endDate < now) {
continue;
}
if (this.config.hideOngoing && event.startDate < now) {
continue;
}
if (this.listContainsEvent(events, event)) {
continue;
}
}
event.url = calendarUrl;
event.today = event.startDate >= today && event.startDate < today + 24 * 60 * 60 * 1000;

View File

@ -8,7 +8,7 @@ const CalendarUtils = require("./calendarutils");
const Log = require("logger");
const NodeHelper = require("node_helper");
const ical = require("node-ical");
const fetch = require("node-fetch");
const fetch = require("fetch");
const digest = require("digest-fetch");
const https = require("https");

View File

@ -498,7 +498,8 @@ const CalendarUtils = {
return a.startDate - b.startDate;
});
return newEvents;
let maxEvents = newEvents.slice(0, config.maximumEntries);
return maxEvents;
},
/**

View File

@ -7,8 +7,9 @@
const Log = require("logger");
const FeedMe = require("feedme");
const NodeHelper = require("node_helper");
const fetch = require("node-fetch");
const fetch = require("fetch");
const iconv = require("iconv-lite");
const stream = require("stream");
/**
* Responsible for requesting an update on the set interval and broadcasting the data.
@ -87,7 +88,13 @@ const NewsfeedFetcher = function (url, reloadInterval, encoding, logFeedWarnings
fetch(url, { headers: headers })
.then(NodeHelper.checkFetchStatus)
.then((response) => {
response.body.pipe(iconv.decodeStream(encoding)).pipe(parser);
let nodeStream;
if (response.body instanceof stream.Readable) {
nodeStream = response.body;
} else {
nodeStream = stream.Readable.fromWeb(response.body);
}
nodeStream.pipe(iconv.decodeStream(encoding)).pipe(parser);
})
.catch((error) => {
fetchFailedCallback(this, error);

View File

@ -154,6 +154,15 @@ Module.register("weather", {
if (this.weatherProvider.currentWeather()) {
this.sendNotification("CURRENTWEATHER_TYPE", { type: this.weatherProvider.currentWeather().weatherType.replace("-", "_") });
}
const notificationPayload = {
currentWeather: this.weatherProvider?.currentWeatherObject?.simpleClone() ?? null,
forecastArray: this.weatherProvider?.weatherForecastArray?.map((ar) => ar.simpleClone()) ?? [],
hourlyArray: this.weatherProvider?.weatherHourlyArray?.map((ar) => ar.simpleClone()) ?? [],
locationName: this.weatherProvider?.fetchedLocationName,
providerName: this.weatherProvider.providerName
};
this.sendNotification("WEATHER_UPDATED", notificationPayload);
},
scheduleUpdate: function (delay = null) {

View File

@ -146,6 +146,23 @@ class WeatherObject {
this.sunrise = moment(times.sunrise, "X");
this.sunset = moment(times.sunset, "X");
}
/**
* Clone to simple object to prevent mutating and deprecation of legacy library.
*
* Before being handed to other modules, mutable values must be cloned safely.
* Especially 'moment' object is not immutable, so original 'date', 'sunrise', 'sunset' could be corrupted or changed by other modules.
*
* @returns {object} plained object clone of original weatherObject
*/
simpleClone() {
const toFlat = ["date", "sunrise", "sunset"];
let clone = { ...this };
for (const prop of toFlat) {
clone[prop] = clone?.[prop]?.valueOf() ?? clone?.[prop];
}
return clone;
}
}
/*************** DO NOT EDIT THE LINE BELOW ***************/

5197
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "magicmirror",
"version": "2.19.0",
"version": "2.20.0",
"description": "The open source modular smart mirror platform.",
"main": "js/electron.js",
"scripts": {
@ -48,48 +48,49 @@
"homepage": "https://magicmirror.builders",
"devDependencies": {
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-jest": "^26.1.3",
"eslint-plugin-jsdoc": "^38.1.3",
"eslint-plugin-jest": "^26.5.3",
"eslint-plugin-jsdoc": "^39.3.3",
"eslint-plugin-prettier": "^4.0.0",
"express-basic-auth": "^1.2.1",
"husky": "^7.0.4",
"jest": "^27.5.1",
"jsdom": "^19.0.0",
"husky": "^8.0.1",
"jest": "^28.1.1",
"jsdom": "^20.0.0",
"lodash": "^4.17.21",
"nyc": "^15.1.0",
"playwright": "^1.20.1",
"prettier": "^2.6.1",
"playwright": "^1.22.2",
"prettier": "^2.7.1",
"pretty-quick": "^3.1.3",
"sinon": "^13.0.1",
"stylelint": "^14.6.1",
"sinon": "^14.0.0",
"stylelint": "^14.9.1",
"stylelint-config-prettier": "^9.0.3",
"stylelint-config-standard": "^25.0.0",
"stylelint-config-standard": "^26.0.0",
"stylelint-prettier": "^2.0.0",
"suncalc": "^1.9.0"
},
"optionalDependencies": {
"electron": "^17.2.0"
"electron": "^19.0.6"
},
"dependencies": {
"colors": "^1.4.0",
"console-stamp": "^3.0.4",
"console-stamp": "^3.0.6",
"digest-fetch": "^1.2.1",
"eslint": "^8.12.0",
"express": "^4.17.3",
"eslint": "^8.18.0",
"express": "^4.18.1",
"express-ipfilter": "^1.2.0",
"feedme": "^2.0.2",
"helmet": "^5.0.2",
"helmet": "^5.1.0",
"iconv-lite": "^0.6.3",
"luxon": "^1.21.3",
"luxon": "^1.28.0",
"module-alias": "^2.2.2",
"moment": "^2.29.1",
"moment": "^2.29.3",
"node-fetch": "^2.6.7",
"node-ical": "^0.15.1",
"socket.io": "^4.4.1"
"socket.io": "^4.5.1"
},
"_moduleAliases": {
"node_helper": "js/node_helper.js",
"logger": "js/logger.js"
"logger": "js/logger.js",
"fetch": "js/fetch.js"
},
"engines": {
"node": ">=14"

View File

@ -1,4 +1,4 @@
const fetch = require("node-fetch");
const fetch = require("fetch");
const helpers = require("./global-setup");
describe("App environment", function () {
@ -6,8 +6,8 @@ describe("App environment", function () {
helpers.startApplication("tests/configs/default.js");
helpers.getDocument(done);
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
it("get request from http://localhost:8080 should return 200", function (done) {

View File

@ -1,4 +1,4 @@
const fetch = require("node-fetch");
const fetch = require("fetch");
const helpers = require("./global-setup");
describe("All font files from roboto.css should be downloadable", function () {
@ -17,8 +17,8 @@ describe("All font files from roboto.css should be downloadable", function () {
beforeAll(function () {
helpers.startApplication("tests/configs/without_modules.js");
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
test.each(fontFiles)("should return 200 HTTP code for file '%s'", (fontFile, done) => {

View File

@ -2,9 +2,7 @@ const jsdom = require("jsdom");
exports.startApplication = function (configFilename, exec) {
jest.resetModules();
if (global.app) {
global.app.stop();
}
this.stopApplication();
// Set config sample for use in test
if (configFilename === "") {
process.env.MM_CONFIG_FILE = "config/config.js";
@ -16,10 +14,11 @@ exports.startApplication = function (configFilename, exec) {
global.app.start();
};
exports.stopApplication = function () {
exports.stopApplication = async function () {
if (global.app) {
global.app.stop();
}
await new Promise((resolve) => setTimeout(resolve, 100));
};
exports.getDocument = function (callback) {

View File

@ -1,4 +1,4 @@
const fetch = require("node-fetch");
const fetch = require("fetch");
const helpers = require("./global-setup");
describe("ipWhitelist directive configuration", function () {
@ -6,8 +6,8 @@ describe("ipWhitelist directive configuration", function () {
beforeAll(function () {
helpers.startApplication("tests/configs/noIpWhiteList.js");
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
it("should return 403", function (done) {
@ -22,8 +22,8 @@ describe("ipWhitelist directive configuration", function () {
beforeAll(function () {
helpers.startApplication("tests/configs/empty_ipWhiteList.js");
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
it("should return 200", function (done) {

View File

@ -5,8 +5,8 @@ describe("Alert module", function () {
helpers.startApplication("tests/configs/modules/alert/default.js");
helpers.getDocument(done);
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
it("should show the welcome message", function () {

View File

@ -25,8 +25,8 @@ describe("Calendar module", function () {
});
};
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
describe("Default configuration", function () {

View File

@ -1,8 +1,8 @@
const helpers = require("../global-setup");
describe("Clock set to spanish language module", function () {
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
const testMatch = function (element, regex) {

View File

@ -2,8 +2,8 @@ const helpers = require("../global-setup");
const moment = require("moment");
describe("Clock module", function () {
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
const testMatch = function (element, regex) {

View File

@ -16,8 +16,8 @@ function doTest(complimentsArray) {
}
describe("Compliments module", function () {
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
describe("parts of days", function () {

View File

@ -1,8 +1,8 @@
const helpers = require("../global-setup");
describe("Test helloworld module", function () {
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
describe("helloworld set config text", function () {

View File

@ -1,8 +1,8 @@
const helpers = require("../global-setup");
describe("Newsfeed module", function () {
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
describe("Default configuration", function () {

View File

@ -40,8 +40,8 @@ describe("Weather module", function () {
helpers.getDocument(callback);
}
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
describe("Current weather", function () {

View File

@ -5,8 +5,8 @@ describe("Display of modules", function () {
helpers.startApplication("tests/configs/modules/display.js");
helpers.getDocument(done);
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
it("should show the test header", function () {

View File

@ -5,8 +5,8 @@ describe("Position of modules", function () {
helpers.startApplication("tests/configs/modules/positions.js");
helpers.getDocument(done);
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
const positions = ["top_bar", "top_left", "top_center", "top_right", "upper_third", "middle_center", "lower_third", "bottom_left", "bottom_center", "bottom_right", "bottom_bar", "fullscreen_above", "fullscreen_below"];

View File

@ -1,4 +1,4 @@
const fetch = require("node-fetch");
const fetch = require("fetch");
const helpers = require("./global-setup");
describe("port directive configuration", function () {
@ -6,8 +6,8 @@ describe("port directive configuration", function () {
beforeAll(function () {
helpers.startApplication("tests/configs/port_8090.js");
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
it("should return 200", function (done) {
@ -22,8 +22,8 @@ describe("port directive configuration", function () {
beforeAll(function () {
helpers.startApplication("tests/configs/port_8090.js", (process.env.MM_PORT = 8100));
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
it("should return 200", function (done) {

View File

@ -1,12 +1,12 @@
const fetch = require("node-fetch");
const fetch = require("fetch");
const helpers = require("./global-setup");
describe("Vendors", function () {
beforeAll(function () {
helpers.startApplication("tests/configs/default.js");
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
describe("Get list vendors", function () {

View File

@ -5,8 +5,8 @@ describe("Check configuration without modules", function () {
helpers.startApplication("tests/configs/without_modules.js");
helpers.getDocument(done);
});
afterAll(function () {
helpers.stopApplication();
afterAll(async function () {
await helpers.stopApplication();
});
it("Show the message MagicMirror² title", function () {

14
vendor/package-lock.json generated vendored
View File

@ -8,7 +8,7 @@
"license": "MIT",
"dependencies": {
"@fortawesome/fontawesome-free": "^6.1.1",
"moment": "^2.29.1",
"moment": "^2.29.3",
"moment-timezone": "^0.5.34",
"nunjucks": "^3.2.3",
"suncalc": "^1.9.0",
@ -43,9 +43,9 @@
}
},
"node_modules/moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==",
"version": "2.29.3",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz",
"integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==",
"engines": {
"node": "*"
}
@ -118,9 +118,9 @@
"integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="
},
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
"version": "2.29.3",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.3.tgz",
"integrity": "sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw=="
},
"moment-timezone": {
"version": "0.5.34",

2
vendor/package.json vendored
View File

@ -11,7 +11,7 @@
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.1.1",
"moment": "^2.29.1",
"moment": "^2.29.3",
"moment-timezone": "^0.5.34",
"nunjucks": "^3.2.3",
"suncalc": "^1.9.0",