diff --git a/.github/workflows/automated-tests.yaml b/.github/workflows/automated-tests.yaml index c9eb45b8..35bbd2b6 100644 --- a/.github/workflows/automated-tests.yaml +++ b/.github/workflows/automated-tests.yaml @@ -22,6 +22,12 @@ jobs: steps: - name: "Checkout code" uses: actions/checkout@v3 + - name: "Set timezone" + uses: szenius/set-timezone@v1.2 + with: + timezoneLinux: "Europe/Berlin" + timezoneMacos: "Europe/Berlin" + timezoneWindows: "Europe/Berlin" - name: "Use Node.js ${{ matrix.node-version }}" uses: actions/setup-node@v3 with: diff --git a/.github/workflows/codecov-test-suites.yaml b/.github/workflows/codecov-test-suites.yaml index 8cdcccbb..adde5b33 100644 --- a/.github/workflows/codecov-test-suites.yaml +++ b/.github/workflows/codecov-test-suites.yaml @@ -19,6 +19,12 @@ jobs: steps: - name: "Checkout code" uses: actions/checkout@v3 + - name: "Set timezone" + uses: szenius/set-timezone@v1.2 + with: + timezoneLinux: "Europe/Berlin" + timezoneMacos: "Europe/Berlin" + timezoneWindows: "Europe/Berlin" - name: "Install dependencies and run coverage" run: | Xvfb :99 -screen 0 1024x768x16 & diff --git a/CHANGELOG.md b/CHANGELOG.md index d715591c..4c8e6b45 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,7 +20,8 @@ _This release is scheduled to be released on 2023-07-01._ ### Updated - Update electron to v24 -- Use node v19 in github workflow (replacing v14). +- Use node v19 in github workflow (replacing v14) +- Refactor formatTime into common util function for default modules ### Fixed diff --git a/modules/default/clock/clock.js b/modules/default/clock/clock.js index 595057c4..348e7a4c 100644 --- a/modules/default/clock/clock.js +++ b/modules/default/clock/clock.js @@ -1,4 +1,4 @@ -/* global SunCalc */ +/* global SunCalc, formatTime */ /* MagicMirror² * Module: Clock @@ -169,21 +169,6 @@ Module.register("clock", { digitalWrapper.appendChild(timeWrapper); } - /** - * Format the time according to the config - * - * @param {object} config The config of the module - * @param {object} time time to format - * @returns {string} The formatted time string - */ - function formatTime(config, time) { - let formatString = `${hourSymbol}:mm`; - if (config.showPeriod && config.timeFormat !== 24) { - formatString += config.showPeriodUpper ? "A" : "a"; - } - return moment(time).format(formatString); - } - /**************************************************************** * Create wrappers for Sun Times, only if specified in config */ diff --git a/modules/default/utils.js b/modules/default/utils.js index 604ab043..16c8f887 100644 --- a/modules/default/utils.js +++ b/modules/default/utils.js @@ -141,7 +141,37 @@ const getHeadersFromResponse = (expectedResponseHeaders, response) => { return responseHeaders; }; +/** + * Format the time according to the config + * + * @param {object} config The config of the module + * @param {object} time time to format + * @returns {string} The formatted time string + */ +const formatTime = (config, time) => { + let date = moment(time); + + if (config.timezone) { + date = moment.tz(config.timezone); + } + + if (config.timeFormat !== 24) { + if (config.showPeriod) { + if (config.showPeriodUpper) { + return date.format("h:mm A"); + } else { + return date.format("h:mm a"); + } + } else { + return date.format("h:mm"); + } + } + + return date.format("HH:mm"); +}; + if (typeof module !== "undefined") module.exports = { - performWebRequest + performWebRequest, + formatTime }; diff --git a/modules/default/weather/weather.js b/modules/default/weather/weather.js index 949c11cd..220b7668 100644 --- a/modules/default/weather/weather.js +++ b/modules/default/weather/weather.js @@ -1,4 +1,4 @@ -/* global WeatherProvider, WeatherUtils */ +/* global WeatherProvider, WeatherUtils, formatTime */ /* MagicMirror² * Module: Weather @@ -211,21 +211,7 @@ Module.register("weather", { this.nunjucksEnvironment().addFilter( "formatTime", function (date) { - date = moment(date); - - if (this.config.timeFormat !== 24) { - if (this.config.showPeriod) { - if (this.config.showPeriodUpper) { - return date.format("h:mm A"); - } else { - return date.format("h:mm a"); - } - } else { - return date.format("h:mm"); - } - } - - return date.format("HH:mm"); + return formatTime(this.config, date); }.bind(this) ); diff --git a/tests/unit/modules/default/utils_spec.js b/tests/unit/modules/default/utils_spec.js index f9c9390a..ff51ec3d 100644 --- a/tests/unit/modules/default/utils_spec.js +++ b/tests/unit/modules/default/utils_spec.js @@ -1,8 +1,9 @@ -const { performWebRequest } = require("../../../../modules/default/utils"); +global.moment = require("moment-timezone"); +const { performWebRequest, formatTime } = require("../../../../modules/default/utils"); const nodeVersion = process.version.match(/^v(\d+)\.*/)[1]; -describe("Utils tests", () => { +describe("Default modules utils tests", () => { describe("The performWebRequest-method", () => { if (nodeVersion > 18) { const locationHost = "localhost:8080"; @@ -109,4 +110,78 @@ describe("Utils tests", () => { test("Always ok, need one test", () => {}); } }); + + describe("formatTime", () => { + const time = new Date(); + + beforeAll(() => { + jest.useFakeTimers(); + moment.tz.setDefault("Europe/Berlin"); + }); + + beforeEach(async () => { + jest.setSystemTime(new Date("2023-01-01 13:13")); + }); + + afterEach(async () => { + jest.setSystemTime(new Date()); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + + it("should convert correctly according to the config", () => { + time.setHours(13, 13); + expect( + formatTime( + { + timeFormat: 24 + }, + time + ) + ).toBe("13:13"); + expect( + formatTime( + { + showPeriod: true, + showPeriodUpper: true, + timeFormat: 12 + }, + time + ) + ).toBe("1:13 PM"); + expect( + formatTime( + { + showPeriod: true, + showPeriodUpper: false, + timeFormat: 12 + }, + time + ) + ).toBe("1:13 pm"); + expect( + formatTime( + { + showPeriod: false, + timeFormat: 12 + }, + time + ) + ).toBe("1:13"); + }); + + it("should convert correctly into another timezone", () => { + expect( + formatTime( + { + timeFormat: 24, + timezone: "America/Toronto" + }, + time + ) + ).toBe("07:13"); + }); + }); }); diff --git a/tests/unit/modules/default/weather/weather_utils_spec.js b/tests/unit/modules/default/weather/weather_utils_spec.js index 8aefd3c9..a7c8d75c 100644 --- a/tests/unit/modules/default/weather/weather_utils_spec.js +++ b/tests/unit/modules/default/weather/weather_utils_spec.js @@ -7,7 +7,7 @@ describe("Weather utils tests", () => { const units = ["mm", "cm"]; for (let i = 0; i < values.length; i++) { - var result = weather.convertPrecipitationUnit(values[i], units[i], undefined); + const result = weather.convertPrecipitationUnit(values[i], units[i], undefined); expect(result).toBe(`${values[i].toFixed(2)} ${units[i]}`); } }); @@ -17,7 +17,7 @@ describe("Weather utils tests", () => { const units = ["mm", "cm"]; for (let i = 0; i < values.length; i++) { - var result = weather.convertPrecipitationUnit(values[i], units[i], "metric"); + const result = weather.convertPrecipitationUnit(values[i], units[i], "metric"); expect(result).toBe(`${values[i].toFixed(2)} ${units[i]}`); } }); @@ -26,7 +26,7 @@ describe("Weather utils tests", () => { const values = [1, 2]; for (let i = 0; i < values.length; i++) { - var result = weather.convertPrecipitationUnit(values[i], undefined, "metric"); + const result = weather.convertPrecipitationUnit(values[i], undefined, "metric"); expect(result).toBe(`${values[i].toFixed(2)} mm`); } }); @@ -37,7 +37,7 @@ describe("Weather utils tests", () => { const expectedValues = [0.04, 0.79]; for (let i = 0; i < values.length; i++) { - var result = weather.convertPrecipitationUnit(values[i], units[i], "imperial"); + const result = weather.convertPrecipitationUnit(values[i], units[i], "imperial"); expect(result).toBe(`${expectedValues[i]} in`); } });