mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-06-27 11:50:00 +00:00
Add option to show hourly forecast in increments (#2998)
Adds new config option to show weather forecast for every X hour (default value is 1 which reflects the current behaviour) Also adds tests for hourly forecast Fixes #2996 Co-authored-by: veeck <michael@veeck.de>
This commit is contained in:
parent
7bc91a742f
commit
6e80e5a295
@ -11,6 +11,8 @@ _This release is scheduled to be released on 2023-04-01._
|
|||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Added increments for hourly forecasts in weather module (#2996)
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
- Removed darksky weather provider
|
- Removed darksky weather provider
|
||||||
|
@ -12,23 +12,25 @@ Module.register("weather", {
|
|||||||
weatherProvider: "openweathermap",
|
weatherProvider: "openweathermap",
|
||||||
roundTemp: false,
|
roundTemp: false,
|
||||||
type: "current", // current, forecast, daily (equivalent to forecast), hourly (only with OpenWeatherMap /onecall endpoint)
|
type: "current", // current, forecast, daily (equivalent to forecast), hourly (only with OpenWeatherMap /onecall endpoint)
|
||||||
|
lang: config.language,
|
||||||
units: config.units,
|
units: config.units,
|
||||||
tempUnits: config.units,
|
tempUnits: config.units,
|
||||||
windUnits: config.units,
|
windUnits: config.units,
|
||||||
|
timeFormat: config.timeFormat,
|
||||||
updateInterval: 10 * 60 * 1000, // every 10 minutes
|
updateInterval: 10 * 60 * 1000, // every 10 minutes
|
||||||
animationSpeed: 1000,
|
animationSpeed: 1000,
|
||||||
timeFormat: config.timeFormat,
|
showFeelsLike: true,
|
||||||
|
showHumidity: false,
|
||||||
|
showIndoorHumidity: false,
|
||||||
|
showIndoorTemperature: false,
|
||||||
showPeriod: true,
|
showPeriod: true,
|
||||||
showPeriodUpper: false,
|
showPeriodUpper: false,
|
||||||
|
showPrecipitationAmount: false,
|
||||||
|
showSun: true,
|
||||||
showWindDirection: true,
|
showWindDirection: true,
|
||||||
showWindDirectionAsArrow: false,
|
showWindDirectionAsArrow: false,
|
||||||
lang: config.language,
|
|
||||||
showHumidity: false,
|
|
||||||
showSun: true,
|
|
||||||
degreeLabel: false,
|
degreeLabel: false,
|
||||||
decimalSymbol: ".",
|
decimalSymbol: ".",
|
||||||
showIndoorTemperature: false,
|
|
||||||
showIndoorHumidity: false,
|
|
||||||
maxNumberOfDays: 5,
|
maxNumberOfDays: 5,
|
||||||
maxEntries: 5,
|
maxEntries: 5,
|
||||||
ignoreToday: false,
|
ignoreToday: false,
|
||||||
@ -39,10 +41,9 @@ Module.register("weather", {
|
|||||||
calendarClass: "calendar",
|
calendarClass: "calendar",
|
||||||
tableClass: "small",
|
tableClass: "small",
|
||||||
onlyTemp: false,
|
onlyTemp: false,
|
||||||
showPrecipitationAmount: false,
|
|
||||||
colored: false,
|
colored: false,
|
||||||
showFeelsLike: true,
|
absoluteDates: false,
|
||||||
absoluteDates: false
|
hourlyForecastIncrements: 1
|
||||||
},
|
},
|
||||||
|
|
||||||
// Module properties.
|
// Module properties.
|
||||||
@ -137,13 +138,17 @@ Module.register("weather", {
|
|||||||
|
|
||||||
// Add all the data to the template.
|
// Add all the data to the template.
|
||||||
getTemplateData: function () {
|
getTemplateData: function () {
|
||||||
const forecast = this.weatherProvider.weatherForecast();
|
const currentData = this.weatherProvider.currentWeather();
|
||||||
|
const forecastData = this.weatherProvider.weatherForecast();
|
||||||
|
|
||||||
|
// Skip some hourly forecast entries if configured
|
||||||
|
const hourlyData = this.weatherProvider.weatherHourly()?.filter((e, i) => (i + 1) % this.config.hourlyForecastIncrements === this.config.hourlyForecastIncrements - 1);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
config: this.config,
|
config: this.config,
|
||||||
current: this.weatherProvider.currentWeather(),
|
current: currentData,
|
||||||
forecast: forecast,
|
forecast: forecastData,
|
||||||
hourly: this.weatherProvider.weatherHourly(),
|
hourly: hourlyData,
|
||||||
indoor: {
|
indoor: {
|
||||||
humidity: this.indoorHumidity,
|
humidity: this.indoorHumidity,
|
||||||
temperature: this.indoorTemperature
|
temperature: this.indoorTemperature
|
||||||
|
25
tests/configs/modules/weather/hourlyweather_default.js
Normal file
25
tests/configs/modules/weather/hourlyweather_default.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/* MagicMirror² Test config hourly weather
|
||||||
|
*
|
||||||
|
* By rejas https://github.com/rejas
|
||||||
|
* MIT Licensed.
|
||||||
|
*/
|
||||||
|
let config = {
|
||||||
|
timeFormat: 12,
|
||||||
|
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
module: "weather",
|
||||||
|
position: "bottom_bar",
|
||||||
|
config: {
|
||||||
|
type: "hourly",
|
||||||
|
location: "Berlin",
|
||||||
|
mockData: '"#####WEATHERDATA#####"'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
26
tests/configs/modules/weather/hourlyweather_options.js
Normal file
26
tests/configs/modules/weather/hourlyweather_options.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/* MagicMirror² Test config hourly weather options
|
||||||
|
*
|
||||||
|
* By rejas https://github.com/rejas
|
||||||
|
* MIT Licensed.
|
||||||
|
*/
|
||||||
|
let config = {
|
||||||
|
timeFormat: 12,
|
||||||
|
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
module: "weather",
|
||||||
|
position: "bottom_bar",
|
||||||
|
config: {
|
||||||
|
type: "hourly",
|
||||||
|
location: "Berlin",
|
||||||
|
mockData: '"#####WEATHERDATA#####"',
|
||||||
|
hourlyForecastIncrements: 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
/*************** DO NOT EDIT THE LINE BELOW ***************/
|
||||||
|
if (typeof module !== "undefined") {
|
||||||
|
module.exports = config;
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
const helpers = require("./global-setup");
|
const helpers = require("./global-setup");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const { generateWeather, generateWeatherForecast } = require("../../mocks/weather_test");
|
const { generateWeather, generateWeatherForecast, generateWeatherHourly } = require("../../mocks/weather_test");
|
||||||
|
|
||||||
exports.getText = async (element, result) => {
|
exports.getText = async (element, result) => {
|
||||||
const elem = await helpers.waitForElement(element);
|
const elem = await helpers.waitForElement(element);
|
||||||
@ -18,6 +18,8 @@ exports.startApp = async (configFile, additionalMockData) => {
|
|||||||
let mockWeather;
|
let mockWeather;
|
||||||
if (configFile.includes("forecast")) {
|
if (configFile.includes("forecast")) {
|
||||||
mockWeather = generateWeatherForecast(additionalMockData);
|
mockWeather = generateWeatherForecast(additionalMockData);
|
||||||
|
} else if (configFile.includes("hourly")) {
|
||||||
|
mockWeather = generateWeatherHourly(additionalMockData);
|
||||||
} else {
|
} else {
|
||||||
mockWeather = generateWeather(additionalMockData);
|
mockWeather = generateWeather(additionalMockData);
|
||||||
}
|
}
|
||||||
|
36
tests/e2e/modules/weather_hourly_spec.js
Normal file
36
tests/e2e/modules/weather_hourly_spec.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -1,7 +1,7 @@
|
|||||||
const helpers = require("./global-setup");
|
const helpers = require("./global-setup");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const { generateWeather, generateWeatherForecast } = require("../../mocks/weather_test");
|
const { generateWeather, generateWeatherForecast, generateWeatherHourly } = require("../../mocks/weather_test");
|
||||||
|
|
||||||
exports.getText = async (element, result) => {
|
exports.getText = async (element, result) => {
|
||||||
const elem = await helpers.getElement(element);
|
const elem = await helpers.getElement(element);
|
||||||
@ -19,6 +19,8 @@ exports.startApp = async (configFile, systemDate) => {
|
|||||||
let mockWeather;
|
let mockWeather;
|
||||||
if (configFile.includes("forecast")) {
|
if (configFile.includes("forecast")) {
|
||||||
mockWeather = generateWeatherForecast();
|
mockWeather = generateWeatherForecast();
|
||||||
|
} else if (configFile.includes("hourly")) {
|
||||||
|
mockWeather = generateWeatherHourly();
|
||||||
} else {
|
} else {
|
||||||
mockWeather = generateWeather();
|
mockWeather = generateWeather();
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user