Bug 1801566 - Fix the message search dialog and its tests. r=aleca

Differential Revision: https://phabricator.services.mozilla.com/D163274

--HG--
extra : rebase_source : add4927602f163f24d1b96a2eeafb619ec874ac1
extra : amend_source : bfc2042ba3d4ae1db68dfb5c7729bd50b49b625d
This commit is contained in:
Geoff Lankow 2022-11-28 22:52:00 +13:00
Родитель 7586061fd0
Коммит a0314f254f
19 изменённых файлов: 187 добавлений и 174 удалений

Просмотреть файл

@ -17,6 +17,9 @@ var { PluralForm } = ChromeUtils.importESModule(
);
var { TagUtils } = ChromeUtils.import("resource:///modules/TagUtils.jsm");
var messenger;
var msgWindow;
var gCurrentFolder;
var gFolderDisplay;

Просмотреть файл

@ -37,6 +37,7 @@
<stringbundle id="bundle_messenger" src="chrome://messenger/locale/messenger.properties"/>
<stringbundle id="bundle_brand" src="chrome://branding/locale/brand.properties"/>
<script src="chrome://messenger/content/commandglue.js"/>
<script src="chrome://messenger/content/searchWidgets.js"/>
<script src="chrome://messenger/content/mailWindow.js"/>
<script src="chrome://messenger/content/folderDisplay.js"/>

Просмотреть файл

