diff options
Diffstat (limited to 'comm/mail/test/browser/quick-filter-bar/browser_filterLogic.js')
-rw-r--r-- | comm/mail/test/browser/quick-filter-bar/browser_filterLogic.js | 462 |
1 files changed, 462 insertions, 0 deletions
diff --git a/comm/mail/test/browser/quick-filter-bar/browser_filterLogic.js b/comm/mail/test/browser/quick-filter-bar/browser_filterLogic.js new file mode 100644 index 0000000000..fb863ea154 --- /dev/null +++ b/comm/mail/test/browser/quick-filter-bar/browser_filterLogic.js @@ -0,0 +1,462 @@ +/* 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/. */ + +/** + * Verify that we are constructing the filters that we expect and that they + * are hooked up to the right buttons. + */ + +"use strict"; + +var { + assert_messages_in_view, + assert_messages_not_in_view, + be_in_folder, + create_folder, + delete_messages, + get_about_3pane, + make_message_sets_in_folders, + mc, +} = ChromeUtils.import( + "resource://testing-common/mozmill/FolderDisplayHelpers.jsm" +); +var { + assert_quick_filter_bar_visible, + assert_results_label_count, + assert_text_constraints_checked, + clear_constraints, + set_filter_text, + toggle_boolean_constraints, + toggle_quick_filter_bar, + toggle_tag_constraints, + toggle_tag_mode, + toggle_text_constraints, + cleanup_qfb_button, +} = ChromeUtils.import( + "resource://testing-common/mozmill/QuickFilterBarHelpers.jsm" +); + +var { MailServices } = ChromeUtils.import( + "resource:///modules/MailServices.jsm" +); + +add_setup(async function () { + // Quick filter bar is hidden by default, need to toggle it on. To toggle + // quick filter bar, need to be inside folder + const folder = await create_folder("QuickFilterBarFilterFilterLogicSetup"); + await be_in_folder(folder); + await ensure_table_view(); + await toggle_quick_filter_bar(); + + registerCleanupFunction(async function () { + await ensure_cards_view(); + await cleanup_qfb_button(); + // Quick filter bar is hidden by default, need to toggle it off. + await toggle_quick_filter_bar(); + }); +}); + +add_task(async function test_filter_unread() { + let folder = await create_folder("QuickFilterBarFilterUnread"); + let [unread, read] = await make_message_sets_in_folders( + [folder], + [{ count: 1 }, { count: 1 }] + ); + read.setRead(true); + + await be_in_folder(folder); + toggle_boolean_constraints("unread"); + assert_messages_in_view(unread); + teardownTest(); +}); + +add_task(async function test_filter_starred() { + let folder = await create_folder("QuickFilterBarFilterStarred"); + let [, starred] = await make_message_sets_in_folders( + [folder], + [{ count: 1 }, { count: 1 }] + ); + starred.setStarred(true); + + await be_in_folder(folder); + toggle_boolean_constraints("starred"); + assert_messages_in_view(starred); + teardownTest(); +}); + +add_task(async function test_filter_simple_intersection_unread_and_starred() { + let folder = await create_folder("QuickFilterBarFilterUnreadAndStarred"); + let [, readUnstarred, unreadStarred, readStarred] = + await make_message_sets_in_folders( + [folder], + [{ count: 1 }, { count: 1 }, { count: 1 }, { count: 1 }] + ); + readUnstarred.setRead(true); + unreadStarred.setStarred(true); + readStarred.setRead(true); + readStarred.setStarred(true); + + await be_in_folder(folder); + toggle_boolean_constraints("unread", "starred"); + + assert_messages_in_view(unreadStarred); + teardownTest(); +}); + +add_task(async function test_filter_attachments() { + let attachSetDef = { + count: 1, + attachments: [ + { + filename: "foo.png", + contentType: "image/png", + encoding: "base64", + charset: null, + body: "YWJj\n", + format: null, + }, + ], + }; + let noAttachSetDef = { + count: 1, + }; + + let folder = await create_folder("QuickFilterBarFilterAttachments"); + let [, setAttach] = await make_message_sets_in_folders( + [folder], + [noAttachSetDef, attachSetDef] + ); + + await be_in_folder(folder); + toggle_boolean_constraints("attachments"); + + assert_messages_in_view(setAttach); + teardownTest(); +}); + +/** + * Create a card for the given e-mail address, adding it to the first address + * book we can find. + */ +function add_email_to_address_book(aEmailAddr) { + let card = Cc["@mozilla.org/addressbook/cardproperty;1"].createInstance( + Ci.nsIAbCard + ); + card.primaryEmail = aEmailAddr; + + for (let addrbook of MailServices.ab.directories) { + addrbook.addCard(card); + return; + } + + throw new Error("Unable to find any suitable address book."); +} + +add_task(async function test_filter_in_address_book() { + let bookSetDef = { + from: ["Qbert Q Qbington", "q@q.invalid"], + count: 1, + }; + add_email_to_address_book(bookSetDef.from[1]); + let folder = await create_folder("MesssageFilterBarInAddressBook"); + let [setBook] = await make_message_sets_in_folders( + [folder], + [bookSetDef, { count: 1 }] + ); + await be_in_folder(folder); + toggle_boolean_constraints("addrbook"); + assert_messages_in_view(setBook); + teardownTest(); +}); + +add_task(async function test_filter_tags() { + let folder = await create_folder("QuickFilterBarTags"); + const tagA = "$label1", + tagB = "$label2", + tagC = "$label3"; + let [setNoTag, setTagA, setTagB, setTagAB, setTagC] = + await make_message_sets_in_folders( + [folder], + [{ count: 1 }, { count: 1 }, { count: 1 }, { count: 1 }, { count: 1 }] + ); + setTagA.addTag(tagA); + setTagB.addTag(tagB); + setTagAB.addTag(tagA); + setTagAB.addTag(tagB); + setTagC.addTag(tagC); + + await be_in_folder(folder); + toggle_boolean_constraints("tags"); // must have a tag + assert_messages_in_view([setTagA, setTagB, setTagAB, setTagC]); + + toggle_tag_constraints(tagA); // must have tag A + assert_messages_in_view([setTagA, setTagAB]); + + toggle_tag_constraints(tagB); + // mode is OR by default -> must have tag A or tag B + assert_messages_in_view([setTagA, setTagB, setTagAB]); + + toggle_tag_mode(); + // mode is now AND -> must have tag A and tag B + assert_messages_in_view([setTagAB]); + + toggle_tag_constraints(tagA); // must have tag B + assert_messages_in_view([setTagB, setTagAB]); + + toggle_tag_constraints(tagB); // have have a tag + assert_messages_in_view([setTagA, setTagB, setTagAB, setTagC]); + + toggle_boolean_constraints("tags"); // no constraints + assert_messages_in_view([setNoTag, setTagA, setTagB, setTagAB, setTagC]); + + // If we have filtered to a specific tag and we disable the tag filter + // entirely, make sure that when we turn it back on we are just back to "any + // tag". + toggle_boolean_constraints("tags"); + toggle_tag_constraints(tagC); + assert_messages_in_view(setTagC); + + toggle_boolean_constraints("tags"); // no constraints + toggle_boolean_constraints("tags"); // should be any tag (not tagC!) + assert_messages_in_view([setTagA, setTagB, setTagAB, setTagC]); + teardownTest(); +}); + +add_task(async function test_filter_text_single_word_and_predicates() { + let folder = await create_folder("QuickFilterBarTextSingleWord"); + let whoFoo = ["zabba", "foo@madeup.invalid"]; + let [, setSenderFoo, setRecipientsFoo, setSubjectFoo, setBodyFoo] = + await make_message_sets_in_folders( + [folder], + [ + { count: 1 }, + { count: 1, from: whoFoo }, + { count: 1, to: [whoFoo] }, + { count: 1, subject: "foo" }, + { count: 1, body: { body: "foo" } }, + ] + ); + await be_in_folder(folder); + + // by default, sender/recipients/subject are selected + assert_text_constraints_checked("sender", "recipients", "subject"); + + // con defaults, por favor + set_filter_text("foo"); + assert_messages_in_view([setSenderFoo, setRecipientsFoo, setSubjectFoo]); + // note: we sequence the changes in the list so there is always at least one + // dude selected. selecting down to nothing has potential UI implications + // we don't want this test to get affected by. + // sender only + toggle_text_constraints("recipients", "subject"); + assert_messages_in_view(setSenderFoo); + // recipients only + toggle_text_constraints("recipients", "sender"); + assert_messages_in_view(setRecipientsFoo); + // subject only + toggle_text_constraints("subject", "recipients"); + assert_messages_in_view(setSubjectFoo); + // body only + toggle_text_constraints("body", "subject"); + assert_messages_in_view(setBodyFoo); + // everybody + toggle_text_constraints("sender", "recipients", "subject"); + assert_messages_in_view([ + setSenderFoo, + setRecipientsFoo, + setSubjectFoo, + setBodyFoo, + ]); + + // sanity check non-matching + set_filter_text("notgonnamatchevercauseisayso"); + assert_messages_in_view([]); + // disable body, still should get nothing + toggle_text_constraints("body"); + assert_messages_in_view([]); + + // (we are leaving with the defaults once again active) + assert_text_constraints_checked("sender", "recipients", "subject"); + teardownTest(); +}); + +/** + * Verify that the multi-word logic is actually splitting the words into + * different terms and that the terms can match in different predicates. + * This means that given "foo bar" we should be able to match "bar foo" in + * a subject and "foo" in the sender and "bar" in the recipient. And that + * constitutes sufficient positive coverage, although we also want to make + * sure that just a single term match is insufficient. + */ +add_task(async function test_filter_text_multi_word() { + let folder = await create_folder("QuickFilterBarTextMultiWord"); + + let whoFoo = ["foo", "zabba@madeup.invalid"]; + let whoBar = ["zabba", "bar@madeup.invalid"]; + let [, setPeepMatch, setSubjReverse] = await make_message_sets_in_folders( + [folder], + [ + { count: 1 }, + { count: 1, from: whoFoo, to: [whoBar] }, + { count: 1, subject: "bar foo" }, + { count: 1, from: whoFoo }, + ] + ); + await be_in_folder(folder); + + // (precondition) + assert_text_constraints_checked("sender", "recipients", "subject"); + + set_filter_text("foo bar"); + assert_messages_in_view([setPeepMatch, setSubjReverse]); + teardownTest(); +}); + +/** + * Verify that the quickfilter bar has OR functionality using + * | (Pipe character) - Bug 586131 + */ +add_task(async function test_filter_or_operator() { + let folder = await create_folder("QuickFilterBarOrOperator"); + + let whoFoo = ["foo", "zabba@madeup.invalid"]; + let whoBar = ["zabba", "bar@madeup.invalid"]; + let whoTest = ["test", "test@madeup.invalid"]; + let [setInert, setSenderFoo, setToBar, , , setSubject3, setMail1] = + await make_message_sets_in_folders( + [folder], + [ + { count: 1 }, + { count: 1, from: whoFoo }, + { count: 1, to: [whoBar] }, + { count: 1, subject: "foo bar" }, + { count: 1, subject: "bar test" }, + { count: 1, subject: "test" }, + { count: 1, to: [whoTest], subject: "logic" }, + { count: 1, from: whoFoo, to: [whoBar], subject: "test" }, + ] + ); + await be_in_folder(folder); + + assert_text_constraints_checked("sender", "recipients", "subject"); + set_filter_text("foo | bar"); + assert_messages_not_in_view([setInert, setSubject3, setMail1]); + + set_filter_text("test | bar"); + assert_messages_not_in_view([setInert, setSenderFoo]); + + set_filter_text("foo | test"); + assert_messages_not_in_view([setInert, setToBar]); + + // consists of leading and trailing spaces and tab character. + set_filter_text("test | foo bar"); + assert_messages_not_in_view([ + setInert, + setSenderFoo, + setToBar, + setSubject3, + setMail1, + ]); + + set_filter_text("test | foo bar |logic"); + assert_messages_not_in_view([setInert, setSenderFoo, setToBar, setSubject3]); + teardownTest(); +}); + +/** + * Make sure that when dropping all constraints on toggle off or changing + * folders that we persist/propagate the state of the + * sender/recipients/subject/body toggle buttons. + */ +add_task(async function test_filter_text_constraints_propagate() { + let whoFoo = ["foo", "zabba@madeup.invalid"]; + let whoBar = ["zabba", "bar@madeup.invalid"]; + + let folderOne = await create_folder("QuickFilterBarTextPropagate1"); + let [setSubjFoo, setWhoFoo] = await make_message_sets_in_folders( + [folderOne], + [ + { count: 1, subject: "foo" }, + { count: 1, from: whoFoo }, + ] + ); + let folderTwo = await create_folder("QuickFilterBarTextPropagate2"); + let [, setWhoBar] = await make_message_sets_in_folders( + [folderTwo], + [ + { count: 1, subject: "bar" }, + { count: 1, from: whoBar }, + ] + ); + + await be_in_folder(folderOne); + set_filter_text("foo"); + // (precondition) + assert_text_constraints_checked("sender", "recipients", "subject"); + assert_messages_in_view([setSubjFoo, setWhoFoo]); + + // -- drop subject, close bar to reset, make sure it sticks + toggle_text_constraints("subject"); + assert_messages_in_view([setWhoFoo]); + + await toggle_quick_filter_bar(); + await toggle_quick_filter_bar(); + + set_filter_text("foo"); + assert_messages_in_view([setWhoFoo]); + assert_text_constraints_checked("sender", "recipients"); + + // -- now change folders and make sure the settings stick + await be_in_folder(folderTwo); + set_filter_text("bar"); + assert_messages_in_view([setWhoBar]); + assert_text_constraints_checked("sender", "recipients"); + teardownTest(); +}); + +/** + * Here is what the results label does: + * - No filter active: results label is not visible. + * - Filter active, messages: it says the number of messages. + * - Filter active, no messages: it says there are no messages. + * + * Additional nuances: + * - The count needs to update as the user deletes messages or what not. + */ +add_task(async function test_results_label() { + let folder = await create_folder("QuickFilterBarResultsLabel"); + let [setImmortal, setMortal, setGoldfish] = + await make_message_sets_in_folders( + [folder], + [{ count: 1 }, { count: 1 }, { count: 1 }] + ); + + await be_in_folder(folder); + + // no filter, the label should not be visible + Assert.ok( + BrowserTestUtils.is_hidden( + get_about_3pane().document.getElementById("qfb-results-label") + ), + "results label should not be visible" + ); + + toggle_boolean_constraints("unread"); + assert_messages_in_view([setImmortal, setMortal, setGoldfish]); + assert_results_label_count(3); + + await delete_messages(setGoldfish); + assert_results_label_count(2); + + await delete_messages(setMortal); + assert_results_label_count(1); + + await delete_messages(setImmortal); + assert_results_label_count(0); + teardownTest(); +}); + +function teardownTest() { + clear_constraints(); +} |