mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-08-23 21:50:24 +00:00
Release 2.22.0 (#2983)
## [2.22.0] - 2023-01-01 Thanks to: @angeldeejay, @buxxi, @dariom, @dWoolridge, @KristjanESPERANTO, @MagMar94, @naveensrinivasan, @retroflex, @SkySails and @Tom. Special thanks to @khassel, @rejas and @sdetweil for taking over most (if not all) of the work on this release as project collaborators. This version would not be there without their effort. Thank you! ### Added - Added test for remoteFile option in compliments module - Added hourlyWeather functionality to Weather.gov weather provider - Removed weatherEndpoint definition from weathergov.js (not used) - Added css class names "today" and "tomorrow" for default calendar - Added Collaboration.md - Added new github action for dependency review (#2862) - Added a WeatherProvider for Open-Meteo - Added Yr as a weather provider - Added config options "ignoreXOriginHeader" and "ignoreContentSecurityPolicy" ### Removed - Removed usage of internal fetch function of node until it is more stable ### Updated - Cleaned up test directory (#2937) and jest config (#2959) - Wait for all modules to start before declaring the system ready (#2487) - Updated e2e tests (moved `done()` in helper functions) and use es6 syntax in all tests - Updated da translation - Rework weather module - Make sure smhi provider api only gets a maximum of 6 digits coordinates (#2955) - Use fetch instead of XMLHttpRequest in weatherprovider (#2935) - Reworked how weatherproviders handle units (#2849) - Use unix() method for parsing times, fix suntimes on the way (#2950) - Refactor conversion functions into utils class (#2958) - The `cors`-method in `server.js` now supports sending and recieving HTTP headers - Replace `…` by `…` - Cleanup compliments module - Updated dependencies including electron to v22 (#2903) ### Fixed - Correctly show apparent temperature in SMHI weather provider - Ensure updatenotification module isn't shown when local is _ahead_ of remote - Handle node_helper errors during startup (#2944) - Possibility to change FontAwesome class in calendar, so icons like `fab fa-facebook-square` works. - Fix cors problems with newsfeed articles (as far as possible), allow disabling cors per feed with option `useCorsProxy: false` (#2840) - Tests not waiting for the application to start and stop before starting the next test - Fix electron tests failing sometimes in github workflow - Fixed gap in clock module when displayed on the left side with displayType=digital - Fixed playwright issue by upgrading to v1.29.1 (#2969) Signed-off-by: naveen <172697+naveensrinivasan@users.noreply.github.com> Co-authored-by: Karsten Hassel <hassel@gmx.de> Co-authored-by: Malte Hallström <46646495+SkySails@users.noreply.github.com> Co-authored-by: Veeck <github@veeck.de> Co-authored-by: veeck <michael@veeck.de> Co-authored-by: dWoolridge <dwoolridge@charter.net> Co-authored-by: Johan <jojjepersson@yahoo.se> Co-authored-by: Dario Mratovich <dario_mratovich@hotmail.com> Co-authored-by: Dario Mratovich <dario.mratovich@outlook.com> Co-authored-by: Magnus <34011212+MagMar94@users.noreply.github.com> Co-authored-by: Naveen <172697+naveensrinivasan@users.noreply.github.com> Co-authored-by: buxxi <buxxi@omfilm.net> Co-authored-by: Thomas Hirschberger <47733292+Tom-Hirschberger@users.noreply.github.com> Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Co-authored-by: Andrés Vanegas Jiménez <142350+angeldeejay@users.noreply.github.com>
This commit is contained in:
@@ -1,42 +1,34 @@
|
||||
// see https://playwright.dev/docs/api/class-electronapplication
|
||||
const helpers = require("./helpers/global-setup");
|
||||
const events = require("events");
|
||||
|
||||
const { _electron: electron } = require("playwright");
|
||||
|
||||
let electronApp = null;
|
||||
process.env.MM_CONFIG_FILE = "tests/configs/modules/display.js";
|
||||
jest.retryTimes(3);
|
||||
|
||||
describe("Electron app environment", function () {
|
||||
beforeEach(async function () {
|
||||
electronApp = await electron.launch({ args: ["js/electron.js"] });
|
||||
describe("Electron app environment", () => {
|
||||
beforeEach(async () => {
|
||||
await helpers.startApplication("tests/configs/modules/display.js");
|
||||
});
|
||||
|
||||
afterEach(async function () {
|
||||
await electronApp.close();
|
||||
afterEach(async () => {
|
||||
await helpers.stopApplication();
|
||||
});
|
||||
|
||||
it("should open browserwindow", async function () {
|
||||
expect(await electronApp.windows().length).toBe(1);
|
||||
const page = await electronApp.firstWindow();
|
||||
expect(await page.title()).toBe("MagicMirror²");
|
||||
expect(await page.isVisible("body")).toBe(true);
|
||||
const module = page.locator("#module_0_helloworld");
|
||||
await module.waitFor();
|
||||
it("should open browserwindow", async () => {
|
||||
const module = await helpers.getElement("#module_0_helloworld");
|
||||
expect(await module.textContent()).toContain("Test Display Header");
|
||||
expect(await global.electronApp.windows().length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Development console tests", function () {
|
||||
beforeEach(async function () {
|
||||
electronApp = await electron.launch({ args: ["js/electron.js", "dev"] });
|
||||
describe("Development console tests", () => {
|
||||
beforeEach(async () => {
|
||||
await helpers.startApplication("tests/configs/modules/display.js", null, ["js/electron.js", "dev"]);
|
||||
});
|
||||
|
||||
afterEach(async function () {
|
||||
await electronApp.close();
|
||||
afterEach(async () => {
|
||||
await helpers.stopApplication();
|
||||
});
|
||||
|
||||
it("should open browserwindow and dev console", async function () {
|
||||
const pageArray = await electronApp.windows();
|
||||
it("should open browserwindow and dev console", async () => {
|
||||
while (global.electronApp.windows().length < 2) await events.once(global.electronApp, "window");
|
||||
const pageArray = await global.electronApp.windows();
|
||||
expect(pageArray.length).toBe(2);
|
||||
for (const page of pageArray) {
|
||||
expect(["MagicMirror²", "DevTools"]).toContain(await page.title());
|
||||
|
46
tests/electron/helpers/global-setup.js
Normal file
46
tests/electron/helpers/global-setup.js
Normal file
@@ -0,0 +1,46 @@
|
||||
// see https://playwright.dev/docs/api/class-electronapplication
|
||||
// https://github.com/microsoft/playwright/issues/6347#issuecomment-1085850728
|
||||
// https://www.anycodings.com/1questions/958135/can-i-set-the-date-for-playwright-browser
|
||||
const { _electron: electron } = require("playwright");
|
||||
|
||||
exports.startApplication = async (configFilename, systemDate = null, electronParams = ["js/electron.js"]) => {
|
||||
global.electronApp = null;
|
||||
global.page = null;
|
||||
process.env.MM_CONFIG_FILE = configFilename;
|
||||
process.env.TZ = "GMT";
|
||||
jest.retryTimes(3);
|
||||
global.electronApp = await electron.launch({ args: electronParams });
|
||||
|
||||
await global.electronApp.firstWindow();
|
||||
|
||||
for (const win of global.electronApp.windows()) {
|
||||
const title = await win.title();
|
||||
expect(["MagicMirror²", "DevTools"]).toContain(title);
|
||||
if (title === "MagicMirror²") {
|
||||
global.page = win;
|
||||
if (systemDate) {
|
||||
await global.page.evaluate((systemDate) => {
|
||||
Date.now = () => {
|
||||
return new Date(systemDate);
|
||||
};
|
||||
}, systemDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.stopApplication = async () => {
|
||||
if (global.electronApp) {
|
||||
await global.electronApp.close();
|
||||
}
|
||||
global.electronApp = null;
|
||||
global.page = null;
|
||||
};
|
||||
|
||||
exports.getElement = async (selector) => {
|
||||
expect(global.page);
|
||||
let elem = global.page.locator(selector);
|
||||
await elem.waitFor();
|
||||
expect(elem).not.toBe(null);
|
||||
return elem;
|
||||
};
|
29
tests/electron/helpers/weather-setup.js
Normal file
29
tests/electron/helpers/weather-setup.js
Normal file
@@ -0,0 +1,29 @@
|
||||
const helpers = require("./global-setup");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const { generateWeather, generateWeatherForecast } = require("../../mocks/weather_test");
|
||||
|
||||
exports.getText = async (element, result) => {
|
||||
const elem = await helpers.getElement(element);
|
||||
await expect(elem).not.toBe(null);
|
||||
const text = await elem.textContent();
|
||||
await expect(
|
||||
text
|
||||
.trim()
|
||||
.replace(/(\r\n|\n|\r)/gm, "")
|
||||
.replace(/[ ]+/g, " ")
|
||||
).toBe(result);
|
||||
};
|
||||
|
||||
exports.startApp = async (configFile, systemDate) => {
|
||||
let mockWeather;
|
||||
if (configFile.includes("forecast")) {
|
||||
mockWeather = generateWeatherForecast();
|
||||
} else {
|
||||
mockWeather = generateWeather();
|
||||
}
|
||||
let content = fs.readFileSync(path.resolve(__dirname + "../../../../" + configFile)).toString();
|
||||
content = content.replace("#####WEATHERDATA#####", mockWeather);
|
||||
fs.writeFileSync(path.resolve(__dirname + "../../../../config/config.js"), content);
|
||||
await helpers.startApplication("", systemDate);
|
||||
};
|
32
tests/electron/modules/calendar_spec.js
Normal file
32
tests/electron/modules/calendar_spec.js
Normal file
@@ -0,0 +1,32 @@
|
||||
const helpers = require("../helpers/global-setup");
|
||||
|
||||
describe("Calendar module", () => {
|
||||
/**
|
||||
* move similar tests in function doTest
|
||||
*
|
||||
* @param {string} cssClass css selector
|
||||
*/
|
||||
const doTest = async (cssClass) => {
|
||||
await helpers.getElement(".calendar");
|
||||
await helpers.getElement(".module-content");
|
||||
const events = await global.page.locator(".event");
|
||||
const elem = await events.locator(cssClass);
|
||||
expect(elem).not.toBe(null);
|
||||
};
|
||||
|
||||
afterEach(async () => {
|
||||
await helpers.stopApplication();
|
||||
});
|
||||
|
||||
describe("Test css classes", () => {
|
||||
it("has css class today", async () => {
|
||||
await helpers.startApplication("tests/configs/modules/calendar/custom.js", "01 Jan 2030 12:30:00 GMT");
|
||||
await doTest(".today");
|
||||
});
|
||||
|
||||
it("has css class tomorrow", async () => {
|
||||
await helpers.startApplication("tests/configs/modules/calendar/custom.js", "31 Dez 2029 12:30:00 GMT");
|
||||
await doTest(".tomorrow");
|
||||
});
|
||||
});
|
||||
});
|
45
tests/electron/modules/compliments_spec.js
Normal file
45
tests/electron/modules/compliments_spec.js
Normal file
@@ -0,0 +1,45 @@
|
||||
const helpers = require("../helpers/global-setup");
|
||||
|
||||
describe("Compliments module", () => {
|
||||
/**
|
||||
* move similar tests in function doTest
|
||||
*
|
||||
* @param {Array} complimentsArray The array of compliments.
|
||||
*/
|
||||
const doTest = async (complimentsArray) => {
|
||||
await helpers.getElement(".compliments");
|
||||
const elem = await helpers.getElement(".module-content");
|
||||
expect(elem).not.toBe(null);
|
||||
expect(complimentsArray).toContain(await elem.textContent());
|
||||
};
|
||||
|
||||
afterEach(async () => {
|
||||
await helpers.stopApplication();
|
||||
});
|
||||
|
||||
describe("parts of days", () => {
|
||||
it("Morning compliments for that part of day", async () => {
|
||||
await helpers.startApplication("tests/configs/modules/compliments/compliments_parts_day.js", "01 Oct 2022 10:00:00 GMT");
|
||||
await doTest(["Hi", "Good Morning", "Morning test"]);
|
||||
});
|
||||
|
||||
it("Afternoon show Compliments for that part of day", async () => {
|
||||
await helpers.startApplication("tests/configs/modules/compliments/compliments_parts_day.js", "01 Oct 2022 15:00:00 GMT");
|
||||
await doTest(["Hello", "Good Afternoon", "Afternoon test"]);
|
||||
});
|
||||
|
||||
it("Evening show Compliments for that part of day", async () => {
|
||||
await helpers.startApplication("tests/configs/modules/compliments/compliments_parts_day.js", "01 Oct 2022 20:00:00 GMT");
|
||||
await doTest(["Hello There", "Good Evening", "Evening test"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Feature date in compliments module", () => {
|
||||
describe("Set date and empty compliments for anytime, morning, evening and afternoon", () => {
|
||||
it("Show happy new year compliment on new years day", async () => {
|
||||
await helpers.startApplication("tests/configs/modules/compliments/compliments_date.js", "01 Jan 2022 10:00:00 GMT");
|
||||
await doTest(["Happy new year!"]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
28
tests/electron/modules/weather_spec.js
Normal file
28
tests/electron/modules/weather_spec.js
Normal file
@@ -0,0 +1,28 @@
|
||||
const helpers = require("../helpers/global-setup");
|
||||
const weatherHelper = require("../helpers/weather-setup");
|
||||
|
||||
describe("Weather module", () => {
|
||||
afterEach(async () => {
|
||||
await helpers.stopApplication();
|
||||
});
|
||||
|
||||
describe("Current weather with sunrise", () => {
|
||||
beforeAll(async () => {
|
||||
await weatherHelper.startApp("tests/configs/modules/weather/currentweather_default.js", "13 Jan 2019 00:30:00 GMT");
|
||||
});
|
||||
|
||||
it("should render sunrise", async () => {
|
||||
await weatherHelper.getText(".weather .normal.medium span:nth-child(4)", "7:00 am");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Current weather with sunset", () => {
|
||||
beforeAll(async () => {
|
||||
await weatherHelper.startApp("tests/configs/modules/weather/currentweather_default.js", "13 Jan 2019 12:30:00 GMT");
|
||||
});
|
||||
|
||||
it("should render sunset", async () => {
|
||||
await weatherHelper.getText(".weather .normal.medium span:nth-child(4)", "3:45 pm");
|
||||
});
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user