@ -664,7 +664,7 @@ var folderPaneContextMenu = {
topChromeWindow.MsgOpenNewWindowForFolder(gFolder.URI, -1);
break;
case "folderPaneContext-searchMessages":
topChromeWindow.gFolderTreeController.searchMessages(gFolder);
commandController.doCommand("cmd_searchMessages");
break;
case "folderPaneContext-subscribe":
topChromeWindow.MsgSubscribe(gFolder);

Просмотреть файл

@ -409,17 +409,6 @@ var gFolderTreeController = {
);
},
/**
* Opens a search window with the given folder, or the selected one if none
* is given.
*
* @param [aFolder] the folder to open the search window for, if different
* from the selected one
*/
searchMessages(aFolder) {
MsgSearchMessages(aFolder);
},
/**
* Prompts for confirmation, if the user hasn't already chosen the "don't ask
* again" option.

Просмотреть файл

@ -286,6 +286,15 @@ var commandController = {
cmd_space() {
// TODO: Implement
},
cmd_searchMessages() {
// We always open a new search dialog for each search command.
top.openDialog(
"chrome://messenger/content/SearchDialog.xhtml",
"_blank",
"chrome,resizable,status,centerscreen,dialog=no",
{ folder: gFolder }
);
},
},
_isCallbackEnabled: {},
@ -464,6 +473,9 @@ var commandController = {
case "cmd_applyFilters": {
return this._getViewCommandStatus(Ci.nsMsgViewCommandType.applyFilters);
}
case "cmd_searchMessages": {
return true;
}
}
return false;

Просмотреть файл

@ -2042,29 +2042,6 @@ function openGlodaSearchTab() {
document.getElementById("tabmail").openTab("glodaFacet");
}
/**
* Opens a search window with the given folder, or the displayed one if none is
* chosen.
*
* @param {nsIMsgFolder} folder - The folder to open the search window for, if
* different from the displayed one.
*/
function MsgSearchMessages(folder) {
// Don't trigger anything if there are no accounts configured. This is to
// disable potential triggers via shortcuts.
if (MailServices.accounts.accounts.length == 0) {
return;
}
// We always open a new search dialog for each search command
window.openDialog(
"chrome://messenger/content/SearchDialog.xhtml",
"_blank",
"chrome,resizable,status,centerscreen,dialog=no",
{ folder }
);
}
function MsgSearchAddresses() {
var args = { directory: null };
OpenOrFocusWindow(

Просмотреть файл

@ -134,6 +134,7 @@
<command id="cmd_findAgain" oncommand="goDoCommand('cmd_findAgain')" disabled="true"/>
<command id="cmd_findPrevious" oncommand="goDoCommand('cmd_findPrevious')"
disabled="true"/>
<command id="cmd_searchMessages" oncommand="goDoCommand('cmd_searchMessages');"/>
<!-- Stop/abort current network activities. -->
<command id="cmd_stop" oncommand="goDoCommand('cmd_stop')"/>
<command id="cmd_reload" oncommand="goDoCommand('cmd_reload')"/>

Просмотреть файл

@ -177,8 +177,8 @@
<!-- Tools Keys -->
<key id="key_searchMail"
key="&searchMailCmd.key;"
oncommand="MsgSearchMessages();"
modifiers="accel,shift"/>
modifiers="accel,shift"
command="cmd_searchMessages"/>
<key id="key_errorConsole"
key="&errorConsoleCmd.commandkey;"
oncommand="toJavaScriptConsole();"

Просмотреть файл

@ -281,7 +281,7 @@
<menuitem id="searchMailCmd" label="&searchMailCmd.label;"
key="key_searchMail"
accesskey="&searchMailCmd.accesskey;"
oncommand="MsgSearchMessages();"/>
command="cmd_searchMessages"/>
<menuitem id="glodaSearchCmd"
label="&glodaSearchCmd.label;"
accesskey="&glodaSearchCmd.accesskey;"

Просмотреть файл

@ -509,7 +509,7 @@
class="subviewbutton subviewbutton-iconic"
data-l10n-id="appmenu-tools-message-search"
key="key_searchMail"
oncommand="MsgSearchMessages();"/>
command="cmd_searchMessages"/>
<toolbarbutton id="appmenu_filtersCmd"
class="subviewbutton subviewbutton-iconic"
data-l10n-id="appmenu-tools-message-filters"

Просмотреть файл

@ -14,7 +14,6 @@ var {
assert_folder_selected,
assert_folder_selected_and_displayed,
assert_folders_selected_and_displayed,
assert_no_folders_selected,
assert_selected_tab,
be_in_folder,
close_popup,
@ -26,7 +25,6 @@ var {
reset_context_menu_background_tabs,
right_click_on_folder,
select_click_folder,
select_no_folders,
select_shift_click_folder,
set_context_menu_background_tabs,
switch_tab,
@ -49,27 +47,6 @@ add_setup(async function() {
await make_message_sets_in_folders([folderC], [{ count: 1 }]);
});
/**
* Make sure that a right-click when there is nothing currently selected does
* not cause us to display something, as well as correctly causing a transient
* selection to occur.
*/
add_task(async function test_right_click_folder_with_nothing_selected() {
// This should cause folderA to be displayed
await be_in_folder(folderA);
select_no_folders();
assert_no_folders_selected();
await right_click_on_folder(folderB);
assert_folder_selected(folderB);
// The displayed folder shouldn't change
assert_folder_displayed(folderA);
await close_popup(mc, getFoldersContext());
assert_no_folders_selected();
}).skip();
/**
* One-thing selected, right-click on something else.
*/
@ -130,33 +107,6 @@ add_task(async function test_right_click_folder_on_existing_multi_selection() {
assert_folders_selected_and_displayed(folderB, folderC);
}).skip();
/**
* Middle clicking should open a message in a tab, but not affect our selection.
*/
async function _middle_click_folder_with_nothing_selected_helper(aBackground) {
// This should cause folderA to be displayed
await be_in_folder(folderA);
select_no_folders();
assert_no_folders_selected();
let originalTab = mc.tabmail.currentTabInfo;
let [newTab] = middle_click_on_folder(folderA);
if (aBackground) {
// Make sure we haven't switched to the new tab.
assert_selected_tab(originalTab);
// Now switch to the new tab and check
await switch_tab(newTab);
}
assert_folder_selected_and_displayed(folderA);
close_tab(newTab);
// XXX This is wrong, we shouldn't have anything selected. Since we don't
// have a special state for nothing selected, we're giving this a pass for
// now.
assert_folder_selected_and_displayed(folderA);
}
/**
* One-thing selected, middle-click on something else.
*/

Просмотреть файл

@ -13,7 +13,6 @@ var {
inboxFolder,
make_message_sets_in_folders,
mc,
select_no_folders,
toggle_main_menu,
} = ChromeUtils.import(
"resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
@ -64,8 +63,6 @@ add_setup(async function() {
tree = mc.folderTreeView;
select_no_folders();
// Main menu is needed for this whole test file.
menu_state = toggle_main_menu(true);

Просмотреть файл

@ -7,9 +7,9 @@ prefs =
mailnews.start_page.url=about:blank
datareporting.policy.dataSubmissionPolicyBypassNotification=true
subsuite = thunderbird
skip-if = true # TODO
[browser_multipleSearchWindows.js]
[browser_rightClickToOpenSearchWindow.js]
[browser_searchWindow.js]
[browser_searchFromSyntheticView.js]
skip-if = true # TODO

Просмотреть файл

@ -73,19 +73,5 @@ add_task(
// Clean up, close both windows
close_search_window(swc1);
close_search_window(swc2);
Assert.report(
false,
undefined,
undefined,
"Test ran to completion successfully"
);
}
);
registerCleanupFunction(() => {
// Some tests that open new windows don't return focus to the main window
// in a way that satisfies mochitest, and the test times out.
Services.focus.focusedWindow = window;
window.gFolderDisplay.tree.focus();
});

Просмотреть файл

@ -6,12 +6,9 @@
var {
assert_folders_selected_and_displayed,
assert_no_folders_selected,
create_folder,
enter_folder,
select_click_folder,
select_no_folders,
show_folder_pane,
} = ChromeUtils.import(
"resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
);
@ -26,26 +23,10 @@ var {
var folderA, folderB;
add_setup(async function() {
show_folder_pane();
folderA = await create_folder("RightClickToOpenSearchWindowA");
folderB = await create_folder("RightClickToOpenSearchWindowB");
});
/**
* Test opening a search window while nothing is selected.
*/
add_task(async function test_open_search_window_with_nothing_selected() {
// Make sure the folders we need are visible
await enter_folder(folderB);
select_no_folders();
assert_no_folders_selected();
let swc = await open_search_window_from_context_menu(folderA);
assert_search_window_folder_displayed(swc, folderA);
close_search_window(swc);
});
/**
* Test opening a search window while the same folder is selected.
*/

Просмотреть файл

@ -10,6 +10,7 @@ const {
create_folder,
create_thread,
delete_messages,
get_about_3pane,
inboxFolder,
} = ChromeUtils.import(
"resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
@ -60,7 +61,7 @@ add_task(async function testSearchDialogFolderSelectedFromSyntheticView() {
GlodaMsgIndexer.indexFolder(folder, { callback, force: true });
});
let dbView = window.gFolderDisplay.view.dbView;
let dbView = get_about_3pane().gDBView;
await TestUtils.waitForCondition(
() =>
thread.synMessages.every((_, i) =>

Просмотреть файл

@ -25,8 +25,6 @@ var {
open_selected_messages,
plan_for_message_display,
reset_open_message_behavior,
select_click_row,
select_shift_click_row,
set_open_message_behavior,
switch_tab,
wait_for_all_messages_to_load,
@ -37,6 +35,9 @@ var {
var {
assert_search_window_folder_displayed,
open_search_window,
assert_messages_in_search_view,
select_click_search_row,
select_shift_click_search_row,
} = ChromeUtils.import(
"resource://testing-common/mozmill/SearchWindowHelpers.jsm"
);
@ -45,11 +46,10 @@ var {
async_plan_for_new_window,
plan_for_window_close,
wait_for_modal_dialog,
wait_for_new_window,
wait_for_window_close,
} = ChromeUtils.import("resource://testing-common/mozmill/WindowHelpers.jsm");
var folder, setFoo, setBar, setFooBar;
var folder, setFooBar;
// Number of messages to open for multi-message tests
var NUM_MESSAGES_TO_OPEN = 5;
@ -59,7 +59,7 @@ var NUM_MESSAGES_TO_OPEN = 5;
*/
add_task(async function test_create_messages() {
folder = await create_folder("SearchWindowA");
[setFoo, setBar, setFooBar] = await make_message_sets_in_folders(
[, , setFooBar] = await make_message_sets_in_folders(
[folder],
[{ subject: "foo" }, { subject: "bar" }, { subject: "foo bar" }]
);
@ -135,7 +135,7 @@ add_task(function test_go_search() {
wait_for_all_messages_to_load(swc);
// - Verify we got the right messages
assert_messages_in_view(setFooBar, swc);
assert_messages_in_search_view(setFooBar, swc);
// - Click the "Save as Search Folder" button, id "saveAsVFButton"
// This will create a virtual folder properties dialog...
@ -160,7 +160,7 @@ add_task(async function test_open_single_search_result_in_tab() {
// Select one message
swc.e("threadTree").focus();
let msgHdr = select_click_row(1, swc);
let msgHdr = select_click_search_row(1, swc);
// Open the selected message
open_selected_message(swc);
// This is going to trigger a message display in the main 3pane window
@ -169,7 +169,7 @@ add_task(async function test_open_single_search_result_in_tab() {
assert_number_of_tabs_open(preCount + 1);
// Check that the currently displayed tab is a message tab (i.e. our newly
// opened tab is in the foreground)
assert_tab_mode_name(null, "message");
assert_tab_mode_name(null, "mailMessageTab");
// Check that the message header displayed is the right one
assert_selected_and_displayed(msgHdr);
// Clean up, close the tab
@ -189,8 +189,11 @@ add_task(async function test_open_multiple_search_results_in_new_tabs() {
// Select a bunch of messages
swc.e("threadTree").focus();
select_click_row(1, swc);
let selectedMessages = select_shift_click_row(NUM_MESSAGES_TO_OPEN, swc);
select_click_search_row(1, swc);
let selectedMessages = select_shift_click_search_row(
NUM_MESSAGES_TO_OPEN,
swc
);
// Open them
open_selected_messages(swc);
// This is going to trigger a message display in the main 3pane window
@ -199,7 +202,7 @@ add_task(async function test_open_multiple_search_results_in_new_tabs() {
assert_number_of_tabs_open(preCount + NUM_MESSAGES_TO_OPEN);
// Check that the currently displayed tab is a message tab (i.e. one of our
// newly opened tabs is in the foreground)
assert_tab_mode_name(null, "message");
assert_tab_mode_name(null, "mailMessageTab");
// Now check whether each of the NUM_MESSAGES_TO_OPEN tabs has the correct
// title
@ -229,7 +232,7 @@ add_task(async function test_open_search_result_in_new_window() {
// Select a message
swc.e("threadTree").focus();
let msgHdr = select_click_row(1, swc);
let msgHdr = select_click_search_row(1, swc);
let newWindowPromise = async_plan_for_new_window("mail:messageWindow");
// Open it
@ -252,14 +255,14 @@ add_task(async function test_open_search_result_in_existing_window() {
// Open up a window
swc.e("threadTree").focus();
select_click_row(1, swc);
select_click_search_row(1, swc);
let newWindowPromise = async_plan_for_new_window("mail:messageWindow");
open_selected_message(swc);
let msgc = await newWindowPromise;
wait_for_message_display_completion(msgc, true);
// Select another message and open it
let msgHdr = select_click_row(2, swc);
let msgHdr = select_click_search_row(2, swc);
plan_for_message_display(msgc);
open_selected_message(swc);
wait_for_message_display_completion(msgc, true);

Просмотреть файл

@ -38,7 +38,6 @@ const EXPORTED_SYMBOLS = [
"assert_messages_not_in_view",
"assert_messages_summarized",
"assert_multimessage_pane_focused",
"assert_no_folders_selected",
"assert_not_selected_tab",
"assert_not_showing_unread_only",
"assert_not_shown",
@ -123,7 +122,6 @@ const EXPORTED_SYMBOLS = [
"select_click_row",
"select_column_click_row",
"select_control_click_row",
"select_no_folders",
"select_none",
"select_shift_click_folder",
"select_shift_click_row",
@ -1439,17 +1437,6 @@ function assert_folder_expanded(aFolder) {
}
}
/**
* Clear the selection in the folder tree view.
*/
function select_no_folders() {
wait_for_message_display_completion();
mc.folderTreeView.selection.clearSelection();
mark_action("fdh", "select_no_folder", []);
// give the event queue a chance to drain...
mc.sleep(0);
}
/**
* Pretend we are clicking on a folder with our mouse.
*
@ -2249,7 +2236,7 @@ function assert_selected(...aArgs) {
let [troller, desiredIndices] = _process_row_message_arguments(...aArgs);
// - get the actual selection (already sorted by integer value)
let selectedIndices = get_about_3pane_or_about_message().gDBView.getIndicesForSelection();
let selectedIndices = get_db_view(troller.window).getIndicesForSelection();
// - test selection equivalence
// which is the same as string equivalence in this case. muah hah hah.
@ -2946,7 +2933,6 @@ function assert_folders_selected_and_displayed(...aArgs) {
}
}
var assert_no_folders_selected = assert_folders_selected_and_displayed;
var assert_folder_selected_and_displayed = assert_folders_selected_and_displayed;
/**

Просмотреть файл

@ -5,24 +5,29 @@
"use strict";
const EXPORTED_SYMBOLS = [
"assert_messages_in_search_view",
"assert_search_window_folder_displayed",
"close_search_window",
"open_search_window",
"open_search_window_from_context_menu",
"close_search_window",
"assert_search_window_folder_displayed",
"select_click_search_row",
"select_shift_click_search_row",
];
var folderDisplayHelper = ChromeUtils.import(
var { get_about_3pane, mc, right_click_on_folder } = ChromeUtils.import(
"resource://testing-common/mozmill/FolderDisplayHelpers.jsm"
);
var windowHelper = ChromeUtils.import(
"resource://testing-common/mozmill/WindowHelpers.jsm"
);
var { Assert } = ChromeUtils.importESModule(
"resource://testing-common/Assert.sys.mjs"
);
var EventUtils = ChromeUtils.import(
"resource://testing-common/mozmill/EventUtils.jsm"
);
var mc = folderDisplayHelper.mc;
/**
* Open a search window using the accel-shift-f shortcut.
*
@ -42,15 +47,14 @@ function open_search_window() {
* @returns the controller for the search window
*/
async function open_search_window_from_context_menu(aFolder) {
await folderDisplayHelper.right_click_on_folder(aFolder);
let win = get_about_3pane();
let context = win.document.getElementById("folderPaneContext");
let item = win.document.getElementById("folderPaneContext-searchMessages");
await right_click_on_folder(aFolder);
windowHelper.plan_for_new_window("mailnews:search");
mc.folderTreeController.searchMessages();
let swc = windowHelper.wait_for_new_window("mailnews:search");
await folderDisplayHelper.close_popup(mc, mc.e("folderPaneContext"));
return swc;
context.activateItem(item);
return windowHelper.wait_for_new_window("mailnews:search");
}
/**
@ -66,12 +70,134 @@ function close_search_window(aController) {
*/
function assert_search_window_folder_displayed(aController, aFolder) {
let currentFolder = aController.currentFolder;
if (currentFolder != aFolder) {
throw new Error(
"The search window's selected folder should have been: " +
aFolder.prettyName +
", but is actually: " +
currentFolder.prettyName
Assert.equal(
currentFolder,
aFolder,
"The search window's selected folder should have been: " +
aFolder.prettyName +
", but is actually: " +
currentFolder?.prettyName
);
}
/**
* Pretend we are clicking on a row with our mouse.
*
* @param {number} aViewIndex - The view index to click.
* @param {MozMillController} aController - The controller in whose context to
* do this.
* @returns {nsIMsgDBHdr} The message header selected.
*/
function select_click_search_row(aViewIndex, aController) {
if (aController == null) {
aController = mc;
}
let tree = aController.threadTree;
let coords = tree.getCoordsForCellItem(
aViewIndex,
tree.columns.subjectCol,
"cell"
);
let treeChildren = tree.lastElementChild;
EventUtils.synthesizeMouse(
treeChildren,
coords.x + coords.width / 2,
coords.y + coords.height / 2,
{},
aController.window
);
return aController.dbView.getMsgHdrAt(aViewIndex);
}
/**
* Pretend we are clicking on a row with our mouse with the shift key pressed,
* adding all the messages between the shift pivot and the shift selected row.
*
* @param {number} aViewIndex - The view index to click.
* @param {MozMillController} aController The controller in whose context to
* do this.
* @returns {nsIMsgDBHdr[]} The message headers for all messages that are now
* selected.
*/
function select_shift_click_search_row(aViewIndex, aController) {
if (aController == null) {
aController = mc;
}
let tree = aController.threadTree;
let coords = tree.getCoordsForCellItem(
aViewIndex,
tree.columns.subjectCol,
"cell"
);
let treeChildren = tree.lastElementChild;
EventUtils.synthesizeMouse(
treeChildren,
coords.x + coords.width / 2,
coords.y + coords.height / 2,
{ shiftKey: true },
aController.window
);
aController.sleep(0);
return aController.folderDisplay.selectedMessages;
}
/**
* Assert that the given synthetic message sets are present in the folder
* display.
*
* Verify that the messages in the provided SyntheticMessageSets are the only
* visible messages in the provided DBViewWrapper.
*
* @param {SyntheticMessageSet} aSynSets - Either a single SyntheticMessageSet
* or a list of them.
* @param {MozMillController} aController - The controller which we get the
* folderDisplay property from.
*/
function assert_messages_in_search_view(aSynSets, aController) {
if (aController == null) {
aController = mc;
}
if (!Array.isArray(aSynSets)) {
aSynSets = [aSynSets];
}
// Iterate over all the message sets, retrieving the message header. Use
// this to construct a URI to populate a dictionary mapping.
let synMessageURIs = {}; // map URI to message header
for (let messageSet of aSynSets) {
for (let msgHdr of messageSet.msgHdrs()) {
synMessageURIs[msgHdr.folder.getUriForMsg(msgHdr)] = msgHdr;
}
}
// Iterate over the contents of the view, nulling out values in
// synMessageURIs for found messages, and exploding for missing ones.
let dbView = aController.folderDisplay.view.dbView;
let treeView = aController.folderDisplay.view.dbView.QueryInterface(
Ci.nsITreeView
);
let rowCount = treeView.rowCount;
for (let iViewIndex = 0; iViewIndex < rowCount; iViewIndex++) {
let msgHdr = dbView.getMsgHdrAt(iViewIndex);
let uri = msgHdr.folder.getUriForMsg(msgHdr);
Assert.ok(
uri in synMessageURIs,
"The view should show the message header" + msgHdr.messageKey
);
delete synMessageURIs[uri];
}
// Iterate over our URI set and make sure every message was shown.
for (let uri in synMessageURIs) {
let msgHdr = synMessageURIs[uri];
Assert.ok(
false,
"The view is should include the message header" + msgHdr.messageKey
);
}
}