mirror of
https://github.com/MichMich/MagicMirror.git
synced 2025-06-27 11:50:00 +00:00
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:
parent
58b9ddcd9f
commit
a8dc563a31
@ -27,6 +27,7 @@ _This release is scheduled to be released on 2023-04-01._
|
|||||||
|
|
||||||
- Use develop as target branch for dependabot
|
- Use develop as target branch for dependabot
|
||||||
- Update issue template and contributing doc
|
- 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
|
- 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
|
- Update dates in Calendar widgets every minute
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ module.exports = async () => {
|
|||||||
testPathIgnorePatterns: ["<rootDir>/tests/e2e/helpers/", "<rootDir>/tests/e2e/mocks"]
|
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"],
|
coverageReporters: ["lcov", "text"],
|
||||||
coverageProvider: "v8"
|
coverageProvider: "v8"
|
||||||
};
|
};
|
||||||
|
@ -11,6 +11,10 @@
|
|||||||
* Currently this is focused on the information which is necessary for the current weather.
|
* 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.
|
* As soon as we start implementing the forecast, mode properties will be added.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @external Moment
|
||||||
|
*/
|
||||||
class WeatherObject {
|
class WeatherObject {
|
||||||
/**
|
/**
|
||||||
* Constructor for a 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() {
|
feelsLike() {
|
||||||
if (this.feelsLikeTemp) {
|
if (this.feelsLikeTemp) {
|
||||||
return this.feelsLikeTemp;
|
return this.feelsLikeTemp;
|
||||||
}
|
}
|
||||||
const windInMph = WeatherUtils.convertWind(this.windSpeed, "imperial");
|
return WeatherUtils.calculateFeelsLike(this.temperature, this.windSpeed, this.humidity);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -105,7 +98,8 @@ class WeatherObject {
|
|||||||
* @returns {boolean} true if it is at dayTime
|
* @returns {boolean} true if it is at dayTime
|
||||||
*/
|
*/
|
||||||
isDayTime() {
|
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, "[]");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -90,6 +90,29 @@ const WeatherUtils = {
|
|||||||
|
|
||||||
convertWindToMs(kmh) {
|
convertWindToMs(kmh) {
|
||||||
return kmh * 0.27777777777778;
|
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
1626
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
14
package.json
14
package.json
@ -51,15 +51,15 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint-config-prettier": "^8.6.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-jest": "^27.2.1",
|
"eslint-plugin-jest": "^27.2.1",
|
||||||
"eslint-plugin-jsdoc": "^39.6.4",
|
"eslint-plugin-jsdoc": "^39.6.8",
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
"express-basic-auth": "^1.2.1",
|
"express-basic-auth": "^1.2.1",
|
||||||
"husky": "^8.0.3",
|
"husky": "^8.0.3",
|
||||||
"jest": "^29.3.1",
|
"jest": "^29.4.0",
|
||||||
"jsdom": "^21.0.0",
|
"jsdom": "^21.1.0",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"playwright": "^1.29.2",
|
"playwright": "^1.30.0",
|
||||||
"prettier": "^2.8.2",
|
"prettier": "^2.8.3",
|
||||||
"pretty-quick": "^3.1.3",
|
"pretty-quick": "^3.1.3",
|
||||||
"sinon": "^15.0.1",
|
"sinon": "^15.0.1",
|
||||||
"stylelint": "^14.16.1",
|
"stylelint": "^14.16.1",
|
||||||
@ -69,13 +69,13 @@
|
|||||||
"suncalc": "^1.9.0"
|
"suncalc": "^1.9.0"
|
||||||
},
|
},
|
||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"electron": "^22.0.0"
|
"electron": "^22.1.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"colors": "^1.4.0",
|
"colors": "^1.4.0",
|
||||||
"console-stamp": "^3.1.0",
|
"console-stamp": "^3.1.0",
|
||||||
"digest-fetch": "^2.0.1",
|
"digest-fetch": "^2.0.1",
|
||||||
"eslint": "^8.31.0",
|
"eslint": "^8.32.0",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"express-ipfilter": "^1.3.1",
|
"express-ipfilter": "^1.3.1",
|
||||||
"feedme": "^2.0.2",
|
"feedme": "^2.0.2",
|
||||||
|
@ -8,7 +8,6 @@ exports.startApplication = async (configFilename, systemDate = null, electronPar
|
|||||||
global.page = null;
|
global.page = null;
|
||||||
process.env.MM_CONFIG_FILE = configFilename;
|
process.env.MM_CONFIG_FILE = configFilename;
|
||||||
process.env.TZ = "GMT";
|
process.env.TZ = "GMT";
|
||||||
jest.retryTimes(3);
|
|
||||||
global.electronApp = await electron.launch({ args: electronParams });
|
global.electronApp = await electron.launch({ args: electronParams });
|
||||||
|
|
||||||
await global.electronApp.firstWindow();
|
await global.electronApp.firstWindow();
|
||||||
|
@ -15,23 +15,40 @@ describe("WeatherObject", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should return true for daytime at noon", () => {
|
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);
|
weatherobject.updateSunTime(-6.774877582342688, 37.63345667023327);
|
||||||
expect(weatherobject.isDayTime()).toBe(true);
|
expect(weatherobject.isDayTime()).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return false for daytime at midnight", () => {
|
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);
|
weatherobject.updateSunTime(-6.774877582342688, 37.63345667023327);
|
||||||
expect(weatherobject.isDayTime()).toBe(false);
|
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(() => {
|
afterAll(() => {
|
||||||
moment.tz.setDefault(originalTimeZone);
|
moment.tz.setDefault(originalTimeZone);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("WeatherObject", () => {
|
describe("WeatherUtils", () => {
|
||||||
it("should convert windspeed correctly from mph to mps", () => {
|
it("should convert windspeed correctly from mph to mps", () => {
|
||||||
expect(Math.round(WeatherUtils.convertWindToMetric(93.951324266285))).toBe(42);
|
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", () => {
|
it("should convert wind direction correctly from cardinal to value", () => {
|
||||||
expect(WeatherUtils.convertWindDirection("SSE")).toBe(157);
|
expect(WeatherUtils.convertWindDirection("SSE")).toBe(157);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should return a calculated feelsLike info", () => {
|
||||||
|
expect(WeatherUtils.calculateFeelsLike(0, 20, 40)).toBe(-9.444444444444445);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user