/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ /* vim: set sts=2 sw=2 et tw=80: */ "use strict"; /* exported testPopupSize */ // This file is imported into the same scope as head.js. /* import-globals-from head.js */ // A test helper that retrives an old and new value after a given delay // and then check that calls an `isCompleted` callback to check that // the value has reached the expected value. function waitUntilValue({ getValue, isCompleted, message, delay: delayTime, times = 1, } = {}) { let i = 0; return BrowserTestUtils.waitForCondition(async () => { const oldVal = await getValue(); await delay(delayTime); const newVal = await getValue(); const done = isCompleted(oldVal, newVal); // Reset the counter if the value wasn't the expected one. if (!done) { i = 0; } return done && times === ++i; }, message); } async function testPopupSize( standardsMode, browserWin = window, arrowSide = "top" ) { let docType = standardsMode ? "" : ""; let extension = ExtensionTestUtils.loadExtension({ manifest: { browser_action: { default_popup: "popup.html", default_area: "navbar", browser_style: false, }, }, files: { "popup.html": `${docType} `, }, }); await extension.startup(); if (arrowSide == "top") { // Test the standalone panel for a toolbar button. let browser = await openBrowserActionPanel(extension, browserWin, true); let dims = await promiseContentDimensions(browser); is( dims.isStandards, standardsMode, "Document has the expected compat mode" ); let { innerWidth, innerHeight } = dims.window; dims = await alterContent(browser, () => { content.document.body.classList.add("bigger"); }); let win = dims.window; ok( Math.abs(win.innerHeight - innerHeight) <= 1, `Window height should not change (${win.innerHeight} ~= ${innerHeight})` ); ok( win.innerWidth > innerWidth, `Window width should increase (${win.innerWidth} > ${innerWidth})` ); dims = await alterContent(browser, () => { content.document.body.classList.remove("bigger"); }); win = dims.window; // The getContentSize calculation is not always reliable to single-pixel // precision. ok( Math.abs(win.innerHeight - innerHeight) <= 1, `Window height should return to approximately its original value (${win.innerHeight} ~= ${innerHeight})` ); ok( Math.abs(win.innerWidth - innerWidth) <= 1, `Window width should return to approximately its original value (${win.innerWidth} ~= ${innerWidth})` ); await closeBrowserAction(extension, browserWin); } // Test the PanelUI panel for a menu panel button. let widget = getBrowserActionWidget(extension); CustomizableUI.addWidgetToArea(widget.id, getCustomizableUIPanelID()); let panel = browserWin.gUnifiedExtensions.panel; panel.setAttribute("animate", "false"); let shownPromise = Promise.resolve(); let browser = await openBrowserActionPanel(extension, browserWin); // Small changes if this is a fixed width window let isFixedWidth = !widget.disallowSubView; // Wait long enough to make sure the initial popup positioning has been completed ( // by waiting until the value stays the same for 20 times in a row). await waitUntilValue({ getValue: () => panel.getBoundingClientRect().top, isCompleted: (oldVal, newVal) => { return oldVal === newVal; }, times: 20, message: "Wait the popup opening to be completed", delay: 500, }); let origPanelRect = panel.getBoundingClientRect(); // Check that the panel is still positioned as expected. let checkPanelPosition = () => { is( panel.getAttribute("side"), arrowSide, "Panel arrow is positioned as expected" ); let panelRect = panel.getBoundingClientRect(); if (arrowSide == "top") { is(panelRect.top, origPanelRect.top, "Panel has not moved downwards"); ok( panelRect.bottom >= origPanelRect.bottom, `Panel has not shrunk from original size (${panelRect.bottom} >= ${origPanelRect.bottom})` ); let screenBottom = browserWin.screen.availTop + browserWin.screen.availHeight; let panelBottom = browserWin.mozInnerScreenY + panelRect.bottom; ok( Math.round(panelBottom) <= screenBottom, `Bottom of popup should be on-screen. (${panelBottom} <= ${screenBottom})` ); } else { is(panelRect.bottom, origPanelRect.bottom, "Panel has not moved upwards"); ok( panelRect.top <= origPanelRect.top, `Panel has not shrunk from original size (${panelRect.top} <= ${origPanelRect.top})` ); let panelTop = browserWin.mozInnerScreenY + panelRect.top; ok( panelTop >= browserWin.screen.availTop, `Top of popup should be on-screen. (${panelTop} >= ${browserWin.screen.availTop})` ); } }; await awaitBrowserLoaded(browser); await shownPromise; // Wait long enough to make sure the initial resize debouncing timer has // expired. await waitUntilValue({ getValue: () => promiseContentDimensions(browser), isCompleted: (oldDims, newDims) => { return ( oldDims.window.innerWidth === newDims.window.innerWidth && oldDims.window.innerHeight === newDims.window.innerHeight ); }, message: "Wait the popup resize to be completed", delay: 500, }); let dims = await promiseContentDimensions(browser); is(dims.isStandards, standardsMode, "Document has the expected compat mode"); // If the browser's preferred height is smaller than the initial height of the // panel, then it will still take up the full available vertical space. Even // so, we need to check that we've gotten the preferred height calculation // correct, so check that explicitly. let getHeight = () => parseFloat(browser.style.height); let { innerWidth, innerHeight } = dims.window; let height = getHeight(); let setClass = className => { content.document.body.className = className; }; info( "Increase body children's width. " + "Expect them to wrap, and the frame to grow vertically rather than widen." ); dims = await alterContent(browser, setClass, "big"); let win = dims.window; ok( getHeight() > height, `Browser height should increase (${getHeight()} > ${height})` ); if (isFixedWidth) { is(win.innerWidth, innerWidth, "Window width should not change"); } else { ok( win.innerWidth >= innerWidth, `Window width should increase (${win.innerWidth} >= ${innerWidth})` ); } ok( win.innerHeight >= innerHeight, `Window height should increase (${win.innerHeight} >= ${innerHeight})` ); Assert.lessOrEqual( win.scrollMaxY, 1, "Document should not be vertically scrollable" ); checkPanelPosition(); if (isFixedWidth) { // Test a fixed width window grows in height when elements wrap info( "Increase body children's width and height. " + "Expect them to wrap, and the frame to grow vertically rather than widen." ); dims = await alterContent(browser, setClass, "bigger"); win = dims.window; ok( getHeight() > height, `Browser height should increase (${getHeight()} > ${height})` ); is(win.innerWidth, innerWidth, "Window width should not change"); ok( win.innerHeight >= innerHeight, `Window height should increase (${win.innerHeight} >= ${innerHeight})` ); Assert.lessOrEqual( win.scrollMaxY, 1, "Document should not be vertically scrollable" ); checkPanelPosition(); } info( "Increase body height beyond the height of the screen. " + "Expect the panel to grow to accommodate, but not larger than the height of the screen." ); dims = await alterContent(browser, setClass, "huge"); win = dims.window; ok( getHeight() > height, `Browser height should increase (${getHeight()} > ${height})` ); is(win.innerWidth, innerWidth, "Window width should not change"); ok( win.innerHeight > innerHeight, `Window height should increase (${win.innerHeight} > ${innerHeight})` ); // Commented out check for the window height here which mysteriously breaks // on infra but not locally. bug 1396843 covers re-enabling this. // ok(win.innerHeight < screen.height, `Window height be less than the screen height (${win.innerHeight} < ${screen.height})`); ok( win.scrollMaxY > 0, `Document should be vertically scrollable (${win.scrollMaxY} > 0)` ); checkPanelPosition(); info("Restore original styling. Expect original dimensions."); dims = await alterContent(browser, setClass, ""); win = dims.window; is(getHeight(), height, "Browser height should return to its original value"); is(win.innerWidth, innerWidth, "Window width should not change"); is( win.innerHeight, innerHeight, "Window height should return to its original value" ); Assert.lessOrEqual( win.scrollMaxY, 1, "Document should not be vertically scrollable" ); checkPanelPosition(); await closeBrowserAction(extension, browserWin); await extension.unload(); }