mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-06-28 12:12:20 +00:00
Merge branch 'develop' into ko
This commit is contained in:
commit
a7202078ce
@ -16,7 +16,7 @@
|
||||
},
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaVersion": 2017,
|
||||
"ecmaVersion": 2018,
|
||||
"ecmaFeatures": {
|
||||
"globalReturn": true
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ _This release is scheduled to be released on 2022-01-01._
|
||||
|
||||
### Added
|
||||
|
||||
|
||||
### Updated
|
||||
|
||||
- Update missed translation for Korean language.
|
||||
@ -18,6 +19,10 @@ _This release is scheduled to be released on 2022-01-01._
|
||||
### Fixed
|
||||
|
||||
- Fixed wrong filename `kr.json` to `ko.json`.
|
||||
- ESLint version supports now ECMAScript 2018
|
||||
- Cleaned up `updatenotification` module and switched to nunjuck template.
|
||||
- Move calendar tests from category `electron` to `e2e`.
|
||||
- Fix feels_like data from openweathermaps current weather being ignored (#2678).
|
||||
|
||||
## [2.17.1] - 2021-10-01
|
||||
|
||||
|
@ -4,48 +4,53 @@ const fs = require("fs");
|
||||
const path = require("path");
|
||||
const Log = require("logger");
|
||||
|
||||
class gitHelper {
|
||||
const BASE_DIR = path.normalize(`${__dirname}/../../../`);
|
||||
|
||||
class GitHelper {
|
||||
constructor() {
|
||||
this.gitRepos = [];
|
||||
this.baseDir = path.normalize(__dirname + "/../../../");
|
||||
}
|
||||
|
||||
getRefRegex(branch) {
|
||||
return new RegExp("s*([a-z,0-9]+[.][.][a-z,0-9]+) " + branch, "g");
|
||||
return new RegExp(`s*([a-z,0-9]+[.][.][a-z,0-9]+) ${branch}`, "g");
|
||||
}
|
||||
|
||||
async execShell(command) {
|
||||
let res = { stdout: "", stderr: "" };
|
||||
const { stdout, stderr } = await exec(command);
|
||||
const { stdout = "", stderr = "" } = await exec(command);
|
||||
|
||||
res.stdout = stdout;
|
||||
res.stderr = stderr;
|
||||
return res;
|
||||
return { stdout, stderr };
|
||||
}
|
||||
|
||||
async isGitRepo(moduleFolder) {
|
||||
let res = await this.execShell("cd " + moduleFolder + " && git remote -v");
|
||||
if (res.stderr) {
|
||||
Log.error("Failed to fetch git data for " + moduleFolder + ": " + res.stderr);
|
||||
const { stderr } = await this.execShell(`cd ${moduleFolder} && git remote -v`);
|
||||
|
||||
if (stderr) {
|
||||
Log.error(`Failed to fetch git data for ${moduleFolder}: ${stderr}`);
|
||||
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
add(moduleName) {
|
||||
let moduleFolder = this.baseDir;
|
||||
async add(moduleName) {
|
||||
let moduleFolder = BASE_DIR;
|
||||
|
||||
if (moduleName !== "default") {
|
||||
moduleFolder = moduleFolder + "modules/" + moduleName;
|
||||
moduleFolder = `${moduleFolder}modules/${moduleName}`;
|
||||
}
|
||||
|
||||
try {
|
||||
Log.info("Checking git for module: " + moduleName);
|
||||
Log.info(`Checking git for module: ${moduleName}`);
|
||||
// Throws error if file doesn't exist
|
||||
fs.statSync(path.join(moduleFolder, ".git"));
|
||||
|
||||
// Fetch the git or throw error if no remotes
|
||||
if (this.isGitRepo(moduleFolder)) {
|
||||
const isGitRepo = await this.isGitRepo(moduleFolder);
|
||||
|
||||
if (isGitRepo) {
|
||||
// Folder has .git and has at least one git remote, watch this folder
|
||||
this.gitRepos.unshift({ module: moduleName, folder: moduleFolder });
|
||||
this.gitRepos.push({ module: moduleName, folder: moduleFolder });
|
||||
}
|
||||
} catch (err) {
|
||||
// Error when directory .git doesn't exist or doesn't have any remotes
|
||||
@ -56,38 +61,34 @@ class gitHelper {
|
||||
async getStatusInfo(repo) {
|
||||
let gitInfo = {
|
||||
module: repo.module,
|
||||
// commits behind:
|
||||
behind: 0,
|
||||
// branch name:
|
||||
current: "",
|
||||
// current hash:
|
||||
hash: "",
|
||||
// remote branch:
|
||||
tracking: "",
|
||||
behind: 0, // commits behind
|
||||
current: "", // branch name
|
||||
hash: "", // current hash
|
||||
tracking: "", // remote branch
|
||||
isBehindInStatus: false
|
||||
};
|
||||
let res;
|
||||
|
||||
if (repo.module === "default") {
|
||||
// the hash is only needed for the mm repo
|
||||
res = await this.execShell("cd " + repo.folder + " && git rev-parse HEAD");
|
||||
if (res.stderr) {
|
||||
Log.error("Failed to get current commit hash for " + repo.module + ": " + res.stderr);
|
||||
const { stderr, stdout } = await this.execShell(`cd ${repo.folder} && git rev-parse HEAD`);
|
||||
|
||||
if (stderr) {
|
||||
Log.error(`Failed to get current commit hash for ${repo.module}: ${stderr}`);
|
||||
}
|
||||
gitInfo.hash = res.stdout;
|
||||
|
||||
gitInfo.hash = stdout;
|
||||
}
|
||||
if (repo.res) {
|
||||
// mocking
|
||||
res = repo.res;
|
||||
} else {
|
||||
res = await this.execShell("cd " + repo.folder + " && git status -sb");
|
||||
}
|
||||
if (res.stderr) {
|
||||
Log.error("Failed to get git status for " + repo.module + ": " + res.stderr);
|
||||
|
||||
const { stderr, stdout } = await this.execShell(`cd ${repo.folder} && git status -sb`);
|
||||
|
||||
if (stderr) {
|
||||
Log.error(`Failed to get git status for ${repo.module}: ${stderr}`);
|
||||
// exit without git status info
|
||||
return;
|
||||
}
|
||||
|
||||
// only the first line of stdout is evaluated
|
||||
let status = res.stdout.split("\n")[0];
|
||||
let status = stdout.split("\n")[0];
|
||||
// examples for status:
|
||||
// ## develop...origin/develop
|
||||
// ## master...origin/master [behind 8]
|
||||
@ -101,72 +102,63 @@ class gitHelper {
|
||||
// [ 'origin/develop' ]
|
||||
// [ 'origin/master', '[behind', '8]' ]
|
||||
gitInfo.tracking = status[0].trim();
|
||||
|
||||
if (status[2]) {
|
||||
// git fetch was already called before so `git status -sb` delivers already the behind number
|
||||
gitInfo.behind = parseInt(status[2].substring(0, status[2].length - 1));
|
||||
gitInfo.isBehindInStatus = true;
|
||||
}
|
||||
|
||||
return gitInfo;
|
||||
}
|
||||
|
||||
async getRepoInfo(repo) {
|
||||
let gitInfo;
|
||||
if (repo.gitInfo) {
|
||||
// mocking
|
||||
gitInfo = repo.gitInfo;
|
||||
} else {
|
||||
gitInfo = await this.getStatusInfo(repo);
|
||||
}
|
||||
const gitInfo = await this.getStatusInfo(repo);
|
||||
|
||||
if (!gitInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gitInfo.isBehindInStatus) {
|
||||
return gitInfo;
|
||||
}
|
||||
let res;
|
||||
if (repo.res) {
|
||||
// mocking
|
||||
res = repo.res;
|
||||
} else {
|
||||
res = await this.execShell("cd " + repo.folder + " && git fetch --dry-run");
|
||||
}
|
||||
|
||||
const { stderr } = await this.execShell(`cd ${repo.folder} && git fetch --dry-run`);
|
||||
|
||||
// example output:
|
||||
// From https://github.com/MichMich/MagicMirror
|
||||
// e40ddd4..06389e3 develop -> origin/develop
|
||||
// here the result is in stderr (this is a git default, don't ask why ...)
|
||||
const matches = res.stderr.match(this.getRefRegex(gitInfo.current));
|
||||
const matches = stderr.match(this.getRefRegex(gitInfo.current));
|
||||
|
||||
if (!matches || !matches[0]) {
|
||||
// no refs found, nothing to do
|
||||
return;
|
||||
}
|
||||
|
||||
// get behind with refs
|
||||
try {
|
||||
res = await this.execShell("cd " + repo.folder + " && git rev-list --ancestry-path --count " + matches[0]);
|
||||
gitInfo.behind = parseInt(res.stdout);
|
||||
const { stdout } = await this.execShell(`cd ${repo.folder} && git rev-list --ancestry-path --count ${matches[0]}`);
|
||||
gitInfo.behind = parseInt(stdout);
|
||||
|
||||
return gitInfo;
|
||||
} catch (err) {
|
||||
Log.error("Failed to get git revisions for " + repo.module + ": " + err);
|
||||
Log.error(`Failed to get git revisions for ${repo.module}: ${err}`);
|
||||
}
|
||||
}
|
||||
|
||||
async getStatus() {
|
||||
const gitResultList = [];
|
||||
for (let repo of this.gitRepos) {
|
||||
const gitInfo = await this.getStatusInfo(repo);
|
||||
if (gitInfo) {
|
||||
gitResultList.unshift(gitInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return gitResultList;
|
||||
}
|
||||
|
||||
async getRepos() {
|
||||
const gitResultList = [];
|
||||
for (let repo of this.gitRepos) {
|
||||
const gitInfo = await this.getRepoInfo(repo);
|
||||
if (gitInfo) {
|
||||
gitResultList.unshift(gitInfo);
|
||||
|
||||
for (const repo of this.gitRepos) {
|
||||
try {
|
||||
const gitInfo = await this.getRepoInfo(repo);
|
||||
|
||||
if (gitInfo) {
|
||||
gitResultList.push(gitInfo);
|
||||
}
|
||||
} catch (e) {
|
||||
Log.error(`Failed to retrieve repo info for ${repo.module}: ${e}`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,4 +166,4 @@ class gitHelper {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.gitHelper = gitHelper;
|
||||
module.exports = GitHelper;
|
||||
|
@ -1,70 +1,66 @@
|
||||
const GitHelper = require(__dirname + "/git_helper.js");
|
||||
const defaultModules = require(__dirname + "/../defaultmodules.js");
|
||||
const GitHelper = require("./git_helper");
|
||||
const defaultModules = require("../defaultmodules");
|
||||
const NodeHelper = require("node_helper");
|
||||
|
||||
const ONE_MINUTE = 60 * 1000;
|
||||
|
||||
module.exports = NodeHelper.create({
|
||||
config: {},
|
||||
|
||||
updateTimer: null,
|
||||
updateProcessStarted: false,
|
||||
|
||||
gitHelper: new GitHelper.gitHelper(),
|
||||
gitHelper: new GitHelper(),
|
||||
|
||||
start: function () {},
|
||||
|
||||
configureModules: async function (modules) {
|
||||
// Push MagicMirror itself , biggest chance it'll show up last in UI and isn't overwritten
|
||||
// others will be added in front
|
||||
// this method returns promises so we can't wait for every one to resolve before continuing
|
||||
this.gitHelper.add("default");
|
||||
|
||||
for (let moduleName in modules) {
|
||||
async configureModules(modules) {
|
||||
for (const moduleName of modules) {
|
||||
if (!this.ignoreUpdateChecking(moduleName)) {
|
||||
this.gitHelper.add(moduleName);
|
||||
await this.gitHelper.add(moduleName);
|
||||
}
|
||||
}
|
||||
|
||||
await this.gitHelper.add("default");
|
||||
},
|
||||
|
||||
socketNotificationReceived: function (notification, payload) {
|
||||
async socketNotificationReceived(notification, payload) {
|
||||
if (notification === "CONFIG") {
|
||||
this.config = payload;
|
||||
} else if (notification === "MODULES") {
|
||||
// if this is the 1st time thru the update check process
|
||||
if (!this.updateProcessStarted) {
|
||||
this.updateProcessStarted = true;
|
||||
this.configureModules(payload).then(() => this.performFetch());
|
||||
await this.configureModules(payload);
|
||||
await this.performFetch();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
performFetch: async function () {
|
||||
for (let gitInfo of await this.gitHelper.getRepos()) {
|
||||
this.sendSocketNotification("STATUS", gitInfo);
|
||||
async performFetch() {
|
||||
const repos = await this.gitHelper.getRepos();
|
||||
|
||||
for (const repo of repos) {
|
||||
this.sendSocketNotification("STATUS", repo);
|
||||
}
|
||||
|
||||
this.scheduleNextFetch(this.config.updateInterval);
|
||||
},
|
||||
|
||||
scheduleNextFetch: function (delay) {
|
||||
if (delay < 60 * 1000) {
|
||||
delay = 60 * 1000;
|
||||
}
|
||||
|
||||
let self = this;
|
||||
scheduleNextFetch(delay) {
|
||||
clearTimeout(this.updateTimer);
|
||||
this.updateTimer = setTimeout(function () {
|
||||
self.performFetch();
|
||||
}, delay);
|
||||
|
||||
this.updateTimer = setTimeout(() => {
|
||||
this.performFetch();
|
||||
}, Math.max(delay, ONE_MINUTE));
|
||||
},
|
||||
|
||||
ignoreUpdateChecking: function (moduleName) {
|
||||
ignoreUpdateChecking(moduleName) {
|
||||
// Should not check for updates for default modules
|
||||
if (defaultModules.indexOf(moduleName) >= 0) {
|
||||
if (defaultModules.includes(moduleName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Should not check for updates for ignored modules
|
||||
if (this.config.ignoreModules.indexOf(moduleName) >= 0) {
|
||||
if (this.config.ignoreModules.includes(moduleName)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,3 @@
|
||||
.module.updatenotification a.difflink {
|
||||
text-decoration: none;
|
||||
}
|
@ -5,42 +5,59 @@
|
||||
* MIT Licensed.
|
||||
*/
|
||||
Module.register("updatenotification", {
|
||||
// Define module defaults
|
||||
defaults: {
|
||||
updateInterval: 10 * 60 * 1000, // every 10 minutes
|
||||
refreshInterval: 24 * 60 * 60 * 1000, // one day
|
||||
ignoreModules: [],
|
||||
timeout: 5000
|
||||
ignoreModules: []
|
||||
},
|
||||
|
||||
suspended: false,
|
||||
moduleList: {},
|
||||
|
||||
// Override start method.
|
||||
start: function () {
|
||||
Log.info("Starting module: " + this.name);
|
||||
start() {
|
||||
Log.info(`Starting module: ${this.name}`);
|
||||
this.addFilters();
|
||||
setInterval(() => {
|
||||
this.moduleList = {};
|
||||
this.updateDom(2);
|
||||
}, this.config.refreshInterval);
|
||||
},
|
||||
|
||||
notificationReceived: function (notification, payload, sender) {
|
||||
suspend() {
|
||||
this.suspended = true;
|
||||
},
|
||||
|
||||
resume() {
|
||||
this.suspended = false;
|
||||
this.updateDom(2);
|
||||
},
|
||||
|
||||
notificationReceived(notification) {
|
||||
if (notification === "DOM_OBJECTS_CREATED") {
|
||||
this.sendSocketNotification("CONFIG", this.config);
|
||||
this.sendSocketNotification("MODULES", Module.definitions);
|
||||
//this.hide(0, { lockString: this.identifier });
|
||||
this.sendSocketNotification("MODULES", Object.keys(Module.definitions));
|
||||
}
|
||||
},
|
||||
|
||||
// Override socket notification handler.
|
||||
socketNotificationReceived: function (notification, payload) {
|
||||
socketNotificationReceived(notification, payload) {
|
||||
if (notification === "STATUS") {
|
||||
this.updateUI(payload);
|
||||
}
|
||||
},
|
||||
|
||||
updateUI: function (payload) {
|
||||
getStyles() {
|
||||
return [`${this.name}.css`];
|
||||
},
|
||||
|
||||
getTemplate() {
|
||||
return `${this.name}.njk`;
|
||||
},
|
||||
|
||||
getTemplateData() {
|
||||
return { moduleList: this.moduleList, suspended: this.suspended };
|
||||
},
|
||||
|
||||
updateUI(payload) {
|
||||
if (payload && payload.behind > 0) {
|
||||
// if we haven't seen info for this module
|
||||
if (this.moduleList[payload.module] === undefined) {
|
||||
@ -48,7 +65,6 @@ Module.register("updatenotification", {
|
||||
this.moduleList[payload.module] = payload;
|
||||
this.updateDom(2);
|
||||
}
|
||||
//self.show(1000, { lockString: self.identifier });
|
||||
} else if (payload && payload.behind === 0) {
|
||||
// if the module WAS in the list, but shouldn't be
|
||||
if (this.moduleList[payload.module] !== undefined) {
|
||||
@ -59,62 +75,15 @@ Module.register("updatenotification", {
|
||||
}
|
||||
},
|
||||
|
||||
diffLink: function (module, text) {
|
||||
const localRef = module.hash;
|
||||
const remoteRef = module.tracking.replace(/.*\//, "");
|
||||
return '<a href="https://github.com/MichMich/MagicMirror/compare/' + localRef + "..." + remoteRef + '" ' + 'class="xsmall dimmed" ' + 'style="text-decoration: none;" ' + 'target="_blank" >' + text + "</a>";
|
||||
},
|
||||
|
||||
// Override dom generator.
|
||||
getDom: function () {
|
||||
const wrapper = document.createElement("div");
|
||||
if (this.suspended === false) {
|
||||
// process the hash of module info found
|
||||
for (const key of Object.keys(this.moduleList)) {
|
||||
let m = this.moduleList[key];
|
||||
|
||||
const message = document.createElement("div");
|
||||
message.className = "small bright";
|
||||
|
||||
const icon = document.createElement("i");
|
||||
icon.className = "fa fa-exclamation-circle";
|
||||
icon.innerHTML = " ";
|
||||
message.appendChild(icon);
|
||||
|
||||
const updateInfoKeyName = m.behind === 1 ? "UPDATE_INFO_SINGLE" : "UPDATE_INFO_MULTIPLE";
|
||||
|
||||
let subtextHtml = this.translate(updateInfoKeyName, {
|
||||
COMMIT_COUNT: m.behind,
|
||||
BRANCH_NAME: m.current
|
||||
});
|
||||
|
||||
const text = document.createElement("span");
|
||||
if (m.module === "default") {
|
||||
text.innerHTML = this.translate("UPDATE_NOTIFICATION");
|
||||
subtextHtml = this.diffLink(m, subtextHtml);
|
||||
} else {
|
||||
text.innerHTML = this.translate("UPDATE_NOTIFICATION_MODULE", {
|
||||
MODULE_NAME: m.module
|
||||
});
|
||||
}
|
||||
message.appendChild(text);
|
||||
|
||||
wrapper.appendChild(message);
|
||||
|
||||
const subtext = document.createElement("div");
|
||||
subtext.innerHTML = subtextHtml;
|
||||
subtext.className = "xsmall dimmed";
|
||||
wrapper.appendChild(subtext);
|
||||
addFilters() {
|
||||
this.nunjucksEnvironment().addFilter("diffLink", (text, status) => {
|
||||
if (status.module !== "default") {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
return wrapper;
|
||||
},
|
||||
|
||||
suspend: function () {
|
||||
this.suspended = true;
|
||||
},
|
||||
resume: function () {
|
||||
this.suspended = false;
|
||||
this.updateDom(2);
|
||||
const localRef = status.hash;
|
||||
const remoteRef = status.tracking.replace(/.*\//, "");
|
||||
return `<a href="https://github.com/MichMich/MagicMirror/compare/${localRef}...${remoteRef}" class="xsmall dimmed difflink" target="_blank">${text}</a>`;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
15
modules/default/updatenotification/updatenotification.njk
Normal file
15
modules/default/updatenotification/updatenotification.njk
Normal file
@ -0,0 +1,15 @@
|
||||
{% if not suspended %}
|
||||
{% for name, status in moduleList %}
|
||||
<div class="small bright">
|
||||
<i class="fa fa-exclamation-circle"></i>
|
||||
<span>
|
||||
{% set mainTextLabel = "UPDATE_NOTIFICATION" if name === "default" else "UPDATE_NOTIFICATION_MODULE" %}
|
||||
{{ mainTextLabel | translate({MODULE_NAME: name}) }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="xsmall dimmed">
|
||||
{% set subTextLabel = "UPDATE_INFO_SINGLE" if status.behind === 1 else "UPDATE_INFO_MULTIPLE" %}
|
||||
{{ subTextLabel | translate({COMMIT_COUNT: status.behind, BRANCH_NAME: status.current}) | diffLink(status) | safe }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
@ -127,6 +127,8 @@ WeatherProvider.register("openweathermap", {
|
||||
|
||||
currentWeather.humidity = currentWeatherData.main.humidity;
|
||||
currentWeather.temperature = currentWeatherData.main.temp;
|
||||
currentWeather.feelsLikeTemp = currentWeatherData.main.feels_like;
|
||||
|
||||
if (this.config.windUnits === "metric") {
|
||||
currentWeather.windSpeed = this.config.useKmh ? currentWeatherData.wind.speed * 3.6 : currentWeatherData.wind.speed;
|
||||
} else {
|
||||
|
1202
package-lock.json
generated
1202
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@ -47,12 +47,12 @@
|
||||
"homepage": "https://magicmirror.builders",
|
||||
"devDependencies": {
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-jest": "^24.4.2",
|
||||
"eslint-plugin-jest": "^24.5.2",
|
||||
"eslint-plugin-jsdoc": "^36.1.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"express-basic-auth": "^1.2.0",
|
||||
"husky": "^7.0.2",
|
||||
"jest": "^27.2.2",
|
||||
"jest": "^27.2.4",
|
||||
"jsdom": "^17.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"nyc": "^15.1.0",
|
||||
@ -114,8 +114,7 @@
|
||||
],
|
||||
"testPathIgnorePatterns": [
|
||||
"<rootDir>/tests/electron/modules/mocks",
|
||||
"<rootDir>/tests/electron/global-setup.js",
|
||||
"<rootDir>/tests/electron/modules/basic-auth.js"
|
||||
"<rootDir>/tests/electron/global-setup.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
@ -131,7 +130,8 @@
|
||||
],
|
||||
"testPathIgnorePatterns": [
|
||||
"<rootDir>/tests/e2e/global-setup.js",
|
||||
"<rootDir>/tests/e2e/mock-console.js"
|
||||
"<rootDir>/tests/e2e/mock-console.js",
|
||||
"<rootDir>/tests/e2e/modules/basic-auth.js"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -3,7 +3,7 @@
|
||||
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
|
||||
* MIT Licensed.
|
||||
*/
|
||||
let config = require(process.cwd() + "/tests/configs/default.js").configFactory({
|
||||
let config = {
|
||||
timeFormat: 12,
|
||||
|
||||
modules: [
|
||||
@ -24,7 +24,7 @@ let config = require(process.cwd() + "/tests/configs/default.js").configFactory(
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||
if (typeof module !== "undefined") {
|
||||
|
@ -3,7 +3,7 @@
|
||||
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
|
||||
* MIT Licensed.
|
||||
*/
|
||||
let config = require(process.cwd() + "/tests/configs/default.js").configFactory({
|
||||
let config = {
|
||||
timeFormat: 12,
|
||||
|
||||
modules: [
|
||||
@ -25,7 +25,7 @@ let config = require(process.cwd() + "/tests/configs/default.js").configFactory(
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||
if (typeof module !== "undefined") {
|
||||
|
@ -3,7 +3,7 @@
|
||||
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
|
||||
* MIT Licensed.
|
||||
*/
|
||||
let config = require(process.cwd() + "/tests/configs/default.js").configFactory({
|
||||
let config = {
|
||||
timeFormat: 12,
|
||||
|
||||
modules: [
|
||||
@ -24,7 +24,7 @@ let config = require(process.cwd() + "/tests/configs/default.js").configFactory(
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||
if (typeof module !== "undefined") {
|
||||
|
@ -3,7 +3,7 @@
|
||||
* By Rejas
|
||||
* MIT Licensed.
|
||||
*/
|
||||
let config = require(process.cwd() + "/tests/configs/default.js").configFactory({
|
||||
let config = {
|
||||
timeFormat: 12,
|
||||
|
||||
modules: [
|
||||
@ -24,7 +24,7 @@ let config = require(process.cwd() + "/tests/configs/default.js").configFactory(
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||
if (typeof module !== "undefined") {
|
||||
|
@ -3,7 +3,7 @@
|
||||
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
|
||||
* MIT Licensed.
|
||||
*/
|
||||
let config = require(process.cwd() + "/tests/configs/default.js").configFactory({
|
||||
let config = {
|
||||
timeFormat: 12,
|
||||
|
||||
modules: [
|
||||
@ -20,7 +20,7 @@ let config = require(process.cwd() + "/tests/configs/default.js").configFactory(
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||
if (typeof module !== "undefined") {
|
||||
|
@ -5,7 +5,7 @@
|
||||
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
|
||||
* MIT Licensed.
|
||||
*/
|
||||
let config = require(process.cwd() + "/tests/configs/default.js").configFactory({
|
||||
let config = {
|
||||
timeFormat: 12,
|
||||
|
||||
modules: [
|
||||
@ -27,7 +27,7 @@ let config = require(process.cwd() + "/tests/configs/default.js").configFactory(
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||
if (typeof module !== "undefined") {
|
||||
|
@ -3,7 +3,7 @@
|
||||
* By Rodrigo Ramírez Norambuena https://rodrigoramirez.com
|
||||
* MIT Licensed.
|
||||
*/
|
||||
let config = require(process.cwd() + "/tests/configs/default.js").configFactory({
|
||||
let config = {
|
||||
timeFormat: 12,
|
||||
|
||||
modules: [
|
||||
@ -22,7 +22,7 @@ let config = require(process.cwd() + "/tests/configs/default.js").configFactory(
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||
if (typeof module !== "undefined") {
|
||||
|
@ -3,7 +3,7 @@
|
||||
* By Rejas
|
||||
* MIT Licensed.
|
||||
*/
|
||||
let config = require(process.cwd() + "/tests/configs/default.js").configFactory({
|
||||
let config = {
|
||||
timeFormat: 12,
|
||||
|
||||
modules: [
|
||||
@ -21,7 +21,7 @@ let config = require(process.cwd() + "/tests/configs/default.js").configFactory(
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
};
|
||||
|
||||
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||
if (typeof module !== "undefined") {
|
||||
|
@ -4,7 +4,7 @@
|
||||
* @param {string} err The error message.
|
||||
*/
|
||||
function mockError(err) {
|
||||
if (err.includes("ECONNREFUSED") || err.includes("ECONNRESET") || err.includes("socket hang up") || err.includes("exports is not defined")) {
|
||||
if (err.includes("ECONNREFUSED") || err.includes("ECONNRESET") || err.includes("socket hang up") || err.includes("exports is not defined") || err.includes("write EPIPE")) {
|
||||
jest.fn();
|
||||
} else {
|
||||
console.dir(err);
|
||||
|
139
tests/e2e/modules/calendar_spec.js
Normal file
139
tests/e2e/modules/calendar_spec.js
Normal file
@ -0,0 +1,139 @@
|
||||
const helpers = require("../global-setup");
|
||||
const serverBasicAuth = require("./basic-auth.js");
|
||||
|
||||
describe("Calendar module", function () {
|
||||
/**
|
||||
* @param {string} element css selector
|
||||
* @param {string} result expected number
|
||||
* @param {string} not reverse result
|
||||
*/
|
||||
function testElementLength(element, result, not) {
|
||||
const elem = document.querySelectorAll(element);
|
||||
expect(elem).not.toBe(null);
|
||||
if (not === "not") {
|
||||
expect(elem.length).not.toBe(result);
|
||||
} else {
|
||||
expect(elem.length).toBe(result);
|
||||
}
|
||||
}
|
||||
|
||||
afterAll(function () {
|
||||
helpers.stopApplication();
|
||||
});
|
||||
|
||||
describe("Default configuration", function () {
|
||||
beforeAll(function (done) {
|
||||
helpers.startApplication("tests/configs/modules/calendar/default.js");
|
||||
helpers.getDocument(done, 3000);
|
||||
});
|
||||
|
||||
it("should show the default maximumEntries of 10", () => {
|
||||
testElementLength(".calendar .event", 10);
|
||||
});
|
||||
|
||||
it("should show the default calendar symbol in each event", () => {
|
||||
testElementLength(".calendar .event .fa-calendar", 0, "not");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Custom configuration", function () {
|
||||
beforeAll(function (done) {
|
||||
helpers.startApplication("tests/configs/modules/calendar/custom.js");
|
||||
helpers.getDocument(done, 3000);
|
||||
});
|
||||
|
||||
it("should show the custom maximumEntries of 4", () => {
|
||||
testElementLength(".calendar .event", 4);
|
||||
});
|
||||
|
||||
it("should show the custom calendar symbol in each event", () => {
|
||||
testElementLength(".calendar .event .fa-birthday-cake", 4);
|
||||
});
|
||||
|
||||
it("should show two custom icons for repeating events", () => {
|
||||
testElementLength(".calendar .event .fa-undo", 2);
|
||||
});
|
||||
|
||||
it("should show two custom icons for day events", () => {
|
||||
testElementLength(".calendar .event .fa-calendar-day", 2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Recurring event", function () {
|
||||
beforeAll(function (done) {
|
||||
helpers.startApplication("tests/configs/modules/calendar/recurring.js");
|
||||
helpers.getDocument(done, 3000);
|
||||
});
|
||||
|
||||
it("should show the recurring birthday event 6 times", () => {
|
||||
testElementLength(".calendar .event", 6);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Changed port", function () {
|
||||
beforeAll(function (done) {
|
||||
helpers.startApplication("tests/configs/modules/calendar/changed-port.js");
|
||||
serverBasicAuth.listen(8010);
|
||||
helpers.getDocument(done, 3000);
|
||||
});
|
||||
|
||||
afterAll(function (done) {
|
||||
serverBasicAuth.close(done());
|
||||
});
|
||||
|
||||
it("should return TestEvents", function () {
|
||||
testElementLength(".calendar .event", 0, "not");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Basic auth", function () {
|
||||
beforeAll(function (done) {
|
||||
helpers.startApplication("tests/configs/modules/calendar/basic-auth.js");
|
||||
helpers.getDocument(done, 3000);
|
||||
});
|
||||
|
||||
it("should return TestEvents", function () {
|
||||
testElementLength(".calendar .event", 0, "not");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Basic auth by default", function () {
|
||||
beforeAll(function (done) {
|
||||
helpers.startApplication("tests/configs/modules/calendar/auth-default.js");
|
||||
helpers.getDocument(done, 3000);
|
||||
});
|
||||
|
||||
it("should return TestEvents", function () {
|
||||
testElementLength(".calendar .event", 0, "not");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Basic auth backward compatibility configuration: DEPRECATED", function () {
|
||||
beforeAll(function (done) {
|
||||
helpers.startApplication("tests/configs/modules/calendar/old-basic-auth.js");
|
||||
helpers.getDocument(done, 3000);
|
||||
});
|
||||
|
||||
it("should return TestEvents", function () {
|
||||
testElementLength(".calendar .event", 0, "not");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Fail Basic auth", function () {
|
||||
beforeAll(function (done) {
|
||||
helpers.startApplication("tests/configs/modules/calendar/fail-basic-auth.js");
|
||||
serverBasicAuth.listen(8020);
|
||||
helpers.getDocument(done, 3000);
|
||||
});
|
||||
|
||||
afterAll(function (done) {
|
||||
serverBasicAuth.close(done());
|
||||
});
|
||||
|
||||
it("should show Unauthorized error", function () {
|
||||
const elem = document.querySelector(".calendar");
|
||||
expect(elem).not.toBe(null);
|
||||
expect(elem.textContent).toContain("Error in the calendar module. Authorization failed");
|
||||
});
|
||||
});
|
||||
});
|
@ -1,150 +0,0 @@
|
||||
const helpers = require("../global-setup");
|
||||
const serverBasicAuth = require("./basic-auth.js");
|
||||
|
||||
describe("Calendar module", function () {
|
||||
helpers.setupTimeout(this);
|
||||
|
||||
let app = null;
|
||||
|
||||
beforeEach(function () {
|
||||
return helpers
|
||||
.startApplication({
|
||||
args: ["js/electron.js"]
|
||||
})
|
||||
.then(function (startedApp) {
|
||||
app = startedApp;
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
return helpers.stopApplication(app);
|
||||
});
|
||||
|
||||
describe("Default configuration", function () {
|
||||
beforeAll(function () {
|
||||
// Set config sample for use in test
|
||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/default.js";
|
||||
});
|
||||
|
||||
it("should show the default maximumEntries of 10", async () => {
|
||||
await app.client.waitUntilTextExists(".calendar", "TestEvent", 10000);
|
||||
const events = await app.client.$$(".calendar .event");
|
||||
return expect(events.length).toBe(10);
|
||||
});
|
||||
|
||||
it("should show the default calendar symbol in each event", async () => {
|
||||
await app.client.waitUntilTextExists(".calendar", "TestEvent", 10000);
|
||||
const icons = await app.client.$$(".calendar .event .fa-calendar");
|
||||
return expect(icons.length).not.toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Custom configuration", function () {
|
||||
beforeAll(function () {
|
||||
// Set config sample for use in test
|
||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/custom.js";
|
||||
});
|
||||
|
||||
it("should show the custom maximumEntries of 4", async () => {
|
||||
await app.client.waitUntilTextExists(".calendar", "TestEvent", 10000);
|
||||
const events = await app.client.$$(".calendar .event");
|
||||
return expect(events.length).toBe(4);
|
||||
});
|
||||
|
||||
it("should show the custom calendar symbol in each event", async () => {
|
||||
await app.client.waitUntilTextExists(".calendar", "TestEvent", 10000);
|
||||
const icons = await app.client.$$(".calendar .event .fa-birthday-cake");
|
||||
return expect(icons.length).toBe(4);
|
||||
});
|
||||
|
||||
it("should show two custom icons for repeating events", async () => {
|
||||
await app.client.waitUntilTextExists(".calendar", "TestEventRepeat", 10000);
|
||||
const icons = await app.client.$$(".calendar .event .fa-undo");
|
||||
return expect(icons.length).toBe(2);
|
||||
});
|
||||
|
||||
it("should show two custom icons for day events", async () => {
|
||||
await app.client.waitUntilTextExists(".calendar", "TestEventDay", 10000);
|
||||
const icons = await app.client.$$(".calendar .event .fa-calendar-day");
|
||||
return expect(icons.length).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Recurring event", function () {
|
||||
beforeAll(function () {
|
||||
// Set config sample for use in test
|
||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/recurring.js";
|
||||
});
|
||||
|
||||
it("should show the recurring birthday event 6 times", async () => {
|
||||
await app.client.waitUntilTextExists(".calendar", "Mar 25th", 10000);
|
||||
const events = await app.client.$$(".calendar .event");
|
||||
return expect(events.length).toBe(6);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Changed port", function () {
|
||||
beforeAll(function () {
|
||||
serverBasicAuth.listen(8010);
|
||||
// Set config sample for use in test
|
||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/changed-port.js";
|
||||
});
|
||||
|
||||
afterAll(function (done) {
|
||||
serverBasicAuth.close(done());
|
||||
});
|
||||
|
||||
it("should return TestEvents", function () {
|
||||
return app.client.waitUntilTextExists(".calendar", "TestEvent", 10000);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Basic auth", function () {
|
||||
beforeAll(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 () {
|
||||
beforeAll(function () {
|
||||
// Set config sample for use in test
|
||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/auth-default.js";
|
||||
});
|
||||
|
||||
it("should return TestEvents", function () {
|
||||
return app.client.waitUntilTextExists(".calendar", "TestEvent", 10000);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Basic auth backward compatibility configuration: DEPRECATED", function () {
|
||||
beforeAll(function () {
|
||||
// Set config sample for use in test
|
||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/old-basic-auth.js";
|
||||
});
|
||||
|
||||
it("should return TestEvents", function () {
|
||||
return app.client.waitUntilTextExists(".calendar", "TestEvent", 10000);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Fail Basic auth", function () {
|
||||
beforeAll(function () {
|
||||
serverBasicAuth.listen(8020);
|
||||
// Set config sample for use in test
|
||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/calendar/fail-basic-auth.js";
|
||||
});
|
||||
|
||||
afterAll(function (done) {
|
||||
serverBasicAuth.close(done());
|
||||
});
|
||||
|
||||
it("should show Unauthorized error", function () {
|
||||
return app.client.waitUntilTextExists(".calendar", "Error in the calendar module. Authorization failed", 10000);
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,34 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Updatenotification custom module returns status information without hash 1`] = `
|
||||
Object {
|
||||
"behind": 7,
|
||||
"current": "master",
|
||||
"hash": "",
|
||||
"isBehindInStatus": false,
|
||||
"module": "MMM-Fuel",
|
||||
"tracking": "origin/master",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Updatenotification default returns status information 1`] = `
|
||||
Object {
|
||||
"behind": 5,
|
||||
"current": "develop",
|
||||
"hash": "332e429a41f1a2339afd4f0ae96dd125da6beada",
|
||||
"isBehindInStatus": false,
|
||||
"module": "default",
|
||||
"tracking": "origin/develop",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Updatenotification default returns status information early if isBehindInStatus 1`] = `
|
||||
Object {
|
||||
"behind": 5,
|
||||
"current": "develop",
|
||||
"hash": "332e429a41f1a2339afd4f0ae96dd125da6beada",
|
||||
"isBehindInStatus": true,
|
||||
"module": "default",
|
||||
"tracking": "origin/develop",
|
||||
}
|
||||
`;
|
@ -1,126 +1,139 @@
|
||||
const path = require("path");
|
||||
const git_Helper = require("../../../modules/default/updatenotification/git_helper.js");
|
||||
const gitHelper = new git_Helper.gitHelper();
|
||||
gitHelper.add("default");
|
||||
jest.mock("util", () => ({
|
||||
...jest.requireActual("util"),
|
||||
promisify: jest.fn()
|
||||
}));
|
||||
|
||||
const test1 = {
|
||||
module: "test1",
|
||||
folder: "",
|
||||
res: {
|
||||
stdout: "## master...origin/master [behind 8]",
|
||||
stderr: ""
|
||||
},
|
||||
gitInfo: {
|
||||
module: "default",
|
||||
// commits behind:
|
||||
behind: 0,
|
||||
// branch name:
|
||||
current: "develop",
|
||||
// current hash:
|
||||
hash: "",
|
||||
// remote branch:
|
||||
tracking: "",
|
||||
isBehindInStatus: false
|
||||
}
|
||||
};
|
||||
jest.mock("fs", () => ({
|
||||
...jest.requireActual("fs"),
|
||||
statSync: jest.fn()
|
||||
}));
|
||||
|
||||
const test2 = {
|
||||
module: "test2",
|
||||
folder: "",
|
||||
res: {
|
||||
stdout: "## develop...origin/develop",
|
||||
stderr: ""
|
||||
}
|
||||
};
|
||||
|
||||
const test3 = {
|
||||
module: "test3",
|
||||
folder: "",
|
||||
res: {
|
||||
stdout: "",
|
||||
stderr: "error"
|
||||
},
|
||||
gitInfo: {
|
||||
module: "default",
|
||||
// commits behind:
|
||||
behind: 2,
|
||||
// branch name:
|
||||
current: "develop",
|
||||
// current hash:
|
||||
hash: "",
|
||||
// remote branch:
|
||||
tracking: "",
|
||||
isBehindInStatus: true
|
||||
}
|
||||
};
|
||||
|
||||
const test4 = {
|
||||
module: "default",
|
||||
folder: path.join(__dirname, "../../.."),
|
||||
res: {
|
||||
stdout: "",
|
||||
stderr: " e40ddd4..06389e3 develop -> origin/develop"
|
||||
},
|
||||
gitInfo: {
|
||||
module: "default",
|
||||
// commits behind:
|
||||
behind: 0,
|
||||
// branch name:
|
||||
current: "develop",
|
||||
// current hash:
|
||||
hash: "",
|
||||
// remote branch:
|
||||
tracking: "",
|
||||
isBehindInStatus: false
|
||||
}
|
||||
};
|
||||
jest.mock("logger", () => ({
|
||||
...jest.requireActual("logger"),
|
||||
error: jest.fn(),
|
||||
info: jest.fn()
|
||||
}));
|
||||
|
||||
describe("Updatenotification", function () {
|
||||
it("should return valid output for git status", async function () {
|
||||
const arr = await gitHelper.getStatus();
|
||||
expect(arr.length).toBe(1);
|
||||
const gitInfo = arr[0];
|
||||
expect(gitInfo.current).not.toBe("");
|
||||
expect(gitInfo.hash).not.toBe("");
|
||||
}, 15000);
|
||||
const execMock = jest.fn();
|
||||
|
||||
it("should return behind=8 for test1", async function () {
|
||||
const gitInfo = await gitHelper.getStatusInfo(test1);
|
||||
expect(gitInfo.behind).toBe(8);
|
||||
expect(gitInfo.isBehindInStatus).toBe(true);
|
||||
let gitHelper;
|
||||
|
||||
let gitRemoteOut;
|
||||
let gitRevParseOut;
|
||||
let gitStatusOut;
|
||||
let gitFetchOut;
|
||||
let gitRevListOut;
|
||||
let gitRemoteErr;
|
||||
let gitRevParseErr;
|
||||
let gitStatusErr;
|
||||
let gitFetchErr;
|
||||
let gitRevListErr;
|
||||
|
||||
beforeAll(async function () {
|
||||
const { promisify } = require("util");
|
||||
promisify.mockReturnValue(execMock);
|
||||
|
||||
const GitHelper = require(`../../../modules/default/updatenotification/git_helper`);
|
||||
gitHelper = new GitHelper();
|
||||
});
|
||||
|
||||
it("should return behind=0 for test2", async function () {
|
||||
const gitInfo = await gitHelper.getStatusInfo(test2);
|
||||
expect(gitInfo.behind).toBe(0);
|
||||
expect(gitInfo.isBehindInStatus).toBe(false);
|
||||
beforeEach(function () {
|
||||
gitRemoteOut = "";
|
||||
gitRevParseOut = "";
|
||||
gitStatusOut = "";
|
||||
gitFetchOut = "";
|
||||
gitRevListOut = "";
|
||||
gitRemoteErr = "";
|
||||
gitRevParseErr = "";
|
||||
gitStatusErr = "";
|
||||
gitFetchErr = "";
|
||||
gitRevListErr = "";
|
||||
|
||||
execMock.mockImplementation(function (command) {
|
||||
if (command.includes("git remote -v")) {
|
||||
return { stdout: gitRemoteOut, stderr: gitRemoteErr };
|
||||
} else if (command.includes("git rev-parse HEAD")) {
|
||||
return { stdout: gitRevParseOut, stderr: gitRevParseErr };
|
||||
} else if (command.includes("git status -sb")) {
|
||||
return { stdout: gitStatusOut, stderr: gitStatusErr };
|
||||
} else if (command.includes("git fetch --dry-run")) {
|
||||
return { stdout: gitFetchOut, stderr: gitFetchErr };
|
||||
} else if (command.includes("git rev-list --ancestry-path --count")) {
|
||||
return { stdout: gitRevListOut, stderr: gitRevListErr };
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("should return empty status object for test3", async function () {
|
||||
const gitInfo = await gitHelper.getStatusInfo(test3);
|
||||
expect(gitInfo).toBe(undefined);
|
||||
afterEach(async function () {
|
||||
gitHelper.gitRepos = [];
|
||||
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it("should return empty repo object for test2", async function () {
|
||||
// no gitInfo provided in res, so returns undefined
|
||||
const gitInfo = await gitHelper.getRepoInfo(test2);
|
||||
expect(gitInfo).toBe(undefined);
|
||||
describe("default", () => {
|
||||
const moduleName = "default";
|
||||
|
||||
beforeEach(async function () {
|
||||
gitRemoteOut = "origin\tgit@github.com:MichMich/MagicMirror.git (fetch)\norigin\tgit@github.com:MichMich/MagicMirror.git (push)\n";
|
||||
gitRevParseOut = "332e429a41f1a2339afd4f0ae96dd125da6beada";
|
||||
gitStatusOut = "## develop...origin/develop\n M tests/unit/functions/updatenotification_spec.js\n";
|
||||
gitFetchErr = "From github.com:MichMich/MagicMirror\n60e0377..332e429 develop -> origin/develop\n";
|
||||
gitRevListOut = "5";
|
||||
|
||||
await gitHelper.add(moduleName);
|
||||
});
|
||||
|
||||
it("returns status information", async function () {
|
||||
const repos = await gitHelper.getRepos();
|
||||
expect(repos[0]).toMatchSnapshot();
|
||||
expect(execMock).toHaveBeenCalledTimes(5);
|
||||
});
|
||||
|
||||
it("returns status information early if isBehindInStatus", async function () {
|
||||
gitStatusOut = "## develop...origin/develop [behind 5]";
|
||||
|
||||
const repos = await gitHelper.getRepos();
|
||||
expect(repos[0]).toMatchSnapshot();
|
||||
expect(execMock).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
||||
it("excludes repo if status can't be retrieved", async function () {
|
||||
const errorMessage = "Failed to retrieve status";
|
||||
execMock.mockRejectedValueOnce(errorMessage);
|
||||
|
||||
const repos = await gitHelper.getRepos();
|
||||
expect(repos.length).toBe(0);
|
||||
|
||||
const { error } = require("logger");
|
||||
expect(error).toHaveBeenCalledWith(`Failed to retrieve repo info for ${moduleName}: Failed to retrieve status`);
|
||||
});
|
||||
|
||||
it("excludes repo if refs don't match regex", async function () {
|
||||
gitFetchErr = "";
|
||||
|
||||
const repos = await gitHelper.getRepos();
|
||||
expect(repos.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
it("should return empty repo object for test1", async function () {
|
||||
// no regex match for refs in empty string, so returns undefined
|
||||
const gitInfo = await gitHelper.getRepoInfo(test1);
|
||||
expect(gitInfo).toBe(undefined);
|
||||
});
|
||||
describe("custom module", () => {
|
||||
const moduleName = "MMM-Fuel";
|
||||
|
||||
it("should return empty repo object for test4", async function () {
|
||||
// git ref list throws error, so returns undefined
|
||||
const gitInfo = await gitHelper.getRepoInfo(test4);
|
||||
expect(gitInfo).toBe(undefined);
|
||||
});
|
||||
beforeEach(async function () {
|
||||
gitRemoteOut = `origin\thttps://github.com/fewieden/${moduleName}.git (fetch)\norigin\thttps://github.com/fewieden/${moduleName}.git (push)\n`;
|
||||
gitRevParseOut = "9d8310163da94441073a93cead711ba43e8888d0";
|
||||
gitStatusOut = "## master...origin/master";
|
||||
gitFetchErr = `From https://github.com/fewieden/${moduleName}\n19f7faf..9d83101 master -> origin/master`;
|
||||
gitRevListOut = "7";
|
||||
|
||||
it("should return behind=2 for test3", async function () {
|
||||
const gitInfo = await gitHelper.getRepoInfo(test3);
|
||||
expect(gitInfo.behind).toBe(2);
|
||||
await gitHelper.add(moduleName);
|
||||
});
|
||||
|
||||
it("returns status information without hash", async function () {
|
||||
const repos = await gitHelper.getRepos();
|
||||
expect(repos[0]).toMatchSnapshot();
|
||||
expect(execMock).toHaveBeenCalledTimes(4);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user