diff options
Diffstat (limited to 'toolkit/components/printing/tests/browser_preview_navigation.js')
-rw-r--r-- | toolkit/components/printing/tests/browser_preview_navigation.js | 478 |
1 files changed, 478 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..1dc23fa9f4 --- /dev/null +++ b/toolkit/components/printing/tests/browser_preview_navigation.js @@ -0,0 +1,478 @@ +/* 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.is_visible(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"); +}); |