mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-06-29 12:39:45 +00:00
Merge branch 'develop' into develop
This commit is contained in:
commit
555e01ec87
@ -45,6 +45,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
|
|||||||
- Basic set of tests for clock module
|
- Basic set of tests for clock module
|
||||||
- Run e2e test in Travis
|
- Run e2e test in Travis
|
||||||
- Estonian Translation.
|
- Estonian Translation.
|
||||||
|
- Add test for compliments module for parts of day
|
||||||
|
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
41
js/main.js
41
js/main.js
@ -308,43 +308,36 @@ var MM = (function() {
|
|||||||
var setSelectionMethodsForModules = function(modules) {
|
var setSelectionMethodsForModules = function(modules) {
|
||||||
|
|
||||||
/* withClass(className)
|
/* withClass(className)
|
||||||
* filters a collection of modules based on classname(s).
|
* calls modulesByClass to filter modules with the specified classes.
|
||||||
*
|
*
|
||||||
* argument className string/array - one or multiple classnames. (array or space divided)
|
* argument className string/array - one or multiple classnames. (array or space divided)
|
||||||
*
|
*
|
||||||
* return array - Filtered collection of modules.
|
* return array - Filtered collection of modules.
|
||||||
*/
|
*/
|
||||||
var withClass = function(className) {
|
var withClass = function(className) {
|
||||||
var searchClasses = className;
|
return modulesByClass(className, true);
|
||||||
if (typeof className === "string") {
|
|
||||||
searchClasses = className.split(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
var newModules = modules.filter(function(module) {
|
|
||||||
var classes = module.data.classes.toLowerCase().split(" ");
|
|
||||||
|
|
||||||
for (var c in searchClasses) {
|
|
||||||
var searchClass = searchClasses[c];
|
|
||||||
if (classes.indexOf(searchClass.toLowerCase()) !== -1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
setSelectionMethodsForModules(newModules);
|
|
||||||
return newModules;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* exceptWithClass(className)
|
/* exceptWithClass(className)
|
||||||
* filters a collection of modules based on classname(s). (NOT)
|
* calls modulesByClass to filter modules without the specified classes.
|
||||||
*
|
*
|
||||||
* argument className string/array - one or multiple classnames. (array or space divided)
|
* argument className string/array - one or multiple classnames. (array or space divided)
|
||||||
*
|
*
|
||||||
* return array - Filtered collection of modules.
|
* return array - Filtered collection of modules.
|
||||||
*/
|
*/
|
||||||
var exceptWithClass = function(className) {
|
var exceptWithClass = function(className) {
|
||||||
|
return modulesByClass(className, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* modulesByClass(className, include)
|
||||||
|
* filters a collection of modules based on classname(s).
|
||||||
|
*
|
||||||
|
* argument className string/array - one or multiple classnames. (array or space divided)
|
||||||
|
* argument include boolean - if the filter should include or exclude the modules with the specific classes.
|
||||||
|
*
|
||||||
|
* return array - Filtered collection of modules.
|
||||||
|
*/
|
||||||
|
var modulesByClass = function(className, include) {
|
||||||
var searchClasses = className;
|
var searchClasses = className;
|
||||||
if (typeof className === "string") {
|
if (typeof className === "string") {
|
||||||
searchClasses = className.split(" ");
|
searchClasses = className.split(" ");
|
||||||
@ -356,11 +349,11 @@ var MM = (function() {
|
|||||||
for (var c in searchClasses) {
|
for (var c in searchClasses) {
|
||||||
var searchClass = searchClasses[c];
|
var searchClass = searchClasses[c];
|
||||||
if (classes.indexOf(searchClass.toLowerCase()) !== -1) {
|
if (classes.indexOf(searchClass.toLowerCase()) !== -1) {
|
||||||
return false;
|
return include;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return !include;
|
||||||
});
|
});
|
||||||
|
|
||||||
setSelectionMethodsForModules(newModules);
|
setSelectionMethodsForModules(newModules);
|
||||||
|
45
js/module.js
45
js/module.js
@ -203,22 +203,7 @@ var Module = Class.extend({
|
|||||||
* argument callback function - Function called when done.
|
* argument callback function - Function called when done.
|
||||||
*/
|
*/
|
||||||
loadStyles: function (callback) {
|
loadStyles: function (callback) {
|
||||||
var self = this;
|
this.loadDependencies("getStyles", callback);
|
||||||
var styles = this.getStyles();
|
|
||||||
|
|
||||||
var loadNextStyle = function () {
|
|
||||||
if (styles.length > 0) {
|
|
||||||
var nextStyle = styles[0];
|
|
||||||
Loader.loadFile(nextStyle, self, function () {
|
|
||||||
styles = styles.slice(1);
|
|
||||||
loadNextStyle();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
loadNextStyle();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/* loadScripts()
|
/* loadScripts()
|
||||||
@ -227,22 +212,32 @@ var Module = Class.extend({
|
|||||||
* argument callback function - Function called when done.
|
* argument callback function - Function called when done.
|
||||||
*/
|
*/
|
||||||
loadScripts: function (callback) {
|
loadScripts: function (callback) {
|
||||||
var self = this;
|
this.loadDependencies("getScripts", callback);
|
||||||
var scripts = this.getScripts();
|
},
|
||||||
|
|
||||||
var loadNextScript = function () {
|
/* loadDependencies(funcName, callback)
|
||||||
if (scripts.length > 0) {
|
* Helper method to load all dependencies.
|
||||||
var nextScript = scripts[0];
|
*
|
||||||
Loader.loadFile(nextScript, self, function () {
|
* argument funcName string - Function name to call to get scripts or styles.
|
||||||
scripts = scripts.slice(1);
|
* argument callback function - Function called when done.
|
||||||
loadNextScript();
|
*/
|
||||||
|
loadDependencies: function (funcName, callback) {
|
||||||
|
var self = this;
|
||||||
|
var dependencies = this[funcName]();
|
||||||
|
|
||||||
|
var loadNextDependency = function () {
|
||||||
|
if (dependencies.length > 0) {
|
||||||
|
var nextDependency = dependencies[0];
|
||||||
|
Loader.loadFile(nextDependency, self, function () {
|
||||||
|
dependencies = dependencies.slice(1);
|
||||||
|
loadNextDependency();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
loadNextScript();
|
loadNextDependency();
|
||||||
},
|
},
|
||||||
|
|
||||||
/* loadScripts()
|
/* loadScripts()
|
||||||
|
@ -327,54 +327,54 @@ Module.register("calendar", {
|
|||||||
/* symbolForUrl(url)
|
/* symbolForUrl(url)
|
||||||
* Retrieves the symbol for a specific url.
|
* Retrieves the symbol for a specific url.
|
||||||
*
|
*
|
||||||
* argument url sting - Url to look for.
|
* argument url string - Url to look for.
|
||||||
*
|
*
|
||||||
* return string - The Symbol
|
* return string - The Symbol
|
||||||
*/
|
*/
|
||||||
symbolForUrl: function (url) {
|
symbolForUrl: function (url) {
|
||||||
for (var c in this.config.calendars) {
|
return this.getCalendarProperty(url, "symbol", this.config.defaultSymbol);
|
||||||
var calendar = this.config.calendars[c];
|
|
||||||
if (calendar.url === url && typeof calendar.symbol === "string") {
|
|
||||||
return calendar.symbol;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.config.defaultSymbol;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/* colorForUrl(url)
|
/* colorForUrl(url)
|
||||||
* Retrieves the color for a specific url.
|
* Retrieves the color for a specific url.
|
||||||
*
|
*
|
||||||
* argument url sting - Url to look for.
|
* argument url string - Url to look for.
|
||||||
*
|
*
|
||||||
* return string - The Color
|
* return string - The Color
|
||||||
*/
|
*/
|
||||||
colorForUrl: function (url) {
|
colorForUrl: function (url) {
|
||||||
for (var c in this.config.calendars) {
|
return this.getCalendarProperty(url, "color", "#fff");
|
||||||
var calendar = this.config.calendars[c];
|
|
||||||
if (calendar.url === url && typeof calendar.color === "string") {
|
|
||||||
return calendar.color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return "#fff";
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/* countTitleForUrl(url)
|
/* countTitleForUrl(url)
|
||||||
* Retrieves the name for a specific url.
|
* Retrieves the name for a specific url.
|
||||||
*
|
*
|
||||||
* argument url sting - Url to look for.
|
* argument url string - Url to look for.
|
||||||
*
|
*
|
||||||
* return string - The Symbol
|
* return string - The Symbol
|
||||||
*/
|
*/
|
||||||
countTitleForUrl: function (url) {
|
countTitleForUrl: function (url) {
|
||||||
|
return this.getCalendarProperty(url, "repeatingCountTitle", this.config.defaultRepeatingCountTitle);
|
||||||
|
},
|
||||||
|
|
||||||
|
/* getCalendarProperty(url, property, defaultValue)
|
||||||
|
* Helper method to retrieve the property for a specific url.
|
||||||
|
*
|
||||||
|
* argument url string - Url to look for.
|
||||||
|
* argument property string - Property to look for.
|
||||||
|
* argument defaultValue string - Value if property is not found.
|
||||||
|
*
|
||||||
|
* return string - The Property
|
||||||
|
*/
|
||||||
|
getCalendarProperty: function (url, property, defaultValue) {
|
||||||
for (var c in this.config.calendars) {
|
for (var c in this.config.calendars) {
|
||||||
var calendar = this.config.calendars[c];
|
var calendar = this.config.calendars[c];
|
||||||
if (calendar.url === url && typeof calendar.repeatingCountTitle === "string") {
|
if (calendar.url === url && typeof calendar[property] === "string") {
|
||||||
return calendar.repeatingCountTitle;
|
return calendar[property];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.config.defaultRepeatingCountTitle;
|
return defaultValue;
|
||||||
},
|
},
|
||||||
|
|
||||||
/* shorten(string, maxLength)
|
/* shorten(string, maxLength)
|
||||||
|
@ -52,6 +52,10 @@ var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumbe
|
|||||||
|
|
||||||
var limitFunction = function(date, i) {return i < maximumEntries;};
|
var limitFunction = function(date, i) {return i < maximumEntries;};
|
||||||
|
|
||||||
|
var eventDate = function(event, time) {
|
||||||
|
return (event[time].length === 8) ? moment(event[time], "YYYYMMDD") : moment(new Date(event[time]));
|
||||||
|
};
|
||||||
|
|
||||||
for (var e in data) {
|
for (var e in data) {
|
||||||
var event = data[e];
|
var event = data[e];
|
||||||
var now = new Date();
|
var now = new Date();
|
||||||
@ -70,10 +74,10 @@ var CalendarFetcher = function(url, reloadInterval, maximumEntries, maximumNumbe
|
|||||||
|
|
||||||
if (event.type === "VEVENT") {
|
if (event.type === "VEVENT") {
|
||||||
|
|
||||||
var startDate = (event.start.length === 8) ? moment(event.start, "YYYYMMDD") : moment(new Date(event.start));
|
var startDate = eventDate(event, "start");
|
||||||
var endDate;
|
var endDate;
|
||||||
if (typeof event.end !== "undefined") {
|
if (typeof event.end !== "undefined") {
|
||||||
endDate = (event.end.length === 8) ? moment(event.end, "YYYYMMDD") : moment(new Date(event.end));
|
endDate = eventDate(event, "end");
|
||||||
} else {
|
} else {
|
||||||
if (!isFacebookBirthday) {
|
if (!isFacebookBirthday) {
|
||||||
endDate = startDate;
|
endDate = startDate;
|
||||||
|
@ -74,23 +74,18 @@ Module.register("clock",{
|
|||||||
if (this.config.timezone) {
|
if (this.config.timezone) {
|
||||||
now.tz(this.config.timezone);
|
now.tz(this.config.timezone);
|
||||||
}
|
}
|
||||||
if (this.config.clockBold === true) {
|
|
||||||
timeString = now.format("HH[<span class=\"bold\">]mm[</span>]");
|
var hourSymbol = "HH";
|
||||||
} else {
|
if (this.config.timeFormat !== 24) {
|
||||||
timeString = now.format("HH:mm");
|
hourSymbol = "h";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.config.timeFormat !== 24) {
|
if (this.config.clockBold === true) {
|
||||||
// var now = new Date();
|
timeString = now.format(hourSymbol + "[<span class=\"bold\">]mm[</span>]");
|
||||||
// var hours = now.getHours() % 12 || 12;
|
} else {
|
||||||
if (this.config.clockBold === true) {
|
timeString = now.format(hourSymbol + ":mm");
|
||||||
//timeString = hours + moment().format("[<span class=\"bold\">]mm[</span>]");
|
|
||||||
timeString = now.format("h[<span class=\"bold\">]mm[</span>]");
|
|
||||||
} else {
|
|
||||||
//timeString = hours + moment().format(":mm");
|
|
||||||
timeString = now.format("h:mm");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.config.showDate){
|
if(this.config.showDate){
|
||||||
dateWrapper.innerHTML = now.format("dddd, LL");
|
dateWrapper.innerHTML = now.format("dddd, LL");
|
||||||
}
|
}
|
||||||
@ -203,30 +198,29 @@ Module.register("clock",{
|
|||||||
digitalWrapper.appendChild(dateWrapper);
|
digitalWrapper.appendChild(dateWrapper);
|
||||||
digitalWrapper.appendChild(timeWrapper);
|
digitalWrapper.appendChild(timeWrapper);
|
||||||
|
|
||||||
|
var appendClocks = function(condition, pos1, pos2) {
|
||||||
|
var padding = [0,0,0,0];
|
||||||
|
padding[(placement === condition) ? pos1 : pos2] = "20px";
|
||||||
|
analogWrapper.style.padding = padding.join(" ");
|
||||||
|
if (placement === condition) {
|
||||||
|
wrapper.appendChild(analogWrapper);
|
||||||
|
wrapper.appendChild(digitalWrapper);
|
||||||
|
} else {
|
||||||
|
wrapper.appendChild(digitalWrapper);
|
||||||
|
wrapper.appendChild(analogWrapper);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (placement === "left" || placement === "right") {
|
if (placement === "left" || placement === "right") {
|
||||||
digitalWrapper.style.display = "inline-block";
|
digitalWrapper.style.display = "inline-block";
|
||||||
digitalWrapper.style.verticalAlign = "top";
|
digitalWrapper.style.verticalAlign = "top";
|
||||||
analogWrapper.style.display = "inline-block";
|
analogWrapper.style.display = "inline-block";
|
||||||
if (placement === "left") {
|
|
||||||
analogWrapper.style.padding = "0 20px 0 0";
|
appendClocks("left", 1, 3);
|
||||||
wrapper.appendChild(analogWrapper);
|
|
||||||
wrapper.appendChild(digitalWrapper);
|
|
||||||
} else {
|
|
||||||
analogWrapper.style.padding = "0 0 0 20px";
|
|
||||||
wrapper.appendChild(digitalWrapper);
|
|
||||||
wrapper.appendChild(analogWrapper);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
digitalWrapper.style.textAlign = "center";
|
digitalWrapper.style.textAlign = "center";
|
||||||
if (placement === "top") {
|
|
||||||
analogWrapper.style.padding = "0 0 20px 0";
|
appendClocks("top", 2, 0);
|
||||||
wrapper.appendChild(analogWrapper);
|
|
||||||
wrapper.appendChild(digitalWrapper);
|
|
||||||
} else {
|
|
||||||
analogWrapper.style.padding = "20px 0 0 0";
|
|
||||||
wrapper.appendChild(digitalWrapper);
|
|
||||||
wrapper.appendChild(analogWrapper);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
42
tests/configs/modules/compliments/compliments_parts_day.js
Normal file
42
tests/configs/modules/compliments/compliments_parts_day.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/* Magic Mirror Test config for default compliments
|
||||||
|
*
|
||||||
|
* 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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
module: "compliments",
|
||||||
|
position: "middle_center",
|
||||||
|
config: {
|
||||||
|
compliments: {
|
||||||
|
morning: [
|
||||||
|
"Hi", "Good Morning", "Morning test"
|
||||||
|
],
|
||||||
|
afternoon: [
|
||||||
|
"Hello", "Good Afternoon", "Afternoon test"
|
||||||
|
],
|
||||||
|
evening: [
|
||||||
|
"Hello There", "Good Evening", "Evening test"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
|
if (typeof module !== "undefined") {module.exports = config;}
|
78
tests/e2e/modules/compliments_spec.js
Normal file
78
tests/e2e/modules/compliments_spec.js
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
const Application = require("spectron").Application;
|
||||||
|
const path = require("path");
|
||||||
|
const chai = require("chai");
|
||||||
|
const expect = chai.expect;
|
||||||
|
const chaiAsPromised = require("chai-as-promised");
|
||||||
|
|
||||||
|
var electronPath = path.join(__dirname, "../../../", "node_modules", ".bin", "electron");
|
||||||
|
|
||||||
|
if (process.platform === "win32") {
|
||||||
|
electronPath += ".cmd";
|
||||||
|
}
|
||||||
|
|
||||||
|
var appPath = path.join(__dirname, "../../../js/electron.js");
|
||||||
|
|
||||||
|
var app = new Application({
|
||||||
|
path: electronPath,
|
||||||
|
args: [appPath]
|
||||||
|
});
|
||||||
|
|
||||||
|
global.before(function () {
|
||||||
|
chai.should();
|
||||||
|
chai.use(chaiAsPromised);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Compliments module", function () {
|
||||||
|
this.timeout(10000);
|
||||||
|
|
||||||
|
describe("parts of days", function() {
|
||||||
|
before(function() {
|
||||||
|
// Set config sample for use in test
|
||||||
|
process.env.MM_CONFIG_FILE = "tests/configs/modules/compliments/compliments_parts_day.js";
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(function (done) {
|
||||||
|
app.start().then(function() { done(); } );
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function (done) {
|
||||||
|
app.stop().then(function() { done(); });
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it("if Morning compliments for that part of day", function () {
|
||||||
|
var hour = new Date().getHours();
|
||||||
|
if (hour >= 3 && hour < 12) {
|
||||||
|
// if morning check
|
||||||
|
return app.client.waitUntilWindowLoaded()
|
||||||
|
.getText(".compliments").then(function (text) {
|
||||||
|
expect(text).to.be.oneOf(["Hi", "Good Morning", "Morning test"]);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("if Afternoon show Compliments for that part of day", function () {
|
||||||
|
var hour = new Date().getHours();
|
||||||
|
if (hour >= 12 && hour < 17) {
|
||||||
|
// if morning check
|
||||||
|
return app.client.waitUntilWindowLoaded()
|
||||||
|
.getText(".compliments").then(function (text) {
|
||||||
|
expect(text).to.be.oneOf(["Hello", "Good Afternoon", "Afternoon test"]);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("if Evening show Compliments for that part of day", function () {
|
||||||
|
var hour = new Date().getHours();
|
||||||
|
if (!(hour >= 3 && hour < 12) && !(hour >= 12 && hour < 17)) {
|
||||||
|
// if evening check
|
||||||
|
return app.client.waitUntilWindowLoaded()
|
||||||
|
.getText(".compliments").then(function (text) {
|
||||||
|
expect(text).to.be.oneOf(["Hello There", "Good Evening", "Evening test"]);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -61,5 +61,11 @@ describe("'global.root_path' set in js/app.js", function() {
|
|||||||
it("should not modify global.version for testing", function() {
|
it("should not modify global.version for testing", function() {
|
||||||
expect(global.version).to.equal(undefined);
|
expect(global.version).to.equal(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should expect the global.version equals package.json file", function() {
|
||||||
|
version_package = JSON.parse(fs.readFileSync("package.json", "utf8")).version;
|
||||||
|
expect(this.sandbox.global.version).to.equal(version_package);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user