Remove client-side isLoggedIn value
[ProtonMail-WebClient.git] / packages / shared / test / calendar / rrule / rrule.spec.js
blob1a104e460abf92f5e399c4d45449591a74cdaae9
1 import { FREQUENCY } from '../../../lib/calendar/constants';
2 import {
3     getDayAndSetpos,
4     getHasConsistentRrule,
5     getHasOccurrences,
6     getIsRruleCustom,
7     getIsRruleSimple,
8     getIsRruleSupported,
9     getIsStandardByday,
10     getSupportedRrule,
11     getSupportedUntil,
12 } from '../../../lib/calendar/recurrence/rrule';
13 import { parse } from '../../../lib/calendar/vcal';
15 describe('getIsStandardByday', () => {
16     it('returns true for standard BYDAY strings', () => {
17         const bydays = ['SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA'];
18         expect(bydays.map(getIsStandardByday)).toEqual(bydays.map(() => true));
19     });
21     it('returns false for non-standard BYDAY strings', () => {
22         const bydays = ['1SU', 'SUN', 'S', 'DO', ''];
23         expect(bydays.map(getIsStandardByday)).toEqual(bydays.map(() => false));
24     });
25 });
27 describe('getDayAndSetpos', () => {
28     it('gets the day and setpos correctly', () => {
29         const bydays = ['1SU', '+2MO', '-1FR', 'WE'];
30         const results = [{ setpos: 1, day: 'SU' }, { setpos: 2, day: 'MO' }, { setpos: -1, day: 'FR' }, { day: 'WE' }];
31         expect(bydays.map((byday) => getDayAndSetpos(byday))).toEqual(results);
32     });
33 });
35 describe('getSupportedUntil', () => {
36     it('should keep the date for all-day events', () => {
37         const tzid = 'Pacific/Niue';
38         const until = { year: 2020, month: 6, day: 27, hours: 10, minutes: 59, seconds: 59, isUTC: true };
39         const dtstartValue = { year: 2010, month: 6, day: 27 };
40         const expected = { year: 2020, month: 6, day: 27 };
41         expect(
42             getSupportedUntil({
43                 until,
44                 dtstart: { parameters: { type: 'date' }, value: dtstartValue },
45                 tzid,
46             })
47         ).toEqual(expected);
48     });
50     it('should always return the same until if it was at the end of the day already', () => {
51         const tzid = 'Pacific/Niue';
52         const until = { year: 2020, month: 6, day: 27, hours: 10, minutes: 59, seconds: 59, isUTC: true };
53         const dtstartValue = { year: 2010, month: 6, day: 27, hours: 10, minutes: 59, seconds: 59, isUTC: false };
54         expect(getSupportedUntil({ until, dtstart: { parameters: { tzid }, value: dtstartValue } })).toEqual(until);
55     });
57     it('should always return an until at the end of the day', () => {
58         const tzid = 'Pacific/Niue';
59         const untils = [
60             { year: 2020, month: 6, day: 27, hours: 15, minutes: 14, isUTC: true },
61             { year: 2020, month: 6, day: 27 },
62         ];
63         const expected = [
64             { year: 2020, month: 6, day: 28, hours: 10, minutes: 59, seconds: 59, isUTC: true },
65             { year: 2020, month: 6, day: 27, hours: 10, minutes: 59, seconds: 59, isUTC: true },
66         ];
67         const dtstartValue = { year: 2010, month: 6, day: 28, hours: 10, minutes: 59, seconds: 59, isUTC: false };
68         expect(
69             untils.map((until) => getSupportedUntil({ until, dtstart: { parameters: { tzid }, value: dtstartValue } }))
70         ).toEqual(expected);
71     });
73     it('should keep the right date for all-day events when a guess tzid is passed', () => {
74         const guessTzid = 'Asia/Taipei';
75         const until = { year: 2020, month: 11, day: 24, hours: 16, minutes: 0, seconds: 0, isUTC: true };
76         const dtstartValue = { year: 2010, month: 11, day: 24 };
77         const expected = { year: 2020, month: 11, day: 25 };
78         expect(
79             getSupportedUntil({
80                 until,
81                 dtstart: { parameters: { type: 'date' }, value: dtstartValue },
82                 guessTzid,
83             })
84         ).toEqual(expected);
85     });
86 });
88 describe('getIsRruleSimple', () => {
89     it('returns true for simple recurring events', () => {
90         const rrules = [
91             {
92                 freq: FREQUENCY.DAILY,
93                 interval: 1,
94             },
95             {
96                 freq: FREQUENCY.WEEKLY,
97                 interval: 1,
98                 byday: 'SA',
99             },
100             {
101                 freq: FREQUENCY.MONTHLY,
102                 interval: 1,
103                 bymonthday: 23,
104             },
105             {
106                 freq: FREQUENCY.YEARLY,
107                 interval: 1,
108                 bymonth: 5,
109             },
110             {
111                 freq: FREQUENCY.YEARLY,
112                 interval: 1,
113                 bymonthday: 23,
114             },
115         ];
116         expect(rrules.map(getIsRruleSimple)).toEqual(rrules.map(() => true));
117     });
119     it('returns false for supported custom-recurring events', () => {
120         const rrules = [
121             {
122                 freq: FREQUENCY.DAILY,
123                 count: 3,
124                 interval: 2,
125             },
126             {
127                 freq: FREQUENCY.WEEKLY,
128                 byday: ['SA', 'FR'],
129             },
130             {
131                 freq: FREQUENCY.WEEKLY,
132                 byday: ['SA', 'FR'],
133                 count: 1,
134             },
135             {
136                 freq: FREQUENCY.WEEKLY,
137                 until: { year: 2020, month: 5, day: 10 },
138             },
139             {
140                 freq: FREQUENCY.MONTHLY,
141                 bysetpos: 2,
142                 byday: 'WE',
143             },
144             {
145                 freq: FREQUENCY.MONTHLY,
146                 byday: '-1WE',
147                 until: { year: 2020, month: 5, day: 10 },
148             },
149             {
150                 freq: FREQUENCY.YEARLY,
151                 interval: 2,
152             },
153             {
154                 freq: FREQUENCY.YEARLY,
155                 count: 3,
156             },
157         ];
158         expect(rrules.map(getIsRruleSimple)).toEqual(rrules.map(() => false));
159     });
161     it('returns false for non-supported custom-recurring events', () => {
162         const rrules = [
163             {
164                 freq: 'HOURLY',
165             },
166             {
167                 freq: FREQUENCY.WEEKLY,
168                 byday: ['SA', 'FR'],
169                 byhour: [8, 9],
170             },
171             {
172                 freq: FREQUENCY.WEEKLY,
173                 byday: 'SA',
174                 bysetpos: 1,
175             },
176             {
177                 freq: FREQUENCY.MONTHLY,
178                 byday: ['MO', 'WE'],
179             },
180             {
181                 freq: FREQUENCY.YEARLY,
182                 bymonthday: 2,
183                 bymonth: 5,
184                 byday: 'TH',
185             },
186             {
187                 freq: FREQUENCY.YEARLY,
188                 byday: 'MO',
189                 byweekno: 20,
190             },
191         ];
192         expect(rrules.map(getIsRruleSimple)).toEqual(rrules.map(() => false));
193     });
196 describe('getIsRruleCustom', () => {
197     it('returns false for simple recurring events', () => {
198         const rrules = [
199             {
200                 freq: FREQUENCY.DAILY,
201                 interval: 1,
202             },
203             {
204                 freq: FREQUENCY.WEEKLY,
205                 interval: 1,
206                 byday: 'SA',
207             },
208             {
209                 freq: FREQUENCY.MONTHLY,
210                 interval: 1,
211                 bymonthday: 23,
212             },
213             {
214                 freq: FREQUENCY.YEARLY,
215                 interval: 1,
216                 bymonth: 5,
217             },
218             {
219                 freq: FREQUENCY.YEARLY,
220                 interval: 1,
221                 bymonthday: 23,
222             },
223         ];
224         expect(rrules.map(getIsRruleCustom)).toEqual(rrules.map(() => false));
225     });
227     it('returns true for supported custom-recurring events', () => {
228         const rrules = [
229             {
230                 freq: FREQUENCY.DAILY,
231                 count: 3,
232                 interval: 2,
233             },
234             {
235                 freq: FREQUENCY.WEEKLY,
236                 byday: ['SA', 'FR'],
237             },
238             {
239                 freq: FREQUENCY.WEEKLY,
240                 byday: ['SA', 'FR'],
241                 count: 1,
242             },
243             {
244                 freq: FREQUENCY.WEEKLY,
245                 until: { year: 2020, month: 5, day: 10 },
246             },
247             {
248                 freq: FREQUENCY.MONTHLY,
249                 bysetpos: 2,
250                 byday: 'WE',
251             },
252             {
253                 freq: FREQUENCY.MONTHLY,
254                 byday: '-1WE',
255                 until: { year: 2020, month: 5, day: 10 },
256             },
257             {
258                 freq: FREQUENCY.YEARLY,
259                 interval: 2,
260             },
261             {
262                 freq: FREQUENCY.YEARLY,
263                 count: 1,
264             },
265         ];
266         expect(rrules.map(getIsRruleCustom)).toEqual(rrules.map(() => true));
267     });
269     it('returns false for non-supported custom-recurring events', () => {
270         const rrules = [
271             {
272                 freq: FREQUENCY.DAILY,
273                 count: 3,
274                 interval: 2,
275                 byday: ['TU', 'TH'],
276             },
277             {
278                 freq: FREQUENCY.WEEKLY,
279                 byday: ['SA', 'FR'],
280                 bymonth: 1,
281                 count: 2,
282             },
283             {
284                 freq: FREQUENCY.WEEKLY,
285                 until: { year: 2020, month: 5, day: 10 },
286                 bysetpos: 3,
287             },
288             {
289                 freq: FREQUENCY.MONTHLY,
290                 bysetpos: 2,
291             },
292             {
293                 freq: FREQUENCY.MONTHLY,
294                 byday: 'SU',
295             },
296         ];
297         expect(rrules.map(getIsRruleCustom)).toEqual(rrules.map(() => false));
298     });
301 describe('getHasOccurrences', () => {
302     it('should filter out events that generate no occurrence', () => {
303         const vevent = {
304             dtstart: {
305                 value: { year: 2015, month: 8, day: 25, hours: 18, minutes: 30, seconds: 0, isUTC: false },
306                 parameters: {
307                     tzid: 'Europe/Paris',
308                 },
309             },
310             rrule: {
311                 value: {
312                     freq: 'DAILY',
313                     count: 2,
314                 },
315             },
316             exdate: [
317                 {
318                     value: { year: 2015, month: 8, day: 25, hours: 18, minutes: 30, seconds: 0, isUTC: false },
319                     parameters: {
320                         tzid: 'Europe/Paris',
321                     },
322                 },
323                 {
324                     value: { year: 2015, month: 8, day: 26, hours: 18, minutes: 30, seconds: 0, isUTC: false },
325                     parameters: {
326                         tzid: 'Europe/Paris',
327                     },
328                 },
329             ],
330         };
331         expect(getHasOccurrences(vevent)).toEqual(false);
332     });
335 describe('getIsRruleSupported', () => {
336     it('should accept events with monthly recurring rules of the form BYDAY=+/-nDD', () => {
337         const vevents = [
338             `BEGIN:VEVENT\r\nRRULE:FREQ=MONTHLY;BYDAY=1SU\r\nEND:VEVENT`,
339             `BEGIN:VEVENT\r\nRRULE:FREQ=MONTHLY;BYDAY=+2WE\r\nEND:VEVENT`,
340             `BEGIN:VEVENT\r\nRRULE:FREQ=MONTHLY;COUNT=1;BYDAY=4MO\r\nEND:VEVENT`,
341             `BEGIN:VEVENT\r\nRRULE:FREQ=MONTHLY;BYDAY=-1SA\r\nEND:VEVENT`,
342             `BEGIN:VEVENT\r\nRRULE:FREQ=MONTHLY;COUNT=3;INTERVAL=2;BYDAY=TH;BYSETPOS=-1\r\nEND:VEVENT`,
343             `BEGIN:VEVENT\r\nRRULE:FREQ=MONTHLY;BYDAY=TU;BYSETPOS=3\r\nEND:VEVENT`,
344         ];
345         const rrules = vevents.map((vevent) => {
346             const { rrule } = parse(vevent);
347             return rrule.value;
348         });
349         expect(rrules.map((rrule) => getIsRruleSupported(rrule))).toEqual(vevents.map(() => true));
350     });
352     it('should accept events with custom recurring rules for invitations that are not supported via import', () => {
353         const vevents = [
354             `BEGIN:VEVENT\r\nRRULE:FREQ=DAILY;BYHOUR=9,11;BYMINUTE=30\r\nEND:VEVENT`,
355             `BEGIN:VEVENT\r\nRRULE:FREQ=WEEKLY;BYMONTH=1,2,3;BYHOUR=9\r\nEND:VEVENT`,
356             `BEGIN:VEVENT\r\nRRULE:FREQ=MONTHLY;BYMONTHDAY=8,9,10,-1\r\nEND:VEVENT`,
357             `BEGIN:VEVENT\r\nRRULE:FREQ=YEARLY;BYWEEKNO=50;BYMONTH=12\r\nEND:VEVENT`,
358         ];
359         const rrules = vevents.map((vevent) => {
360             const { rrule } = parse(vevent);
361             return rrule.value;
362         });
363         expect(rrules.map((rrule) => getIsRruleSupported(rrule))).toEqual(vevents.map(() => false));
364         expect(rrules.map((rrule) => getIsRruleSupported(rrule, true))).toEqual(vevents.map(() => true));
365     });
367     it('should accept events with valid yearly recurring rules', () => {
368         const vevents = [
369             `BEGIN:VEVENT\r\nRRULE:FREQ=YEARLY;UNTIL=20200330T150000Z;INTERVAL=1;BYMONTHDAY=30;BYMONTH=3\r\nEND:VEVENT`,
370             `BEGIN:VEVENT\r\nRRULE:FREQ=YEARLY;INTERVAL=2;BYMONTH=5\r\nEND:VEVENT`,
371             `BEGIN:VEVENT\r\nRRULE:FREQ=YEARLY;WKST=MO;UNTIL=20160103\r\nEND:VEVENT`,
372         ];
373         const rrules = vevents.map((vevent) => {
374             const { rrule } = parse(vevent);
375             return rrule.value;
376         });
377         expect(rrules.map((rrule) => getIsRruleSupported(rrule))).toEqual(vevents.map(() => true));
378     });
380     it('should refuse events with invalid monthly recurring rules', () => {
381         const vevents = [
382             `BEGIN:VEVENT\r\nRRULE:FREQ=MONTHLY;BYDAY=1SU,2MO\r\nEND:VEVENT`,
383             `BEGIN:VEVENT\r\nRRULE:FREQ=MONTHLY;BYDAY=-2WE\r\nEND:VEVENT`,
384             `BEGIN:VEVENT\r\nRRULE:FREQ=MONTHLY;BYDAY=5TH\r\nEND:VEVENT`,
385             `BEGIN:VEVENT\r\nRRULE:FREQ=MONTHLY;BYDAY=FR\r\nEND:VEVENT`,
386             `BEGIN:VEVENT\r\nRRULE:FREQ=MONTHLY;BYDAY=FR;BYSETPOS=5\r\nEND:VEVENT`,
387             `BEGIN:VEVENT\r\nRRULE:FREQ=MONTHLY;BYDAY=TU;BYSETPOS=-2\r\nEND:VEVENT`,
388             `BEGIN:VEVENT\r\nRRULE:FREQ=MONTHLY;INTERVAL=2;BYMONTHDAY=10,13,14\r\nEND:VEVENT`,
389             `BEGIN:VEVENT\r\nRRULE:FREQ=MONTHLY;INTERVAL=1;BYSETPOS=1;BYDAY=SU,MO,TU,WE,TH,FR,SA\r\nEND:VEVENT`,
390         ];
391         const rrules = vevents.map((vevent) => {
392             const { rrule } = parse(vevent);
393             return rrule.value;
394         });
395         expect(rrules.map((rrule) => getIsRruleSupported(rrule))).toEqual(vevents.map(() => false));
396     });
398     it('should refuse events with invalid yearly recurring rules', () => {
399         const vevents = [
400             `BEGIN:VEVENT\r\nRRULE:FREQ=YEARLY;INTERVAL=1;BYMONTH=1,2,3,4,5,6,7,8,9,10,11,12\r\nEND:VEVENT`,
401             `BEGIN:VEVENT\r\nRRULE:FREQ=YEARLY;BYMONTHDAY=11,22\r\nEND:VEVENT`,
402             `BEGIN:VEVENT\r\nRRULE:FREQ=YEARLY;INTERVAL=2;BYMONTHDAY=17\r\nEND:VEVENT`,
403         ];
404         const rrules = vevents.map((vevent) => {
405             const { rrule } = parse(vevent);
406             return rrule.value;
407         });
408         expect(rrules.map((rrule) => getIsRruleSupported(rrule))).toEqual(vevents.map(() => false));
409     });
412 describe('getSupportedRrule', () => {
413     const dtstartPartDayUTC = {
414         value: { year: 2020, month: 5, day: 11, hours: 12, minutes: 0, seconds: 0, isUTC: true },
415     };
416     const dtstartPartDayZoned = {
417         value: { year: 2020, month: 5, day: 11, hours: 12, minutes: 0, seconds: 0, isUTC: false },
418         parameters: { tzid: 'Antarctica/Troll' },
419     };
420     const dtstartAllDay = {
421         value: { year: 2020, month: 5, day: 11 },
422         parameters: { type: 'date' },
423     };
425     it('should reformat rrules with a badly formatted UNTIL', () => {
426         const vevents = [
427             {
428                 dtstart: dtstartPartDayUTC,
429                 rrule: { value: { freq: 'WEEKLY', until: { year: 2020, month: 5, day: 15 } } },
430             },
431             {
432                 dtstart: dtstartPartDayZoned,
433                 rrule: { value: { freq: 'WEEKLY', until: { year: 2020, month: 5, day: 15 } } },
434             },
435             {
436                 dtstart: dtstartAllDay,
437                 rrule: {
438                     value: {
439                         freq: 'WEEKLY',
440                         until: { year: 2020, month: 5, day: 15, hours: 12, minutes: 0, seconds: 30, isUTC: false },
441                     },
442                 },
443             },
444         ];
445         const expected = [
446             {
447                 value: {
448                     freq: 'WEEKLY',
449                     until: { year: 2020, month: 5, day: 15, hours: 23, minutes: 59, seconds: 59, isUTC: true },
450                 },
451             },
452             {
453                 value: {
454                     freq: 'WEEKLY',
455                     until: { year: 2020, month: 5, day: 15, hours: 21, minutes: 59, seconds: 59, isUTC: true },
456                 },
457             },
458             { value: { freq: 'WEEKLY', until: { year: 2020, month: 5, day: 15 } } },
459         ];
460         expect(vevents.map((vevent) => getSupportedRrule(vevent))).toEqual(expected);
461     });
463     it('should reformat rrules with UNTIL in the middle of the day', () => {
464         const vevents = [
465             {
466                 dtstart: dtstartPartDayUTC,
467                 rrule: {
468                     value: {
469                         freq: 'WEEKLY',
470                         until: { year: 2020, month: 5, day: 15, hours: 12, minutes: 0, seconds: 30, isUTC: true },
471                     },
472                 },
473             },
474             {
475                 dtstart: dtstartPartDayZoned,
476                 rrule: {
477                     value: {
478                         freq: 'WEEKLY',
479                         until: { year: 2020, month: 5, day: 15, hours: 12, minutes: 0, seconds: 30, isUTC: true },
480                     },
481                 },
482             },
483         ];
484         const expected = [
485             {
486                 value: {
487                     freq: 'WEEKLY',
488                     until: { year: 2020, month: 5, day: 15, hours: 23, minutes: 59, seconds: 59, isUTC: true },
489                 },
490             },
491             {
492                 value: {
493                     freq: 'WEEKLY',
494                     until: { year: 2020, month: 5, day: 15, hours: 21, minutes: 59, seconds: 59, isUTC: true },
495                 },
496             },
497         ];
498         expect(vevents.map((vevent) => getSupportedRrule(vevent))).toEqual(expected);
499     });
502 describe('getHasConsistentRrule', () => {
503     const dtstartPartDayUTC = {
504         value: { year: 2020, month: 5, day: 11, hours: 12, minutes: 0, seconds: 0, isUTC: true },
505     };
507     it('should not allow count and until together', () => {
508         const dtstart = {
509             value: { year: 2015, month: 8, day: 25, hours: 18, minutes: 30, seconds: 0, isUTC: false },
510             parameters: {
511                 tzid: 'Europe/Paris',
512             },
513         };
514         const until = { year: 2015, month: 8, day: 30, hours: 16, minutes: 29, seconds: 59, isUTC: true };
516         expect(
517             getHasConsistentRrule({
518                 dtstart,
519                 rrule: {
520                     value: {
521                         freq: 'DAILY',
522                         until,
523                     },
524                 },
525             })
526         ).toEqual(true);
527         expect(
528             getHasConsistentRrule({
529                 dtstart,
530                 rrule: {
531                     value: {
532                         freq: 'DAILY',
533                         count: 1,
534                     },
535                 },
536             })
537         ).toEqual(true);
538         expect(
539             getHasConsistentRrule({
540                 dtstart,
541                 rrule: {
542                     value: {
543                         freq: 'DAILY',
544                         until,
545                         count: 1,
546                     },
547                 },
548             })
549         ).toEqual(false);
550     });
552     it('should not allow byyearday for frequencies other than yearly', () => {
553         const dtstart = {
554             value: { year: 2022, month: 1, day: 27, hours: 18, minutes: 30, seconds: 0, isUTC: false },
555             parameters: {
556                 tzid: 'Europe/Paris',
557             },
558         };
560         expect(
561             getHasConsistentRrule({
562                 dtstart,
563                 rrule: {
564                     value: {
565                         freq: 'DAILY',
566                         byyearday: 27,
567                     },
568                 },
569             })
570         ).toEqual(false);
571         expect(
572             getHasConsistentRrule({
573                 dtstart,
574                 rrule: {
575                     value: {
576                         freq: 'WEEKLY',
577                         byyearday: 27,
578                         count: 3,
579                         interval: 2,
580                     },
581                 },
582             })
583         ).toEqual(false);
584         expect(
585             getHasConsistentRrule({
586                 dtstart,
587                 rrule: {
588                     value: {
589                         freq: 'MONTHLY',
590                         bymonthday: 27,
591                         byyearday: 27,
592                     },
593                 },
594             })
595         ).toEqual(false);
596         expect(
597             getHasConsistentRrule({
598                 dtstart,
599                 rrule: {
600                     value: {
601                         freq: 'YEARLY',
602                         byyearday: 27,
603                     },
604                 },
605             })
606         ).toEqual(true);
607     });
609     it('should filter out inconsistent rrules', () => {
610         const rrules = [
611             {
612                 freq: 'MONTHLY',
613                 byday: '1MO',
614             },
615             {
616                 freq: 'MONTHLY',
617                 byday: '-2MO',
618             },
619             {
620                 freq: 'MONTHLY',
621                 byday: 'SU',
622             },
623             {
624                 freq: 'MONTHLY',
625                 byday: 'MO',
626                 bysetpos: 3,
627             },
628         ];
629         const vevents = rrules.map((rrule) => ({
630             dtstart: dtstartPartDayUTC,
631             rrule: { value: rrule },
632         }));
633         const expected = vevents.map(() => false);
634         expect(vevents.map((vevent) => getHasConsistentRrule(vevent))).toEqual(expected);
635     });
637     it('should exclude exdate when checking consistency', () => {
638         const vevent = {
639             dtstart: {
640                 value: { year: 2015, month: 8, day: 25, hours: 18, minutes: 30, seconds: 0, isUTC: false },
641                 parameters: {
642                     tzid: 'Europe/Paris',
643                 },
644             },
645             rrule: {
646                 value: {
647                     freq: 'DAILY',
648                     until: { year: 2015, month: 8, day: 30, hours: 16, minutes: 29, seconds: 59, isUTC: true },
649                 },
650             },
651             exdate: [
652                 {
653                     value: { year: 2015, month: 8, day: 25, hours: 18, minutes: 30, seconds: 0, isUTC: false },
654                     parameters: {
655                         tzid: 'Europe/Paris',
656                     },
657                 },
658             ],
659         };
660         expect(getHasConsistentRrule(vevent)).toEqual(true);
661     });
663     it('should not care about COUNT = 0', () => {
664         const vevent = {
665             dtstart: {
666                 value: { year: 2015, month: 8, day: 25, hours: 18, minutes: 30, seconds: 0, isUTC: false },
667                 parameters: {
668                     tzid: 'Europe/Paris',
669                 },
670             },
671             rrule: {
672                 value: {
673                     freq: 'DAILY',
674                     count: 0,
675                 },
676             },
677         };
678         expect(getHasConsistentRrule(vevent)).toEqual(true);
679     });
681     it('should not care about UNTIL earlier than DTSTART', () => {
682         const vevent = {
683             dtstart: {
684                 value: { year: 2015, month: 8, day: 25, hours: 18, minutes: 30, seconds: 0, isUTC: false },
685                 parameters: {
686                     tzid: 'Europe/Paris',
687                 },
688             },
689             rrule: {
690                 value: {
691                     freq: 'DAILY',
692                     until: { year: 2015, month: 8, day: 25, hours: 16, minutes: 0, seconds: 0, isUTC: true },
693                 },
694             },
695         };
696         expect(getHasConsistentRrule(vevent)).toEqual(true);
697     });