summaryrefslogtreecommitdiffstats
path: root/toolkit/components/printing/tests/browser_preview_navigation.js
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/printing/tests/browser_preview_navigation.js')
-rw-r--r--toolkit/components/printing/tests/browser_preview_navigation.js477
1 files changed, 477 insertions, 0 deletions
diff --git a/toolkit/components/printing/tests/browser_preview_navigation.js b/toolkit/components/printing/tests/browser_preview_navigation.js
new file mode 100644
index 0000000000..b4c0920185
--- /dev/null
+++ b/toolkit/components/printing/tests/browser_preview_navigation.js
@@ -0,0 +1,477 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+function compare10nArgs(elem, expectedValues) {
+ let l10nArgs = elem.ownerDocument.l10n.getAttributes(elem).args;
+ for (let [name, value] of Object.entries(expectedValues)) {
+ if (value !== l10nArgs[name]) {
+ info(
+ `compare10nArgs, expected ${name}: ${value}, actual: ${l10nArgs[name]}`
+ );
+ return false;
+ }
+ }
+ return true;
+}
+
+async function waitForPageStatusUpdate(elem, expected, message) {
+ await TestUtils.waitForCondition(
+ () => compare10nArgs(elem, expected),
+ message
+ );
+}
+
+async function waitUntilVisible(elem, visible = true) {
+ await TestUtils.waitForCondition(
+ () =>
+ BrowserTestUtils.isVisible(elem) && getComputedStyle(elem).opacity == "1",
+ "Waiting for element to be visible and have opacity:1"
+ );
+}
+
+async function waitUntilTransparent(elem) {
+ // Note that is_visible considers a fully transparent element "visible"
+ await TestUtils.waitForCondition(
+ () => getComputedStyle(elem).opacity == "0",
+ "Waiting for element to be have opacity:0"
+ );
+}
+
+async function mouseMoveAndWait(elem) {
+ let mouseMovePromise = BrowserTestUtils.waitForEvent(elem, "mousemove");
+ EventUtils.synthesizeMouseAtCenter(elem, { type: "mousemove" });
+ await mouseMovePromise;
+ await TestUtils.waitForTick();
+}
+
+add_task(async function testToolbarVisibility() {
+ // move the mouse to a known position
+ await mouseMoveAndWait(gURLBar.textbox);
+
+ await PrintHelper.withTestPage(async helper => {
+ await helper.startPrint();
+
+ let previewStack = document.querySelector(".previewStack");
+
+ // The toolbar has 0 opacity until we hover or focus it
+ is(
+ getComputedStyle(helper.paginationElem).opacity,
+ "0",
+ "Initially transparent"
+ );
+
+ let visiblePromise = waitUntilVisible(helper.paginationElem);
+ helper.paginationElem.shadowRoot.querySelector("#navigateEnd").focus();
+ await visiblePromise;
+ is(
+ getComputedStyle(helper.paginationElem).opacity,
+ "1",
+ "Opaque with button focused"
+ );
+
+ await EventUtils.synthesizeKey("KEY_Tab", {});
+ await waitUntilTransparent(helper.paginationElem);
+ is(
+ getComputedStyle(helper.paginationElem).opacity,
+ "0",
+ "Returns to transparent"
+ );
+
+ visiblePromise = waitUntilVisible(helper.paginationElem);
+ info("Waiting for mousemove event, and for the toolbar to become opaque");
+ await mouseMoveAndWait(previewStack);
+ await visiblePromise;
+ is(getComputedStyle(helper.paginationElem).opacity, "1", "Opaque toolbar");
+
+ // put the mouse back where it won't interfere with later tests
+ await mouseMoveAndWait(gURLBar.textbox);
+ await helper.closeDialog();
+ });
+});
+
+add_task(async function testPreviewSheetCount() {
+ await PrintHelper.withTestPage(async helper => {
+ await helper.startPrint();
+
+ // We have to wait for the first _updatePrintPreview to get the sheet count
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 1, sheetCount: 3 },
+ "Paginator indicates the correct number of sheets"
+ );
+
+ // then switch to page range 1-1 and verify page count changes
+ await helper.dispatchSettingsChange({
+ pageRanges: ["1", "1"],
+ });
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 1, sheetCount: 1 },
+ "Indicates the updated number of sheets"
+ );
+
+ await helper.closeDialog();
+ }, "longerArticle.html");
+});
+
+add_task(async function testPreviewScroll() {
+ await PrintHelper.withTestPage(async helper => {
+ await helper.startPrint();
+
+ // Wait for the first _updatePrintPreview before interacting with the preview
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 1, sheetCount: 3 },
+ "Paginator indicates the correct number of sheets"
+ );
+ let previewBrowser = helper.currentPrintPreviewBrowser;
+
+ // scroll down the document
+ // and verify the indicator is updated correctly
+ await SpecialPowers.spawn(previewBrowser, [], async function () {
+ const { ContentTaskUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/ContentTaskUtils.sys.mjs"
+ );
+ const EventUtils = ContentTaskUtils.getEventUtils(content);
+ content.focus();
+ EventUtils.synthesizeKey("VK_PAGE_DOWN", {}, content);
+ });
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 2, sheetCount: 3 },
+ "Indicator updates on scroll"
+ );
+
+ // move focus before closing the dialog
+ helper.get("cancel-button").focus();
+ await helper.closeDialog();
+ }, "longerArticle.html");
+});
+
+add_task(async function testPreviewNavigationCommands() {
+ await PrintHelper.withTestPage(async helper => {
+ await helper.startPrint();
+
+ // Wait for the first _updatePrintPreview before interacting with the preview
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 1, sheetCount: 3 },
+ "Paginator indicates the correct number of sheets"
+ );
+
+ // click the navigation buttons
+ // and verify the indicator is updated correctly
+ EventUtils.synthesizeMouseAtCenter(
+ helper.paginationElem.shadowRoot.querySelector("#navigateNext"),
+ {}
+ );
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 2, sheetCount: 3 },
+ "Indicator updates on navigation to next"
+ );
+
+ EventUtils.synthesizeMouseAtCenter(
+ helper.paginationElem.shadowRoot.querySelector("#navigatePrevious"),
+ {}
+ );
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 1, sheetCount: 3 },
+ "Indicator updates on navigation to previous"
+ );
+
+ EventUtils.synthesizeMouseAtCenter(
+ helper.paginationElem.shadowRoot.querySelector("#navigateEnd"),
+ {}
+ );
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 3, sheetCount: 3 },
+ "Indicator updates on navigation to end"
+ );
+
+ EventUtils.synthesizeMouseAtCenter(
+ helper.paginationElem.shadowRoot.querySelector("#navigateHome"),
+ {}
+ );
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 1, sheetCount: 3 },
+ "Indicator updates on navigation to start"
+ );
+
+ // Test rapid clicks on the navigation buttons
+ EventUtils.synthesizeMouseAtCenter(
+ helper.paginationElem.shadowRoot.querySelector("#navigateNext"),
+ {}
+ );
+ EventUtils.synthesizeMouseAtCenter(
+ helper.paginationElem.shadowRoot.querySelector("#navigateNext"),
+ {}
+ );
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 3, sheetCount: 3 },
+ "2 successive 'next' clicks correctly update the sheet indicator"
+ );
+
+ EventUtils.synthesizeMouseAtCenter(
+ helper.paginationElem.shadowRoot.querySelector("#navigatePrevious"),
+ {}
+ );
+ EventUtils.synthesizeMouseAtCenter(
+ helper.paginationElem.shadowRoot.querySelector("#navigatePrevious"),
+ {}
+ );
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 1, sheetCount: 3 },
+ "2 successive 'previous' clicks correctly update the sheet indicator"
+ );
+
+ // move focus before closing the dialog
+ helper.get("cancel-button").focus();
+ await helper.closeDialog();
+ }, "longerArticle.html");
+});
+
+add_task(async function testMultiplePreviewNavigation() {
+ await PrintHelper.withTestPage(async helper => {
+ await helper.startPrint();
+ const tab1 = gBrowser.selectedTab;
+
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 1, sheetCount: 3 },
+ "Indicator has the correct initial sheetCount"
+ );
+
+ const tab2 = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ PrintHelper.defaultTestPageUrl
+ );
+ let helper2 = new PrintHelper(tab2.linkedBrowser);
+ await helper2.startPrint();
+
+ let [previewBrowser1, previewBrowser2] = document.querySelectorAll(
+ ".printPreviewBrowser[previewtype='source']"
+ );
+ ok(previewBrowser1 && previewBrowser2, "There are 2 preview browsers");
+
+ let [toolbar1, toolbar2] = document.querySelectorAll(
+ ".printPreviewNavigation"
+ );
+ ok(toolbar1 && toolbar2, "There are 2 preview navigation toolbars");
+ is(
+ toolbar1.previewBrowser,
+ previewBrowser1,
+ "toolbar1 has the correct previewBrowser"
+ );
+ ok(
+ compare10nArgs(helper.paginationSheetIndicator, {
+ sheetNum: 1,
+ sheetCount: 3,
+ }),
+ "First toolbar has the correct content"
+ );
+
+ is(
+ toolbar2.previewBrowser,
+ previewBrowser2,
+ "toolbar2 has the correct previewBrowser"
+ );
+ ok(
+ compare10nArgs(helper2.paginationSheetIndicator, {
+ sheetNum: 1,
+ sheetCount: 1,
+ }),
+ "2nd toolbar has the correct content"
+ );
+
+ // Switch back to the first tab and ensure the correct preview navigation is updated when clicked
+ await BrowserTestUtils.switchTab(gBrowser, tab1);
+
+ EventUtils.synthesizeMouseAtCenter(
+ toolbar1.shadowRoot.querySelector("#navigateNext"),
+ {}
+ );
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 2, sheetCount: 3 },
+ "Indicator updates on navigation multiple"
+ );
+
+ gBrowser.removeTab(tab2);
+ }, "longerArticle.html");
+});
+
+add_task(async function testPreviewNavigationSelection() {
+ await PrintHelper.withTestPage(async helper => {
+ await SpecialPowers.spawn(helper.sourceBrowser, [], async function () {
+ let element = content.document.querySelector("#page-2");
+ content.window.getSelection().selectAllChildren(element);
+ });
+
+ await helper.startPrint();
+
+ // Wait for the first _updatePrintPreview before interacting with the preview
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 1, sheetCount: 3 },
+ "Paginator indicates the correct number of sheets"
+ );
+
+ // click a navigation button
+ // and verify the indicator is updated correctly
+ EventUtils.synthesizeMouseAtCenter(
+ helper.paginationElem.shadowRoot.querySelector("#navigateNext"),
+ {}
+ );
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 2, sheetCount: 3 },
+ "Indicator updates on navigation next selection"
+ );
+
+ await helper.openMoreSettings();
+ let printSelect = helper.get("source-version-selection-radio");
+ await helper.waitForPreview(() => helper.click(printSelect));
+
+ // Wait for the first _updatePrintPreview before interacting with the preview
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 1, sheetCount: 2 },
+ "Paginator indicates the correct number of sheets"
+ );
+
+ // click a navigation button
+ // and verify the indicator is updated correctly
+ EventUtils.synthesizeMouseAtCenter(
+ helper.paginationElem.shadowRoot.querySelector("#navigateNext"),
+ {}
+ );
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 2, sheetCount: 2 },
+ "Indicator updates on navigation next selection 2"
+ );
+
+ // move focus before closing the dialog
+ helper.get("cancel-button").focus();
+ await helper.closeDialog();
+ }, "longerArticle.html");
+});
+
+add_task(async function testPaginatorAfterSettingsUpdate() {
+ const mockPrinterName = "Fake Printer";
+ await PrintHelper.withTestPage(async helper => {
+ helper.addMockPrinter(mockPrinterName);
+ await helper.startPrint();
+
+ // Wait for the first _updatePrintPreview before interacting with the preview
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 1, sheetCount: 3 },
+ "Paginator indicates the correct number of sheets"
+ );
+
+ // click the navigation buttons
+ // and verify the indicator is updated correctly
+ EventUtils.synthesizeMouseAtCenter(
+ helper.paginationElem.shadowRoot.querySelector("#navigateNext"),
+ {}
+ );
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 2, sheetCount: 3 },
+ "Indicator updates on navigation next after update"
+ );
+
+ // Select a new printer
+ await helper.dispatchSettingsChange({ printerName: mockPrinterName });
+ await waitForPageStatusUpdate(
+ helper.paginationSheetIndicator,
+ { sheetNum: 1, sheetCount: 3 },
+ "Indicator updates on navigation next after printer change"
+ );
+ ok(
+ compare10nArgs(helper.paginationSheetIndicator, {
+ sheetNum: 1,
+ sheetCount: 3,
+ }),
+ "Sheet indicator has correct value"
+ );
+
+ // move focus before closing the dialog
+ helper.get("cancel-button").focus();
+ await helper.closeDialog();
+ }, "longerArticle.html");
+});
+
+add_task(async function testTooltips() {
+ await SpecialPowers.pushPrefEnv({ set: [["ui.tooltipDelay", 0]] });
+ const mockPrinterName = "Fake Printer";
+ await PrintHelper.withTestPage(async helper => {
+ helper.addMockPrinter(mockPrinterName);
+ await helper.startPrint();
+
+ let paginationElem = document.querySelector(".printPreviewNavigation");
+ let paginationSheetIndicator =
+ paginationElem.shadowRoot.querySelector("#sheetIndicator");
+
+ // Wait for the first _updatePrintPreview before interacting with the preview
+ await waitForPageStatusUpdate(
+ paginationSheetIndicator,
+ { sheetNum: 1, sheetCount: 3 },
+ "Paginator indicates the correct number of sheets"
+ );
+
+ let awaitTooltipOpen = new Promise(resolve => {
+ window.addEventListener(
+ "popupshown",
+ function (event) {
+ resolve(event.originalTarget);
+ },
+ { once: true }
+ );
+ });
+
+ let navigateEnd = paginationElem.shadowRoot.querySelector("#navigateEnd");
+ info("Initial mouse move to end navigation button");
+ EventUtils.synthesizeMouseAtCenter(navigateEnd, { type: "mousemove" });
+ let tooltip = await awaitTooltipOpen;
+ is(tooltip.label, navigateEnd.title, "Tooltip shows correct text");
+ awaitTooltipOpen = new Promise(resolve => {
+ window.addEventListener(
+ "popupshown",
+ function (event) {
+ resolve(event.originalTarget);
+ },
+ { once: true }
+ );
+ });
+
+ let navigateNext = paginationElem.shadowRoot.querySelector("#navigateNext");
+ let navigateNextRect = navigateNext.getBoundingClientRect();
+ info("Initial mouse move to next navigation button");
+ EventUtils.synthesizeMouseAtCenter(navigateNext, { type: "mousemove" });
+ info("Waiting");
+ EventUtils.synthesizeMouse(
+ navigateNext,
+ navigateNextRect.width / 2 + 5,
+ navigateNextRect.height / 2,
+ { type: "mousemove" },
+ window
+ );
+ tooltip = await awaitTooltipOpen;
+ is(tooltip.label, navigateNext.title, "Tooltip shows correct text");
+
+ // move focus before closing the dialog
+ helper.get("cancel-button").focus();
+ await helper.awaitAnimationFrame();
+ await helper.closeDialog();
+ }, "longerArticle.html");
+});