diff options
Diffstat (limited to 'mobile/android/components/extensions/test/mochitest/test_ext_options_ui.html')
-rw-r--r-- | mobile/android/components/extensions/test/mochitest/test_ext_options_ui.html | 498 |
1 files changed, 498 insertions, 0 deletions
diff --git a/mobile/android/components/extensions/test/mochitest/test_ext_options_ui.html b/mobile/android/components/extensions/test/mochitest/test_ext_options_ui.html new file mode 100644 index 0000000000..138bb054a9 --- /dev/null +++ b/mobile/android/components/extensions/test/mochitest/test_ext_options_ui.html @@ -0,0 +1,498 @@ +<!DOCTYPE HTML> +<html> +<head> + <meta charset="utf-8"> + <title>PageAction Test</title> + <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> + <script src="chrome://mochikit/content/tests/SimpleTest/ExtensionTestUtils.js"></script> + <script type="text/javascript" src="head.js"></script> + <link rel="stylesheet" href="chrome://mochikit/contents/tests/SimpleTest/test.css"/> +</head> +<body> + +<script type="text/javascript"> +"use strict"; + +async function waitAboutAddonsRendered(addonId) { + await ContentTaskUtils.waitForCondition(() => { + return content.document.querySelector(`div.addon-item[addonID="${addonId}"]`); + }, `wait Addon Item for ${addonId} to be rendered`); +} + +async function navigateToAddonDetails(addonId) { + const item = content.document.querySelector(`div.addon-item[addonID="${addonId}"]`); + const rect = item.getBoundingClientRect(); + const x = rect.left + rect.width / 2; + const y = rect.top + rect.height / 2; + const domWinUtils = content.window.windowUtils; + + domWinUtils.sendMouseEventToWindow("mousedown", x, y, 0, 1, 0); + domWinUtils.sendMouseEventToWindow("mouseup", x, y, 0, 1, 0); +} + +async function waitAddonOptionsPage([addonId, expectedText]) { + await ContentTaskUtils.waitForCondition(() => { + const optionsIframe = content.document.querySelector(`#addon-options`); + return optionsIframe && optionsIframe.contentDocument.readyState === "complete" && + optionsIframe.contentDocument.body.innerText.includes(expectedText); + }, `wait Addon Options ${expectedText} for ${addonId} to be loaded`); + + const optionsIframe = content.document.querySelector(`#addon-options`); + + return { + iframeHeight: optionsIframe.style.height, + documentHeight: optionsIframe.contentDocument.documentElement.scrollHeight, + bodyHeight: optionsIframe.contentDocument.body.scrollHeight, + }; +} + +async function clickOnLinkInOptionsPage(selector) { + const optionsIframe = content.document.querySelector(`#addon-options`); + optionsIframe.contentDocument.querySelector(selector).click(); +} + +async function clickAddonOptionButton() { + content.document.querySelector(`button#open-addon-options`).click(); +} + +async function navigateBack() { + content.window.history.back(); +} + +function waitDOMContentLoaded(checkUrlCb) { + const {BrowserApp} = Services.wm.getMostRecentWindow("navigator:browser"); + + return new Promise(resolve => { + const listener = (event) => { + if (checkUrlCb(event.target.defaultView.location.href)) { + BrowserApp.deck.removeEventListener("DOMContentLoaded", listener); + resolve(); + } + }; + + BrowserApp.deck.addEventListener("DOMContentLoaded", listener); + }); +} + +function waitAboutAddonsLoaded() { + return waitDOMContentLoaded(url => url === "about:addons"); +} + +function clickAddonDisable() { + content.document.querySelector("#disable-btn").click(); +} + +function clickAddonEnable() { + content.document.querySelector("#enable-btn").click(); +} + +add_task(async function test_options_ui_iframe_height() { + const addonID = "test-options-ui@mozilla.org"; + + const extension = ExtensionTestUtils.loadExtension({ + useAddonManager: "temporary", + manifest: { + browser_specific_settings: { + gecko: {id: addonID}, + }, + name: "Options UI Extension", + description: "Longer addon description", + options_ui: { + page: "options.html", + }, + }, + files: { + // An option page with the document element bigger than the body. + "options.html": `<!DOCTYPE html> + <html> + <head> + <meta charset="utf-8"> + <style> + html { height: 500px; border: 1px solid black; } + body { height: 200px; } + </style> + </head> + <body> + <h1>Options page 1</h1> + <a href="options2.html">go to page 2</a> + </body> + </html> + `, + // A second option page with the body element bigger than the document. + "options2.html": `<!DOCTYPE html> + <html> + <head> + <meta charset="utf-8"> + <style> + html { height: 200px; border: 1px solid black; } + body { height: 350px; } + </style> + </head> + <body> + <h1>Options page 2</h1> + </body> + </html> + `, + }, + }); + + await extension.startup(); + + const {BrowserApp} = Services.wm.getMostRecentWindow("navigator:browser"); + + const onceAboutAddonsLoaded = waitAboutAddonsLoaded(); + + BrowserApp.addTab("about:addons", { + selected: true, + parentId: BrowserApp.selectedTab.id, + }); + + await onceAboutAddonsLoaded; + + is(BrowserApp.selectedTab.currentURI.spec, "about:addons", + "about:addons is the currently selected tab"); + + await SpecialPowers.spawn(BrowserApp.selectedTab.browser, [addonID], waitAboutAddonsRendered); + + await SpecialPowers.spawn(BrowserApp.selectedTab.browser, [addonID], navigateToAddonDetails); + + const optionsSizes = await SpecialPowers.spawn( + BrowserApp.selectedTab.browser, [[addonID, "Options page 1"]], waitAddonOptionsPage + ); + + ok(parseInt(optionsSizes.iframeHeight, 10) >= 500, + "The addon options iframe is at least 500px"); + + is(optionsSizes.iframeHeight, optionsSizes.documentHeight + "px", + "The addon options iframe has the expected height"); + + await SpecialPowers.spawn(BrowserApp.selectedTab.browser, ["a"], clickOnLinkInOptionsPage); + + const options2Sizes = await SpecialPowers.spawn( + BrowserApp.selectedTab.browser, [[addonID, "Options page 2"]], waitAddonOptionsPage + ); + + // The second option page has a body bigger than the document element + // and we expect the iframe to be bigger than that. + ok(parseInt(options2Sizes.iframeHeight, 10) > 200, + `The iframe is bigger then 200px (${options2Sizes.iframeHeight})`); + + // The second option page has a body smaller than the document element of the first + // page and we expect the iframe to be smaller than for the previous options page. + ok(parseInt(options2Sizes.iframeHeight, 10) < 500, + `The iframe is smaller then 500px (${options2Sizes.iframeHeight})`); + + is(options2Sizes.iframeHeight, options2Sizes.documentHeight + "px", + "The second addon options page has the expected height"); + + await SpecialPowers.spawn(BrowserApp.selectedTab.browser, [], navigateBack); + + const backToOptionsSizes = await SpecialPowers.spawn( + BrowserApp.selectedTab.browser, [[addonID, "Options page 1"]], waitAddonOptionsPage + ); + + // After going back to the first options page, + // we expect the iframe to have the same size of the previous load. + is(backToOptionsSizes.iframeHeight, optionsSizes.iframeHeight, + `When navigating back, the old iframe size is restored (${backToOptionsSizes.iframeHeight})`); + + BrowserApp.closeTab(BrowserApp.selectedTab); + + await extension.unload(); +}); + +add_task(async function test_options_ui_open_aboutaddons_details() { + const addonID = "test-options-ui-open-addon-details@mozilla.org"; + + function background() { + browser.test.onMessage.addListener(msg => { + if (msg !== "runtime.openOptionsPage") { + browser.test.fail(`Received unexpected test message: ${msg}`); + return; + } + + browser.runtime.openOptionsPage(); + }); + } + + function optionsScript() { + browser.test.sendMessage("options-page-loaded", window.location.href); + } + + const extension = ExtensionTestUtils.loadExtension({ + useAddonManager: "temporary", + background, + manifest: { + browser_specific_settings: { + gecko: {id: addonID}, + }, + name: "Options UI open addon details Extension", + description: "Longer addon description", + options_ui: { + page: "options.html", + }, + }, + files: { + "options.js": optionsScript, + "options.html": `<!DOCTYPE html> + <html> + <head> + <meta charset="utf-8"> + </head> + <body> + <h1>Options page</h1> + <script src="options.js"><\/script> + </body> + </html> + `, + }, + }); + + await extension.startup(); + + const {BrowserApp} = Services.wm.getMostRecentWindow("navigator:browser"); + + const onceAboutAddonsLoaded = waitAboutAddonsLoaded(); + + BrowserApp.addTab("about:addons", { + selected: true, + parentId: BrowserApp.selectedTab.id, + }); + + await onceAboutAddonsLoaded; + + is(BrowserApp.selectedTab.currentURI.spec, "about:addons", + "about:addons is the currently selected tab"); + + info("Wait runtime.openOptionsPage to open the about:addond details in the existent tab"); + extension.sendMessage("runtime.openOptionsPage"); + await extension.awaitMessage("options-page-loaded"); + + is(BrowserApp.selectedTab.currentURI.spec, "about:addons", + "about:addons is still the currently selected tab once the options has been loaded"); + + BrowserApp.closeTab(BrowserApp.selectedTab); + + await extension.unload(); +}); + +add_task(async function test_options_ui_open_in_tab() { + const addonID = "test-options-ui@mozilla.org"; + + function background() { + browser.test.onMessage.addListener(msg => { + if (msg !== "runtime.openOptionsPage") { + browser.test.fail(`Received unexpected test message: ${msg}`); + return; + } + + browser.runtime.openOptionsPage(); + }); + } + + function optionsScript() { + browser.test.sendMessage("options-page-loaded", window.location.href); + } + + const extension = ExtensionTestUtils.loadExtension({ + useAddonManager: "temporary", + background, + manifest: { + browser_specific_settings: { + gecko: {id: addonID}, + }, + name: "Options UI open_in_tab Extension", + description: "Longer addon description", + options_ui: { + page: "options.html", + open_in_tab: true, + }, + }, + files: { + "options.js": optionsScript, + "options.html": `<!DOCTYPE html> + <html> + <head> + <meta charset="utf-8"> + </head> + <body> + <h1>Options page</h1> + <script src="options.js"><\/script> + </body> + </html> + `, + }, + }); + + await extension.startup(); + + const {BrowserApp} = Services.wm.getMostRecentWindow("navigator:browser"); + + const onceAboutAddonsLoaded = waitAboutAddonsLoaded(); + + BrowserApp.selectOrAddTab("about:addons", { + selected: true, + parentId: BrowserApp.selectedTab.id, + }); + + await onceAboutAddonsLoaded; + + const aboutAddonsTab = BrowserApp.selectedTab; + + is(aboutAddonsTab.currentURI.spec, "about:addons", + "about:addons is the currently selected tab"); + + await SpecialPowers.spawn(aboutAddonsTab.browser, [addonID], waitAboutAddonsRendered); + await SpecialPowers.spawn(aboutAddonsTab.browser, [addonID], navigateToAddonDetails); + + const onceAddonOptionsLoaded = waitDOMContentLoaded(url => url.endsWith("options.html")); + + info("Click the Options button in the addon details"); + await SpecialPowers.spawn(aboutAddonsTab.browser, [], clickAddonOptionButton); + + info("Waiting that the addon options are loaded in a new tab"); + await onceAddonOptionsLoaded; + + const addonOptionsTab = BrowserApp.selectedTab; + + ok(aboutAddonsTab.id !== addonOptionsTab.id, + "The Addon Options page has been loaded in a new tab"); + + let optionsURL = await extension.awaitMessage("options-page-loaded"); + + is(addonOptionsTab.currentURI.spec, optionsURL, + "Got the expected extension url opened in the addon options tab"); + + const waitTabClosed = (nativeTab) => { + return new Promise(resolve => { + const {BrowserApp} = Services.wm.getMostRecentWindow("navigator:browser"); + const expectedBrowser = nativeTab.browser; + + const tabCloseListener = (event) => { + const browser = event.target; + if (browser !== expectedBrowser) { + return; + } + + BrowserApp.deck.removeEventListener("TabClose", tabCloseListener); + resolve(); + }; + + BrowserApp.deck.addEventListener("TabClose", tabCloseListener); + }); + }; + + const onceOptionsTabClosed = waitTabClosed(addonOptionsTab); + const onceAboutAddonsClosed = waitTabClosed(aboutAddonsTab); + + info("Close the opened about:addons and options tab"); + BrowserApp.closeTab(addonOptionsTab); + BrowserApp.closeTab(aboutAddonsTab); + + info("Wait the tabs to be closed"); + await Promise.all([onceOptionsTabClosed, onceAboutAddonsClosed]); + + const oldSelectedTab = BrowserApp.selectedTab; + info("Call runtime.openOptionsPage"); + extension.sendMessage("runtime.openOptionsPage"); + + info("Wait runtime.openOptionsPage to open the options in a new tab"); + optionsURL = await extension.awaitMessage("options-page-loaded"); + is(BrowserApp.selectedTab.currentURI.spec, optionsURL, + "runtime.openOptionsPage has opened the expected extension page"); + ok(BrowserApp.selectedTab !== oldSelectedTab, + "runtime.openOptionsPage has opened a new tab"); + + BrowserApp.closeTab(BrowserApp.selectedTab); + + await extension.unload(); +}); + +add_task(async function test_options_ui_on_disable_and_enable() { + // Temporarily disabled for races. + /* eslint-disable no-unreachable */ + return; + + const addonID = "test-options-ui-disable-enable@mozilla.org"; + + function optionsScript() { + browser.test.sendMessage("options-page-loaded", window.location.href); + } + + const extension = ExtensionTestUtils.loadExtension({ + useAddonManager: "temporary", + manifest: { + browser_specific_settings: { + gecko: {id: addonID}, + }, + name: "Options UI open addon details Extension", + description: "Longer addon description", + options_ui: { + page: "options.html", + }, + }, + files: { + "options.js": optionsScript, + "options.html": `<!DOCTYPE html> + <html> + <head> + <meta charset="utf-8"> + </head> + <body> + <h1>Options page</h1> + <script src="options.js"><\/script> + </body> + </html> + `, + }, + }); + + await extension.startup(); + + const {BrowserApp} = Services.wm.getMostRecentWindow("navigator:browser"); + + const onceAboutAddonsLoaded = waitAboutAddonsLoaded(); + + BrowserApp.addTab("about:addons", { + selected: true, + parentId: BrowserApp.selectedTab.id, + }); + + await onceAboutAddonsLoaded; + + const aboutAddonsTab = BrowserApp.selectedTab; + + is(aboutAddonsTab.currentURI.spec, "about:addons", + "about:addons is the currently selected tab"); + + info("Wait the addon details to have been loaded"); + await SpecialPowers.spawn(aboutAddonsTab.browser, [addonID], waitAboutAddonsRendered); + await SpecialPowers.spawn(aboutAddonsTab.browser, [addonID], navigateToAddonDetails); + + info("Wait the addon options page to have been loaded"); + await extension.awaitMessage("options-page-loaded"); + + info("Click the addon disable button"); + await SpecialPowers.spawn(aboutAddonsTab.browser, [], clickAddonDisable); + + // NOTE: Currently after disabling the addon the extension.awaitMessage seems + // to fail be able to receive events coming from the browser.test.sendMessage API + // (nevertheless `await extension.unload()` seems to be able to remove the extension), + // falling back to wait for the options page to be loaded here. + const onceAddonOptionsLoaded = waitDOMContentLoaded(url => url.endsWith("options.html")); + + info("Click the addon enable button"); + await SpecialPowers.spawn(aboutAddonsTab.browser, [], clickAddonEnable); + + info("Wait the addon options page to have been loaded after clicking the addon enable button"); + await onceAddonOptionsLoaded; + + BrowserApp.closeTab(BrowserApp.selectedTab); + + await extension.unload(); +}); + +</script> + +</body> +</html> |