mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-08-27 08:22:05 +00:00
Release 2.23.0 (#3078)
## [2.23.0] - 2023-04-04 Thanks to: @angeldeejay, @buxxi, @CarJem, @dariom, @DaveChild, @dWoolridge, @grenagit, @Hirschberger, @KristjanESPERANTO, @MagMar94, @naveensrinivasan, @nfogal, @psieg, @rajniszp, @retroflex, @SkySails and @tomzt. 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 guys! You are awesome! ### Added - Added increments for hourly forecasts in weather module (#2996) - Added tests for hourly weather forecast - Added possibility to ignore MagicMirror repo in updatenotification module - Added Pirate Weather as new weather provider (#3005) - Added possibility to use your own templates in Alert module - Added error message if `<modulename>.js` file is missing in module folder to get a hint in the logs (#2403) - Added possibility to use environment variables in `config.js` (#1756) - Added option `pastDaysCount` to default calendar module to control of how many days past events should be displayed - Added thai language to alert module - Added option `sendNotifications` in clock module (#3056) ### Removed - Removed darksky weather provider - Removed unneeded (and unwanted) '.' after the year in calendar repeatingCountTitle (#2896) ### Updated - Use develop as target branch for dependabot - Update issue template, contributing doc and sample config - The weather modules clearly separates precipitation amount and probability (risk of rain/snow) - This requires all providers that only supports probability to change the config from `showPrecipitationAmount` to `showPrecipitationProbability`. - Update tests for weather and calendar module - Changed updatenotification module for MagicMirror repo only: Send only notifications for `master` if there is a tag on a newer commit - Update dates in Calendar widgets every minute - Cleanup jest coverage for patches - Update `stylelint` dependencies, switch to `stylelint-config-standard` and handle `stylelint` issues, update `main.css` matching new rules - Update Eslint config, add new rule and handle issue - Convert lots of callbacks to async/await - Revise require imports (#3071 and #3072) ### Fixed - Fix wrong day labels in envcanada forecast (#2987) - Fix for missing default class name prefix for customEvents in calendar - Fix electron flashing white screen on startup (#1919) - Fix weathergov provider hourly forecast (#3008) - Fix message display with HTML code into alert module (#2828) - Fix typo in french translation - Yr wind direction is no longer inverted - Fix async node_helper stopping electron start (#2487) - The wind direction arrow now points in the direction the wind is flowing, not into the wind (#3019) - Fix precipitation css styles and rounding value - Fix wrong vertical alignment of calendar title column when wrapEvents is true (#3053) - Fix empty news feed stopping the reload forever - Fix e2e tests (failed after async changes) by running calendar and newsfeed tests last - Lint: Use template literals instead of string concatenation - Fix default alert module to render HTML for title and message - Fix Open-Meteo wind speed units
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
const helpers = require("../helpers/global-setup");
|
||||
const serverBasicAuth = require("../helpers/basic-auth.js");
|
||||
const serverBasicAuth = require("../helpers/basic-auth");
|
||||
|
||||
describe("Calendar module", () => {
|
||||
/**
|
||||
@@ -48,14 +48,18 @@ describe("Calendar module", () => {
|
||||
await helpers.getDocument();
|
||||
});
|
||||
|
||||
it("should show the custom maximumEntries of 4", async () => {
|
||||
await testElementLength(".calendar .event", 4);
|
||||
it("should show the custom maximumEntries of 5", async () => {
|
||||
await testElementLength(".calendar .event", 5);
|
||||
});
|
||||
|
||||
it("should show the custom calendar symbol in each event", async () => {
|
||||
it("should show the custom calendar symbol in four events", async () => {
|
||||
await testElementLength(".calendar .event .fa-birthday-cake", 4);
|
||||
});
|
||||
|
||||
it("should show a customEvent calendar symbol in one event", async () => {
|
||||
await testElementLength(".calendar .event .fa-dice", 1);
|
||||
});
|
||||
|
||||
it("should show two custom icons for repeating events", async () => {
|
||||
await testElementLength(".calendar .event .fa-undo", 2);
|
||||
});
|
||||
@@ -87,7 +91,7 @@ describe("Calendar module", () => {
|
||||
await helpers.getDocument();
|
||||
});
|
||||
|
||||
it('should contain text "Mar 25th" in timezone UTC ' + -i, async () => {
|
||||
it(`should contain text "Mar 25th" in timezone UTC ${-i}`, async () => {
|
||||
await testTextContain(".calendar", "Mar 25th");
|
||||
});
|
||||
});
|
||||
|
@@ -1,5 +1,5 @@
|
||||
const helpers = require("../helpers/global-setup");
|
||||
const moment = require("moment");
|
||||
const helpers = require("../helpers/global-setup");
|
||||
|
||||
describe("Clock module", () => {
|
||||
afterAll(async () => {
|
||||
@@ -89,7 +89,7 @@ describe("Clock module", () => {
|
||||
|
||||
it("should show the week with the correct number of week of year", async () => {
|
||||
const currentWeekNumber = moment().week();
|
||||
const weekToShow = "Week " + currentWeekNumber;
|
||||
const weekToShow = `Week ${currentWeekNumber}`;
|
||||
const elem = await helpers.waitForElement(".clock .week");
|
||||
expect(elem).not.toBe(null);
|
||||
expect(elem.textContent).toBe(weekToShow);
|
||||
@@ -103,7 +103,7 @@ describe("Clock module", () => {
|
||||
});
|
||||
|
||||
it("should show the analog clock face", async () => {
|
||||
const elem = helpers.waitForElement(".clockCircle");
|
||||
const elem = helpers.waitForElement(".clock-circle");
|
||||
expect(elem).not.toBe(null);
|
||||
});
|
||||
});
|
||||
|
@@ -46,7 +46,7 @@ describe("Weather module", () => {
|
||||
});
|
||||
|
||||
it("should render windDirection with an arrow", async () => {
|
||||
const elem = await helpers.waitForElement(".weather .normal.medium sup i.fa-long-arrow-alt-up");
|
||||
const elem = await helpers.waitForElement(".weather .normal.medium sup i.fa-long-arrow-alt-down");
|
||||
expect(elem).not.toBe(null);
|
||||
expect(elem.outerHTML).toContain("transform:rotate(250deg);");
|
||||
});
|
||||
|
@@ -13,14 +13,14 @@ describe("Weather module: Weather Forecast", () => {
|
||||
|
||||
const days = ["Today", "Tomorrow", "Sun", "Mon", "Tue"];
|
||||
for (const [index, day] of days.entries()) {
|
||||
it("should render day " + day, async () => {
|
||||
it(`should render day ${day}`, async () => {
|
||||
await weatherFunc.getText(`.weather table.small tr:nth-child(${index + 1}) td:nth-child(1)`, day);
|
||||
});
|
||||
}
|
||||
|
||||
const icons = ["day-cloudy", "rain", "day-sunny", "day-sunny", "day-sunny"];
|
||||
for (const [index, icon] of icons.entries()) {
|
||||
it("should render icon " + icon, async () => {
|
||||
it(`should render icon ${icon}`, async () => {
|
||||
const elem = await helpers.waitForElement(`.weather table.small tr:nth-child(${index + 1}) td:nth-child(2) span.wi-${icon}`);
|
||||
expect(elem).not.toBe(null);
|
||||
});
|
||||
@@ -28,21 +28,21 @@ describe("Weather module: Weather Forecast", () => {
|
||||
|
||||
const maxTemps = ["24.4°", "21.0°", "22.9°", "23.4°", "20.6°"];
|
||||
for (const [index, temp] of maxTemps.entries()) {
|
||||
it("should render max temperature " + temp, async () => {
|
||||
it(`should render max temperature ${temp}`, async () => {
|
||||
await weatherFunc.getText(`.weather table.small tr:nth-child(${index + 1}) td:nth-child(3)`, temp);
|
||||
});
|
||||
}
|
||||
|
||||
const minTemps = ["15.3°", "13.6°", "13.8°", "13.9°", "10.9°"];
|
||||
for (const [index, temp] of minTemps.entries()) {
|
||||
it("should render min temperature " + temp, async () => {
|
||||
it(`should render min temperature ${temp}`, async () => {
|
||||
await weatherFunc.getText(`.weather table.small tr:nth-child(${index + 1}) td:nth-child(4)`, temp);
|
||||
});
|
||||
}
|
||||
|
||||
const opacities = [1, 1, 0.8, 0.5333333333333333, 0.2666666666666667];
|
||||
for (const [index, opacity] of opacities.entries()) {
|
||||
it("should render fading of rows with opacity=" + opacity, async () => {
|
||||
it(`should render fading of rows with opacity=${opacity}`, async () => {
|
||||
const elem = await helpers.waitForElement(`.weather table.small tr:nth-child(${index + 1})`);
|
||||
expect(elem).not.toBe(null);
|
||||
expect(elem.outerHTML).toContain(`<tr style="opacity: ${opacity};">`);
|
||||
@@ -57,7 +57,7 @@ describe("Weather module: Weather Forecast", () => {
|
||||
|
||||
const days = ["Fri", "Sat", "Sun", "Mon", "Tue"];
|
||||
for (const [index, day] of days.entries()) {
|
||||
it("should render day " + day, async () => {
|
||||
it(`should render day ${day}`, async () => {
|
||||
await weatherFunc.getText(`.weather table.small tr:nth-child(${index + 1}) td:nth-child(1)`, day);
|
||||
});
|
||||
}
|
||||
@@ -79,18 +79,40 @@ describe("Weather module: Weather Forecast", () => {
|
||||
expect(table.rows).not.toBe(null);
|
||||
expect(table.rows.length).toBe(5);
|
||||
});
|
||||
|
||||
const precipitations = [undefined, "2.51 mm"];
|
||||
for (const [index, precipitation] of precipitations.entries()) {
|
||||
if (precipitation) {
|
||||
it(`should render precipitation amount ${precipitation}`, async () => {
|
||||
await weatherFunc.getText(`.weather table tr:nth-child(${index + 1}) td.precipitation-amount`, precipitation);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe("Forecast weather units", () => {
|
||||
describe("Forecast weather with imperial units", () => {
|
||||
beforeAll(async () => {
|
||||
await weatherFunc.startApp("tests/configs/modules/weather/forecastweather_units.js", {});
|
||||
});
|
||||
|
||||
const temperatures = ["75_9°", "69_8°", "73_2°", "74_1°", "69_1°"];
|
||||
for (const [index, temp] of temperatures.entries()) {
|
||||
it("should render custom decimalSymbol = '_' for temp " + temp, async () => {
|
||||
await weatherFunc.getText(`.weather table.small tr:nth-child(${index + 1}) td:nth-child(3)`, temp);
|
||||
});
|
||||
}
|
||||
describe("Temperature units", () => {
|
||||
const temperatures = ["75_9°", "69_8°", "73_2°", "74_1°", "69_1°"];
|
||||
for (const [index, temp] of temperatures.entries()) {
|
||||
it(`should render custom decimalSymbol = '_' for temp ${temp}`, async () => {
|
||||
await weatherFunc.getText(`.weather table.small tr:nth-child(${index + 1}) td:nth-child(3)`, temp);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe("Precipitation units", () => {
|
||||
const precipitations = [undefined, "0.10 in"];
|
||||
for (const [index, precipitation] of precipitations.entries()) {
|
||||
if (precipitation) {
|
||||
it(`should render precipitation amount ${precipitation}`, async () => {
|
||||
await weatherFunc.getText(`.weather table.small tr:nth-child(${index + 1}) td.precipitation-amount`, precipitation);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
64
tests/e2e/modules/weather_hourly_spec.js
Normal file
64
tests/e2e/modules/weather_hourly_spec.js
Normal file
@@ -0,0 +1,64 @@
|
||||
const helpers = require("../helpers/global-setup");
|
||||
const weatherFunc = require("../helpers/weather-functions");
|
||||
|
||||
describe("Weather module: Weather Hourly Forecast", () => {
|
||||
afterAll(async () => {
|
||||
await helpers.stopApplication();
|
||||
});
|
||||
|
||||
describe("Default configuration", () => {
|
||||
beforeAll(async () => {
|
||||
await weatherFunc.startApp("tests/configs/modules/weather/hourlyweather_default.js", {});
|
||||
});
|
||||
|
||||
const minTemps = ["7:00 pm", "8:00 pm", "9:00 pm", "10:00 pm", "11:00 pm"];
|
||||
for (const [index, hour] of minTemps.entries()) {
|
||||
it(`should render forecast for hour ${hour}`, async () => {
|
||||
await weatherFunc.getText(`.weather table.small tr:nth-child(${index + 1}) td.day`, hour);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe("Hourly weather options", () => {
|
||||
beforeAll(async () => {
|
||||
await weatherFunc.startApp("tests/configs/modules/weather/hourlyweather_options.js", {});
|
||||
});
|
||||
|
||||
describe("Hourly increments of 2", () => {
|
||||
const minTemps = ["7:00 pm", "9:00 pm", "11:00 pm", "1:00 am", "3:00 am"];
|
||||
for (const [index, hour] of minTemps.entries()) {
|
||||
it(`should render forecast for hour ${hour}`, async () => {
|
||||
await weatherFunc.getText(`.weather table.small tr:nth-child(${index + 1}) td.day`, hour);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("Show precipitations", () => {
|
||||
beforeAll(async () => {
|
||||
await weatherFunc.startApp("tests/configs/modules/weather/hourlyweather_showPrecipitation.js", {});
|
||||
});
|
||||
|
||||
describe("Shows precipitation amount", () => {
|
||||
const amounts = [undefined, undefined, undefined, "0.13 mm", "0.13 mm"];
|
||||
for (const [index, amount] of amounts.entries()) {
|
||||
if (amount) {
|
||||
it(`should render precipitation amount ${amount}`, async () => {
|
||||
await weatherFunc.getText(`.weather table.small tr:nth-child(${index + 1}) td.precipitation-amount`, amount);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
describe("Shows precipitation probability", () => {
|
||||
const propabilities = [undefined, undefined, "12 %", "36 %", "44 %"];
|
||||
for (const [index, pop] of propabilities.entries()) {
|
||||
if (pop) {
|
||||
it(`should render probability ${pop}`, async () => {
|
||||
await weatherFunc.getText(`.weather table.small tr:nth-child(${index + 1}) td.precipitation-prob`, pop);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user