Bug 1492436 - Delete a recurring item if the last occurrence is deleted; r=philipp
This commit is contained in:
Родитель
8ac8015373
Коммит
123cb6336c
|
@ -10,6 +10,7 @@
|
|||
*/
|
||||
|
||||
var { cal } = ChromeUtils.import("resource://calendar/modules/calUtils.jsm", null);
|
||||
const { countOccurrences } = ChromeUtils.import("resource://calendar/modules/calRecurrenceUtils.jsm", null);
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Preferences.jsm");
|
||||
|
||||
|
@ -115,23 +116,45 @@ var calendarViewController = {
|
|||
// are readonly.
|
||||
let occurrences = aOccurrences.filter(item => cal.acl.isCalendarWritable(item.calendar));
|
||||
|
||||
// we check how many occurrences the parent item has
|
||||
let parents = new Map();
|
||||
for (let occ of occurrences) {
|
||||
if (!parents.has(occ.id)) {
|
||||
parents.set(occ.id, countOccurrences(occ));
|
||||
}
|
||||
}
|
||||
|
||||
let promptUser = !aDoNotConfirm;
|
||||
let previousResponse = 0;
|
||||
for (let itemToDelete of occurrences) {
|
||||
if (aUseParentItems) {
|
||||
if (parents.get(itemToDelete.id) == -1) {
|
||||
// we have scheduled the master item for deletion in a previous
|
||||
// loop already
|
||||
continue;
|
||||
}
|
||||
if (aUseParentItems ||
|
||||
parents.get(itemToDelete.id) == 1 ||
|
||||
previousResponse == 3) {
|
||||
// Usually happens when ctrl-click is used. In that case we
|
||||
// don't need to ask the user if he wants to delete an
|
||||
// occurrence or not.
|
||||
// if an occurrence is the only one of a series or the user
|
||||
// decided so before, we delete the series, too.
|
||||
itemToDelete = itemToDelete.parentItem;
|
||||
} else if (!aDoNotConfirm && occurrences.length == 1) {
|
||||
// Only give the user the selection if only one occurrence is
|
||||
// selected. Otherwise he will get a dialog for each occurrence
|
||||
// he deletes.
|
||||
parents.set(itemToDelete.id, -1);
|
||||
} else if (promptUser) {
|
||||
let [targetItem, , response] = promptOccurrenceModification(itemToDelete, false, "delete");
|
||||
if (!response) {
|
||||
// The user canceled the dialog, bail out
|
||||
break;
|
||||
}
|
||||
|
||||
itemToDelete = targetItem;
|
||||
|
||||
// if we have multiple items and the user decided already for one
|
||||
// item whether to delete the occurrence or the entire series,
|
||||
// we apply that decission also to subsequent items
|
||||
previoiusResponse = response;
|
||||
promptUser = false;
|
||||
}
|
||||
|
||||
// Now some dirty work: Make sure more than one occurrence can be
|
||||
|
|
|
@ -2,12 +2,17 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* exported recurrenceRule2String, splitRecurrenceRules, checkRecurrenceRule */
|
||||
/* exported recurrenceRule2String, splitRecurrenceRules, checkRecurrenceRule
|
||||
* countOccurrences
|
||||
*/
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/PluralForm.jsm");
|
||||
const { cal } = ChromeUtils.import("resource://calendar/modules/calUtils.jsm", null);
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["recurrenceRule2String", "splitRecurrenceRules", "checkRecurrenceRule"];
|
||||
this.EXPORTED_SYMBOLS = [
|
||||
"recurrenceRule2String", "splitRecurrenceRules", "checkRecurrenceRule",
|
||||
"countOccurrences"
|
||||
];
|
||||
|
||||
/**
|
||||
* This function takes the recurrence info passed as argument and creates a
|
||||
|
@ -406,3 +411,72 @@ function checkRecurrenceRule(aRule, aArray) {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the occurrences of the parent item if any of a provided item
|
||||
*
|
||||
* @param {(calIEvent|calIToDo)} aItem item to count for
|
||||
* @returns {(number|null)} number of occurrences or null if the
|
||||
* passed item's parent item isn't a
|
||||
* recurring item or its recurrence is
|
||||
* infinite
|
||||
*/
|
||||
function countOccurrences(aItem) {
|
||||
let occCounter = null;
|
||||
let recInfo = aItem.parentItem.recurrenceInfo;
|
||||
if (recInfo &&
|
||||
recInfo.isFinite) {
|
||||
occCounter = 0;
|
||||
let excCounter = 0;
|
||||
let byCount = false;
|
||||
let ritems = recInfo.getRecurrenceItems({});
|
||||
for (let ritem of ritems) {
|
||||
if (ritem instanceof Ci.calIRecurrenceRule) {
|
||||
if (ritem.isByCount) {
|
||||
occCounter = occCounter + ritem.count;
|
||||
byCount = true;
|
||||
} else {
|
||||
// the rule is limited by as an until date
|
||||
let from = aItem.parentItem.startDate.clone();
|
||||
let until = aItem.parentItem.endDate.clone();
|
||||
if (until.compare(ritem.untilDate) == -1) {
|
||||
until = ritem.untilDate.clone();
|
||||
}
|
||||
|
||||
let exceptionIds = recInfo.getExceptionIds({});
|
||||
for (let exceptionId of exceptionIds) {
|
||||
let recur = recInfo.getExceptionFor(exceptionId);
|
||||
if (from.compare(recur.startDate) == 1) {
|
||||
from = recur.startDate.clone();
|
||||
}
|
||||
if (until.compare(recur.endDate) == -1) {
|
||||
until = recur.endDate.clone();
|
||||
}
|
||||
}
|
||||
|
||||
// we add an extra day at beginning and end, so we don't
|
||||
// neeed to take care of any timezone conversion
|
||||
from.addDuration(cal.createDuration("-P1D"));
|
||||
until.addDuration(cal.createDuration("P1D"));
|
||||
|
||||
let occurrences = recInfo.getOccurrences(from, until, 0, {});
|
||||
occCounter = occCounter + occurrences.length;
|
||||
}
|
||||
} else if (ritem instanceof Ci.calIRecurrenceDate) {
|
||||
if (ritem.isNegative) {
|
||||
// this is an exdate
|
||||
excCounter++;
|
||||
} else {
|
||||
// this is an (additional) rdate
|
||||
occCounter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (byCount) {
|
||||
// for a rrule by count, we still need to substract exceptions if any
|
||||
occCounter = occCounter - excCounter;
|
||||
}
|
||||
}
|
||||
return occCounter;
|
||||
}
|
||||
|
|
|
@ -19,7 +19,8 @@ ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|||
const {
|
||||
recurrenceRule2String,
|
||||
splitRecurrenceRules,
|
||||
checkRecurrenceRule
|
||||
checkRecurrenceRule,
|
||||
countOccurrences
|
||||
} = ChromeUtils.import("resource://calendar/modules/calRecurrenceUtils.jsm", null);
|
||||
ChromeUtils.import("resource://gre/modules/PluralForm.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/Preferences.jsm");
|
||||
|
@ -3225,11 +3226,19 @@ function onCommandDeleteItem() {
|
|||
eventDialogCalendarObserver.cancel();
|
||||
if (window.calendarItem.parentItem.recurrenceInfo && window.calendarItem.recurrenceId) {
|
||||
// if this is a single occurrence of a recurring item
|
||||
let newItem = window.calendarItem.parentItem.clone();
|
||||
newItem.recurrenceInfo.removeOccurrenceAt(window.calendarItem.recurrenceId);
|
||||
|
||||
gMainWindow.doTransaction("modify", newItem, newItem.calendar,
|
||||
window.calendarItem.parentItem, deleteListener);
|
||||
if (countOccurrences(window.calendarItem) == 1) {
|
||||
// this is the last occurrence, hence we delete the parent item
|
||||
// to not leave a parent item without children in the calendar
|
||||
gMainWindow.doTransaction("delete", window.calendarItem.parentItem,
|
||||
window.calendarItem.calendar, null,
|
||||
deleteListener);
|
||||
} else {
|
||||
// we just need to remove the occurrence
|
||||
let newItem = window.calendarItem.parentItem.clone();
|
||||
newItem.recurrenceInfo.removeOccurrenceAt(window.calendarItem.recurrenceId);
|
||||
gMainWindow.doTransaction("modify", newItem, newItem.calendar,
|
||||
window.calendarItem.parentItem, deleteListener);
|
||||
}
|
||||
} else {
|
||||
gMainWindow.doTransaction("delete", window.calendarItem, window.calendarItem.calendar,
|
||||
null, deleteListener);
|
||||
|
|
|
@ -0,0 +1,351 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const { countOccurrences } = ChromeUtils.import("resource://calendar/modules/calRecurrenceUtils.jsm", null);
|
||||
|
||||
function run_test() {
|
||||
do_calendar_startup(run_next_test);
|
||||
}
|
||||
|
||||
// tests for calRecurrenceUtils.jsm
|
||||
/* Incomplete - still missing test coverage for:
|
||||
* recurrenceRule2String
|
||||
* splitRecurrenceRules
|
||||
* checkRecurrenceRule
|
||||
*/
|
||||
|
||||
function getIcs(aProperties) {
|
||||
let calendar = [
|
||||
"BEGIN:VCALENDAR",
|
||||
"PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN",
|
||||
"VERSION:2.0",
|
||||
"BEGIN:VTIMEZONE",
|
||||
"TZID:Europe/Berlin",
|
||||
"BEGIN:DAYLIGHT",
|
||||
"TZOFFSETFROM:+0100",
|
||||
"TZOFFSETTO:+0200",
|
||||
"TZNAME:CEST",
|
||||
"DTSTART:19700329T020000",
|
||||
"RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3",
|
||||
"END:DAYLIGHT",
|
||||
"BEGIN:STANDARD",
|
||||
"TZOFFSETFROM:+0200",
|
||||
"TZOFFSETTO:+0100",
|
||||
"TZNAME:CET",
|
||||
"DTSTART:19701025T030000",
|
||||
"RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10",
|
||||
"END:STANDARD",
|
||||
"END:VTIMEZONE",
|
||||
];
|
||||
calendar = calendar.concat(aProperties);
|
||||
calendar = calendar.concat(["END:VCALENDAR"]);
|
||||
|
||||
return calendar.join("\r\n");
|
||||
}
|
||||
|
||||
add_task(async function countOccurrences_test() {
|
||||
let data = [{
|
||||
input: [
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98000",
|
||||
"SUMMARY:Occurring 3 times until a date",
|
||||
"RRULE:FREQ=DAILY;UNTIL=20180922T100000Z",
|
||||
"DTSTART;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180920T130000",
|
||||
"END:VEVENT",
|
||||
],
|
||||
expected: 3
|
||||
}, {
|
||||
input: [
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98001",
|
||||
"SUMMARY:Occurring 3 times until a date with one exception in the middle",
|
||||
"RRULE:FREQ=DAILY;UNTIL=20180922T100000Z",
|
||||
"EXDATE;TZID=Europe/Berlin:20180921T120000",
|
||||
"DTSTART;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180920T130000",
|
||||
"END:VEVENT",
|
||||
],
|
||||
expected: 2
|
||||
}, {
|
||||
input: [
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98002",
|
||||
"SUMMARY:Occurring 3 times until a date with one exception at the end",
|
||||
"RRULE:FREQ=DAILY;UNTIL=20180922T100000Z",
|
||||
"EXDATE;TZID=Europe/Berlin:20180922T120000",
|
||||
"DTSTART;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180920T130000",
|
||||
"END:VEVENT",
|
||||
],
|
||||
expected: 2
|
||||
}, {
|
||||
input: [
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98003",
|
||||
"SUMMARY:Occurring 3 times until a date with one exception at the beginning",
|
||||
"RRULE:FREQ=DAILY;UNTIL=20180922T100000Z",
|
||||
"EXDATE;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTSTART;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180920T130000",
|
||||
"END:VEVENT",
|
||||
],
|
||||
expected: 2
|
||||
}, {
|
||||
input: [
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98004",
|
||||
"SUMMARY:Occurring 3 times until a date with the middle occurrence moved after the end",
|
||||
"RRULE:FREQ=DAILY;UNTIL=20180922T100000Z",
|
||||
"DTSTART;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180920T130000",
|
||||
"END:VEVENT",
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98004",
|
||||
"SUMMARY:The moved occurrence",
|
||||
"RECURRENCE-ID:20180921T100000Z",
|
||||
"DTSTART;TZID=Europe/Berlin:20180924T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180924T130000",
|
||||
"END:VEVENT",
|
||||
],
|
||||
expected: 3
|
||||
}, {
|
||||
input: [
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98005",
|
||||
"SUMMARY:Occurring 3 times until a date with the middle occurrence moved before the beginning",
|
||||
"RRULE:FREQ=DAILY;UNTIL=20180922T100000Z",
|
||||
"DTSTART;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180920T130000",
|
||||
"END:VEVENT",
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98005",
|
||||
"SUMMARY:The moved occurrence",
|
||||
"RECURRENCE-ID:20180921T100000Z",
|
||||
"DTSTART;TZID=Europe/Berlin:20180918T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180918T130000",
|
||||
"END:VEVENT",
|
||||
],
|
||||
expected: 3
|
||||
}, {
|
||||
input: [
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98006",
|
||||
"SUMMARY:Occurring 1 times until a date",
|
||||
"RRULE:FREQ=DAILY;UNTIL=20180920T100000Z",
|
||||
"DTSTART;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180920T130000",
|
||||
"END:VEVENT",
|
||||
],
|
||||
expected: 1
|
||||
}, {
|
||||
input: [
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98007",
|
||||
"SUMMARY:Occurring 1 times until a date with occernce removed",
|
||||
"RRULE:FREQ=DAILY;UNTIL=20180920T100000Z",
|
||||
"EXDATE;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTSTART;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180920T130000",
|
||||
"END:VEVENT",
|
||||
],
|
||||
expected: 0
|
||||
}, {
|
||||
input: [
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98008",
|
||||
"SUMMARY:Occurring for 3 times",
|
||||
"RRULE:FREQ=DAILY;COUNT=3",
|
||||
"DTSTART;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180920T130000",
|
||||
"END:VEVENT",
|
||||
],
|
||||
expected: 3
|
||||
}, {
|
||||
input: [
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98009",
|
||||
"SUMMARY:Occurring for 3 times with an exception in the middle",
|
||||
"EXDATE;TZID=Europe/Berlin:20180921T120000",
|
||||
"RRULE:FREQ=DAILY;COUNT=3",
|
||||
"DTSTART;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180920T130000",
|
||||
"END:VEVENT",
|
||||
],
|
||||
expected: 2
|
||||
}, {
|
||||
input: [
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98010",
|
||||
"SUMMARY:Occurring for 3 times with an exception at the end",
|
||||
"EXDATE;TZID=Europe/Berlin:20180922T120000",
|
||||
"RRULE:FREQ=DAILY;COUNT=3",
|
||||
"DTSTART;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180920T130000",
|
||||
"END:VEVENT",
|
||||
],
|
||||
expected: 2
|
||||
}, {
|
||||
input: [
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98011",
|
||||
"SUMMARY:Occurring for 3 times with an exception at the beginning",
|
||||
"EXDATE;TZID=Europe/Berlin:20180920T120000",
|
||||
"RRULE:FREQ=DAILY;COUNT=3",
|
||||
"DTSTART;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180920T130000",
|
||||
"END:VEVENT",
|
||||
],
|
||||
expected: 2
|
||||
}, {
|
||||
input: [
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98012",
|
||||
"SUMMARY:Occurring for 1 time",
|
||||
"RRULE:FREQ=DAILY;COUNT=1",
|
||||
"DTSTART;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180920T130000",
|
||||
"END:VEVENT",
|
||||
],
|
||||
expected: 1
|
||||
}, {
|
||||
input: [
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98013",
|
||||
"SUMMARY:Occurring for 0 times",
|
||||
"RRULE:FREQ=DAILY;COUNT=1",
|
||||
"EXDATE;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTSTART;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180920T130000",
|
||||
"END:VEVENT",
|
||||
],
|
||||
expected: 0
|
||||
}, {
|
||||
input: [
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98014",
|
||||
"SUMMARY:Occurring infinitely",
|
||||
"RRULE:FREQ=DAILY",
|
||||
"DTSTART;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180920T130000",
|
||||
"END:VEVENT",
|
||||
],
|
||||
expected: null
|
||||
}, {
|
||||
input: [
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98015",
|
||||
"SUMMARY:Non-occurring item",
|
||||
"DTSTART;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180920T130000",
|
||||
"END:VEVENT",
|
||||
],
|
||||
expected: null
|
||||
}, {
|
||||
input: [
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98016",
|
||||
"SUMMARY:Occurring for 3 time and 1 rdate",
|
||||
"RRULE:FREQ=DAILY;COUNT=3",
|
||||
"RDATE;TZID=Europe/Berlin:20180923T100000",
|
||||
"DTSTART;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180920T130000",
|
||||
"END:VEVENT",
|
||||
],
|
||||
expected: 4
|
||||
}, {
|
||||
input: [
|
||||
"BEGIN:VEVENT",
|
||||
"CREATED:20180912T090539Z",
|
||||
"LAST-MODIFIED:20180912T090539Z",
|
||||
"DTSTAMP:20180912T090539Z",
|
||||
"UID:5b47fa17-f2fe-4d96-8cc2-19ce5be98017",
|
||||
"SUMMARY:Occurring for 3 rdates",
|
||||
"RDATE;TZID=Europe/Berlin:20180920T120000",
|
||||
"RDATE;TZID=Europe/Berlin:20180921T100000",
|
||||
"RDATE;TZID=Europe/Berlin:20180922T140000",
|
||||
"DTSTART;TZID=Europe/Berlin:20180920T120000",
|
||||
"DTEND;TZID=Europe/Berlin:20180920T130000",
|
||||
"END:VEVENT",
|
||||
],
|
||||
expected: 3
|
||||
}];
|
||||
|
||||
let i = 0;
|
||||
for (let test of data) {
|
||||
i++;
|
||||
|
||||
let ics = getIcs(test.input);
|
||||
let parser = Cc["@mozilla.org/calendar/ics-parser;1"]
|
||||
.createInstance(Ci.calIIcsParser);
|
||||
parser.parseString(ics);
|
||||
let items = parser.getItems({});
|
||||
|
||||
ok(items.length > 0, "parsing input suceeded (test #" + i + ")");
|
||||
for (let item of items) {
|
||||
equal(
|
||||
countOccurrences(item),
|
||||
test.expected,
|
||||
"expected number of occurrences (test #" + i + " - '" + item.title + "')"
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
|
@ -42,6 +42,7 @@ skip-if = true # See bug 1481180. requesttimeoutfactor = 2
|
|||
[test_ltninvitationutils.js]
|
||||
[test_providers.js]
|
||||
[test_recur.js]
|
||||
[test_recurrence_utils.js]
|
||||
[test_relation.js]
|
||||
[test_rfc3339_parser.js]
|
||||
[test_search_service.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче