Release 2.30.0 (#3673)

## [2.30.0] - 2025-01-01

Thanks to: @xsorifc28, @HeikoGr, @bugsounet, @khassel,
@KristjanESPERANTO, @rejas, @sdetweil.

> ⚠️ This release needs nodejs version `v20` or `v22 or higher`, minimum
version is `v20.18.1`

### Added

- [core] Add wayland and windows start options to `package.json` (#3594)
- [docs] Add step for npm publishing in release process (#3595)
- [core] Add GitHub workflow to run spellcheck a few days before each
release (#3623)
- [core] Add test flag to `index.html` to pass to module js for test
mode detection (needed by #3630)
- [core] Add export on animation names (#3644)
- [compliments] Add support for refreshing remote compliments file, and
test cases (#3630)
- [linter] Re-add `eslint-plugin-import`now that it supports ESLint v9
(#3586)
- [linter] Re-activate `eslint-plugin-package-json` to lint
`package.json` (#3643)
- [linter] Add linting for markdown files (#3646)
- [linter] Add some handy ESLint rules.
- [calendar] Add ability to display end date for full date events, where
end is not same day (showEnd=true) (#3650)
- [core] Add text to the config.js.sample file about the locale variable
(#3654, #3655)
- [core] Add fetch timeout for all node_helpers (thru undici, forces
node 20.18.1 minimum) to help on slower systems. (#3660) (3661)

### Changed

- [core] Run code style checks in workflow only once (#3648)
- [core] Fix animations export #3644 only on server side (#3649)
- [core] Use project URL in fallback config (#3656)
- [core] Fix Access Denied crash writing js/positions.js (on synology
nas) #3651. new message, MM starts, but no modules showing (#3652)
- [linter] Switch to 'npx' for lint-staged in pre-commit hook (#3658)

### Removed

- [tests] Remove `node-pty` and `drivelist` from rebuilded test (#3575)
- [deps] Remove `@eslint/js` dependency. Already installed with `eslint`
in deep (#3636)

### Updated

- [repo] Reactivate `stale.yaml` as GitHub action to mark issues as
stale after 60 days and close them 7 days later (if no activity) (#3577,
#3580, #3581)
- [core] Update electron dependency to v32 (test electron rebuild) and
all other dependencies too (#3657)
- [tests] All test configs have been updated to allow full external
access, allowing for easier debugging (especially when running as a
container)
- [core] Run and test with node 23 (#3588)
- [workflow] delete exception `allow-ghsas: GHSA-8hc4-vh64-cxmj` in
`dep-review.yaml` (#3659)

### Fixed

- [updatenotification] Fix pm2 using detection when pm2 script is inside
or outside MagicMirror root folder (#3576) (#3605) (#3626) (#3628)
- [core] Fix loading node_helper of modules: avoid black screen, display
errors and continue loading with next module (#3578)
- [weather] Change default value for weatherEndpoint of provider
openweathermap to "/onecall" (#3574)
- [tests] Fix electron tests with mock dates, the mock on server side
was missing (#3597)
- [tests] Fix testcases with hard coded Date.now (#3597)
- [core] Fix missing `basePath` where `location.host` is used (#3613)
- [compliments] croner library changed filenames used in latest version
(#3624)
- [linter] Fix ESLint ignore pattern which caused that default modules
not to be linted (#3632)
- [core] Fix module path in case of sub/sub folder is used and use
path.resolve for resolve `moduleFolder` and `defaultModuleFolder` in
app.js (#3653)
- [calendar] Update to resolve issues #3098 #3144 #3351 #3422 #3443
#3467 #3537 related to timezone changes
- [calendar] Fix #3267 (styles array), also fixes event with both exdate
AND recurrence(and testcase)
- [calendar] Fix showEndsOnlyWithDuration not working, #3598, applies
ONLY to full day events
- [calendar] Fix showEnd for Full Day events (#3602)
- [tests] Suppress "module is not defined" in e2e tests (#3647)
- [calendar] Fix #3267 (styles array, really this time!)
- [core] Fix #3662 js/positions.js created incorrectly

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Michael Teeuw <michael@xonaymedia.nl>
Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Karsten Hassel <hassel@gmx.de>
Co-authored-by: Ross Younger <crazyscot@gmail.com>
Co-authored-by: Veeck <github@veeck.de>
Co-authored-by: Bugsounet - Cédric <github@bugsounet.fr>
Co-authored-by: jkriegshauser <joshuakr@nvidia.com>
Co-authored-by: illimarkangur <116028111+illimarkangur@users.noreply.github.com>
Co-authored-by: vppencilsharpener <tim.pray@gmail.com>
Co-authored-by: veeck <michael.veeck@nebenan.de>
Co-authored-by: Paranoid93 <6515818+Paranoid93@users.noreply.github.com>
Co-authored-by: Brian O'Connor <btoconnor@users.noreply.github.com>
Co-authored-by: WallysWellies <59727507+WallysWellies@users.noreply.github.com>
Co-authored-by: Jason Stieber <jrstieber@gmail.com>
Co-authored-by: jargordon <50050429+jargordon@users.noreply.github.com>
Co-authored-by: Daniel <32464403+dkallen78@users.noreply.github.com>
Co-authored-by: Ryan Williams <65094007+ryan-d-williams@users.noreply.github.com>
Co-authored-by: Panagiotis Skias <panagiotis.skias@gmail.com>
Co-authored-by: Marc Landis <dirk.rettschlag@gmail.com>
Co-authored-by: HeikoGr <20295490+HeikoGr@users.noreply.github.com>
Co-authored-by: Pedro Lamas <pedrolamas@gmail.com>
Co-authored-by: veeck <gitkraken@veeck.de>
This commit is contained in:
sam detweiler
2025-01-01 08:27:27 -06:00
committed by GitHub
parent 94c3c699e8
commit c24de64d77
145 changed files with 4895 additions and 1915 deletions

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules:
// Using exotic content. This is why don't accept go to JSON configuration file
(() => {

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules: [
{
module: "alert",

View File

@@ -0,0 +1,35 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 24,
units: "metric",
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
fade: false,
hideDuplicates: false,
maximumEntries: 100,
urgency: 0,
dateFormat: "Do.MMM, HH:mm",
fullDayEventDateFormat: "Do.MMM",
timeFormat: "absolute",
getRelative: 0,
maximumNumberOfDays: 28,
calendars: [
{
maximumEntries: 100,
url: "http://localhost:8080/tests/mocks/3_move_first_allday_repeating_event.ics"
}
]
}
}
]
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
logLevel: ["INFO", "LOG", "WARN", "ERROR", "DEBUG"],
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -0,0 +1,33 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 24,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
fade: false,
urgency: 0,
dateFormat: "Do.MMM, HH:mm",
fullDayEventDateFormat: "Do.MMM",
timeFormat: "absolute",
getRelative: 0,
maximumNumberOfDays: 28,
showEnd: true,
calendars: [
{
maximumEntries: 100,
url: "http://localhost:8080/tests/mocks/end_of_day_berlin_moved.ics"
}
]
}
}
]
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -0,0 +1,33 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 24,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
fade: false,
urgency: 0,
dateFormat: "Do.MMM, HH:mm",
fullDayEventDateFormat: "Do.MMM",
timeFormat: "absolute",
getRelative: 0,
maximumNumberOfDays: 28,
showEnd: true,
calendars: [
{
maximumEntries: 100,
url: "http://localhost:8080/tests/mocks/RepeatingEvent.Oct21.ics"
}
]
}
}
]
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -0,0 +1,33 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 24,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
fade: false,
urgency: 0,
dateFormat: "Do.MMM, HH:mm",
fullDayEventDateFormat: "Do.MMM",
timeFormat: "absolute",
getRelative: 0,
maximumNumberOfDays: 28,
showEnd: true,
calendars: [
{
maximumEntries: 100,
url: "http://localhost:8080/tests/mocks/whole_day_moved_over_dst_change_berlin.ics"
}
]
}
}
]
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -0,0 +1,33 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 24,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
fade: false,
urgency: 0,
dateFormat: "Do.MMM, HH:mm",
fullDayEventDateFormat: "Do.MMM",
timeFormat: "absolute",
getRelative: 0,
maximumNumberOfDays: 20,
calendars: [
{
maximumEntries: 100,
//url: "http://localhost:8080/tests/mocks/chicago_late_in_timezone.ics"
url: "http://localhost:8080/tests/mocks/chicago_late_in_timezone.ics"
}
]
}
}
]
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [
@@ -11,6 +13,8 @@ let config = {
calendars: [
{
maximumEntries: 5,
pastDaysCount: 5,
broadcastPastEvents: true,
maximumNumberOfDays: 10000,
symbol: "birthday-cake",
fullDaySymbol: "calendar-day",

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -0,0 +1,34 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 24,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
fade: false,
urgency: 0,
dateFormat: "Do.MMM, HH:mm",
dateEndFormat: "Do.MMM, HH:mm",
fullDayEventDateFormat: "Do.MMM",
timeFormat: "absolute",
getRelative: 0,
maximumNumberOfDays: 28,
showEnd: true,
calendars: [
{
maximumEntries: 100,
url: "http://localhost:8080/tests/mocks/diff_tz_start_end.ics"
}
]
}
}
]
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -0,0 +1,33 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 24,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
fade: false,
urgency: 0,
dateFormat: "Do.MMM, HH:mm",
fullDayEventDateFormat: "Do.MMM",
timeFormat: "absolute",
getRelative: 0,
maximumNumberOfDays: 28,
showEnd: true,
calendars: [
{
maximumEntries: 100,
url: "http://localhost:8080/tests/mocks/end_of_day_berlin_moved.ics"
}
]
}
}
]
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -0,0 +1,33 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 24,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
fade: false,
urgency: 0,
dateFormat: "Do.MMM, HH:mm",
dateEndFormat: "Do.MMM, HH:mm",
fullDayEventDateFormat: "Do.MMM",
timeFormat: "absolute",
getRelative: 0,
showEnd: true,
calendars: [
{
maximumEntries: 100,
url: "http://localhost:8080/tests/mocks/event_with_time_over_multiple_days_non_repeating.ics"
}
]
}
}
]
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -0,0 +1,34 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 24,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
fade: false,
urgency: 0,
dateFormat: "Do.MMM, HH:mm",
dateEndFormat: "Do.MMM, HH:mm",
fullDayEventDateFormat: "Do.MMM",
timeFormat: "absolute",
getRelative: 0,
showEnd: true,
showEndsOnlyWithDuration: true,
calendars: [
{
maximumEntries: 100,
url: "http://localhost:8080/tests/mocks/event_with_time_over_multiple_days_non_repeating.ics"
}
]
}
}
]
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -0,0 +1,33 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 24,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
fade: false,
urgency: 0,
dateFormat: "Do.MMM, HH:mm",
fullDayEventDateFormat: "Do.MMM",
timeFormat: "absolute",
getRelative: 0,
maximumNumberOfDays: 28,
showEnd: true,
calendars: [
{
maximumEntries: 100,
url: "http://localhost:8080/tests/mocks/exdate_and_recurrence_together.ics"
}
]
}
}
]
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -8,6 +8,8 @@
* See tests/electron/modules/calendar_spec.js
*/
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [
@@ -28,10 +30,6 @@ let config = {
]
};
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

@@ -8,6 +8,8 @@
* See tests/electron/modules/calendar_spec.js
*/
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [
@@ -28,10 +30,6 @@ let config = {
]
};
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

@@ -8,6 +8,8 @@
* See tests/electron/modules/calendar_spec.js
*/
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [
@@ -28,10 +30,6 @@ let config = {
]
};
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

@@ -8,6 +8,8 @@
* See tests/electron/modules/calendar_spec.js
*/
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [
@@ -28,10 +30,6 @@ let config = {
]
};
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

@@ -8,6 +8,8 @@
* See tests/electron/modules/calendar_spec.js
*/
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [
@@ -28,10 +30,6 @@ let config = {
]
};
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

@@ -8,6 +8,8 @@
* See tests/electron/modules/calendar_spec.js
*/
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [
@@ -28,10 +30,6 @@ let config = {
]
};
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

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -0,0 +1,32 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 24,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
fade: false,
urgency: 0,
dateFormat: "Do.MMM, HH:mm",
fullDayEventDateFormat: "Do.MMM",
timeFormat: "absolute",
getRelative: 0,
showEnd: true,
calendars: [
{
maximumEntries: 100,
url: "http://localhost:8080/tests/mocks/fullday_event_over_multiple_days_nonrepeating.ics"
}
]
}
}
]
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -0,0 +1,33 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [
{
module: "calendar",
position: "bottom_bar",
config: {
hideDuplicates: false,
maximumEntries: 100,
sliceMultiDayEvents: true,
dateFormat: "MMM Do, HH:mm",
timeFormat: "absolute",
getRelative: 0,
urgency: 0,
calendars: [
{
maximumEntries: 100,
url: "http://localhost:8080/tests/mocks/germany_at_end_of_day_repeating.ics"
}
]
}
}
]
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;
}

View File

@@ -5,6 +5,8 @@
* MIT Licensed.
*/
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [
@@ -20,10 +22,6 @@ let config = {
]
};
Date.now = () => {
return new Date("07 Mar 2024 10:38:00 GMT-07:00").valueOf();
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -5,6 +5,8 @@
* MIT Licensed.
*/
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [
@@ -20,10 +22,6 @@ let config = {
]
};
Date.now = () => {
return new Date("01 Sept 2024 10:38:00 GMT+2:00").valueOf();
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") {
module.exports = config;

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules: [
{
module: "clock",

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules: [
{
module: "clock",

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
language: "es",
timeFormat: 12,

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
language: "es",
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
language: "es",
timeFormat: 12,

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
language: "es",
timeFormat: 12,

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules: [
{
module: "compliments",

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules: [
{
module: "compliments",

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules: [
{
module: "compliments",

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules: [
{
module: "compliments",

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules: [
{
module: "compliments",

View File

@@ -0,0 +1,17 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules: [
{
module: "compliments",
position: "bottom_bar",
config: {
updateInterval: 3000,
remoteFile: "http://localhost:8080/tests/mocks/compliments_test.json"
}
}
]
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") { module.exports = config; }

View File

@@ -0,0 +1,19 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules: [
{
module: "compliments",
position: "bottom_bar",
config: {
updateInterval: 3000,
remoteFileRefreshInterval: 1500,
remoteFile: "http://localhost:8080/tests/mocks/compliments_test.json",
remoteFile2: "http://localhost:8080/tests/mocks/compliments_file.json"
}
}
]
};
/*************** DO NOT EDIT THE LINE BELOW ***************/
if (typeof module !== "undefined") { module.exports = config; }

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules: [
{
module: "compliments",

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules: [
{
module: "compliments",

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules: [
{
module: "compliments",

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules: [
{
module: "helloworld",

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules: [
{
module: "helloworld",

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules: [
{
module: "helloworld",

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules:
// Using exotic content. This is why don't accept go to JSON configuration file
(() => {

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules: [
{
module: "compliments",
@@ -15,6 +17,8 @@ let config = {
position: "bottom_bar",
config: {
location: "Munich",
weatherProvider: "openweathermap",
weatherEndpoint: "/weather",
mockData: '"#####WEATHERDATA#####"'
}
}

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [
@@ -8,6 +10,8 @@ let config = {
config: {
location: "Munich",
showHumidity: "feelslike",
weatherProvider: "openweathermap",
weatherEndpoint: "/weather",
mockData: '"#####WEATHERDATA#####"'
}
}

View File

@@ -1,10 +1,14 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
modules: [
{
module: "weather",
position: "bottom_bar",
config: {
location: "Munich",
weatherProvider: "openweathermap",
weatherEndpoint: "/weather",
mockData: '"#####WEATHERDATA#####"',
windUnits: "beaufort",
showWindDirectionAsArrow: true,

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
units: "imperial",
modules: [
@@ -7,6 +9,8 @@ let config = {
position: "bottom_bar",
config: {
location: "Munich",
weatherProvider: "openweathermap",
weatherEndpoint: "/weather",
mockData: '"#####WEATHERDATA#####"',
decimalSymbol: ",",
showHumidity: "wind"

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [
@@ -8,8 +10,9 @@ let config = {
config: {
type: "forecast",
location: "Munich",
mockData: '"#####WEATHERDATA#####"',
weatherProvider: "openweathermap",
weatherEndpoint: "/forecast/daily",
mockData: '"#####WEATHERDATA#####"',
absoluteDates: true
}
}

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [
@@ -8,8 +10,9 @@ let config = {
config: {
type: "forecast",
location: "Munich",
mockData: '"#####WEATHERDATA#####"',
weatherEndpoint: "/forecast/daily"
weatherProvider: "openweathermap",
weatherEndpoint: "/forecast/daily",
mockData: '"#####WEATHERDATA#####"'
}
}
]

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [
@@ -8,8 +10,9 @@ let config = {
config: {
type: "forecast",
location: "Munich",
mockData: '"#####WEATHERDATA#####"',
weatherProvider: "openweathermap",
weatherEndpoint: "/forecast/daily",
mockData: '"#####WEATHERDATA#####"',
showPrecipitationAmount: true,
colored: true,
tableClass: "myTableClass"

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
units: "imperial",
modules: [
@@ -8,8 +10,9 @@ let config = {
config: {
type: "forecast",
location: "Munich",
mockData: '"#####WEATHERDATA#####"',
weatherProvider: "openweathermap",
weatherEndpoint: "/forecast/daily",
mockData: '"#####WEATHERDATA#####"',
decimalSymbol: "_",
showPrecipitationAmount: true
}

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [
@@ -8,6 +10,8 @@ let config = {
config: {
type: "hourly",
location: "Berlin",
weatherProvider: "openweathermap",
weatherEndpoint: "/onecall",
mockData: '"#####WEATHERDATA#####"'
}
}

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [
@@ -8,6 +10,8 @@ let config = {
config: {
type: "hourly",
location: "Berlin",
weatherProvider: "openweathermap",
weatherEndpoint: "/onecall",
mockData: '"#####WEATHERDATA#####"',
hourlyForecastIncrements: 2
}

View File

@@ -1,4 +1,6 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],
timeFormat: 12,
modules: [
@@ -8,6 +10,8 @@ let config = {
config: {
type: "hourly",
location: "Berlin",
weatherProvider: "openweathermap",
weatherEndpoint: "/onecall",
mockData: '"#####WEATHERDATA#####"',
showPrecipitationAmount: true,
showPrecipitationProbability: true

View File

@@ -1,5 +1,6 @@
let config = {
ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.10.1"]
address: "0.0.0.0",
ipWhitelist: []
};
/*************** DO NOT EDIT THE LINE BELOW ***************/

View File

@@ -26,6 +26,7 @@ exports.startApplication = async (configFilename, exec) => {
} else {
process.env.MM_CONFIG_FILE = configFilename;
}
process.env.mmTestMode = "true";
if (exec) exec;
global.app = require("../../../js/app");

View File

@@ -8,6 +8,7 @@ const mockError = (err) => {
|| err.includes("ECONNRESET")
|| err.includes("socket hang up")
|| err.includes("exports is not defined")
|| err.includes("module is not defined")
|| err.includes("write EPIPE")
|| err.includes("AggregateError")
|| err.includes("ERR_SOCKET_CONNECTION_TIMEOUT")

View File

@@ -89,4 +89,37 @@ describe("Compliments module", () => {
});
});
});
describe("Feature remote compliments file", () => {
describe("get list from remote file", () => {
beforeAll(async () => {
await helpers.startApplication("tests/configs/modules/compliments/compliments_file.js");
await helpers.getDocument();
});
it("shows 'Remote compliment file works!' as only anytime list set", async () => {
//await helpers.startApplication("tests/configs/modules/compliments/compliments_file.js", "01 Jan 2022 10:00:00 GMT");
await expect(doTest(["Remote compliment file works!"])).resolves.toBe(true);
});
// afterAll(async () =>{
// await helpers.stopApplication()
// });
});
describe("get list from remote file w update", () => {
beforeAll(async () => {
await helpers.startApplication("tests/configs/modules/compliments/compliments_file_change.js");
await helpers.getDocument();
});
it("shows 'test in morning' as test time set to 10am", async () => {
//await helpers.startApplication("tests/configs/modules/compliments/compliments_file_change.js", "01 Jan 2022 10:00:00 GMT");
await expect(doTest(["Remote compliment file works!"])).resolves.toBe(true);
await new Promise((r) => setTimeout(r, 10000));
await expect(doTest(["test in morning"])).resolves.toBe(true);
});
// afterAll(async () =>{
// await helpers.stopApplication()
// });
});
});
});

View File

@@ -15,9 +15,9 @@ describe("Check configuration without modules", () => {
expect(elem.textContent).toContain("MagicMirror²");
});
it("shows the url of michael's website", async () => {
it("shows the project URL", async () => {
const elem = await helpers.waitForElement("#module_5_helloworld .module-content");
expect(elem).not.toBeNull();
expect(elem.textContent).toContain("www.michaelteeuw.nl");
expect(elem.textContent).toContain("https://magicmirror.builders/");
});
});

View File

@@ -8,6 +8,11 @@ exports.startApplication = async (configFilename, systemDate = null, electronPar
global.page = null;
process.env.MM_CONFIG_FILE = configFilename;
process.env.TZ = timezone;
if (systemDate) {
process.env.MOCK_DATE = systemDate;
}
process.env.mmTestMode = "true";
global.electronApp = await electron.launch({ args: electronParams });
await global.electronApp.firstWindow();
@@ -34,6 +39,7 @@ exports.stopApplication = async () => {
}
global.electronApp = null;
global.page = null;
process.env.MOCK_DATE = undefined;
};
exports.getElement = async (selector) => {

View File

@@ -22,6 +22,21 @@ describe("Calendar module", () => {
return await loc.count();
};
const first = 0;
const second = 1;
const third = 2;
const last = -1;
// get results of table row and column, can select specific row of results,
// row is 0 based index -1 is last, 0 is first... need 10th(human count), use 9 as row
// uses playwright nth locator syntax
const doTestTableContent = async (table_row, table_column, content, row = first) => {
const elem = await global.page.locator(table_row);
const date = await global.page.locator(table_column).locator(`nth=${row}`);
await expect(date.textContent()).resolves.toContain(content);
return true;
};
afterEach(async () => {
await helpers.stopApplication();
});
@@ -147,4 +162,121 @@ describe("Calendar module", () => {
});
});
describe("sliceMultiDayEvents direct count", () => {
it("Issue #3452 split multiday in Europe", async () => {
await helpers.startApplication("tests/configs/modules/calendar/sliceMultiDayEvents.js", "01 Sept 2024 10:38:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin");
await expect(doTestCount()).resolves.toBe(6);
});
});
describe("germany timezone", () => {
it("Issue #unknown fullday timezone East of UTC edge", async () => {
await helpers.startApplication("tests/configs/modules/calendar/germany_at_end_of_day_repeating.js", "01 Oct 2024 10:38:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin");
await expect(doTestTableContent(".calendar .event", ".time", "Oct 22nd, 23:00", first)).resolves.toBe(true);
});
});
describe("germany all day repeating moved (recurrence and exdate)", () => {
it("Issue #unknown fullday timezone East of UTC event moved", async () => {
await helpers.startApplication("tests/configs/modules/calendar/3_move_first_allday_repeating_event.js", "01 Oct 2024 10:38:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin");
await expect(doTestTableContent(".calendar .event", ".time", "12th.Oct")).resolves.toBe(true);
});
});
describe("chicago late in timezone", () => {
it("Issue #unknown rrule US close to timezone edge", async () => {
await helpers.startApplication("tests/configs/modules/calendar/chicago_late_in_timezone.js", "01 Sept 2024 10:38:00 GMT-5:00", ["js/electron.js"], "America/Chicago");
await expect(doTestTableContent(".calendar .event", ".time", "10th.Sep, 20:15")).resolves.toBe(true);
});
});
describe("berlin late in day event moved, viewed from berlin", () => {
it("Issue #unknown rrule ETC+2 close to timezone edge", async () => {
await helpers.startApplication("tests/configs/modules/calendar/end_of_day_berlin_moved.js", "08 Oct 2024 12:30:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin");
await expect(doTestTableContent(".calendar .event", ".time", "24th.Oct, 23:00-00:00", last)).resolves.toBe(true);
});
});
describe("berlin late in day event moved, viewed from sydney", () => {
it("Issue #unknown rrule ETC+2 close to timezone edge", async () => {
await helpers.startApplication("tests/configs/modules/calendar/end_of_day_berlin_moved.js", "08 Oct 2024 12:30:00 GMT+02:00", ["js/electron.js"], "Australia/Sydney");
await expect(doTestTableContent(".calendar .event", ".time", "25th.Oct, 01:00-02:00", last)).resolves.toBe(true);
});
});
describe("berlin late in day event moved, viewed from chicago", () => {
it("Issue #unknown rrule ETC+2 close to timezone edge", async () => {
await helpers.startApplication("tests/configs/modules/calendar/end_of_day_berlin_moved.js", "08 Oct 2024 12:30:00 GMT+02:00", ["js/electron.js"], "America/Chicago");
await expect(doTestTableContent(".calendar .event", ".time", "24th.Oct, 16:00-17:00", last)).resolves.toBe(true);
});
});
describe("berlin multi-events inside offset", () => {
it("some events before DST. some after midnight", async () => {
await helpers.startApplication("tests/configs/modules/calendar/berlin_multi.js", "08 Oct 2024 12:30:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin");
await expect(doTestTableContent(".calendar .event", ".time", "30th.Oct, 00:00-01:00", last)).resolves.toBe(true);
await expect(doTestTableContent(".calendar .event", ".time", "21st.Oct, 00:00-01:00", first)).resolves.toBe(true);
});
});
describe("berlin whole day repeating, start moved after end", () => {
it("some events before DST. some after", async () => {
await helpers.startApplication("tests/configs/modules/calendar/berlin_whole_day_event_moved_over_dst_change.js", "08 Oct 2024 12:30:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin");
await expect(doTestTableContent(".calendar .event", ".time", "30th.Oct", last)).resolves.toBe(true);
await expect(doTestTableContent(".calendar .event", ".time", "27th.Oct", first)).resolves.toBe(true);
});
});
describe("berlin 11pm-midnight", () => {
it("right inside the offset, before midnight", async () => {
await helpers.startApplication("tests/configs/modules/calendar/berlin_end_of_day_repeating.js", "08 Oct 2024 12:30:00 GMT+02:00", ["js/electron.js"], "Europe/Berlin");
await expect(doTestTableContent(".calendar .event", ".time", "24th.Oct, 23:00-00:00", last)).resolves.toBe(true);
await expect(doTestTableContent(".calendar .event", ".time", "22nd.Oct, 23:00-00:00", first)).resolves.toBe(true);
});
});
describe("both moved and delete events in recurring list", () => {
it("with moved before and after original", async () => {
await helpers.startApplication("tests/configs/modules/calendar/exdate_and_recurrence_together.js", "08 Oct 2024 12:30:00 GMT-07:00", ["js/electron.js"], "America/Los_Angeles");
// moved after end at oct 26
await expect(doTestTableContent(".calendar .event", ".time", "27th.Oct, 14:30-15:30", last)).resolves.toBe(true);
// moved before start at oct 23
await expect(doTestTableContent(".calendar .event", ".time", "22nd.Oct, 14:30-15:30", first)).resolves.toBe(true);
// remaining original 4th, now 3rd
await expect(doTestTableContent(".calendar .event", ".time", "26th.Oct, 14:30-15:30", second)).resolves.toBe(true);
});
});
describe("one event diff tz", () => {
it("start/end in diff timezones", async () => {
await helpers.startApplication("tests/configs/modules/calendar/diff_tz_start_end.js", "08 Oct 2024 12:30:00 GMT-07:00", ["js/electron.js"], "America/Chicago");
// just
await expect(doTestTableContent(".calendar .event", ".time", "29th.Oct, 05:00-30th.Oct, 18:00", first)).resolves.toBe(true);
});
});
describe("one event non repeating", () => {
it("fullday non-repeating", async () => {
await helpers.startApplication("tests/configs/modules/calendar/fullday_event_over_multiple_days_nonrepeating.js", "08 Oct 2024 12:30:00 GMT-07:00", ["js/electron.js"], "America/Chicago");
// just
await expect(doTestTableContent(".calendar .event", ".time", "25th.Oct-30th.Oct", first)).resolves.toBe(true);
});
});
describe("one event no end display", () => {
it("don't display end", async () => {
await helpers.startApplication("tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_no_display_end.js", "08 Oct 2024 12:30:00 GMT-07:00", ["js/electron.js"], "America/Chicago");
// just
await expect(doTestTableContent(".calendar .event", ".time", "25th.Oct, 20:00", first)).resolves.toBe(true);
});
});
describe("display end display end", () => {
it("display end", async () => {
await helpers.startApplication("tests/configs/modules/calendar/event_with_time_over_multiple_days_non_repeating_display_end.js", "08 Oct 2024 12:30:00 GMT-07:00", ["js/electron.js"], "America/Chicago");
// just
await expect(doTestTableContent(".calendar .event", ".time", "25th.Oct, 20:00-26th.Oct, 06:00", first)).resolves.toBe(true);
});
});
});

View File

@@ -78,6 +78,22 @@ describe("Compliments module", () => {
await expect(doTest(["just a test"])).resolves.toBe(true);
});
});
});
describe("Feature remote compliments file", () => {
describe("get list from remote file", () => {
it("shows 'Remote compliment file works!' as only anytime list set", async () => {
await helpers.startApplication("tests/configs/modules/compliments/compliments_file.js", "01 Jan 2022 10:00:00 GMT");
await expect(doTest(["Remote compliment file works!"])).resolves.toBe(true);
});
});
describe("get updated list from remote file", () => {
it("shows 'test in morning'", async () => {
await helpers.startApplication("tests/configs/modules/compliments/compliments_file_change.js", "01 Jan 2022 10:00:00 GMT");
await expect(doTest(["Remote compliment file works!"])).resolves.toBe(true);
await new Promise((r) => setTimeout(r, 10000));
await expect(doTest(["test in morning"])).resolves.toBe(true);
});
});
});
});

View File

@@ -0,0 +1,35 @@
BEGIN:VCALENDAR
PRODID:-//Google Inc//Google Calendar 70.9054//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:TestCal
X-WR-TIMEZONE:Europe/Berlin
X-WR-CALDESC:Calendar for testing purposes
BEGIN:VEVENT
DTSTART;VALUE=DATE:20241011
DTEND;VALUE=DATE:20241012
RRULE:FREQ=WEEKLY;WKST=MO;COUNT=5;BYDAY=FR
DTSTAMP:20241009T153220Z
UID:2m6mt1p89l2anl74915ur3hsgm@google.com
CREATED:20241009T153058Z
LAST-MODIFIED:20241009T153205Z
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:TestCal_AllDayRepeatingEvent
TRANSP:TRANSPARENT
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20241012
DTEND;VALUE=DATE:20241013
DTSTAMP:20241009T153220Z
UID:2m6mt1p89l2anl74915ur3hsgm@google.com
RECURRENCE-ID;VALUE=DATE:20241011
CREATED:20241009T153058Z
LAST-MODIFIED:20241009T153205Z
SEQUENCE:1
STATUS:CONFIRMED
SUMMARY:TestCal_AllDayRepeatingEvent
TRANSP:TRANSPARENT
END:VEVENT
END:VCALENDAR

View File

@@ -0,0 +1,28 @@
BEGIN:VCALENDAR
BEGIN:VEVENT
DTSTART;TZID=Europe/Berlin:20241028T000000
DTEND;TZID=Europe/Berlin:20241028T010000
RRULE:FREQ=DAILY;COUNT=3
DTSTAMP:20241020T093758Z
UID:053fdshnnibo92lu97rsoeqoti@google.com
CREATED:20241020T093230Z
LAST-MODIFIED:20241020T093230Z
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:RepeatingEventWeekAfterToday
TRANSP:OPAQUE
END:VEVENT
BEGIN:VEVENT
DTSTART;TZID=Europe/Berlin:20241021T000000
DTEND;TZID=Europe/Berlin:20241021T010000
RRULE:FREQ=DAILY;COUNT=3
DTSTAMP:20241020T093758Z
UID:1a6kk47pp61k4td2h9rlf0lv69@google.com
CREATED:20241020T093255Z
LAST-MODIFIED:20241020T093437Z
SEQUENCE:1
STATUS:CONFIRMED
SUMMARY:RepeatingEventDayAfterToday
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR

View File

@@ -0,0 +1,15 @@
BEGIN:VEVENT
CREATED:20240904T053053Z
DTEND;TZID=America/Chicago:20240910T211500
DTSTAMP:20240925T005517Z
DTSTART;TZID=America/Chicago:20240910T201500
LAST-MODIFIED:20240925T005515Z
LOCATION:Dance Class
RELATED-TO;RELTYPE=X-CALENDARSERVER-RECURRENCE-SET:2D48CA37-FCE5-4E16-871
9-1F47160BDBA3
RRULE:FREQ=WEEKLY;UNTIL=20250601T011500Z
SEQUENCE:3
SUMMARY:Wife Barre Class
UID:39669340-7AFD-4685-9BD6-6CE4B715486E
X-APPLE-CREATOR-IDENTITY:com.apple.mobilecal
END:VEVENT

View File

@@ -0,0 +1,3 @@
{
"anytime": ["test in morning"]
}

View File

@@ -0,0 +1,14 @@
BEGIN:VCALENDAR
BEGIN:VEVENT
DTSTART:20241029T100000Z
DTEND:20241030T230000Z
DTSTAMP:20241022T203806Z
UID:04ivnntdi20rqsk0iesabsdhmj@google.com
CREATED:20241022T203738Z
LAST-MODIFIED:20241022T203738Z
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:start/end on diff tz
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR

View File

@@ -0,0 +1,54 @@
BEGIN:VCALENDAR
PRODID:-//Google Inc//Google Calendar 70.9054//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:test for mirror
X-WR-TIMEZONE:America/Chicago
X-WR-CALDESC:used to test mirror
BEGIN:VTIMEZONE
TZID:Europe/Berlin
X-LIC-LOCATION:Europe/Berlin
BEGIN:DAYLIGHT
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
TZNAME:GMT+2
DTSTART:19700329T020000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
TZNAME:GMT+1
DTSTART:19701025T030000
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
DTSTART;TZID=Europe/Berlin:20241021T230000
DTEND;TZID=Europe/Berlin:20241022T000000
RRULE:FREQ=DAILY;WKST=SU;COUNT=3
DTSTAMP:20241019T133432Z
UID:0kj3dtvgskhhpli1392n111145@google.com
CREATED:20241018T213040Z
LAST-MODIFIED:20241018T213126Z
SEQUENCE:1
STATUS:CONFIRMED
SUMMARY:test
TRANSP:OPAQUE
END:VEVENT
BEGIN:VEVENT
DTSTART;TZID=Europe/Berlin:20241024T230000
DTEND;TZID=Europe/Berlin:20241025T000000
DTSTAMP:20241019T133432Z
UID:0kj3dtvgskhhpli1392n111145@google.com
RECURRENCE-ID;TZID=Europe/Berlin:20241021T230000
CREATED:20241018T213040Z
LAST-MODIFIED:20241018T213126Z
SEQUENCE:2
STATUS:CONFIRMED
SUMMARY:test
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR

View File

@@ -0,0 +1,14 @@
BEGIN:VCALENDAR
BEGIN:VEVENT
DTSTART:20241026T010000Z
DTEND:20241026T110000Z
DTSTAMP:20241024T153358Z
UID:4maud6s79m41a99pj2g7j5km0a@google.com
CREATED:20241024T153313Z
LAST-MODIFIED:20241024T153330Z
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:Sleep over at Bobs
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR

View File

@@ -0,0 +1,48 @@
BEGIN:VCALENDAR
BEGIN:VEVENT
DTSTART;TZID=America/Los_Angeles:20241023T143000
DTEND;TZID=America/Los_Angeles:20241023T153000
RRULE:FREQ=DAILY;COUNT=4
EXDATE;TZID=America/Los_Angeles:20241025T143000
DTSTAMP:20241021T193426Z
UID:18rd721lfqpue2o08icsqek198@google.com
CREATED:20241021T192450Z
DESCRIPTION:we will move one entry and delete another  ending w 3 of the 4 
start/end\, middle moved after end and 3rd deleted
LAST-MODIFIED:20241021T193419Z
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:recurrence and exclusion together
TRANSP:OPAQUE
END:VEVENT
BEGIN:VEVENT
DTSTART;TZID=America/Los_Angeles:20241022T143000
DTEND;TZID=America/Los_Angeles:20241022T153000
DTSTAMP:20241021T193426Z
UID:18rd721lfqpue2o08icsqek198@google.com
RECURRENCE-ID;TZID=America/Los_Angeles:20241023T143000
CREATED:20241021T192450Z
DESCRIPTION:we will move one entry and delete another  ending w 3 of the 4 
start/end\, middle moved after end and 3rd deleted
LAST-MODIFIED:20241021T193419Z
SEQUENCE:1
STATUS:CONFIRMED
SUMMARY:recurrence and exclusion together
TRANSP:OPAQUE
END:VEVENT
BEGIN:VEVENT
DTSTART;TZID=America/Los_Angeles:20241027T143000
DTEND;TZID=America/Los_Angeles:20241027T153000
DTSTAMP:20241021T193426Z
UID:18rd721lfqpue2o08icsqek198@google.com
RECURRENCE-ID;TZID=America/Los_Angeles:20241024T143000
CREATED:20241021T192450Z
DESCRIPTION:we will move one entry and delete another  ending w 3 of the 4 
start/end\, middle moved after end and 3rd deleted
LAST-MODIFIED:20241021T193419Z
SEQUENCE:1
STATUS:CONFIRMED
SUMMARY:recurrence and exclusion together
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR

View File

@@ -0,0 +1,15 @@
BEGIN:VCALENDAR
BEGIN:VEVENT
DTSTART;VALUE=DATE:20241025
DTEND;VALUE=DATE:20241031
DTSTAMP:20241023T141110Z
UID:60nobfcu0ct96jgsh5nhcia24b@google.com
CREATED:20241023T141019Z
DESCRIPTION:test for all day end viewing
LAST-MODIFIED:20241023T141019Z
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:simple all day event over many days (not repeating)
TRANSP:TRANSPARENT
END:VEVENT
END:VCALENDAR

View File

@@ -0,0 +1,15 @@
BEGIN:VCALENDAR
BEGIN:VEVENT
DTSTART;TZID=Europe/Berlin:20241022T230000
DTEND;TZID=Europe/Berlin:20241023T000000
RRULE:FREQ=DAILY;WKST=MO;COUNT=4
DTSTAMP:20241009T153220Z
UID:2m6mt1p89l2anl74915ur3hsgm@google.com
CREATED:20241009T153058Z
LAST-MODIFIED:20241009T153205Z
SEQUENCE:0
STATUS:CONFIRMED
SUMMARY:TestCal_AllDayRepeatingEvent
TRANSP:TRANSPARENT
END:VEVENT
END:VCALENDAR

View File

@@ -0,0 +1,28 @@
BEGIN:VCALENDAR
BEGIN:VEVENT
DTSTART;VALUE=DATE:20241027
DTEND;VALUE=DATE:20241028
RRULE:FREQ=DAILY;WKST=SU;COUNT=3
DTSTAMP:20241020T152634Z
UID:14nv8jl8d6dvdbl477lod4fftf@google.com
CREATED:20241020T152434Z
LAST-MODIFIED:20241020T152536Z
SEQUENCE:1
STATUS:CONFIRMED
SUMMARY:test whole day moved
TRANSP:TRANSPARENT
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20241030
DTEND;VALUE=DATE:20241031
DTSTAMP:20241020T152634Z
UID:14nv8jl8d6dvdbl477lod4fftf@google.com
RECURRENCE-ID;VALUE=DATE:20241028
CREATED:20241020T152434Z
LAST-MODIFIED:20241020T152536Z
SEQUENCE:2
STATUS:CONFIRMED
SUMMARY:test whole day moved
TRANSP:TRANSPARENT
END:VEVENT
END:VCALENDAR