1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
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.
|