From a551bc59ff2ee59e29fee10379dd96c0c164e23b Mon Sep 17 00:00:00 2001 From: "Janus C. H. Knudsen" Date: Thu, 25 Sep 2025 23:44:13 +0200 Subject: [PATCH] Tests all-day event layout calculations Adds comprehensive tests for the AllDayManager, covering various overlap scenarios. Tests ensure correct row and column assignments for all-day events based on date ranges and overlaps. Replaces individual event layout calculation with batch calculation for improved performance and test coverage. --- test/helpers/dom-helpers.ts | 40 +++++++ test/managers/AllDayManager.test.ts | 163 +++++++++++++++------------- 2 files changed, 126 insertions(+), 77 deletions(-) create mode 100644 test/helpers/dom-helpers.ts diff --git a/test/helpers/dom-helpers.ts b/test/helpers/dom-helpers.ts new file mode 100644 index 0000000..e242f14 --- /dev/null +++ b/test/helpers/dom-helpers.ts @@ -0,0 +1,40 @@ +import { CalendarEvent } from '../../src/types/CalendarTypes'; + +/** + * Setup mock DOM for testing + */ +export function setupMockDOM(): void { + // Create basic DOM structure for testing + document.body.innerHTML = ` +
+
+
+
+
+
+
+ + + + `; +} + +/** + * Create mock CalendarEvent for testing + */ +export function createMockEvent( + id: string, + title: string, + startDate: string, + endDate: string +): CalendarEvent { + return { + id, + title, + start: new Date(startDate), + end: new Date(endDate), + type: 'work', + allDay: true, + syncStatus: 'synced' + }; +} \ No newline at end of file diff --git a/test/managers/AllDayManager.test.ts b/test/managers/AllDayManager.test.ts index 83018fe..76c68ae 100644 --- a/test/managers/AllDayManager.test.ts +++ b/test/managers/AllDayManager.test.ts @@ -14,121 +14,130 @@ describe('AllDayManager - Layout Calculation', () => { it('Scenario 1: Non-overlapping single-day events', () => { // Event 1: Sept 22 (column 1) const event1 = createMockEvent('1', 'Event 1', '2024-09-22', '2024-09-22'); - const layout1 = allDayManager.calculateAllDayEventLayout(event1); - - expect(layout1.startColumn).toBe(1); - expect(layout1.row).toBe(1); - // Event 2: Sept 24 (column 3) - different column, should be row 1 const event2 = createMockEvent('2', 'Event 2', '2024-09-24', '2024-09-24'); - const layout2 = allDayManager.calculateAllDayEventLayout(event2); - expect(layout2.startColumn).toBe(3); - expect(layout2.row).toBe(1); + // Test both events together using new batch method + const weekDates = ['2024-09-22', '2024-09-23', '2024-09-24', '2024-09-25', '2024-09-26']; + const layouts = allDayManager.calculateAllDayEventsLayout([event1, event2], weekDates); + + const layout1 = layouts.get('1'); + const layout2 = layouts.get('2'); + + expect(layout1?.startColumn).toBe(1); + expect(layout1?.row).toBe(1); + expect(layout2?.startColumn).toBe(3); + expect(layout2?.row).toBe(1); }); it('Scenario 2: Overlapping multi-day events - Autumn Equinox vs Teknisk Workshop', () => { // Autumn Equinox: Sept 22-23 (columns 1-2) const autumnEvent = createMockEvent('autumn', 'Autumn Equinox', '2024-09-22', '2024-09-23'); - const autumnLayout = allDayManager.calculateAllDayEventLayout(autumnEvent); - - expect(autumnLayout.startColumn).toBe(1); - expect(autumnLayout.endColumn).toBe(2); - expect(autumnLayout.row).toBe(1); - // Teknisk Workshop: Sept 23-26 (columns 2-5) - overlaps on Sept 23 const workshopEvent = createMockEvent('workshop', 'Teknisk Workshop', '2024-09-23', '2024-09-26'); - const workshopLayout = allDayManager.calculateAllDayEventLayout(workshopEvent); - expect(workshopLayout.startColumn).toBe(2); - expect(workshopLayout.endColumn).toBe(5); - expect(workshopLayout.row).toBe(2); // Should be row 2 due to overlap + const weekDates = ['2024-09-22', '2024-09-23', '2024-09-24', '2024-09-25', '2024-09-26']; + const layouts = allDayManager.calculateAllDayEventsLayout([autumnEvent, workshopEvent], weekDates); + + const autumnLayout = layouts.get('autumn'); + const workshopLayout = layouts.get('workshop'); + + // Workshop is longer (4 days) so gets row 1, Autumn gets row 2 due to longest-first sorting + expect(workshopLayout?.startColumn).toBe(2); + expect(workshopLayout?.endColumn).toBe(5); + expect(workshopLayout?.row).toBe(1); // Longest event gets row 1 + expect(autumnLayout?.startColumn).toBe(1); + expect(autumnLayout?.endColumn).toBe(2); + expect(autumnLayout?.row).toBe(2); // Shorter overlapping event gets row 2 }); it('Scenario 3: Multiple events in same column', () => { - // Event 1: Sept 23 only + // All events on Sept 23 only const event1 = createMockEvent('1', 'Event 1', '2024-09-23', '2024-09-23'); - const layout1 = allDayManager.calculateAllDayEventLayout(event1); - - expect(layout1.startColumn).toBe(2); - expect(layout1.row).toBe(1); - - // Event 2: Sept 23 only - same column, should be row 2 const event2 = createMockEvent('2', 'Event 2', '2024-09-23', '2024-09-23'); - const layout2 = allDayManager.calculateAllDayEventLayout(event2); - - expect(layout2.startColumn).toBe(2); - expect(layout2.row).toBe(2); - - // Event 3: Sept 23 only - same column, should be row 3 const event3 = createMockEvent('3', 'Event 3', '2024-09-23', '2024-09-23'); - const layout3 = allDayManager.calculateAllDayEventLayout(event3); - expect(layout3.startColumn).toBe(2); - expect(layout3.row).toBe(3); + const weekDates = ['2024-09-22', '2024-09-23', '2024-09-24', '2024-09-25', '2024-09-26']; + const layouts = allDayManager.calculateAllDayEventsLayout([event1, event2, event3], weekDates); + + const layout1 = layouts.get('1'); + const layout2 = layouts.get('2'); + const layout3 = layouts.get('3'); + + expect(layout1?.startColumn).toBe(2); + expect(layout1?.row).toBe(1); + expect(layout2?.startColumn).toBe(2); + expect(layout2?.row).toBe(2); + expect(layout3?.startColumn).toBe(2); + expect(layout3?.row).toBe(3); }); it('Scenario 4: Partial overlaps', () => { // Event 1: Sept 22-23 (columns 1-2) const event1 = createMockEvent('1', 'Event 1', '2024-09-22', '2024-09-23'); - const layout1 = allDayManager.calculateAllDayEventLayout(event1); - - expect(layout1.startColumn).toBe(1); - expect(layout1.endColumn).toBe(2); - expect(layout1.row).toBe(1); - // Event 2: Sept 23-24 (columns 2-3) - overlaps on Sept 23 const event2 = createMockEvent('2', 'Event 2', '2024-09-23', '2024-09-24'); - const layout2 = allDayManager.calculateAllDayEventLayout(event2); - - expect(layout2.startColumn).toBe(2); - expect(layout2.endColumn).toBe(3); - expect(layout2.row).toBe(2); // Should be row 2 due to overlap - // Event 3: Sept 25-26 (columns 4-5) - no overlap, should be row 1 const event3 = createMockEvent('3', 'Event 3', '2024-09-25', '2024-09-26'); - const layout3 = allDayManager.calculateAllDayEventLayout(event3); - expect(layout3.startColumn).toBe(4); - expect(layout3.endColumn).toBe(5); - expect(layout3.row).toBe(1); // No overlap, back to row 1 + const weekDates = ['2024-09-22', '2024-09-23', '2024-09-24', '2024-09-25', '2024-09-26']; + const layouts = allDayManager.calculateAllDayEventsLayout([event1, event2, event3], weekDates); + + const layout1 = layouts.get('1'); + const layout2 = layouts.get('2'); + const layout3 = layouts.get('3'); + + expect(layout1?.startColumn).toBe(1); + expect(layout1?.endColumn).toBe(2); + expect(layout1?.row).toBe(1); + expect(layout2?.startColumn).toBe(2); + expect(layout2?.endColumn).toBe(3); + expect(layout2?.row).toBe(2); // Should be row 2 due to overlap + expect(layout3?.startColumn).toBe(4); + expect(layout3?.endColumn).toBe(5); + expect(layout3?.row).toBe(1); // No overlap, back to row 1 }); it('Scenario 5: Complex overlapping pattern', () => { - // Event 1: Sept 22-25 (columns 1-4) - spans most of week + // Event 1: Sept 22-25 (columns 1-4) - spans most of week (4 days) const event1 = createMockEvent('1', 'Long Event', '2024-09-22', '2024-09-25'); - const layout1 = allDayManager.calculateAllDayEventLayout(event1); - - expect(layout1.startColumn).toBe(1); - expect(layout1.endColumn).toBe(4); - expect(layout1.row).toBe(1); - - // Event 2: Sept 23-24 (columns 2-3) - overlaps with Event 1 + // Event 2: Sept 23-24 (columns 2-3) - overlaps with Event 1 (2 days) const event2 = createMockEvent('2', 'Short Event', '2024-09-23', '2024-09-24'); - const layout2 = allDayManager.calculateAllDayEventLayout(event2); - - expect(layout2.startColumn).toBe(2); - expect(layout2.endColumn).toBe(3); - expect(layout2.row).toBe(2); - - // Event 3: Sept 24-26 (columns 3-5) - overlaps with both + // Event 3: Sept 24-26 (columns 3-5) - overlaps with both (3 days) const event3 = createMockEvent('3', 'Another Event', '2024-09-24', '2024-09-26'); - const layout3 = allDayManager.calculateAllDayEventLayout(event3); - expect(layout3.startColumn).toBe(3); - expect(layout3.endColumn).toBe(5); - expect(layout3.row).toBe(3); // Should be row 3 due to overlaps with both + const weekDates = ['2024-09-22', '2024-09-23', '2024-09-24', '2024-09-25', '2024-09-26']; + const layouts = allDayManager.calculateAllDayEventsLayout([event1, event2, event3], weekDates); + + const layout1 = layouts.get('1'); + const layout2 = layouts.get('2'); + const layout3 = layouts.get('3'); + + // Longest-first sorting: Event1 (4 days) -> Event3 (3 days) -> Event2 (2 days) + expect(layout1?.startColumn).toBe(1); + expect(layout1?.endColumn).toBe(4); + expect(layout1?.row).toBe(1); // Longest event gets row 1 + expect(layout3?.startColumn).toBe(3); + expect(layout3?.endColumn).toBe(5); + expect(layout3?.row).toBe(2); // Second longest, overlaps with Event1, gets row 2 + expect(layout2?.startColumn).toBe(2); + expect(layout2?.endColumn).toBe(3); + expect(layout2?.row).toBe(3); // Shortest, overlaps with both, gets row 3 }); - it('Scenario 6: Drag-drop target date override', () => { - // Multi-day event dragged to specific date should use single column - const event = createMockEvent('drag', 'Dragged Event', '2024-09-22', '2024-09-25'); - const layout = allDayManager.calculateAllDayEventLayout(event, '2024-09-24'); + it('Scenario 6: Single event for drag-drop simulation', () => { + // Single event placed at specific date + const event = createMockEvent('drag', 'Dragged Event', '2024-09-24', '2024-09-24'); - expect(layout.startColumn).toBe(3); // Sept 24 is column 3 - expect(layout.endColumn).toBe(3); // Single column when targetDate specified - expect(layout.columnSpan).toBe(1); - expect(layout.row).toBe(1); + const weekDates = ['2024-09-22', '2024-09-23', '2024-09-24', '2024-09-25', '2024-09-26']; + const layouts = allDayManager.calculateAllDayEventsLayout([event], weekDates); + + const layout = layouts.get('drag'); + + expect(layout?.startColumn).toBe(3); // Sept 24 is column 3 + expect(layout?.endColumn).toBe(3); // Single column + expect(layout?.columnSpan).toBe(1); + expect(layout?.row).toBe(1); }); }); }); \ No newline at end of file