diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /comm/calendar/test/browser/browser_taskDisplay.js | |
parent | Initial commit. (diff) | |
download | thunderbird-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.js | 274 |
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"); +}); |