Better fixes for #3291 and the underlying exdate issues (#3342)

* Worked around several issues in the RRULE library that were causing
deleted calender events to still show, some initial and recurring events
to not show, and some event times to be off an hour. (#3291)
* Renamed variables in *calendarfetcherutils.js* to be more clear about
use of `moment` and js's `Date` class.
* Added calendar config option `forceUseCurrentTime` (default:`false`)
which will ignore overridden `Date.now` in the config in order to keep
some tests consistent.
* Added several unit tests for crossing DST in different timezones with
excluded events.
This commit is contained in:
jkriegshauser
2024-01-26 22:56:54 -08:00
committed by GitHub
parent 27f3c86c41
commit 7f0b8e4054
20 changed files with 528 additions and 219 deletions

View File

@@ -7,6 +7,7 @@ let config = {
position: "bottom_bar",
config: {
customEvents: [{ keyword: "CustomEvent", symbol: "dice", eventClass: "undo" }],
forceUseCurrentTime: true,
calendars: [
{
maximumEntries: 5,

View File

@@ -1,31 +0,0 @@
/* NOTE: calendar_test_exdate.ics has exdate entries for the next 20 years, but without some
* way to set a debug date for tests, this test may become flaky on specific days (i.e. could
* not test easily on leap-years, the BYDAY specified in exdate, etc.) or when the 20 years
* elapses if this project is still in active development ;)
* See issue #3250
*/
let config = {
timeFormat: 12,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
maximumEntries: 100,
calendars: [
{
maximumEntries: 100,
maximumNumberOfDays: 364,
url: "http://localhost:8080/tests/mocks/calendar_test_exdate.ics"
}
]
}
}
]
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -0,0 +1,37 @@
/* MagicMirror² Test calendar exdate
*
* By jkriegshauser
* MIT Licensed.
*
* See issue #3250
* See tests/electron/modules/calendar_spec.js
*/
let config = {
timeFormat: 12,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
maximumEntries: 100,
calendars: [
{
maximumEntries: 100,
maximumNumberOfDays: 28, // 4 weeks, 2 of which are skipped
url: "http://localhost:8080/tests/mocks/exdate_la_at_midnight_dst.ics"
}
]
}
}
]
};
Date.now = () => {
return new Date("19 Oct 2023 12:30:00 GMT-07:00").valueOf();
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -0,0 +1,37 @@
/* MagicMirror² Test calendar exdate
*
* By jkriegshauser
* MIT Licensed.
*
* See issue #3250
* See tests/electron/modules/calendar_spec.js
*/
let config = {
timeFormat: 12,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
maximumEntries: 100,
calendars: [
{
maximumEntries: 100,
maximumNumberOfDays: 28, // 4 weeks, 2 of which are skipped
url: "http://localhost:8080/tests/mocks/exdate_la_at_midnight_std.ics"
}
]
}
}
]
};
Date.now = () => {
return new Date("19 Oct 2023 12:30:00 GMT-07:00").valueOf();
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -0,0 +1,37 @@
/* MagicMirror² Test calendar exdate
*
* By jkriegshauser
* MIT Licensed.
*
* See issue #3250
* See tests/electron/modules/calendar_spec.js
*/
let config = {
timeFormat: 12,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
maximumEntries: 100,
calendars: [
{
maximumEntries: 100,
maximumNumberOfDays: 28, // 4 weeks, 2 of which are skipped
url: "http://localhost:8080/tests/mocks/exdate_la_before_midnight.ics"
}
]
}
}
]
};
Date.now = () => {
return new Date("19 Oct 2023 12:30:00 GMT-07:00").valueOf();
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -0,0 +1,37 @@
/* MagicMirror² Test calendar exdate
*
* By jkriegshauser
* MIT Licensed.
*
* See issue #3250
* See tests/electron/modules/calendar_spec.js
*/
let config = {
timeFormat: 12,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
maximumEntries: 100,
calendars: [
{
maximumEntries: 100,
maximumNumberOfDays: 28, // 4 weeks, 2 of which are skipped
url: "http://localhost:8080/tests/mocks/exdate_syd_at_midnight_dst.ics"
}
]
}
}
]
};
Date.now = () => {
return new Date("14 Sep 2023 12:30:00 GMT+10:00").valueOf();
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -0,0 +1,37 @@
/* MagicMirror² Test calendar exdate
*
* By jkriegshauser
* MIT Licensed.
*
* See issue #3250
* See tests/electron/modules/calendar_spec.js
*/
let config = {
timeFormat: 12,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
maximumEntries: 100,
calendars: [
{
maximumEntries: 100,
maximumNumberOfDays: 28, // 4 weeks, 2 of which are skipped
url: "http://localhost:8080/tests/mocks/exdate_syd_at_midnight_std.ics"
}
]
}
}
]
};
Date.now = () => {
return new Date("14 Sep 2023 12:30:00 GMT+10:00").valueOf();
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -0,0 +1,37 @@
/* MagicMirror² Test calendar exdate
*
* By jkriegshauser
* MIT Licensed.
*
* See issue #3250
* See tests/electron/modules/calendar_spec.js
*/
let config = {
timeFormat: 12,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
maximumEntries: 100,
calendars: [
{
maximumEntries: 100,
maximumNumberOfDays: 28, // 4 weeks, 2 of which are skipped
url: "http://localhost:8080/tests/mocks/exdate_syd_before_midnight.ics"
}
]
}
}
]
};
Date.now = () => {
return new Date("14 Sep 2023 12:30:00 GMT+10:00").valueOf();
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -3,11 +3,11 @@
// https://www.anycodings.com/1questions/958135/can-i-set-the-date-for-playwright-browser
const { _electron: electron } = require("playwright");
exports.startApplication = async (configFilename, systemDate = null, electronParams = ["js/electron.js"]) => {
exports.startApplication = async (configFilename, systemDate = null, electronParams = ["js/electron.js"], timezone = "GMT") => {
global.electronApp = null;
global.page = null;
process.env.MM_CONFIG_FILE = configFilename;
process.env.TZ = "GMT";
process.env.TZ = timezone;
global.electronApp = await electron.launch({ args: electronParams });
await global.electronApp.firstWindow();
@@ -20,7 +20,7 @@ exports.startApplication = async (configFilename, systemDate = null, electronPar
if (systemDate) {
await global.page.evaluate((systemDate) => {
Date.now = () => {
return new Date(systemDate);
return new Date(systemDate).valueOf();
};
}, systemDate);
}

View File

@@ -44,17 +44,96 @@ describe("Calendar module", () => {
});
});
describe("Exdate check", () => {
it("should show the recurring event 51 times (excluded once) in a 364-day (inclusive) period", async () => {
// test must run on a Thursday
await helpers.startApplication("tests/configs/modules/calendar/exdate.js", "14 Dec 2023 12:30:00 GMT");
/****************************/
// LOS ANGELES TESTS:
// In 2023, DST (GMT-7) was until 5 Nov, after which is standard (STD) (GMT-8) time.
// Test takes place on Thu 19 Oct, recurring event on a Wednesday. maximumNumberOfDays=28, so there should be
// 4 events (25 Oct, 1 Nov, (switch to STD), 8 Nov, Nov 15), but 1 Nov and 8 Nov are excluded.
// There are three separate tests:
// * before midnight GMT (3pm local time)
// * at midnight GMT in STD time (4pm local time)
// * at midnight GMT in DST time (5pm local time)
describe("Exdate: LA crossover DST before midnight GMT", () => {
it("LA crossover DST before midnight GMT should have 2 events", async () => {
await helpers.startApplication("tests/configs/modules/calendar/exdate_la_before_midnight.js", "19 Oct 2023 12:30:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles");
expect(global.page).not.toBeNull();
const loc = await global.page.locator(".calendar .event");
const elem = loc.first();
await elem.waitFor();
expect(elem).not.toBeNull();
const cnt = await loc.count();
expect(cnt).toBe(51);
expect(cnt).toBe(2);
});
});
describe("Exdate: LA crossover DST at midnight GMT local STD", () => {
it("LA crossover DST before midnight GMT should have 2 events", async () => {
await helpers.startApplication("tests/configs/modules/calendar/exdate_la_at_midnight_std.js", "19 Oct 2023 12:30:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles");
expect(global.page).not.toBeNull();
const loc = await global.page.locator(".calendar .event");
const elem = loc.first();
await elem.waitFor();
expect(elem).not.toBeNull();
const cnt = await loc.count();
expect(cnt).toBe(2);
});
});
describe("Exdate: LA crossover DST at midnight GMT local DST", () => {
it("LA crossover DST before midnight GMT should have 2 events", async () => {
await helpers.startApplication("tests/configs/modules/calendar/exdate_la_at_midnight_dst.js", "19 Oct 2023 12:30:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles");
expect(global.page).not.toBeNull();
const loc = await global.page.locator(".calendar .event");
const elem = loc.first();
await elem.waitFor();
expect(elem).not.toBeNull();
const cnt = await loc.count();
expect(cnt).toBe(2);
});
});
/****************************/
// SYDNEY TESTS:
// In 2023, standard time (STD) (GMT+10) was until 1 Oct, after which is DST (GMT+11).
// Test takes place on Thu 14 Sep, recurring event on a Wednesday. maximumNumberOfDays=28, so there should be
// 4 events (20 Sep, 27 Sep, (switch to DST), 4 Oct, 11 Oct), but 27 Sep and 4 Oct are excluded.
// There are three separate tests:
// * before midnight GMT (9am local time)
// * at midnight GMT in STD time (10am local time)
// * at midnight GMT in DST time (11am local time)
describe("Exdate: SYD crossover DST before midnight GMT", () => {
it("LA crossover DST before midnight GMT should have 2 events", async () => {
await helpers.startApplication("tests/configs/modules/calendar/exdate_syd_before_midnight.js", "14 Sep 2023 12:30:00 GMT+10:00", ["js/electron.js"], "Australia/Sydney");
expect(global.page).not.toBeNull();
const loc = await global.page.locator(".calendar .event");
const elem = loc.first();
await elem.waitFor();
expect(elem).not.toBeNull();
const cnt = await loc.count();
expect(cnt).toBe(2);
});
});
describe("Exdate: SYD crossover DST at midnight GMT local STD", () => {
it("LA crossover DST before midnight GMT should have 2 events", async () => {
await helpers.startApplication("tests/configs/modules/calendar/exdate_syd_at_midnight_std.js", "14 Sep 2023 12:30:00 GMT+10:00", ["js/electron.js"], "Australia/Sydney");
expect(global.page).not.toBeNull();
const loc = await global.page.locator(".calendar .event");
const elem = loc.first();
await elem.waitFor();
expect(elem).not.toBeNull();
const cnt = await loc.count();
expect(cnt).toBe(2);
});
});
describe("Exdate: SYD crossover DST at midnight GMT local DST", () => {
it("SYD crossover DST at midnight GMT local DST should have 2 events", async () => {
await helpers.startApplication("tests/configs/modules/calendar/exdate_syd_at_midnight_dst.js", "14 Sep 2023 12:30:00 GMT+10:00", ["js/electron.js"], "Australia/Sydney");
expect(global.page).not.toBeNull();
const loc = await global.page.locator(".calendar .event");
const elem = loc.first();
await elem.waitFor();
expect(elem).not.toBeNull();
const cnt = await loc.count();
expect(cnt).toBe(2);
});
});
});

View File

@@ -1,34 +0,0 @@
BEGIN:VEVENT
DTSTART;TZID=UTC:20231025T181000
DTEND;TZID=UTC:20231025T195000
RRULE:FREQ=WEEKLY;BYDAY=WE
EXDATE;TZID=UTC:20231101T181000
EXDATE;TZID=UTC:20241030T181000
EXDATE;TZID=UTC:20251029T181000
EXDATE;TZID=UTC:20261028T181000
EXDATE;TZID=UTC:20271027T181000
EXDATE;TZID=UTC:20281025T181000
EXDATE;TZID=UTC:20291024T181000
EXDATE;TZID=UTC:20301023T181000
EXDATE;TZID=UTC:20311022T181000
EXDATE;TZID=UTC:20321020T181000
EXDATE;TZID=UTC:20331019T181000
EXDATE;TZID=UTC:20341018T181000
EXDATE;TZID=UTC:20351017T181000
EXDATE;TZID=UTC:20361015T181000
EXDATE;TZID=UTC:20371014T181000
EXDATE;TZID=UTC:20381013T181000
EXDATE;TZID=UTC:20391012T181000
EXDATE;TZID=UTC:20401010T181000
EXDATE;TZID=UTC:20411009T181000
EXDATE;TZID=UTC:20421008T181000
EXDATE;TZID=UTC:20431007T181000
DTSTAMP:20231025T233434Z
UID:sdflbkasuhdb5fkauglkb@google.com
CREATED:20230306T193128Z
LAST-MODIFIED:20231024T222515Z
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:My Event
TRANSP:OPAQUE
END:VEVENT

View File

@@ -0,0 +1,15 @@
BEGIN:VEVENT
DTSTART;TZID=America/Los_Angeles:20231025T170000
DTEND;TZID=America/Los_Angeles:20231025T180000
RRULE:FREQ=WEEKLY;BYDAY=WE
EXDATE;TZID=America/Los_Angeles:20231101T170000
EXDATE;TZID=America/Los_Angeles:20231108T170000
DTSTAMP:20231025T233434Z
UID:sdflbkasuhdb5fkauglkb@google.com
CREATED:20230306T193128Z
LAST-MODIFIED:20231024T222515Z
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:My Event
TRANSP:OPAQUE
END:VEVENT

View File

@@ -0,0 +1,15 @@
BEGIN:VEVENT
DTSTART;TZID=America/Los_Angeles:20231025T160000
DTEND;TZID=America/Los_Angeles:20231025T170000
RRULE:FREQ=WEEKLY;BYDAY=WE
EXDATE;TZID=America/Los_Angeles:20231101T160000
EXDATE;TZID=America/Los_Angeles:20231108T160000
DTSTAMP:20231025T233434Z
UID:sdflbkasuhdb5fkauglkb@google.com
CREATED:20230306T193128Z
LAST-MODIFIED:20231024T222515Z
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:My Event
TRANSP:OPAQUE
END:VEVENT

View File

@@ -0,0 +1,15 @@
BEGIN:VEVENT
DTSTART;TZID=America/Los_Angeles:20231025T150000
DTEND;TZID=America/Los_Angeles:20231025T160000
RRULE:FREQ=WEEKLY;BYDAY=WE
EXDATE;TZID=America/Los_Angeles:20231101T150000
EXDATE;TZID=America/Los_Angeles:20231108T150000
DTSTAMP:20231025T233434Z
UID:sdflbkasuhdb5fkauglkb@google.com
CREATED:20230306T193128Z
LAST-MODIFIED:20231024T222515Z
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:My Event
TRANSP:OPAQUE
END:VEVENT

View File

@@ -0,0 +1,15 @@
BEGIN:VEVENT
DTSTART;TZID=Australia/Sydney:20230920T110000
DTEND;TZID=Australia/Sydney:20230920T111000
RRULE:FREQ=WEEKLY;BYDAY=WE
EXDATE;TZID=Australia/Sydney:20230927T110000
EXDATE;TZID=Australia/Sydney:20231004T110000
DTSTAMP:20231025T233434Z
UID:sdflbkasuhdb5fkauglkb@google.com
CREATED:20230306T193128Z
LAST-MODIFIED:20231024T222515Z
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:My Event
TRANSP:OPAQUE
END:VEVENT

View File

@@ -0,0 +1,15 @@
BEGIN:VEVENT
DTSTART;TZID=Australia/Sydney:20230920T100000
DTEND;TZID=Australia/Sydney:20230920T110000
RRULE:FREQ=WEEKLY;BYDAY=WE
EXDATE;TZID=Australia/Sydney:20230927T100000
EXDATE;TZID=Australia/Sydney:20231004T100000
DTSTAMP:20231025T233434Z
UID:sdflbkasuhdb5fkauglkb@google.com
CREATED:20230306T193128Z
LAST-MODIFIED:20231024T222515Z
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:My Event
TRANSP:OPAQUE
END:VEVENT

View File

@@ -0,0 +1,15 @@
BEGIN:VEVENT
DTSTART;TZID=Australia/Sydney:20230920T090000
DTEND;TZID=Australia/Sydney:20230920T100000
RRULE:FREQ=WEEKLY;BYDAY=WE
EXDATE;TZID=Australia/Sydney:20230927T090000
EXDATE;TZID=Australia/Sydney:20231004T090000
DTSTAMP:20231025T233434Z
UID:sdflbkasuhdb5fkauglkb@google.com
CREATED:20230306T193128Z
LAST-MODIFIED:20231024T222515Z
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:My Event
TRANSP:OPAQUE
END:VEVENT