Merge branch 'develop' into feature/add-error-to-callback

This commit is contained in:
Michael Teeuw 2021-02-23 14:10:35 +01:00 committed by GitHub
commit 13010ecaee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 115 additions and 60 deletions

View File

@ -19,7 +19,9 @@ _This release is scheduled to be released on 2021-04-01._
- Portuguese translations for "MODULE_CONFIG_CHANGED" and PRECIP. - Portuguese translations for "MODULE_CONFIG_CHANGED" and PRECIP.
- Respect parameter ColoredSymbolOnly also for custom events - Respect parameter ColoredSymbolOnly also for custom events
- Added a new parameter to hide time portion on relative times - Added a new parameter to hide time portion on relative times
- [`module.show` has now the option for a callback on error.](https://github.com/MichMich/MagicMirror/pull/2439) - `module.show` has now the option for a callback on error.
- Added locale to sample config file
- Added support for self-signed certificates for the default calendar module (#466)
### Updated ### Updated
@ -32,7 +34,8 @@ _This release is scheduled to be released on 2021-04-01._
- Moving weather provider specific code and configuration into each provider and making hourly part of the interface. - Moving weather provider specific code and configuration into each provider and making hourly part of the interface.
- Bump electron to v11. - Bump electron to v11.
- Dont update the DOM when a module is not displayed. - Dont update the DOM when a module is not displayed.
- Cleaned up jsdoc. - Cleaned up jsdoc and tests.
- Exposed logger as node module for easier access for 3rd party modules
### Removed ### Removed

View File

@ -28,6 +28,7 @@ var config = {
httpsCertificate: "", // HTTPS Certificate path, only require when useHttps is true httpsCertificate: "", // HTTPS Certificate path, only require when useHttps is true
language: "en", language: "en",
locale: "en-US",
logLevel: ["INFO", "LOG", "WARN", "ERROR"], // Add "DEBUG" for even more logging logLevel: ["INFO", "LOG", "WARN", "ERROR"], // Add "DEBUG" for even more logging
timeFormat: 24, timeFormat: 24,
units: "metric", units: "metric",

View File

@ -4,16 +4,17 @@
* By Michael Teeuw https://michaelteeuw.nl * By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed. * MIT Licensed.
*/ */
const fs = require("fs");
const path = require("path");
const Log = require(`${__dirname}/logger`);
const Server = require(`${__dirname}/server`);
const Utils = require(`${__dirname}/utils`);
const defaultModules = require(`${__dirname}/../modules/default/defaultmodules`);
// Alias modules mentioned in package.js under _moduleAliases. // Alias modules mentioned in package.js under _moduleAliases.
require("module-alias/register"); require("module-alias/register");
const fs = require("fs");
const path = require("path");
const Log = require("logger");
const Server = require(`${__dirname}/server`);
const Utils = require(`${__dirname}/utils`);
const defaultModules = require(`${__dirname}/../modules/default/defaultmodules`);
// Get version number. // Get version number.
global.version = require(`${__dirname}/../package.json`).version; global.version = require(`${__dirname}/../package.json`).version;
Log.log("Starting MagicMirror: v" + global.version); Log.log("Starting MagicMirror: v" + global.version);

View File

@ -2,7 +2,7 @@
const electron = require("electron"); const electron = require("electron");
const core = require("./app.js"); const core = require("./app.js");
const Log = require("./logger.js"); const Log = require("logger");
// Config // Config
let config = process.env.config ? JSON.parse(process.env.config) : {}; let config = process.env.config ? JSON.parse(process.env.config) : {};

View File

@ -5,7 +5,7 @@
* MIT Licensed. * MIT Licensed.
*/ */
const Class = require("./class.js"); const Class = require("./class.js");
const Log = require("./logger.js"); const Log = require("logger");
const express = require("express"); const express = require("express");
const NodeHelper = Class.extend({ const NodeHelper = Class.extend({

View File

@ -11,7 +11,7 @@ const ipfilter = require("express-ipfilter").IpFilter;
const fs = require("fs"); const fs = require("fs");
const helmet = require("helmet"); const helmet = require("helmet");
const Log = require("./logger.js"); const Log = require("logger");
const Utils = require("./utils.js"); const Utils = require("./utils.js");
/** /**

View File

@ -58,7 +58,8 @@ Module.register("calendar", {
excludedEvents: [], excludedEvents: [],
sliceMultiDayEvents: false, sliceMultiDayEvents: false,
broadcastPastEvents: false, broadcastPastEvents: false,
nextDaysRelative: false nextDaysRelative: false,
selfSignedCert: false
}, },
requiresVersion: "2.1.0", requiresVersion: "2.1.0",
@ -101,7 +102,8 @@ Module.register("calendar", {
var calendarConfig = { var calendarConfig = {
maximumEntries: calendar.maximumEntries, maximumEntries: calendar.maximumEntries,
maximumNumberOfDays: calendar.maximumNumberOfDays, maximumNumberOfDays: calendar.maximumNumberOfDays,
broadcastPastEvents: calendar.broadcastPastEvents broadcastPastEvents: calendar.broadcastPastEvents,
selfSignedCert: calendar.selfSignedCert
}; };
if (calendar.symbolClass === "undefined" || calendar.symbolClass === null) { if (calendar.symbolClass === "undefined" || calendar.symbolClass === null) {
calendarConfig.symbolClass = ""; calendarConfig.symbolClass = "";
@ -372,8 +374,8 @@ Module.register("calendar", {
} else { } else {
timeWrapper.innerHTML = this.capFirst( timeWrapper.innerHTML = this.capFirst(
moment(event.startDate, "x").calendar(null, { moment(event.startDate, "x").calendar(null, {
sameDay: "[Today]", sameDay: "[" + this.translate("TODAY") + "]",
nextDay: "[Tomorrow]", nextDay: "[" + this.translate("TOMORROW") + "]",
nextWeek: "dddd" nextWeek: "dddd"
}) })
); );
@ -606,7 +608,8 @@ Module.register("calendar", {
titleClass: calendarConfig.titleClass, titleClass: calendarConfig.titleClass,
timeClass: calendarConfig.timeClass, timeClass: calendarConfig.timeClass,
auth: auth, auth: auth,
broadcastPastEvents: calendarConfig.broadcastPastEvents || this.config.broadcastPastEvents broadcastPastEvents: calendarConfig.broadcastPastEvents || this.config.broadcastPastEvents,
selfSignedCert: calendarConfig.selfSignedCert || this.config.selfSignedCert
}); });
}, },

View File

@ -4,7 +4,7 @@
* By Michael Teeuw https://michaelteeuw.nl * By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed. * MIT Licensed.
*/ */
const Log = require("../../../js/logger.js"); const Log = require("logger");
const ical = require("node-ical"); const ical = require("node-ical");
const request = require("request"); const request = require("request");
@ -25,9 +25,10 @@ const moment = require("moment");
* @param {number} maximumNumberOfDays The maximum number of days an event should be in the future. * @param {number} maximumNumberOfDays The maximum number of days an event should be in the future.
* @param {object} auth The object containing options for authentication against the calendar. * @param {object} auth The object containing options for authentication against the calendar.
* @param {boolean} includePastEvents If true events from the past maximumNumberOfDays will be fetched too * @param {boolean} includePastEvents If true events from the past maximumNumberOfDays will be fetched too
* @param {boolean} selfSignedCert If true, the server certificate is not verified against the list of supplied CAs.
* @class * @class
*/ */
const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, includePastEvents) { const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, includePastEvents, selfSignedCert) {
const self = this; const self = this;
let reloadTimer = null; let reloadTimer = null;
@ -51,6 +52,13 @@ const CalendarFetcher = function (url, reloadInterval, excludedEvents, maximumEn
gzip: true gzip: true
}; };
if (selfSignedCert) {
var agentOptions = {
rejectUnauthorized: false
};
opts.agentOptions = agentOptions;
}
if (auth) { if (auth) {
if (auth.method === "bearer") { if (auth.method === "bearer") {
opts.auth = { opts.auth = {

View File

@ -7,7 +7,7 @@
const NodeHelper = require("node_helper"); const NodeHelper = require("node_helper");
const validUrl = require("valid-url"); const validUrl = require("valid-url");
const CalendarFetcher = require("./calendarfetcher.js"); const CalendarFetcher = require("./calendarfetcher.js");
const Log = require("../../../js/logger"); const Log = require("logger");
module.exports = NodeHelper.create({ module.exports = NodeHelper.create({
// Override start method. // Override start method.
@ -19,7 +19,7 @@ module.exports = NodeHelper.create({
// Override socketNotificationReceived method. // Override socketNotificationReceived method.
socketNotificationReceived: function (notification, payload) { socketNotificationReceived: function (notification, payload) {
if (notification === "ADD_CALENDAR") { if (notification === "ADD_CALENDAR") {
this.createFetcher(payload.url, payload.fetchInterval, payload.excludedEvents, payload.maximumEntries, payload.maximumNumberOfDays, payload.auth, payload.broadcastPastEvents, payload.id); this.createFetcher(payload.url, payload.fetchInterval, payload.excludedEvents, payload.maximumEntries, payload.maximumNumberOfDays, payload.auth, payload.broadcastPastEvents, payload.selfSignedCert, payload.id);
} }
}, },
@ -34,9 +34,10 @@ module.exports = NodeHelper.create({
* @param {number} maximumNumberOfDays The maximum number of days an event should be in the future. * @param {number} maximumNumberOfDays The maximum number of days an event should be in the future.
* @param {object} auth The object containing options for authentication against the calendar. * @param {object} auth The object containing options for authentication against the calendar.
* @param {boolean} broadcastPastEvents If true events from the past maximumNumberOfDays will be included in event broadcasts * @param {boolean} broadcastPastEvents If true events from the past maximumNumberOfDays will be included in event broadcasts
* @param {boolean} selfSignedCert If true, the server certificate is not verified against the list of supplied CAs.
* @param {string} identifier ID of the module * @param {string} identifier ID of the module
*/ */
createFetcher: function (url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, broadcastPastEvents, identifier) { createFetcher: function (url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, broadcastPastEvents, selfSignedCert, identifier) {
var self = this; var self = this;
if (!validUrl.isUri(url)) { if (!validUrl.isUri(url)) {
@ -47,7 +48,7 @@ module.exports = NodeHelper.create({
var fetcher; var fetcher;
if (typeof self.fetchers[identifier + url] === "undefined") { if (typeof self.fetchers[identifier + url] === "undefined") {
Log.log("Create new calendar fetcher for url: " + url + " - Interval: " + fetchInterval); Log.log("Create new calendar fetcher for url: " + url + " - Interval: " + fetchInterval);
fetcher = new CalendarFetcher(url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, broadcastPastEvents); fetcher = new CalendarFetcher(url, fetchInterval, excludedEvents, maximumEntries, maximumNumberOfDays, auth, broadcastPastEvents, selfSignedCert);
fetcher.onReceive(function (fetcher) { fetcher.onReceive(function (fetcher) {
self.sendSocketNotification("CALENDAR_EVENTS", { self.sendSocketNotification("CALENDAR_EVENTS", {

View File

@ -1,5 +1,5 @@
const NodeHelper = require("node_helper"); const NodeHelper = require("node_helper");
const Log = require("../../../js/logger"); const Log = require("logger");
module.exports = NodeHelper.create({ module.exports = NodeHelper.create({
// Override start method. // Override start method.

View File

@ -4,7 +4,7 @@
* By Michael Teeuw https://michaelteeuw.nl * By Michael Teeuw https://michaelteeuw.nl
* MIT Licensed. * MIT Licensed.
*/ */
const Log = require("../../../js/logger.js"); const Log = require("logger");
const FeedMe = require("feedme"); const FeedMe = require("feedme");
const request = require("request"); const request = require("request");
const iconv = require("iconv-lite"); const iconv = require("iconv-lite");

View File

@ -8,7 +8,7 @@
const NodeHelper = require("node_helper"); const NodeHelper = require("node_helper");
const validUrl = require("valid-url"); const validUrl = require("valid-url");
const NewsfeedFetcher = require("./newsfeedfetcher.js"); const NewsfeedFetcher = require("./newsfeedfetcher.js");
const Log = require("../../../js/logger"); const Log = require("logger");
module.exports = NodeHelper.create({ module.exports = NodeHelper.create({
// Override start method. // Override start method.

View File

@ -3,7 +3,7 @@ const simpleGits = [];
const fs = require("fs"); const fs = require("fs");
const path = require("path"); const path = require("path");
const defaultModules = require(__dirname + "/../defaultmodules.js"); const defaultModules = require(__dirname + "/../defaultmodules.js");
const Log = require(__dirname + "/../../../js/logger.js"); const Log = require("logger");
const NodeHelper = require("node_helper"); const NodeHelper = require("node_helper");
module.exports = NodeHelper.create({ module.exports = NodeHelper.create({

View File

@ -1,5 +1,5 @@
const NodeHelper = require("node_helper"); const NodeHelper = require("node_helper");
const Log = require("../../../js/logger"); const Log = require("logger");
module.exports = NodeHelper.create({ module.exports = NodeHelper.create({
// Override start method. // Override start method.

View File

@ -89,7 +89,8 @@
"valid-url": "^1.0.9" "valid-url": "^1.0.9"
}, },
"_moduleAliases": { "_moduleAliases": {
"node_helper": "js/node_helper.js" "node_helper": "js/node_helper.js",
"logger": "js/logger.js"
}, },
"engines": { "engines": {
"node": ">=10" "node": ">=10"

View File

@ -1,5 +1,5 @@
const app = require("../js/app.js"); const app = require("../js/app.js");
const Log = require("../js/logger.js"); const Log = require("logger");
app.start(function (config) { app.start(function (config) {
var bindAddress = config.address ? config.address : "localhost"; var bindAddress = config.address ? config.address : "localhost";

View File

@ -26,7 +26,7 @@ var config = {
calendars: [ calendars: [
{ {
maximumNumberOfDays: 10000, maximumNumberOfDays: 10000,
url: "http://localhost:8011/tests/configs/data/calendar_test.ics", url: "http://localhost:8080/tests/configs/data/calendar_test.ics",
auth: { auth: {
user: "MagicMirror", user: "MagicMirror",
pass: "CallMeADog" pass: "CallMeADog"

View File

@ -26,7 +26,7 @@ var config = {
calendars: [ calendars: [
{ {
maximumNumberOfDays: 10000, maximumNumberOfDays: 10000,
url: "http://localhost:8010/tests/configs/data/calendar_test.ics", url: "http://localhost:8080/tests/configs/data/calendar_test.ics",
auth: { auth: {
user: "MagicMirror", user: "MagicMirror",
pass: "CallMeADog", pass: "CallMeADog",

View File

@ -0,0 +1,44 @@
/* Magic Mirror Test config default calendar with auth by default
*
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
* MIT Licensed.
*/
var config = {
port: 8080,
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"],
language: "en",
timeFormat: 12,
units: "metric",
electronOptions: {
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true
}
},
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
calendars: [
{
maximumNumberOfDays: 10000,
url: "http://localhost:8010/tests/configs/data/calendar_test.ics",
auth: {
user: "MagicMirror",
pass: "CallMeADog"
}
}
]
}
}
]
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@ -26,7 +26,7 @@ var config = {
calendars: [ calendars: [
{ {
maximumNumberOfDays: 10000, maximumNumberOfDays: 10000,
url: "http://localhost:8012/tests/configs/data/calendar_test.ics", url: "http://localhost:8080/tests/configs/data/calendar_test.ics",
user: "MagicMirror", user: "MagicMirror",
pass: "CallMeADog" pass: "CallMeADog"
} }

View File

@ -20,7 +20,7 @@ global.before(function () {
}); });
exports.getElectronPath = function () { exports.getElectronPath = function () {
var electronPath = path.join(__dirname, "..", "..", "node_modules", ".bin", "electron"); let electronPath = path.join(__dirname, "..", "..", "node_modules", ".bin", "electron");
if (process.platform === "win32") { if (process.platform === "win32") {
electronPath += ".cmd"; electronPath += ".cmd";
} }
@ -42,9 +42,9 @@ exports.startApplication = function (options) {
options.startTimeout = 30000; options.startTimeout = 30000;
} }
var app = new Application(options); const app = new Application(options);
return app.start().then(function () { return app.start().then(function () {
assert.equal(app.isRunning(), true); assert.strictEqual(app.isRunning(), true);
chaiAsPromised.transferPromiseness = app.transferPromiseness; chaiAsPromised.transferPromiseness = app.transferPromiseness;
return app; return app;
}); });
@ -56,6 +56,6 @@ exports.stopApplication = function (app) {
} }
return app.stop().then(function () { return app.stop().then(function () {
assert.equal(app.isRunning(), false); assert.strictEqual(app.isRunning(), false);
}); });
}; };

View File

@ -76,11 +76,11 @@ describe("Calendar module", function () {
}); });
}); });
describe("Basic auth", function () { describe("Changed port", function () {
before(function () { before(function () {
serverBasicAuth.listen(8010); serverBasicAuth.listen(8010);
// Set config sample for use in test // Set config sample for use in test
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/basic-auth.js"; process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/changed-port.js";
}); });
after(function (done) { after(function (done) {
@ -92,17 +92,23 @@ describe("Calendar module", function () {
}); });
}); });
describe("Basic auth", function () {
before(function () {
// Set config sample for use in test
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/basic-auth.js";
});
it("should return TestEvents", function () {
return app.client.waitUntilTextExists(".calendar", "TestEvent", 10000);
});
});
describe("Basic auth by default", function () { describe("Basic auth by default", function () {
before(function () { before(function () {
serverBasicAuth.listen(8011);
// Set config sample for use in test // Set config sample for use in test
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/auth-default.js"; process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/auth-default.js";
}); });
after(function (done) {
serverBasicAuth.close(done());
});
it("should return TestEvents", function () { it("should return TestEvents", function () {
return app.client.waitUntilTextExists(".calendar", "TestEvent", 10000); return app.client.waitUntilTextExists(".calendar", "TestEvent", 10000);
}); });
@ -110,15 +116,10 @@ describe("Calendar module", function () {
describe("Basic auth backward compatibility configuration: DEPRECATED", function () { describe("Basic auth backward compatibility configuration: DEPRECATED", function () {
before(function () { before(function () {
serverBasicAuth.listen(8012);
// Set config sample for use in test // Set config sample for use in test
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/old-basic-auth.js"; process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/old-basic-auth.js";
}); });
after(function (done) {
serverBasicAuth.close(done());
});
it("should return TestEvents", function () { it("should return TestEvents", function () {
return app.client.waitUntilTextExists(".calendar", "TestEvent", 10000); return app.client.waitUntilTextExists(".calendar", "TestEvent", 10000);
}); });

View File

@ -15,7 +15,8 @@ describe("Weather module", function () {
async function setup(responses) { async function setup(responses) {
app = await helpers.startApplication({ app = await helpers.startApplication({
args: ["js/electron.js"] args: ["js/electron.js"],
waitTimeout: 100000
}); });
wdajaxstub.init(app.client, responses); wdajaxstub.init(app.client, responses);
@ -101,16 +102,7 @@ describe("Weather module", function () {
const weather = generateWeather(); const weather = generateWeather();
await setup({ template, data: weather }); await setup({ template, data: weather });
const wait = (time) => new Promise((resolve) => setTimeout(resolve, time)); return app.client.waitUntilTextExists(".compliments .module-content span", "snow");
var text = "";
do {
await wait(3000);
elem = await app.client.$(".compliments");
text = await elem.getText(".compliments .module-content span");
} while (text === "");
return expect(text.trim()).to.equal("snow");
}); });
}); });

View File

@ -28,7 +28,7 @@ describe("Vendors", function () {
}); });
describe("Get list vendors", function () { describe("Get list vendors", function () {
var 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 () { it(`should return 200 HTTP code for vendor "${vendor}"`, function () {
var urlVendor = "http://localhost:8080/vendor/" + vendors[vendor]; var urlVendor = "http://localhost:8080/vendor/" + vendors[vendor];