diff options
Diffstat (limited to 'comm/calendar/test/browser/browser_eventUndoRedo.js')
-rw-r--r-- | comm/calendar/test/browser/browser_eventUndoRedo.js | 260 |
1 files changed, 260 insertions, 0 deletions
diff --git a/comm/calendar/test/browser/browser_eventUndoRedo.js b/comm/calendar/test/browser/browser_eventUndoRedo.js new file mode 100644 index 0000000000..34ea8d0523 --- /dev/null +++ b/comm/calendar/test/browser/browser_eventUndoRedo.js @@ -0,0 +1,260 @@ +/* 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/. */ + +"use strict"; + +/** + * Tests for ensuring the undo/redo options are enabled properly when + * manipulating events. + */ + +XPCOMUtils.defineLazyModuleGetters(this, { + CalEvent: "resource:///modules/CalEvent.jsm", + CalTransactionManager: "resource:///modules/CalTransactionManager.jsm", +}); + +const calendar = CalendarTestUtils.createCalendar("Undo Redo Test"); +const calTransManager = CalTransactionManager.getInstance(); + +/** + * Checks the value of the "disabled" property for items in either the "Edit" + * menu bar or the app menu. Display of the relevant menu is triggered first so + * the UI code can update the respective items. + * + * @param {XULElement} element - The menu item we want to check, if its id begins + * with "menu" then we assume it is in the menu + * bar, if "appmenu" then the app menu. + */ +async function isDisabled(element) { + let targetMenu = document.getElementById("menu_EditPopup"); + + let shownPromise = BrowserTestUtils.waitForEvent(targetMenu, "popupshown"); + EventUtils.synthesizeMouseAtCenter(document.getElementById("menu_Edit"), {}); + await shownPromise; + + let hiddenPromise = BrowserTestUtils.waitForEvent(targetMenu, "popuphidden"); + let status = element.disabled; + targetMenu.hidePopup(); + await hiddenPromise; + return status; +} + +async function clickItem(element) { + let targetMenu = document.getElementById("menu_EditPopup"); + + let shownPromise = BrowserTestUtils.waitForEvent(targetMenu, "popupshown"); + EventUtils.synthesizeMouseAtCenter(document.getElementById("menu_Edit"), {}); + await shownPromise; + + targetMenu.activateItem(element); +} + +/** + * Removes CalTransaction items from the CalTransactionManager stacks so other + * tests are unhindered. + */ +function clearTransactions() { + calTransManager.undoStack = []; + calTransManager.redoStack = []; +} + +/** + * Test the undo/redo functionality for event creation. + * + * @param {string} undoId - The id of the "undo" menu item. + * @param {string} redoId - The id of the "redo" menu item. + */ +async function testAddUndoRedoEvent(undoId, redoId) { + let undo = document.getElementById(undoId); + let redo = document.getElementById(redoId); + Assert.ok(await isDisabled(undo), `#${undoId} is disabled`); + Assert.ok(await isDisabled(redo), `#${redoId} is disabled`); + + let newBtn = document.getElementById("sidePanelNewEvent"); + let windowOpened = CalendarTestUtils.waitForEventDialog("edit"); + EventUtils.synthesizeMouseAtCenter(newBtn, {}); + + let win = await windowOpened; + let iframeWin = win.document.getElementById("calendar-item-panel-iframe").contentWindow; + await CalendarTestUtils.items.setData(win, iframeWin, { title: "A New Event" }); + await CalendarTestUtils.items.saveAndCloseItemDialog(win); + + let eventItem; + await TestUtils.waitForCondition(() => { + eventItem = document.querySelector("calendar-month-day-box-item"); + return eventItem; + }, "event not created in time"); + + Assert.ok(!(await isDisabled(undo)), `#${undoId} is enabled`); + Assert.ok(await isDisabled(redo), `#${redoId} is disabled`); + + // Test undo. + await clickItem(undo); + await TestUtils.waitForCondition(() => { + eventItem = document.querySelector("calendar-month-day-box-item"); + return !eventItem; + }, "undo did not remove item in time"); + + Assert.ok(!eventItem, `#${undoId} reverses item creation`); + + // Test redo. + await clickItem(redo); + await TestUtils.waitForCondition(() => { + eventItem = document.querySelector("calendar-month-day-box-item"); + return eventItem; + }, `${redoId} did not re-create item in time`); + Assert.ok(eventItem, `#${redoId} redos item creation`); + + await calendar.deleteItem(eventItem.item); + clearTransactions(); +} + +/** + * Test the undo/redo functionality for event modification. + * + * @param {string} undoId - The id of the "undo" menu item. + * @param {string} redoId - The id of the "redo" menu item. + */ +async function testModifyUndoRedoEvent(undoId, redoId) { + let undo = document.getElementById(undoId); + let redo = document.getElementById(redoId); + Assert.ok(await isDisabled(undo), `#${undoId} is disabled`); + Assert.ok(await isDisabled(redo), `#${redoId} is disabled`); + + let event = new CalEvent(); + event.title = "Modifiable Event"; + event.startDate = cal.dtz.now(); + await calendar.addItem(event); + window.goToDate(event.startDate); + + let eventItem; + await TestUtils.waitForCondition(() => { + eventItem = document.querySelector("calendar-month-day-box-item"); + return eventItem; + }, "event not created in time"); + + let { dialogWindow, iframeWindow } = await CalendarTestUtils.editItem(window, eventItem); + await CalendarTestUtils.items.setData(dialogWindow, iframeWindow, { + title: "Modified Event", + }); + await CalendarTestUtils.items.saveAndCloseItemDialog(dialogWindow); + + await TestUtils.waitForCondition(() => { + eventItem = document.querySelector("calendar-month-day-box-item"); + return eventItem && eventItem.item.title == "Modified Event"; + }, "event not modified in time"); + + Assert.ok(!(await isDisabled(undo)), `#${undoId} is enabled`); + Assert.ok(await isDisabled(redo), `#${redoId} is disabled`); + + // Test undo. + await clickItem(undo); + await TestUtils.waitForCondition(() => { + eventItem = document.querySelector("calendar-month-day-box-item"); + return eventItem && eventItem.item.title == "Modifiable Event"; + }, `#${undoId} did not un-modify event in time`); + + Assert.equal(eventItem.item.title, "Modifiable Event", `#${undoId} reverses item modification`); + + // Test redo. + await clickItem(redo); + await TestUtils.waitForCondition(() => { + eventItem = document.querySelector("calendar-month-day-box-item"); + return eventItem && eventItem.item.title == "Modified Event"; + }, `${redoId} did not re-modify item in time`); + + Assert.equal(eventItem.item.title, "Modified Event", `#${redoId} redos item modification`); + + clearTransactions(); + await calendar.deleteItem(eventItem.item); +} + +/** + * Test the undo/redo functionality for event deletion. + * + * @param {string} undoId - The id of the "undo" menu item. + * @param {string} redoId - The id of the "redo" menu item. + */ +async function testDeleteUndoRedo(undoId, redoId) { + let undo = document.getElementById(undoId); + let redo = document.getElementById(redoId); + Assert.ok(await isDisabled(undo), `#${undoId} is disabled`); + Assert.ok(await isDisabled(redo), `#${redoId} is disabled`); + + let event = new CalEvent(); + event.title = "Deletable Event"; + event.startDate = cal.dtz.now(); + await calendar.addItem(event); + window.goToDate(event.startDate); + + let eventItem; + await TestUtils.waitForCondition(() => { + eventItem = document.querySelector("calendar-month-day-box-item"); + return eventItem; + }, "event not created in time"); + + EventUtils.synthesizeMouseAtCenter(eventItem, {}); + EventUtils.synthesizeKey("VK_DELETE"); + + await TestUtils.waitForCondition(() => { + eventItem = document.querySelector("calendar-month-day-box-item"); + return !eventItem; + }, "event not deleted in time"); + + Assert.ok(!(await isDisabled(undo)), `#${undoId} is enabled`); + Assert.ok(await isDisabled(redo), `#${redoId} is disabled`); + + // Test undo. + await clickItem(undo); + await TestUtils.waitForCondition(() => { + eventItem = document.querySelector("calendar-month-day-box-item"); + return eventItem; + }, `#${undoId} did not add event in time`); + Assert.ok(eventItem, `#${undoId} reverses item deletion`); + + // Test redo. + await clickItem(redo); + await TestUtils.waitForCondition(() => { + eventItem = document.querySelector("calendar-month-day-box-item"); + return !eventItem; + }, "redo did not delete item in time"); + + Assert.ok(!eventItem, `#${redoId} redos item deletion`); + clearTransactions(); +} + +/** + * Ensure the menu bar is visible and navigate the calendar view to today. + */ +add_setup(async function () { + registerCleanupFunction(() => { + CalendarTestUtils.removeCalendar(calendar); + }); + + clearTransactions(); + document.getElementById("toolbar-menubar").setAttribute("autohide", null); + await CalendarTestUtils.setCalendarView(window, "month"); + window.goToDate(cal.dtz.now()); +}); + +/** + * Tests the menu bar's undo/redo after adding an event. + */ +add_task(async function testMenuBarAddEventUndoRedo() { + return testAddUndoRedoEvent("menu_undo", "menu_redo"); +}).__skipMe = AppConstants.platform == "macosx"; // Can't click menu bar on Mac. + +/** + * Tests the menu bar's undo/redo after modifying an event. + */ +add_task(async function testMenuBarModifyEventUndoRedo() { + return testModifyUndoRedoEvent("menu_undo", "menu_redo"); +}).__skipMe = AppConstants.platform == "macosx"; // Can't click menu bar on Mac. + +/** + * Tests the menu bar's undo/redo after deleting an event. + */ +add_task(async function testMenuBarDeleteEventUndoRedo() { + return testDeleteUndoRedo("menu_undo", "menu_redo"); +}).__skipMe = AppConstants.platform == "macosx"; // Can't click menu bar on Mac. |