Update weather tests (#3008)

Added a few tests for sunset/sunrise and feelsLike 
Lets see if they run through first...

Co-authored-by: veeck <michael@veeck.de>
This commit is contained in:
Veeck 2023-01-26 19:43:34 +01:00 committed by GitHub
parent 58b9ddcd9f
commit a8dc563a31
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 885 additions and 849 deletions

View File

@ -27,6 +27,7 @@ _This release is scheduled to be released on 2023-04-01._
- Use develop as target branch for dependabot
- Update issue template and contributing doc
- Update weather tests
- 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

View File

@ -25,7 +25,7 @@ module.exports = async () => {
testPathIgnorePatterns: ["<rootDir>/tests/e2e/helpers/", "<rootDir>/tests/e2e/mocks"]
}
],
collectCoverageFrom: ["./clientonly/**/*.js", "./js/**/*.js", "./modules/**/*.js", "./serveronly/**/*.js"],
collectCoverageFrom: ["./clientonly/**/*.js", "./js/**/*.js", "./modules/default/**/*.js", "./serveronly/**/*.js"],
coverageReporters: ["lcov", "text"],
coverageProvider: "v8"
};

View File

@ -11,6 +11,10 @@
* Currently this is focused on the information which is necessary for the current weather.
* As soon as we start implementing the forecast, mode properties will be added.
*/
/**
* @external Moment
*/
class WeatherObject {
/**
* Constructor for a WeatherObject
@ -69,34 +73,23 @@ class WeatherObject {
}
}
nextSunAction() {
return moment().isBetween(this.sunrise, this.sunset) ? "sunset" : "sunrise";
/**
* Determines if the sun sets or rises next. Uses the current time and not
* the date from the weather-forecast.
*
* @param {Moment} date an optional date where you want to get the next
* action for. Useful only in tests, defaults to the current time.
* @returns {string} "sunset" or "sunrise"
*/
nextSunAction(date = moment()) {
return date.isBetween(this.sunrise, this.sunset) ? "sunset" : "sunrise";
}
feelsLike() {
if (this.feelsLikeTemp) {
return this.feelsLikeTemp;
}
const windInMph = WeatherUtils.convertWind(this.windSpeed, "imperial");
const tempInF = WeatherUtils.convertTemp(this.temperature, "imperial");
let feelsLike = tempInF;
if (windInMph > 3 && tempInF < 50) {
feelsLike = Math.round(35.74 + 0.6215 * tempInF - 35.75 * Math.pow(windInMph, 0.16) + 0.4275 * tempInF * Math.pow(windInMph, 0.16));
} else if (tempInF > 80 && this.humidity > 40) {
feelsLike =
-42.379 +
2.04901523 * tempInF +
10.14333127 * this.humidity -
0.22475541 * tempInF * this.humidity -
6.83783 * Math.pow(10, -3) * tempInF * tempInF -
5.481717 * Math.pow(10, -2) * this.humidity * this.humidity +
1.22874 * Math.pow(10, -3) * tempInF * tempInF * this.humidity +
8.5282 * Math.pow(10, -4) * tempInF * this.humidity * this.humidity -
1.99 * Math.pow(10, -6) * tempInF * tempInF * this.humidity * this.humidity;
}
return ((feelsLike - 32) * 5) / 9;
return WeatherUtils.calculateFeelsLike(this.temperature, this.windSpeed, this.humidity);
}
/**
@ -105,7 +98,8 @@ class WeatherObject {
* @returns {boolean} true if it is at dayTime
*/
isDayTime() {
return this.date.isBetween(this.sunrise, this.sunset, undefined, "[]");
const now = !this.date ? moment() : this.date;
return now.isBetween(this.sunrise, this.sunset, undefined, "[]");
}
/**

View File

@ -90,6 +90,29 @@ const WeatherUtils = {
convertWindToMs(kmh) {
return kmh * 0.27777777777778;
},
calculateFeelsLike(temperature, windSpeed, humidity) {
const windInMph = this.convertWind(windSpeed, "imperial");
const tempInF = this.convertTemp(temperature, "imperial");
let feelsLike = tempInF;
if (windInMph > 3 && tempInF < 50) {
feelsLike = Math.round(35.74 + 0.6215 * tempInF - 35.75 * Math.pow(windInMph, 0.16) + 0.4275 * tempInF * Math.pow(windInMph, 0.16));
} else if (tempInF > 80 && humidity > 40) {
feelsLike =
-42.379 +
2.04901523 * tempInF +
10.14333127 * humidity -
0.22475541 * tempInF * humidity -
6.83783 * Math.pow(10, -3) * tempInF * tempInF -
5.481717 * Math.pow(10, -2) * humidity * humidity +
1.22874 * Math.pow(10, -3) * tempInF * tempInF * humidity +
8.5282 * Math.pow(10, -4) * tempInF * humidity * humidity -
1.99 * Math.pow(10, -6) * tempInF * tempInF * humidity * humidity;
}
return ((feelsLike - 32) * 5) / 9;
}
};

1626
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -51,15 +51,15 @@
"devDependencies": {
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-jest": "^27.2.1",
"eslint-plugin-jsdoc": "^39.6.4",
"eslint-plugin-jsdoc": "^39.6.8",
"eslint-plugin-prettier": "^4.2.1",
"express-basic-auth": "^1.2.1",
"husky": "^8.0.3",
"jest": "^29.3.1",
"jsdom": "^21.0.0",
"jest": "^29.4.0",
"jsdom": "^21.1.0",
"lodash": "^4.17.21",
"playwright": "^1.29.2",
"prettier": "^2.8.2",
"playwright": "^1.30.0",
"prettier": "^2.8.3",
"pretty-quick": "^3.1.3",
"sinon": "^15.0.1",
"stylelint": "^14.16.1",
@ -69,13 +69,13 @@
"suncalc": "^1.9.0"
},
"optionalDependencies": {
"electron": "^22.0.0"
"electron": "^22.1.0"
},
"dependencies": {
"colors": "^1.4.0",
"console-stamp": "^3.1.0",
"digest-fetch": "^2.0.1",
"eslint": "^8.31.0",
"eslint": "^8.32.0",
"express": "^4.18.2",
"express-ipfilter": "^1.3.1",
"feedme": "^2.0.2",

View File

@ -8,7 +8,6 @@ exports.startApplication = async (configFilename, systemDate = null, electronPar
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();

View File

@ -15,23 +15,40 @@ describe("WeatherObject", () => {
});
it("should return true for daytime at noon", () => {
weatherobject.date = moment(12, "HH");
weatherobject.date = moment("12:00", "HH:mm");
weatherobject.updateSunTime(-6.774877582342688, 37.63345667023327);
expect(weatherobject.isDayTime()).toBe(true);
});
it("should return false for daytime at midnight", () => {
weatherobject.date = moment(0, "HH");
weatherobject.date = moment("00:00", "HH:mm");
weatherobject.updateSunTime(-6.774877582342688, 37.63345667023327);
expect(weatherobject.isDayTime()).toBe(false);
});
it("should return sunrise as the next sunaction", () => {
weatherobject.updateSunTime(-6.774877582342688, 37.63345667023327);
let midnight = moment("00:00", "HH:mm");
expect(weatherobject.nextSunAction(midnight)).toBe("sunrise");
});
it("should return sunset as the next sunaction", () => {
weatherobject.updateSunTime(-6.774877582342688, 37.63345667023327);
let noon = moment(weatherobject.sunrise).hour(14);
expect(weatherobject.nextSunAction(noon)).toBe("sunset");
});
it("should return an already defined feelsLike info", () => {
weatherobject.feelsLikeTemp = "feelsLikeTempValue";
expect(weatherobject.feelsLike()).toBe("feelsLikeTempValue");
});
afterAll(() => {
moment.tz.setDefault(originalTimeZone);
});
});
describe("WeatherObject", () => {
describe("WeatherUtils", () => {
it("should convert windspeed correctly from mph to mps", () => {
expect(Math.round(WeatherUtils.convertWindToMetric(93.951324266285))).toBe(42);
});
@ -43,4 +60,8 @@ describe("WeatherObject", () => {
it("should convert wind direction correctly from cardinal to value", () => {
expect(WeatherUtils.convertWindDirection("SSE")).toBe(157);
});
it("should return a calculated feelsLike info", () => {
expect(WeatherUtils.calculateFeelsLike(0, 20, 40)).toBe(-9.444444444444445);
});
});