Skip to content

Commit e30441b

Browse files
[scheduler] Add tests for the sortOccurrences utility (#20605)
1 parent c9708af commit e30441b

File tree

1 file changed

+197
-0
lines changed

1 file changed

+197
-0
lines changed
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
import { adapter, EventBuilder } from 'test/utils/scheduler';
2+
import { sortEventOccurrences } from './sortEventOccurrences';
3+
4+
describe('sortEventOccurrences', () => {
5+
describe('basic sorting', () => {
6+
it('should return empty array when given empty array', () => {
7+
expect(sortEventOccurrences([], adapter)).toEqual([]);
8+
});
9+
10+
it('should return single occurrence unchanged', () => {
11+
const occurrence = EventBuilder.new().singleDay('2024-01-15T10:00:00').toOccurrence();
12+
expect(sortEventOccurrences([occurrence], adapter)).toEqual([occurrence]);
13+
});
14+
15+
it('should sort occurrences by start date (earliest first)', () => {
16+
const first = EventBuilder.new().id('first').singleDay('2024-01-15T08:00:00').toOccurrence();
17+
const second = EventBuilder.new()
18+
.id('second')
19+
.singleDay('2024-01-15T10:00:00')
20+
.toOccurrence();
21+
const third = EventBuilder.new().id('third').singleDay('2024-01-15T14:00:00').toOccurrence();
22+
23+
expect(sortEventOccurrences([third, first, second], adapter)).to.deep.equal([
24+
first,
25+
second,
26+
third,
27+
]);
28+
});
29+
});
30+
31+
describe('same start date tiebreaker', () => {
32+
it('should sort by end date (later end first) when start dates are equal', () => {
33+
const short = EventBuilder.new()
34+
.id('short')
35+
.singleDay('2024-01-15T10:00:00', 30)
36+
.toOccurrence();
37+
const long = EventBuilder.new()
38+
.id('long')
39+
.singleDay('2024-01-15T10:00:00', 120)
40+
.toOccurrence();
41+
42+
expect(sortEventOccurrences([short, long], adapter)).to.deep.equal([long, short]);
43+
});
44+
45+
it('should handle multiple events with same start but different ends', () => {
46+
const short = EventBuilder.new()
47+
.id('short')
48+
.singleDay('2024-01-15T10:00:00', 30)
49+
.toOccurrence();
50+
const medium = EventBuilder.new()
51+
.id('medium')
52+
.singleDay('2024-01-15T10:00:00')
53+
.toOccurrence();
54+
const long = EventBuilder.new()
55+
.id('long')
56+
.singleDay('2024-01-15T10:00:00', 120)
57+
.toOccurrence();
58+
59+
expect(sortEventOccurrences([short, medium, long], adapter)).to.deep.equal([
60+
long,
61+
medium,
62+
short,
63+
]);
64+
});
65+
});
66+
67+
describe('all-day events', () => {
68+
it('should sort all-day events by start of day', () => {
69+
const day1 = EventBuilder.new()
70+
.id('day1')
71+
.span('2024-01-15T00:00:00', '2024-01-15T23:59:59')
72+
.allDay(true)
73+
.toOccurrence();
74+
const day2 = EventBuilder.new()
75+
.id('day2')
76+
.span('2024-01-16T00:00:00', '2024-01-16T23:59:59')
77+
.allDay(true)
78+
.toOccurrence();
79+
80+
expect(sortEventOccurrences([day2, day1], adapter)).to.deep.equal([day1, day2]);
81+
});
82+
83+
it('should sort all-day events with same start by end date (longer first)', () => {
84+
const singleDay = EventBuilder.new()
85+
.id('single')
86+
.span('2024-01-15T00:00:00', '2024-01-15T23:59:59')
87+
.allDay(true)
88+
.toOccurrence();
89+
const multiDay = EventBuilder.new()
90+
.id('multi')
91+
.span('2024-01-15T00:00:00', '2024-01-17T23:59:59')
92+
.allDay(true)
93+
.toOccurrence();
94+
95+
expect(sortEventOccurrences([singleDay, multiDay], adapter)).to.deep.equal([
96+
multiDay,
97+
singleDay,
98+
]);
99+
});
100+
});
101+
102+
describe('mixed timed and all-day events', () => {
103+
it('should correctly sort mixed all-day and timed events on the same day', () => {
104+
const allDay = EventBuilder.new()
105+
.id('allDay')
106+
.span('2024-01-15T00:00:00', '2024-01-15T23:59:59')
107+
.allDay(true)
108+
.toOccurrence();
109+
const timed = EventBuilder.new().id('timed').singleDay('2024-01-15T10:00:00').toOccurrence();
110+
111+
// All-day event starts at midnight (start of day), so it should come first
112+
expect(sortEventOccurrences([timed, allDay], adapter)).to.deep.equal([allDay, timed]);
113+
});
114+
115+
it('should sort all-day event after timed event that starts earlier in the day', () => {
116+
const allDay = EventBuilder.new()
117+
.id('allDay')
118+
.span('2024-01-16T00:00:00', '2024-01-16T23:59:59')
119+
.allDay(true)
120+
.toOccurrence();
121+
const timedEarlier = EventBuilder.new()
122+
.id('timed')
123+
.singleDay('2024-01-15T10:00:00')
124+
.toOccurrence();
125+
126+
expect(sortEventOccurrences([allDay, timedEarlier], adapter)).to.deep.equal([
127+
timedEarlier,
128+
allDay,
129+
]);
130+
});
131+
});
132+
133+
describe('edge cases', () => {
134+
it('should maintain stable sort for identical occurrences', () => {
135+
// Two events with exactly the same start and end
136+
const event1 = EventBuilder.new()
137+
.id('event1')
138+
.singleDay('2024-01-15T10:00:00')
139+
.toOccurrence();
140+
const event2 = EventBuilder.new()
141+
.id('event2')
142+
.singleDay('2024-01-15T10:00:00')
143+
.toOccurrence();
144+
145+
// Should maintain original order when equal
146+
expect(sortEventOccurrences([event1, event2], adapter)).to.deep.equal([event1, event2]);
147+
});
148+
149+
it('should handle events spanning multiple days', () => {
150+
const multiDay = EventBuilder.new()
151+
.id('multiDay')
152+
.span('2024-01-15T10:00:00', '2024-01-17T14:00:00')
153+
.toOccurrence();
154+
const singleDay = EventBuilder.new()
155+
.id('singleDay')
156+
.singleDay('2024-01-15T12:00:00')
157+
.toOccurrence();
158+
159+
// multiDay starts earlier (10:00), so it should come first
160+
expect(sortEventOccurrences([singleDay, multiDay], adapter)).to.deep.equal([
161+
multiDay,
162+
singleDay,
163+
]);
164+
});
165+
166+
it('should handle events on different days', () => {
167+
const monday = EventBuilder.new()
168+
.id('monday')
169+
.singleDay('2024-01-15T10:00:00')
170+
.toOccurrence();
171+
const wednesday = EventBuilder.new()
172+
.id('wednesday')
173+
.singleDay('2024-01-17T10:00:00')
174+
.toOccurrence();
175+
const tuesday = EventBuilder.new()
176+
.id('tuesday')
177+
.singleDay('2024-01-16T10:00:00')
178+
.toOccurrence();
179+
180+
expect(sortEventOccurrences([wednesday, monday, tuesday], adapter)).to.deep.equal([
181+
monday,
182+
tuesday,
183+
wednesday,
184+
]);
185+
});
186+
187+
it('should not mutate the original array', () => {
188+
const early = EventBuilder.new().id('early').singleDay('2024-01-15T08:00:00').toOccurrence();
189+
const late = EventBuilder.new().id('late').singleDay('2024-01-15T14:00:00').toOccurrence();
190+
191+
const original = [late, early];
192+
193+
expect(sortEventOccurrences(original, adapter)).to.deep.equal([early, late]);
194+
expect(original).to.deep.equal([late, early]);
195+
});
196+
});
197+
});

0 commit comments

Comments
 (0)