diff options
Diffstat (limited to 'comm/mail/test/browser/shared-modules/QuickFilterBarHelpers.jsm')
-rw-r--r-- | comm/mail/test/browser/shared-modules/QuickFilterBarHelpers.jsm | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/comm/mail/test/browser/shared-modules/QuickFilterBarHelpers.jsm b/comm/mail/test/browser/shared-modules/QuickFilterBarHelpers.jsm new file mode 100644 index 0000000000..04dee48e09 --- /dev/null +++ b/comm/mail/test/browser/shared-modules/QuickFilterBarHelpers.jsm @@ -0,0 +1,391 @@ +/* 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"; + +const EXPORTED_SYMBOLS = [ + "assert_quick_filter_button_enabled", + "assert_quick_filter_bar_visible", + "toggle_quick_filter_bar", + "assert_constraints_expressed", + "toggle_boolean_constraints", + "toggle_tag_constraints", + "toggle_tag_mode", + "assert_tag_constraints_visible", + "assert_tag_constraints_checked", + "toggle_text_constraints", + "assert_text_constraints_checked", + "set_filter_text", + "assert_filter_text", + "assert_results_label_count", + "clear_constraints", + "cleanup_qfb_button", +]; + +var { get_about_3pane, mc, wait_for_all_messages_to_load } = ChromeUtils.import( + "resource://testing-common/mozmill/FolderDisplayHelpers.jsm" +); +var EventUtils = ChromeUtils.import( + "resource://testing-common/mozmill/EventUtils.jsm" +); + +var { Assert } = ChromeUtils.importESModule( + "resource://testing-common/Assert.sys.mjs" +); +var { BrowserTestUtils } = ChromeUtils.importESModule( + "resource://testing-common/BrowserTestUtils.sys.mjs" +); + +const { getState, storeState } = ChromeUtils.importESModule( + "resource:///modules/CustomizationState.mjs" +); + +const { getDefaultItemIdsForSpace } = ChromeUtils.importESModule( + "resource:///modules/CustomizableItems.sys.mjs" +); + +let about3Pane = get_about_3pane(); +about3Pane.quickFilterBar.deferredUpdateSearch = + about3Pane.quickFilterBar.updateSearch; + +/** + * Maps names to bar DOM ids to simplify checking. + */ +var nameToBarDomId = { + sticky: "qfb-sticky", + unread: "qfb-unread", + starred: "qfb-starred", + addrbook: "qfb-inaddrbook", + tags: "qfb-tags", + attachments: "qfb-attachment", +}; + +async function ensure_qfb_unified_toolbar_button() { + const document = mc.window.document; + + const state = getState(); + if (state.mail?.includes("quick-filter-bar")) { + return; + } + if (!state.mail) { + state.mail = getDefaultItemIdsForSpace("mail"); + if (state.mail.includes("quick-filter-bar")) { + return; + } + } + state.mail.push("quick-filter-bar"); + storeState(state); + await BrowserTestUtils.waitForMutationCondition( + document.getElementById("unifiedToolbarContent"), + { + subtree: true, + childList: true, + }, + () => + document.querySelector("#unifiedToolbarContent .quick-filter-bar button") + ); +} + +async function cleanup_qfb_button() { + const document = mc.window.document; + const state = getState(); + if (!state.mail?.includes("quick-filter-bar")) { + return; + } + state.mail = getDefaultItemIdsForSpace("mail"); + storeState(state); + await BrowserTestUtils.waitForMutationCondition( + document.getElementById("unifiedToolbarContent"), + { + subtree: true, + childList: true, + }, + () => !document.querySelector("#unifiedToolbarContent .quick-filter-bar") + ); +} + +async function assert_quick_filter_button_enabled(aEnabled) { + await ensure_qfb_unified_toolbar_button(); + if ( + mc.window.document.querySelector( + "#unifiedToolbarContent .quick-filter-bar button" + ).disabled == aEnabled + ) { + throw new Error( + "Quick filter bar button should be " + (aEnabled ? "enabled" : "disabled") + ); + } +} + +function assert_quick_filter_bar_visible(aVisible) { + let bar = about3Pane.document.getElementById("quick-filter-bar"); + if (aVisible) { + Assert.ok( + BrowserTestUtils.is_visible(bar), + "Quick filter bar should be visible" + ); + } else { + Assert.ok( + BrowserTestUtils.is_hidden(bar), + "Quick filter bar should be hidden" + ); + } +} + +/** + * Toggle the state of the message filter bar as if by a mouse click. + */ +async function toggle_quick_filter_bar() { + await ensure_qfb_unified_toolbar_button(); + EventUtils.synthesizeMouseAtCenter( + mc.window.document.querySelector( + "#unifiedToolbarContent .quick-filter-bar" + ), + { clickCount: 1 }, + mc.window + ); + wait_for_all_messages_to_load(); +} + +/** + * Assert that the state of the constraints visually expressed by the bar is + * consistent with the passed-in constraints. This method does not verify + * that the search constraints are in effect. Check that elsewhere. + */ +function assert_constraints_expressed(aConstraints) { + for (let name in nameToBarDomId) { + let domId = nameToBarDomId[name]; + let expectedValue = name in aConstraints ? aConstraints[name] : false; + let domNode = about3Pane.document.getElementById(domId); + Assert.equal( + domNode.pressed, + expectedValue, + name + "'s pressed state should be " + expectedValue + ); + } +} + +/** + * Toggle the given filter buttons by name (from nameToBarDomId); variable + * argument magic enabled. + */ +function toggle_boolean_constraints(...aArgs) { + aArgs.forEach(arg => + EventUtils.synthesizeMouseAtCenter( + about3Pane.document.getElementById(nameToBarDomId[arg]), + { clickCount: 1 }, + about3Pane + ) + ); + wait_for_all_messages_to_load(mc); +} + +/** + * Toggle the tag faceting buttons by tag key. Wait for messages after. + */ +function toggle_tag_constraints(...aArgs) { + aArgs.forEach(function (arg) { + let tagId = "qfb-tag-" + arg; + let button = about3Pane.document.getElementById(tagId); + button.scrollIntoView(); + EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, about3Pane); + }); + wait_for_all_messages_to_load(mc); +} + +/** + * Set the tag filtering mode. Wait for messages after. + */ +function toggle_tag_mode() { + let qbm = about3Pane.document.getElementById("qfb-boolean-mode"); + if (qbm.value === "AND") { + qbm.selectedIndex--; // = move to "OR"; + Assert.equal(qbm.value, "OR", "qfb-boolean-mode has wrong state"); + } else if (qbm.value === "OR") { + qbm.selectedIndex++; // = move to "AND"; + Assert.equal(qbm.value, "AND", "qfb-boolean-mode has wrong state"); + } else { + throw new Error("qfb-boolean-mode value=" + qbm.value); + } + wait_for_all_messages_to_load(mc); +} + +/** + * Verify that tag buttons exist for exactly the given set of tag keys in the + * provided variable argument list. Ordering is significant. + */ +function assert_tag_constraints_visible(...aArgs) { + // the stupid bar should be visible if any arguments are specified + let tagBar = get_about_3pane().document.getElementById( + "quickFilterBarTagsContainer" + ); + if (aArgs.length > 0) { + Assert.ok( + BrowserTestUtils.is_visible(tagBar), + "The tag bar should not be collapsed!" + ); + } + + let kids = tagBar.children; + let tagLength = kids.length - 1; // -1 for the qfb-boolean-mode widget + // this is bad error reporting in here for now. + if (tagLength != aArgs.length) { + throw new Error( + "Mismatch in expected tag count and actual. " + + "Expected " + + aArgs.length + + " actual " + + tagLength + ); + } + for (let iArg = 0; iArg < aArgs.length; iArg++) { + let nodeId = "qfb-tag-" + aArgs[iArg]; + if (nodeId != kids[iArg + 1].id) { + throw new Error( + "Mismatch at tag " + + iArg + + " expected " + + nodeId + + " but got " + + kids[iArg + 1].id + ); + } + } +} + +/** + * Verify that only the buttons corresponding to the provided tag keys are + * checked. + */ +function assert_tag_constraints_checked(...aArgs) { + let expected = {}; + for (let arg of aArgs) { + let nodeId = "qfb-tag-" + arg; + expected[nodeId] = true; + } + + let kids = mc.window.document.getElementById( + "quickFilterBarTagsContainer" + ).children; + for (let iNode = 0; iNode < kids.length; iNode++) { + let node = kids[iNode]; + if (node.pressed != node.id in expected) { + throw new Error( + "node " + + node.id + + " should " + + (node.id in expected ? "be " : "not be ") + + "checked." + ); + } + } +} + +var nameToTextDomId = { + sender: "qfb-qs-sender", + recipients: "qfb-qs-recipients", + subject: "qfb-qs-subject", + body: "qfb-qs-body", +}; + +function toggle_text_constraints(...aArgs) { + aArgs.forEach(arg => + EventUtils.synthesizeMouseAtCenter( + about3Pane.document.getElementById(nameToTextDomId[arg]), + { clickCount: 1 }, + about3Pane + ) + ); + wait_for_all_messages_to_load(mc); +} + +/** + * Assert that the text constraint buttons are checked. Variable-argument + * support where the arguments are one of sender/recipients/subject/body. + */ +function assert_text_constraints_checked(...aArgs) { + let expected = {}; + for (let arg of aArgs) { + let nodeId = nameToTextDomId[arg]; + expected[nodeId] = true; + } + + let kids = about3Pane.document.querySelectorAll( + "#quick-filter-bar-filter-text-bar button" + ); + for (let iNode = 0; iNode < kids.length; iNode++) { + let node = kids[iNode]; + if (node.tagName == "label") { + continue; + } + if (node.pressed != node.id in expected) { + throw new Error( + "node " + + node.id + + " should " + + (node.id in expected ? "be " : "not be ") + + "checked." + ); + } + } +} + +/** + * Set the text in the text filter box, trigger it like enter was pressed, then + * wait for all messages to load. + */ +function set_filter_text(aText) { + // We're not testing the reliability of the textbox widget; just poke our text + // in and trigger the command logic. + let textbox = about3Pane.document.getElementById("qfb-qs-textbox"); + textbox.value = aText; + textbox.doCommand(); + wait_for_all_messages_to_load(mc); +} + +function assert_filter_text(aText) { + let textbox = get_about_3pane().document.getElementById("qfb-qs-textbox"); + if (textbox.value != aText) { + throw new Error( + "Expected text filter value of '" + + aText + + "' but got '" + + textbox.value + + "'" + ); + } +} + +/** + * Assert that the results label is telling us there are aCount messages + * using the appropriate string. + */ +function assert_results_label_count(aCount) { + let resultsLabel = about3Pane.document.getElementById("qfb-results-label"); + let attributes = about3Pane.document.l10n.getAttributes(resultsLabel); + if (aCount == 0) { + Assert.deepEqual( + attributes, + { id: "quick-filter-bar-no-results", args: null }, + "results label should be displaying the no messages case" + ); + } else { + Assert.deepEqual( + attributes, + { id: "quick-filter-bar-results", args: { count: aCount } }, + `result count should show ${aCount}` + ); + } +} + +/** + * Clear active constraints via any means necessary; state cleanup for testing, + * not to be used as part of a test. Unlike normal clearing, this will kill + * the sticky bit. + * + * This is automatically called by the test teardown helper. + */ +function clear_constraints() { + about3Pane.quickFilterBar._testHelperResetFilterState(); +} |