cleanup
This commit is contained in:
parent
faa59f6a3c
commit
69495ce00f
9 changed files with 337 additions and 1306 deletions
|
|
@ -1,287 +0,0 @@
|
|||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import { OverlapDetector } from '../../src/utils/OverlapDetector';
|
||||
import { CalendarEvent } from '../../src/types/CalendarTypes';
|
||||
|
||||
describe('OverlapDetector', () => {
|
||||
let detector: OverlapDetector;
|
||||
|
||||
beforeEach(() => {
|
||||
detector = new OverlapDetector();
|
||||
});
|
||||
|
||||
// Helper function to create test events
|
||||
const createEvent = (id: string, startHour: number, startMin: number, endHour: number, endMin: number): CalendarEvent => {
|
||||
const start = new Date(2024, 0, 1, startHour, startMin);
|
||||
const end = new Date(2024, 0, 1, endHour, endMin);
|
||||
return {
|
||||
id,
|
||||
title: `Event ${id}`,
|
||||
start,
|
||||
end,
|
||||
type: 'meeting',
|
||||
allDay: false,
|
||||
syncStatus: 'synced'
|
||||
};
|
||||
};
|
||||
|
||||
describe('resolveOverlap', () => {
|
||||
it('should detect no overlap when events do not overlap', () => {
|
||||
const event1 = createEvent('1', 9, 0, 10, 0); // 09:00-10:00
|
||||
const event2 = createEvent('2', 10, 0, 11, 0); // 10:00-11:00
|
||||
|
||||
const overlaps = detector.resolveOverlap(event1, [event2]);
|
||||
|
||||
expect(overlaps).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should detect overlap when events partially overlap', () => {
|
||||
const event1 = createEvent('1', 9, 0, 10, 30); // 09:00-10:30
|
||||
const event2 = createEvent('2', 10, 0, 11, 0); // 10:00-11:00
|
||||
|
||||
const overlaps = detector.resolveOverlap(event1, [event2]);
|
||||
|
||||
expect(overlaps).toHaveLength(1);
|
||||
expect(overlaps[0].id).toBe('2');
|
||||
});
|
||||
|
||||
it('should detect overlap when one event contains another', () => {
|
||||
const event1 = createEvent('1', 9, 0, 12, 0); // 09:00-12:00
|
||||
const event2 = createEvent('2', 10, 0, 11, 0); // 10:00-11:00
|
||||
|
||||
const overlaps = detector.resolveOverlap(event1, [event2]);
|
||||
|
||||
expect(overlaps).toHaveLength(1);
|
||||
expect(overlaps[0].id).toBe('2');
|
||||
});
|
||||
|
||||
it('should detect overlap when events have same start time', () => {
|
||||
const event1 = createEvent('1', 9, 0, 10, 0); // 09:00-10:00
|
||||
const event2 = createEvent('2', 9, 0, 10, 30); // 09:00-10:30
|
||||
|
||||
const overlaps = detector.resolveOverlap(event1, [event2]);
|
||||
|
||||
expect(overlaps).toHaveLength(1);
|
||||
expect(overlaps[0].id).toBe('2');
|
||||
});
|
||||
|
||||
it('should detect overlap when events have same end time', () => {
|
||||
const event1 = createEvent('1', 9, 0, 10, 0); // 09:00-10:00
|
||||
const event2 = createEvent('2', 9, 30, 10, 0); // 09:30-10:00
|
||||
|
||||
const overlaps = detector.resolveOverlap(event1, [event2]);
|
||||
|
||||
expect(overlaps).toHaveLength(1);
|
||||
expect(overlaps[0].id).toBe('2');
|
||||
});
|
||||
|
||||
it('should detect multiple overlapping events', () => {
|
||||
const event1 = createEvent('1', 9, 0, 11, 0); // 09:00-11:00
|
||||
const event2 = createEvent('2', 9, 30, 10, 30); // 09:30-10:30
|
||||
const event3 = createEvent('3', 10, 0, 11, 30); // 10:00-11:30
|
||||
const event4 = createEvent('4', 12, 0, 13, 0); // 12:00-13:00 (no overlap)
|
||||
|
||||
const overlaps = detector.resolveOverlap(event1, [event2, event3, event4]);
|
||||
|
||||
expect(overlaps).toHaveLength(2);
|
||||
expect(overlaps.map(e => e.id)).toEqual(['2', '3']);
|
||||
});
|
||||
|
||||
it('should handle edge case where event ends exactly when another starts', () => {
|
||||
const event1 = createEvent('1', 9, 0, 10, 0); // 09:00-10:00
|
||||
const event2 = createEvent('2', 10, 0, 11, 0); // 10:00-11:00
|
||||
|
||||
const overlaps = detector.resolveOverlap(event1, [event2]);
|
||||
|
||||
// Events that touch at boundaries should NOT overlap
|
||||
expect(overlaps).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should handle events with 1-minute overlap', () => {
|
||||
const event1 = createEvent('1', 9, 0, 10, 1); // 09:00-10:01
|
||||
const event2 = createEvent('2', 10, 0, 11, 0); // 10:00-11:00
|
||||
|
||||
const overlaps = detector.resolveOverlap(event1, [event2]);
|
||||
|
||||
expect(overlaps).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('decorateWithStackLinks', () => {
|
||||
it('should return empty result when no overlapping events', () => {
|
||||
const event1 = createEvent('1', 9, 0, 10, 0);
|
||||
|
||||
const result = detector.decorateWithStackLinks(event1, []);
|
||||
|
||||
expect(result.overlappingEvents).toHaveLength(0);
|
||||
expect(result.stackLinks.size).toBe(0);
|
||||
});
|
||||
|
||||
it('should assign stack levels based on start time order', () => {
|
||||
const event1 = createEvent('1', 9, 0, 10, 30); // 09:00-10:30
|
||||
const event2 = createEvent('2', 9, 30, 11, 0); // 09:30-11:00
|
||||
|
||||
const result = detector.decorateWithStackLinks(event1, [event2]);
|
||||
|
||||
expect(result.stackLinks.size).toBe(2);
|
||||
|
||||
const link1 = result.stackLinks.get('1' as any);
|
||||
const link2 = result.stackLinks.get('2' as any);
|
||||
|
||||
expect(link1?.stackLevel).toBe(0);
|
||||
expect(link1?.prev).toBeUndefined();
|
||||
expect(link1?.next).toBe('2');
|
||||
|
||||
expect(link2?.stackLevel).toBe(1);
|
||||
expect(link2?.prev).toBe('1');
|
||||
expect(link2?.next).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should create linked chain for multiple overlapping events', () => {
|
||||
const event1 = createEvent('1', 9, 0, 11, 0); // 09:00-11:00
|
||||
const event2 = createEvent('2', 9, 30, 10, 30); // 09:30-10:30
|
||||
const event3 = createEvent('3', 10, 0, 11, 30); // 10:00-11:30
|
||||
|
||||
const result = detector.decorateWithStackLinks(event1, [event2, event3]);
|
||||
|
||||
expect(result.stackLinks.size).toBe(3);
|
||||
|
||||
const link1 = result.stackLinks.get('1' as any);
|
||||
const link2 = result.stackLinks.get('2' as any);
|
||||
const link3 = result.stackLinks.get('3' as any);
|
||||
|
||||
// Check chain: 1 -> 2 -> 3
|
||||
expect(link1?.stackLevel).toBe(0);
|
||||
expect(link1?.prev).toBeUndefined();
|
||||
expect(link1?.next).toBe('2');
|
||||
|
||||
expect(link2?.stackLevel).toBe(1);
|
||||
expect(link2?.prev).toBe('1');
|
||||
expect(link2?.next).toBe('3');
|
||||
|
||||
expect(link3?.stackLevel).toBe(2);
|
||||
expect(link3?.prev).toBe('2');
|
||||
expect(link3?.next).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should handle events with same start time', () => {
|
||||
const event1 = createEvent('1', 9, 0, 10, 0); // 09:00-10:00
|
||||
const event2 = createEvent('2', 9, 0, 10, 30); // 09:00-10:30
|
||||
|
||||
const result = detector.decorateWithStackLinks(event1, [event2]);
|
||||
|
||||
const link1 = result.stackLinks.get('1' as any);
|
||||
const link2 = result.stackLinks.get('2' as any);
|
||||
|
||||
// Both start at same time - order may vary but levels should be 0 and 1
|
||||
const levels = [link1?.stackLevel, link2?.stackLevel].sort();
|
||||
expect(levels).toEqual([0, 1]);
|
||||
|
||||
// Verify they are linked together
|
||||
expect(result.stackLinks.size).toBe(2);
|
||||
});
|
||||
|
||||
it('KNOWN ISSUE: should NOT stack events that do not overlap', () => {
|
||||
// This test documents the current bug
|
||||
const event1 = createEvent('1', 9, 0, 10, 0); // 09:00-10:00
|
||||
const event2 = createEvent('2', 9, 30, 10, 30); // 09:30-10:30 (overlaps with 1)
|
||||
const event3 = createEvent('3', 11, 0, 12, 0); // 11:00-12:00 (NO overlap with 1 or 2)
|
||||
|
||||
const result = detector.decorateWithStackLinks(event1, [event2, event3]);
|
||||
|
||||
const link3 = result.stackLinks.get('3' as any);
|
||||
|
||||
// CURRENT BEHAVIOR (BUG): Event 3 gets stackLevel 2
|
||||
expect(link3?.stackLevel).toBe(2);
|
||||
|
||||
// EXPECTED BEHAVIOR: Event 3 should get stackLevel 0 since it doesn't overlap
|
||||
// expect(link3?.stackLevel).toBe(0);
|
||||
// expect(link3?.prev).toBeUndefined();
|
||||
// expect(link3?.next).toBeUndefined();
|
||||
});
|
||||
|
||||
it('KNOWN ISSUE: should reuse stack levels when possible', () => {
|
||||
// This test documents another aspect of the bug
|
||||
const event1 = createEvent('1', 9, 0, 10, 0); // 09:00-10:00
|
||||
const event2 = createEvent('2', 10, 30, 11, 30); // 10:30-11:30 (NO overlap)
|
||||
const event3 = createEvent('3', 12, 0, 13, 0); // 12:00-13:00 (NO overlap)
|
||||
|
||||
const result = detector.decorateWithStackLinks(event1, [event2, event3]);
|
||||
|
||||
const link1 = result.stackLinks.get('1' as any);
|
||||
const link2 = result.stackLinks.get('2' as any);
|
||||
const link3 = result.stackLinks.get('3' as any);
|
||||
|
||||
// CURRENT BEHAVIOR (BUG): All get different stack levels
|
||||
expect(link1?.stackLevel).toBe(0);
|
||||
expect(link2?.stackLevel).toBe(1);
|
||||
expect(link3?.stackLevel).toBe(2);
|
||||
|
||||
// EXPECTED BEHAVIOR: All should reuse level 0 since none overlap
|
||||
// expect(link1?.stackLevel).toBe(0);
|
||||
// expect(link2?.stackLevel).toBe(0);
|
||||
// expect(link3?.stackLevel).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle complex overlapping pattern correctly', () => {
|
||||
// Event 1: 09:00-11:00 (base)
|
||||
// Event 2: 09:30-10:30 (overlaps with 1)
|
||||
// Event 3: 10:00-11:30 (overlaps with 1 and 2)
|
||||
// Event 4: 11:00-12:00 (overlaps with 3 only)
|
||||
|
||||
const event1 = createEvent('1', 9, 0, 11, 0);
|
||||
const event2 = createEvent('2', 9, 30, 10, 30);
|
||||
const event3 = createEvent('3', 10, 0, 11, 30);
|
||||
const event4 = createEvent('4', 11, 0, 12, 0);
|
||||
|
||||
const result = detector.decorateWithStackLinks(event1, [event2, event3, event4]);
|
||||
|
||||
expect(result.stackLinks.size).toBe(4);
|
||||
|
||||
// All events are linked in one chain (current behavior)
|
||||
const link1 = result.stackLinks.get('1' as any);
|
||||
const link2 = result.stackLinks.get('2' as any);
|
||||
const link3 = result.stackLinks.get('3' as any);
|
||||
const link4 = result.stackLinks.get('4' as any);
|
||||
|
||||
expect(link1?.stackLevel).toBe(0);
|
||||
expect(link2?.stackLevel).toBe(1);
|
||||
expect(link3?.stackLevel).toBe(2);
|
||||
expect(link4?.stackLevel).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Edge Cases', () => {
|
||||
it('should handle zero-duration events', () => {
|
||||
const event1 = createEvent('1', 9, 0, 9, 0); // 09:00-09:00
|
||||
const event2 = createEvent('2', 9, 0, 10, 0); // 09:00-10:00
|
||||
|
||||
const overlaps = detector.resolveOverlap(event1, [event2]);
|
||||
|
||||
// Zero-duration event at start of another should not overlap
|
||||
expect(overlaps).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should handle events spanning multiple hours', () => {
|
||||
const event1 = createEvent('1', 8, 0, 17, 0); // 08:00-17:00 (9 hours)
|
||||
const event2 = createEvent('2', 12, 0, 13, 0); // 12:00-13:00
|
||||
|
||||
const overlaps = detector.resolveOverlap(event1, [event2]);
|
||||
|
||||
expect(overlaps).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('should handle many events in same time slot', () => {
|
||||
const event1 = createEvent('1', 9, 0, 10, 0);
|
||||
const events = [
|
||||
createEvent('2', 9, 0, 10, 0),
|
||||
createEvent('3', 9, 0, 10, 0),
|
||||
createEvent('4', 9, 0, 10, 0),
|
||||
createEvent('5', 9, 0, 10, 0)
|
||||
];
|
||||
|
||||
const overlaps = detector.resolveOverlap(event1, events);
|
||||
|
||||
expect(overlaps).toHaveLength(4);
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue