summaryrefslogtreecommitdiffstats
path: root/comm/calendar/test/browser/browser_taskDisplay.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /comm/calendar/test/browser/browser_taskDisplay.js
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/calendar/test/browser/browser_taskDisplay.js')
-rw-r--r--comm/calendar/test/browser/browser_taskDisplay.js274
1 files changed, 274 insertions, 0 deletions
diff --git a/comm/calendar/test/browser/browser_taskDisplay.js b/comm/calendar/test/browser/browser_taskDisplay.js
new file mode 100644
index 0000000000..1ccd0dac3f
--- /dev/null
+++ b/comm/calendar/test/browser/browser_taskDisplay.js
@@ -0,0 +1,274 @@
+/* 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/. */
+
+XPCOMUtils.defineLazyModuleGetters(this, {
+ CalRecurrenceInfo: "resource:///modules/CalRecurrenceInfo.jsm",
+ CalTodo: "resource:///modules/CalTodo.jsm",
+});
+
+var calendar = CalendarTestUtils.createCalendar();
+registerCleanupFunction(() => {
+ CalendarTestUtils.removeCalendar(calendar);
+});
+
+let tree = document.getElementById("calendar-task-tree");
+
+add_task(async () => {
+ async function createTask(title, attributes = {}) {
+ let task = new CalTodo();
+ task.title = title;
+ for (let [key, value] of Object.entries(attributes)) {
+ task[key] = value;
+ }
+ return calendar.addItem(task);
+ }
+
+ function treeRefresh() {
+ return BrowserTestUtils.waitForEvent(tree, "refresh");
+ }
+
+ async function setFilterGroup(name) {
+ info(`Setting filter to ${name}`);
+ let radio = document.getElementById(`opt_${name}_filter`);
+ EventUtils.synthesizeMouseAtCenter(radio, {});
+ await treeRefresh();
+ Assert.equal(
+ document.getElementById("calendar-task-tree").getAttribute("filterValue"),
+ radio.value,
+ "Filter group changed"
+ );
+ }
+
+ async function setFilterText(text) {
+ EventUtils.synthesizeMouseAtCenter(document.getElementById("task-text-filter-field"), {});
+ EventUtils.sendString(text);
+ Assert.equal(document.getElementById("task-text-filter-field").value, text, "Filter text set");
+ await treeRefresh();
+ }
+
+ async function clearFilterText() {
+ EventUtils.synthesizeMouseAtCenter(document.getElementById("task-text-filter-field"), {});
+ EventUtils.synthesizeKey("VK_ESCAPE");
+ Assert.equal(
+ document.getElementById("task-text-filter-field").value,
+ "",
+ "Filter text cleared"
+ );
+ await treeRefresh();
+ }
+
+ async function checkVisibleTasks(...expectedTasks) {
+ function toPrettyString(task) {
+ if (task.recurrenceId) {
+ return `${task.title}#${task.recurrenceId}`;
+ }
+ return task.title;
+ }
+ tree.getBoundingClientRect(); // Try and trigger a reflow...
+ tree.invalidate();
+
+ // It seems that under certain conditions notifyOperationComplete() is
+ // called in CalStorageCalender.getItems before all the results have been
+ // retrieved. This results in the "refresh" event being fired prematurely in
+ // calendar-task-tree. After some investigation, the cause of this seems to
+ // be related to multiple calls of executeAsync() in CalStorageItemModel.
+ // getAdditionalDataForItemMap() not finishing before notifyOperationComplete()
+ // is called despite being awaited on.
+ // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
+ await new Promise(r => setTimeout(r, 500));
+
+ let actualTasks = [];
+ for (let i = 0; i < tree.view.rowCount; i++) {
+ actualTasks.push(tree.getTaskAtRow(i));
+ }
+ info("Expected: " + expectedTasks.map(toPrettyString).join(", "));
+ info("Actual: " + actualTasks.map(toPrettyString).join(", "));
+
+ Assert.equal(tree.view.rowCount, expectedTasks.length, "Correct number of tasks");
+ await new Promise(r => setTimeout(r));
+
+ // Although the order of expectedTasks matches the observed behaviour when
+ // this test was written, order is NOT checked here. The order of the list
+ // is not well defined (particularly when changing the filter text).
+ for (let aTask of actualTasks) {
+ Assert.ok(
+ expectedTasks.some(eTask => eTask.hasSameIds(aTask)),
+ toPrettyString(aTask)
+ );
+ }
+ }
+
+ let today = cal.dtz.now();
+ today.hour = today.minute = today.second = 0;
+ let yesterday = today.clone();
+ yesterday.addDuration(cal.createDuration("-P1D"));
+ let tomorrow = today.clone();
+ tomorrow.addDuration(cal.createDuration("P1D"));
+ let later = today.clone();
+ later.addDuration(cal.createDuration("P2W"));
+
+ let tasks = {
+ incomplete: await createTask("Incomplete"),
+ started30: await createTask("30% started", { percentComplete: 30 }),
+ started60: await createTask("60% started", { percentComplete: 60 }),
+ complete: await createTask("Complete", { isCompleted: true }),
+ overdue: await createTask("Overdue", { dueDate: yesterday }),
+ startsToday: await createTask("Starts today", { entryDate: today }),
+ startsTomorrow: await createTask("Starts tomorrow", { entryDate: tomorrow }),
+ startsLater: await createTask("Starts later", { entryDate: later }),
+ };
+
+ let repeatingTask = new CalTodo();
+ repeatingTask.title = "Repeating";
+ repeatingTask.entryDate = yesterday;
+ repeatingTask.recurrenceInfo = new CalRecurrenceInfo(repeatingTask);
+ repeatingTask.recurrenceInfo.appendRecurrenceItem(
+ cal.createRecurrenceRule("RRULE:FREQ=DAILY;COUNT=3")
+ );
+
+ let firstOccurrence = repeatingTask.recurrenceInfo.getOccurrenceFor(yesterday);
+ firstOccurrence.isCompleted = true;
+ firstOccurrence.completedDate = yesterday;
+ repeatingTask.recurrenceInfo.modifyException(firstOccurrence, true);
+
+ repeatingTask = await calendar.addItem(repeatingTask);
+
+ let occurrences = repeatingTask.recurrenceInfo.getOccurrences(yesterday, later, 10);
+ Assert.equal(occurrences.length, 3);
+
+ await openTasksTab();
+
+ await setFilterGroup("all");
+ await checkVisibleTasks(
+ tasks.incomplete,
+ tasks.started30,
+ tasks.started60,
+ tasks.complete,
+ tasks.overdue,
+ tasks.startsToday,
+ tasks.startsTomorrow,
+ tasks.startsLater,
+ repeatingTask
+ );
+
+ await setFilterGroup("open");
+ await checkVisibleTasks(
+ tasks.incomplete,
+ tasks.started30,
+ tasks.started60,
+ tasks.overdue,
+ tasks.startsToday,
+ tasks.startsTomorrow,
+ tasks.startsLater,
+ occurrences[1],
+ occurrences[2]
+ );
+
+ await setFilterGroup("completed");
+ await checkVisibleTasks(tasks.complete, occurrences[0]);
+
+ await setFilterGroup("overdue");
+ await checkVisibleTasks(tasks.overdue);
+
+ await setFilterGroup("notstarted");
+ await checkVisibleTasks(tasks.overdue, tasks.incomplete, tasks.startsToday, occurrences[1]);
+
+ await setFilterGroup("next7days");
+ await checkVisibleTasks(
+ tasks.overdue,
+ tasks.incomplete,
+ tasks.startsToday,
+ tasks.started30,
+ tasks.started60,
+ tasks.complete,
+ tasks.startsTomorrow,
+ occurrences[1],
+ occurrences[2]
+ );
+
+ await setFilterGroup("today");
+ await checkVisibleTasks(
+ tasks.overdue,
+ tasks.incomplete,
+ tasks.startsToday,
+ tasks.started30,
+ tasks.started60,
+ tasks.complete,
+ occurrences[1]
+ );
+
+ await setFilterGroup("throughcurrent");
+ await checkVisibleTasks(
+ tasks.overdue,
+ tasks.incomplete,
+ tasks.startsToday,
+ tasks.started30,
+ tasks.started60,
+ tasks.complete,
+ occurrences[1]
+ );
+
+ await setFilterText("No matches");
+ await checkVisibleTasks();
+
+ await clearFilterText();
+ await checkVisibleTasks(
+ tasks.incomplete,
+ tasks.started30,
+ tasks.started60,
+ tasks.complete,
+ tasks.overdue,
+ tasks.startsToday,
+ occurrences[1]
+ );
+
+ await setFilterText("StArTeD");
+ await checkVisibleTasks(tasks.started30, tasks.started60);
+
+ await setFilterGroup("today");
+ Assert.equal(document.getElementById("task-text-filter-field").value, "StArTeD");
+ await checkVisibleTasks(tasks.started30, tasks.started60);
+
+ await setFilterGroup("next7days");
+ Assert.equal(document.getElementById("task-text-filter-field").value, "StArTeD");
+ await checkVisibleTasks(tasks.started30, tasks.started60);
+
+ await setFilterGroup("notstarted");
+ Assert.equal(document.getElementById("task-text-filter-field").value, "StArTeD");
+ await checkVisibleTasks();
+
+ await setFilterGroup("overdue");
+ Assert.equal(document.getElementById("task-text-filter-field").value, "StArTeD");
+ await checkVisibleTasks();
+
+ await setFilterGroup("completed");
+ Assert.equal(document.getElementById("task-text-filter-field").value, "StArTeD");
+ await checkVisibleTasks();
+
+ await setFilterGroup("open");
+ Assert.equal(document.getElementById("task-text-filter-field").value, "StArTeD");
+ await checkVisibleTasks(tasks.started30, tasks.started60);
+
+ await setFilterGroup("all");
+ Assert.equal(document.getElementById("task-text-filter-field").value, "StArTeD");
+ await checkVisibleTasks(tasks.started30, tasks.started60);
+
+ await clearFilterText();
+ await checkVisibleTasks(
+ tasks.started30,
+ tasks.started60,
+ tasks.incomplete,
+ tasks.complete,
+ tasks.overdue,
+ tasks.startsToday,
+ tasks.startsTomorrow,
+ tasks.startsLater,
+ repeatingTask
+ );
+
+ for (let task of Object.values(tasks)) {
+ await calendar.deleteItem(task);
+ }
+ await setFilterGroup("throughcurrent");
+});