|
|
|
Lines 45-60
Cu.import('resource://mozmill/stdlib/Eve
|
Link Here
|
|---|
|
| 45 |
var mozmill = {}; |
45 |
var mozmill = {}; |
| 46 |
Cu.import('resource://mozmill/modules/mozmill.js', mozmill); |
46 |
Cu.import('resource://mozmill/modules/mozmill.js', mozmill); |
| 47 |
var controller = {}; |
47 |
var controller = {}; |
| 48 |
Cu.import('resource://mozmill/modules/controller.js', controller); |
48 |
Cu.import('resource://mozmill/modules/controller.js', controller); |
| 49 |
var frame = {}; |
49 |
var frame = {}; |
| 50 |
Cu.import('resource://mozmill/modules/frame.js', frame); |
50 |
Cu.import('resource://mozmill/modules/frame.js', frame); |
| 51 |
var os = {}; |
51 |
var os = {}; |
| 52 |
Cu.import('resource://mozmill/stdlib/os.js', os); |
52 |
Cu.import('resource://mozmill/stdlib/os.js', os); |
|
|
53 |
var utils = {}; |
| 54 |
Cu.import('resource://mozmill/modules/utils.js', utils); |
| 53 |
|
55 |
|
| 54 |
Cu.import("resource:///modules/gloda/log4moz.js"); |
56 |
Cu.import("resource:///modules/gloda/log4moz.js"); |
| 55 |
|
57 |
|
| 56 |
const MODULE_NAME = 'folder-display-helpers'; |
58 |
const MODULE_NAME = 'folder-display-helpers'; |
| 57 |
|
59 |
|
| 58 |
const RELATIVE_ROOT = '../shared-modules'; |
60 |
const RELATIVE_ROOT = '../shared-modules'; |
| 59 |
// we need window-helpers for augment_controller |
61 |
// we need window-helpers for augment_controller |
| 60 |
const MODULE_REQUIRES = ['window-helpers']; |
62 |
const MODULE_REQUIRES = ['window-helpers']; |
|
Lines 409-427
function teardownImporter(customTeardown
|
Link Here
|
|---|
|
| 409 |
/* |
411 |
/* |
| 410 |
* Although we all agree that the use of generators when dealing with async |
412 |
* Although we all agree that the use of generators when dealing with async |
| 411 |
* operations is awesome, the mozmill idiom is for calls to be synchronous and |
413 |
* operations is awesome, the mozmill idiom is for calls to be synchronous and |
| 412 |
* just spin event loops when they need to wait for things to happen. This |
414 |
* just spin event loops when they need to wait for things to happen. This |
| 413 |
* does make the test code significantly less confusing, so we do it too. |
415 |
* does make the test code significantly less confusing, so we do it too. |
| 414 |
* All of our operations are synchronous and just spin until they are happy. |
416 |
* All of our operations are synchronous and just spin until they are happy. |
| 415 |
*/ |
417 |
*/ |
| 416 |
|
418 |
|
| 417 |
const NORMAL_TIMEOUT = 6000; |
|
|
| 418 |
const FAST_INTERVAL = 100; |
| 419 |
|
| 420 |
/** |
419 |
/** |
| 421 |
* Create a folder and rebuild the folder tree view. |
420 |
* Create a folder and rebuild the folder tree view. |
| 422 |
*/ |
421 |
*/ |
| 423 |
function create_folder(aFolderName) { |
422 |
function create_folder(aFolderName) { |
| 424 |
let folder = testHelperModule.make_empty_folder(aFolderName); |
423 |
let folder = testHelperModule.make_empty_folder(aFolderName); |
| 425 |
mc.folderTreeView.mode = "all"; |
424 |
mc.folderTreeView.mode = "all"; |
| 426 |
return folder; |
425 |
return folder; |
| 427 |
} |
426 |
} |
|
Lines 483-501
function enter_folder(aFolder) {
|
Link Here
|
|---|
|
| 483 |
mark_action("fdh", "enter_folder", [aFolder]); |
482 |
mark_action("fdh", "enter_folder", [aFolder]); |
| 484 |
|
483 |
|
| 485 |
// this selection event may not be synchronous... |
484 |
// this selection event may not be synchronous... |
| 486 |
mc.folderTreeView.selectFolder(aFolder); |
485 |
mc.folderTreeView.selectFolder(aFolder); |
| 487 |
// ... so wait until it goes through by waiting on the displayedFolder... |
486 |
// ... so wait until it goes through by waiting on the displayedFolder... |
| 488 |
function isDisplayedFolder() { |
487 |
function isDisplayedFolder() { |
| 489 |
return mc.folderDisplay.displayedFolder == aFolder; |
488 |
return mc.folderDisplay.displayedFolder == aFolder; |
| 490 |
} |
489 |
} |
| 491 |
if (!controller.waitForEval('subject()', NORMAL_TIMEOUT, FAST_INTERVAL, |
490 |
utils.waitFor(isDisplayedFolder, |
| 492 |
isDisplayedFolder)) |
491 |
"Timeout trying to enter folder" + aFolder.URI); |
| 493 |
mark_failure(["Timeout trying to enter folder", aFolder.URI]); |
|
|
| 494 |
|
492 |
|
| 495 |
wait_for_all_messages_to_load(); |
493 |
wait_for_all_messages_to_load(); |
| 496 |
|
494 |
|
| 497 |
// and drain the event queue |
495 |
// and drain the event queue |
| 498 |
controller.sleep(0); |
496 |
controller.sleep(0); |
| 499 |
} |
497 |
} |
| 500 |
|
498 |
|
| 501 |
/** |
499 |
/** |
|
Lines 872-889
function select_none(aController) {
|
Link Here
|
|---|
|
| 872 |
focus_thread_tree(); |
870 |
focus_thread_tree(); |
| 873 |
aController.dbView.selection.clearSelection(); |
871 |
aController.dbView.selection.clearSelection(); |
| 874 |
// Because the selection event may not be generated immediately, we need to |
872 |
// Because the selection event may not be generated immediately, we need to |
| 875 |
// spin until the message display thinks it is not displaying a message, |
873 |
// spin until the message display thinks it is not displaying a message, |
| 876 |
// which is the sign that the event actually happened. |
874 |
// which is the sign that the event actually happened. |
| 877 |
function noMessageChecker() { |
875 |
function noMessageChecker() { |
| 878 |
return aController.messageDisplay.displayedMessage == null; |
876 |
return aController.messageDisplay.displayedMessage == null; |
| 879 |
} |
877 |
} |
| 880 |
controller.sleep('subject()', |
878 |
try { |
| 881 |
NORMAL_TIMEOUT, FAST_INTERVAL, noMessageChecker); |
879 |
utils.waitFor(noMessageChecker); |
|
|
880 |
} catch (e if e instanceof utils.TimeoutError) { |
| 881 |
mark_failure(["Timeout waiting for displayedMessage to become null.", |
| 882 |
"Current value: ", |
| 883 |
aController.messageDisplay.displayedMessage]); |
| 884 |
} |
| 882 |
wait_for_blank_content_pane(aController); |
885 |
wait_for_blank_content_pane(aController); |
| 883 |
} |
886 |
} |
| 884 |
|
887 |
|
| 885 |
/** |
888 |
/** |
| 886 |
* Normalize a view index to be an absolute index, handling slice-style negative |
889 |
* Normalize a view index to be an absolute index, handling slice-style negative |
| 887 |
* references as well as piercing complex things like message headers and |
890 |
* references as well as piercing complex things like message headers and |
| 888 |
* synthetic message sets. |
891 |
* synthetic message sets. |
| 889 |
* |
892 |
* |
|
Lines 1357-1373
function delete_via_popup() {
|
Link Here
|
|---|
|
| 1357 |
mc.click(mc.eid("mailContext-delete")); |
1360 |
mc.click(mc.eid("mailContext-delete")); |
| 1358 |
// for reasons unknown, the pop-up does not close itself? |
1361 |
// for reasons unknown, the pop-up does not close itself? |
| 1359 |
close_popup(mc, mc.eid("mailContext")); |
1362 |
close_popup(mc, mc.eid("mailContext")); |
| 1360 |
wait_for_folder_events(); |
1363 |
wait_for_folder_events(); |
| 1361 |
} |
1364 |
} |
| 1362 |
|
1365 |
|
| 1363 |
function wait_for_popup_to_open(popupElem) { |
1366 |
function wait_for_popup_to_open(popupElem) { |
| 1364 |
mark_action("fdh", "wait_for_popup_to_open", [popupElem]); |
1367 |
mark_action("fdh", "wait_for_popup_to_open", [popupElem]); |
| 1365 |
mc.waitForEval("subject.state == 'open'", 1000, 50, popupElem); |
1368 |
utils.waitFor(function () popupElem.state == "open", |
|
|
1369 |
"Timeout waiting for popup to open", 1000, 50); |
| 1366 |
} |
1370 |
} |
| 1367 |
|
1371 |
|
| 1368 |
/** |
1372 |
/** |
| 1369 |
* Close the open pop-up. |
1373 |
* Close the open pop-up. |
| 1370 |
*/ |
1374 |
*/ |
| 1371 |
function close_popup(aController, eid) { |
1375 |
function close_popup(aController, eid) { |
| 1372 |
if (aController == null) |
1376 |
if (aController == null) |
| 1373 |
aController = mc; |
1377 |
aController = mc; |
|
Lines 1380-1398
function close_popup(aController, eid) {
|
Link Here
|
|---|
|
| 1380 |
} |
1384 |
} |
| 1381 |
mark_action("fdh", "close_popup", [elem]); |
1385 |
mark_action("fdh", "close_popup", [elem]); |
| 1382 |
// if it's in the process of closing, don't push escape |
1386 |
// if it's in the process of closing, don't push escape |
| 1383 |
if (elem.state == "hiding") |
1387 |
if (elem.state == "hiding") |
| 1384 |
mark_action("fdh", "close_popup", |
1388 |
mark_action("fdh", "close_popup", |
| 1385 |
["popup suspiciously already closing..."]); |
1389 |
["popup suspiciously already closing..."]); |
| 1386 |
else // actually push escape because it's not closing/closed |
1390 |
else // actually push escape because it's not closing/closed |
| 1387 |
aController.keypress(eid, "VK_ESCAPE", {}); |
1391 |
aController.keypress(eid, "VK_ESCAPE", {}); |
| 1388 |
if (!controller.waitForEval("subject.state == 'closed'", 1000, 50, |
1392 |
utils.waitFor(function () elem.state == "closed", "Popup did not close!", |
| 1389 |
elem)) |
1393 |
1000, 50); |
| 1390 |
throw new Error("Popup did not close!"); |
|
|
| 1391 |
} |
1394 |
} |
| 1392 |
|
1395 |
|
| 1393 |
/** |
1396 |
/** |
| 1394 |
* Pretend we are pressing the delete key, triggering message deletion of the |
1397 |
* Pretend we are pressing the delete key, triggering message deletion of the |
| 1395 |
* selected messages. |
1398 |
* selected messages. |
| 1396 |
* |
1399 |
* |
| 1397 |
* @param aController The controller in whose context to do this, defaults to |
1400 |
* @param aController The controller in whose context to do this, defaults to |
| 1398 |
* |mc| if omitted. |
1401 |
* |mc| if omitted. |
|
Lines 1437-1455
function archive_selected_messages(aCont
|
Link Here
|
|---|
|
| 1437 |
if (expectedCount && aController.messageDisplay.visible) |
1440 |
if (expectedCount && aController.messageDisplay.visible) |
| 1438 |
plan_for_message_display(aController); |
1441 |
plan_for_message_display(aController); |
| 1439 |
aController.keypress(null, "a", {}); |
1442 |
aController.keypress(null, "a", {}); |
| 1440 |
|
1443 |
|
| 1441 |
// Wait for the view rowCount to decrease by the number of selected messages. |
1444 |
// Wait for the view rowCount to decrease by the number of selected messages. |
| 1442 |
let messagesDeletedFromView = function() { |
1445 |
let messagesDeletedFromView = function() { |
| 1443 |
return aController.dbView.rowCount == expectedCount; |
1446 |
return aController.dbView.rowCount == expectedCount; |
| 1444 |
}; |
1447 |
}; |
| 1445 |
controller.waitForEval('subject()', |
1448 |
utils.waitFor(messagesDeletedFromView, |
| 1446 |
NORMAL_TIMEOUT, |
1449 |
"Timeout waiting for messages to be archived"); |
| 1447 |
FAST_INTERVAL, messagesDeletedFromView); |
|
|
| 1448 |
wait_for_message_display_completion( |
1450 |
wait_for_message_display_completion( |
| 1449 |
aController, expectedCount && aController.messageDisplay.visible); |
1451 |
aController, expectedCount && aController.messageDisplay.visible); |
| 1450 |
// The above may return immediately, meaning the event queue might not get a |
1452 |
// The above may return immediately, meaning the event queue might not get a |
| 1451 |
// chance. give it a chance now. |
1453 |
// chance. give it a chance now. |
| 1452 |
aController.sleep(0); |
1454 |
aController.sleep(0); |
| 1453 |
} |
1455 |
} |
| 1454 |
|
1456 |
|
| 1455 |
/** |
1457 |
/** |
|
Lines 1481-1499
function press_enter(aController) {
|
Link Here
|
|---|
|
| 1481 |
* search. |
1483 |
* search. |
| 1482 |
* This method is generally called automatically most of the time, and you |
1484 |
* This method is generally called automatically most of the time, and you |
| 1483 |
* should not need to call it yourself unless you are operating outside the |
1485 |
* should not need to call it yourself unless you are operating outside the |
| 1484 |
* helper methods in this file. |
1486 |
* helper methods in this file. |
| 1485 |
*/ |
1487 |
*/ |
| 1486 |
function wait_for_all_messages_to_load(aController) { |
1488 |
function wait_for_all_messages_to_load(aController) { |
| 1487 |
if (aController == null) |
1489 |
if (aController == null) |
| 1488 |
aController = mc; |
1490 |
aController = mc; |
| 1489 |
if (!controller.waitForEval('subject.allMessagesLoaded', NORMAL_TIMEOUT, |
1491 |
utils.waitFor(function () aController.folderDisplay.allMessagesLoaded, |
| 1490 |
FAST_INTERVAL, aController.folderDisplay)) |
1492 |
"Messages never finished loading. Timed Out."); |
| 1491 |
mark_failure(["Messages never finished loading. Timed Out."]); |
|
|
| 1492 |
// the above may return immediately, meaning the event queue might not get a |
1493 |
// the above may return immediately, meaning the event queue might not get a |
| 1493 |
// chance. give it a chance now. |
1494 |
// chance. give it a chance now. |
| 1494 |
aController.sleep(0); |
1495 |
aController.sleep(0); |
| 1495 |
} |
1496 |
} |
| 1496 |
|
1497 |
|
| 1497 |
/** |
1498 |
/** |
| 1498 |
* Call this before triggering a message display that you are going to wait for |
1499 |
* Call this before triggering a message display that you are going to wait for |
| 1499 |
* using |wait_for_message_display_completion| where you are passing true for |
1500 |
* using |wait_for_message_display_completion| where you are passing true for |
|
Lines 1590-1608
function wait_for_message_display_comple
|
Link Here
|
|---|
|
| 1590 |
let urlRunningObj = {}; |
1591 |
let urlRunningObj = {}; |
| 1591 |
uri.GetUrlState(urlRunningObj); |
1592 |
uri.GetUrlState(urlRunningObj); |
| 1592 |
// GetUrlState returns true if the url is still running |
1593 |
// GetUrlState returns true if the url is still running |
| 1593 |
return !urlRunningObj.value; |
1594 |
return !urlRunningObj.value; |
| 1594 |
} |
1595 |
} |
| 1595 |
// not a mailnews URL, just check the busy flags... |
1596 |
// not a mailnews URL, just check the busy flags... |
| 1596 |
return !docShell.busyFlags; |
1597 |
return !docShell.busyFlags; |
| 1597 |
}; |
1598 |
}; |
| 1598 |
if (!controller.waitForEval('subject()', NORMAL_TIMEOUT, FAST_INTERVAL, |
1599 |
utils.waitFor(isLoadedChecker, |
| 1599 |
isLoadedChecker)) |
1600 |
"Timed out waiting for message display completion."); |
| 1600 |
mark_failure(["Timed out waiting for message display completion."]); |
|
|
| 1601 |
// the above may return immediately, meaning the event queue might not get a |
1601 |
// the above may return immediately, meaning the event queue might not get a |
| 1602 |
// chance. give it a chance now. |
1602 |
// chance. give it a chance now. |
| 1603 |
aController.sleep(0); |
1603 |
aController.sleep(0); |
| 1604 |
mark_action("fdhb", "/wait_for_message_display_completion", |
1604 |
mark_action("fdhb", "/wait_for_message_display_completion", |
| 1605 |
["waited?", checkCount > 1]); |
1605 |
["waited?", checkCount > 1]); |
| 1606 |
} |
1606 |
} |
| 1607 |
|
1607 |
|
| 1608 |
/** |
1608 |
/** |
|
Lines 1615-1634
function wait_for_message_display_comple
|
Link Here
|
|---|
|
| 1615 |
function wait_for_blank_content_pane(aController) { |
1615 |
function wait_for_blank_content_pane(aController) { |
| 1616 |
if (aController == null) |
1616 |
if (aController == null) |
| 1617 |
aController = mc; |
1617 |
aController = mc; |
| 1618 |
mark_action("fdh", "wait_for_blank_content_pane", []); |
1618 |
mark_action("fdh", "wait_for_blank_content_pane", []); |
| 1619 |
|
1619 |
|
| 1620 |
let isBlankChecker = function() { |
1620 |
let isBlankChecker = function() { |
| 1621 |
return aController.window.content.location.href == "about:blank"; |
1621 |
return aController.window.content.location.href == "about:blank"; |
| 1622 |
}; |
1622 |
}; |
| 1623 |
if (!controller.waitForEval('subject()', NORMAL_TIMEOUT, FAST_INTERVAL, |
1623 |
try { |
| 1624 |
isBlankChecker)) |
1624 |
utils.waitFor(isBlankChecker); |
|
|
1625 |
} catch (e if e instanceof utils.TimeoutError) { |
| 1625 |
mark_failure(["Timeout waiting for blank content pane. Current location:", |
1626 |
mark_failure(["Timeout waiting for blank content pane. Current location:", |
| 1626 |
aController.window.content.location.href]); |
1627 |
aController.window.content.location.href]); |
|
|
1628 |
} |
| 1629 |
|
| 1627 |
// the above may return immediately, meaning the event queue might not get a |
1630 |
// the above may return immediately, meaning the event queue might not get a |
| 1628 |
// chance. give it a chance now. |
1631 |
// chance. give it a chance now. |
| 1629 |
aController.sleep(0); |
1632 |
aController.sleep(0); |
| 1630 |
mark_action("fdh", "/wait_for_blank_content_pane", []); |
1633 |
mark_action("fdh", "/wait_for_blank_content_pane", []); |
| 1631 |
} |
1634 |
} |
| 1632 |
|
1635 |
|
| 1633 |
|
1636 |
|
| 1634 |
var FolderListener = { |
1637 |
var FolderListener = { |
|
Lines 1652-1670
var FolderListener = {
|
Link Here
|
|---|
|
| 1652 |
this.sawEvents = false; |
1655 |
this.sawEvents = false; |
| 1653 |
this.watchingFor = []; |
1656 |
this.watchingFor = []; |
| 1654 |
for (let i = 0; i < arguments.length; i++) |
1657 |
for (let i = 0; i < arguments.length; i++) |
| 1655 |
this.watchingFor[i] = arguments[i]; |
1658 |
this.watchingFor[i] = arguments[i]; |
| 1656 |
}, |
1659 |
}, |
| 1657 |
waitForEvents: function FolderListener_waitForEvents() { |
1660 |
waitForEvents: function FolderListener_waitForEvents() { |
| 1658 |
if (this.sawEvents) |
1661 |
if (this.sawEvents) |
| 1659 |
return; |
1662 |
return; |
| 1660 |
if (!controller.waitForEval('subject.sawEvents', NORMAL_TIMEOUT, |
1663 |
let self = this; |
| 1661 |
FAST_INTERVAL, this)) |
1664 |
try { |
|
|
1665 |
utils.waitFor(function () self.sawEvents); |
| 1666 |
} catch (e if e instanceof utils.TimeoutError) { |
| 1662 |
mark_failure(["Timeout waiting for events:", this.watchingFor]); |
1667 |
mark_failure(["Timeout waiting for events:", this.watchingFor]); |
|
|
1668 |
} |
| 1663 |
}, |
1669 |
}, |
| 1664 |
|
1670 |
|
| 1665 |
OnItemEvent: function FolderNotificationHelper_OnItemEvent( |
1671 |
OnItemEvent: function FolderNotificationHelper_OnItemEvent( |
| 1666 |
aFolder, aEvent) { |
1672 |
aFolder, aEvent) { |
| 1667 |
if (!this.watchingFor) |
1673 |
if (!this.watchingFor) |
| 1668 |
return; |
1674 |
return; |
| 1669 |
if (this.watchingFor.indexOf(aEvent.toString()) != -1) { |
1675 |
if (this.watchingFor.indexOf(aEvent.toString()) != -1) { |
| 1670 |
this.watchingFor = null; |
1676 |
this.watchingFor = null; |