'use strict'; const assert = require('node:assert/strict'); const { buildOverview } = require('./days.js'); const ICS = `BEGIN:VCALENDAR VERSION:2.0 PRODID:-//test//test//EN BEGIN:VEVENT UID:standup-1@test DTSTAMP:20260101T000000Z DTSTART;TZID=UTC:20260105T090000 DTEND;TZID=UTC:20260105T093000 SUMMARY:Standup RRULE:FREQ=WEEKLY;BYDAY=MO;COUNT=5 EXDATE;TZID=UTC:20260119T090000 END:VEVENT BEGIN:VEVENT UID:standup-1@test RECURRENCE-ID;TZID=UTC:20260126T090000 DTSTAMP:20260101T000000Z DTSTART;TZID=UTC:20260127T140000 DTEND;TZID=UTC:20260127T143000 SUMMARY:Standup (moved) END:VEVENT BEGIN:VEVENT UID:trip-1@test DTSTAMP:20260101T000000Z DTSTART;VALUE=DATE:20260110 DTEND;VALUE=DATE:20260112 SUMMARY:💜 Weekend trip END:VEVENT BEGIN:VEVENT UID:flight-1@test DTSTAMP:20260101T000000Z DTSTART;TZID=UTC:20260106T100000 DTEND;TZID=UTC:20260106T103000 SUMMARY:✈️ Flight to Spain END:VEVENT BEGIN:VEVENT UID:party-1@test DTSTAMP:20260101T000000Z DTSTART;TZID=UTC:20260108T200000 DTEND;TZID=UTC:20260108T220000 SUMMARY:🎉 Party END:VEVENT BEGIN:VEVENT UID:combo-1@test DTSTAMP:20260101T000000Z DTSTART;TZID=UTC:20260115T090000 DTEND;TZID=UTC:20260115T093000 SUMMARY:✈️💜 Trip with Tessa END:VEVENT BEGIN:VEVENT UID:combo-2@test DTSTAMP:20260101T000000Z DTSTART;VALUE=DATE:20260122 DTEND;VALUE=DATE:20260123 SUMMARY:✈️ 💜 Madeira END:VEVENT END:VCALENDAR `; const tagsConfig = { '💜': { label: 'Partner Tessa', color: 'magenta' }, '✈️': { label: 'Holidays', color: 'aqua' }, }; const overview = buildOverview(ICS, tagsConfig, '2026-01-01', '2026-01-31'); // plain weekly recurrence: morning segment, untagged -> muted assert.deepEqual(overview['2026-01-05'].segments, ['muted', null, null]); assert.match(overview['2026-01-05'].tooltip, /09:00 Standup/); // EXDATE removes this occurrence entirely (nothing else touches this day) assert.equal(overview['2026-01-19'], undefined); // RECURRENCE-ID moved the Jan 26 occurrence away assert.equal(overview['2026-01-26'], undefined); // ...to Jan 27, 14:00 -> afternoon segment assert.deepEqual(overview['2026-01-27'].segments, [null, 'muted', null]); assert.match(overview['2026-01-27'].tooltip, /14:00 Standup \(moved\)/); // all-day multi-day event with a known leading emoji lights every segment, both spanned days assert.deepEqual(overview['2026-01-10'].segments, ['magenta', 'magenta', 'magenta']); assert.deepEqual(overview['2026-01-11'].segments, ['magenta', 'magenta', 'magenta']); assert.match(overview['2026-01-10'].tooltip, /All day 💜 Weekend trip/); // DTEND is exclusive: Jan 12 is NOT part of the trip, but it IS a Monday standup assert.deepEqual(overview['2026-01-12'].segments, ['muted', null, null]); // leading emoji that IS in tagsConfig takes that entry's color, not re-prefixed in tooltip assert.deepEqual(overview['2026-01-06'].segments, ['aqua', null, null]); assert.equal(overview['2026-01-06'].tooltip, '10:00 ✈️ Flight to Spain'); // leading emoji NOT in tagsConfig still stands out (not muted) via the fallback color assert.deepEqual(overview['2026-01-08'].segments, [null, null, 'blue']); assert.equal(overview['2026-01-08'].tooltip, '20:00 🎉 Party'); // two consecutive leading emoji (no space between) split the segment into both colors assert.deepEqual(overview['2026-01-15'].segments, [['aqua', 'magenta'], null, null]); assert.equal(overview['2026-01-15'].tooltip, '09:00 ✈️💜 Trip with Tessa'); // single-emoji case (Jan 6, asserted above) still resolves to a plain string, not an array — // the split path only triggers for a genuine two-emoji run. assert.equal(Array.isArray(overview['2026-01-06'].segments[0]), false); // two leading emoji WITH a space between them (how this calendar actually types combos) still split assert.deepEqual(overview['2026-01-22'].segments, [['aqua', 'magenta'], ['aqua', 'magenta'], ['aqua', 'magenta']]); assert.equal(overview['2026-01-22'].tooltip, 'All day ✈️ 💜 Madeira'); console.log('all assertions passed');