/** * COPIED FROM browser/base/content/test/general/head.js. * This function should be removed and replaced with BTU withNewTab calls * * Waits for a load (or custom) event to finish in a given tab. If provided * load an uri into the tab. * * @param tab * The tab to load into. * @param [optional] url * The url to load, or the current url. * @return {Promise} resolved when the event is handled. * @resolves to the received event * @rejects if a valid load event is not received within a meaningful interval */ function promiseTabLoadEvent(tab, url) { info("Wait tab event: load"); function handle(loadedUrl) { if (loadedUrl === "about:blank" || (url && loadedUrl !== url)) { info(`Skipping spurious load event for ${loadedUrl}`); return false; } info("Tab event received: load"); return true; } let loaded = BrowserTestUtils.browserLoaded(tab.linkedBrowser, false, handle); if (url) { BrowserTestUtils.loadURIString(tab.linkedBrowser, url); } return loaded; } var gInvalidFormPopup = gBrowser.selectedBrowser.browsingContext.currentWindowGlobal .getActor("FormValidation") ._getAndMaybeCreatePanel(document); ok( gInvalidFormPopup, "The browser should have a popup to show when a form is invalid" ); function isWithinHalfPixel(a, b) { return Math.abs(a - b) <= 0.5; } function checkPopupShow(anchorRect) { ok( gInvalidFormPopup.state == "showing" || gInvalidFormPopup.state == "open", "[Test " + testId + "] The invalid form popup should be shown" ); // Just check the vertical position, as the horizontal position of an // arrow panel will be offset. is( isWithinHalfPixel(gInvalidFormPopup.screenY), isWithinHalfPixel(anchorRect.bottom), "popup top" ); } function checkPopupHide() { ok( gInvalidFormPopup.state != "showing" && gInvalidFormPopup.state != "open", "[Test " + testId + "] The invalid form popup should not be shown" ); } var testId = 0; function incrementTest() { testId++; info("Starting next part of test"); } function getDocHeader() { return "" + getEmptyFrame(); } function getDocFooter() { return ""; } function getEmptyFrame() { return ( "" ); } async function openNewTab(uri, background) { let tab = BrowserTestUtils.addTab(gBrowser); let browser = gBrowser.getBrowserForTab(tab); if (!background) { gBrowser.selectedTab = tab; } await promiseTabLoadEvent(tab, "data:text/html," + escape(uri)); return browser; } function clickChildElement(browser) { return SpecialPowers.spawn(browser, [], async function () { let element = content.document.getElementById("s"); element.click(); return { bottom: content.mozInnerScreenY + element.getBoundingClientRect().bottom, }; }); } async function blurChildElement(browser) { await SpecialPowers.spawn(browser, [], async function () { content.document.getElementById("i").blur(); }); } async function checkChildFocus(browser, message) { await SpecialPowers.spawn( browser, [[message, testId]], async function (args) { let [msg, id] = args; var focused = content.document.activeElement == content.document.getElementById("i"); var validMsg = true; if (msg) { validMsg = msg == content.document.getElementById("i").validationMessage; } Assert.equal( focused, true, "Test " + id + " First invalid element should be focused" ); Assert.equal( validMsg, true, "Test " + id + " The panel should show the message from validationMessage" ); } ); } /** * In this test, we check that no popup appears if the form is valid. */ add_task(async function () { incrementTest(); let uri = getDocHeader() + "
" + getDocFooter(); let browser = await openNewTab(uri); await clickChildElement(browser); await new Promise((resolve, reject) => { // XXXndeakin This isn't really going to work when the content is another process executeSoon(function () { checkPopupHide(); resolve(); }); }); gBrowser.removeCurrentTab(); }); /** * In this test, we check that, when an invalid form is submitted, * the invalid element is focused and a popup appears. */ add_task(async function () { incrementTest(); let uri = getDocHeader() + "
" + getDocFooter(); let browser = await openNewTab(uri); let popupShownPromise = BrowserTestUtils.waitForEvent( gInvalidFormPopup, "popupshown" ); let anchorRect = await clickChildElement(browser); await popupShownPromise; checkPopupShow(anchorRect); await checkChildFocus( browser, gInvalidFormPopup.firstElementChild.textContent ); gBrowser.removeCurrentTab(); }); /** * In this test, we check that, when an invalid form is submitted, * the first invalid element is focused and a popup appears. */ add_task(async function () { incrementTest(); let uri = getDocHeader() + "
" + getDocFooter(); let browser = await openNewTab(uri); let popupShownPromise = BrowserTestUtils.waitForEvent( gInvalidFormPopup, "popupshown" ); let anchorRect = await clickChildElement(browser); await popupShownPromise; checkPopupShow(anchorRect); await checkChildFocus( browser, gInvalidFormPopup.firstElementChild.textContent ); gBrowser.removeCurrentTab(); }); /** * In this test, we check that, we hide the popup by interacting with the * invalid element if the element becomes valid. */ add_task(async function () { incrementTest(); let uri = getDocHeader() + "
" + getDocFooter(); let browser = await openNewTab(uri); let popupShownPromise = BrowserTestUtils.waitForEvent( gInvalidFormPopup, "popupshown" ); let anchorRect = await clickChildElement(browser); await popupShownPromise; checkPopupShow(anchorRect); await checkChildFocus( browser, gInvalidFormPopup.firstElementChild.textContent ); let popupHiddenPromise = BrowserTestUtils.waitForEvent( gInvalidFormPopup, "popuphidden" ); EventUtils.sendString("a"); await popupHiddenPromise; gBrowser.removeCurrentTab(); }); /** * In this test, we check that, we don't hide the popup by interacting with the * invalid element if the element is still invalid. */ add_task(async function () { incrementTest(); let uri = getDocHeader() + "
" + getDocFooter(); let browser = await openNewTab(uri); let popupShownPromise = BrowserTestUtils.waitForEvent( gInvalidFormPopup, "popupshown" ); let anchorRect = await clickChildElement(browser); await popupShownPromise; checkPopupShow(anchorRect); await checkChildFocus( browser, gInvalidFormPopup.firstElementChild.textContent ); await new Promise((resolve, reject) => { EventUtils.sendString("a"); executeSoon(function () { checkPopupShow(anchorRect); resolve(); }); }); gBrowser.removeCurrentTab(); }); /** * In this test, we check that we can hide the popup by blurring the invalid * element. */ add_task(async function () { incrementTest(); let uri = getDocHeader() + "
" + getDocFooter(); let browser = await openNewTab(uri); let popupShownPromise = BrowserTestUtils.waitForEvent( gInvalidFormPopup, "popupshown" ); let anchorRect = await clickChildElement(browser); await popupShownPromise; checkPopupShow(anchorRect); await checkChildFocus( browser, gInvalidFormPopup.firstElementChild.textContent ); let popupHiddenPromise = BrowserTestUtils.waitForEvent( gInvalidFormPopup, "popuphidden" ); await blurChildElement(browser); await popupHiddenPromise; gBrowser.removeCurrentTab(); }); /** * In this test, we check that we can hide the popup by pressing TAB. */ add_task(async function () { incrementTest(); let uri = getDocHeader() + "
" + getDocFooter(); let browser = await openNewTab(uri); let popupShownPromise = BrowserTestUtils.waitForEvent( gInvalidFormPopup, "popupshown" ); let anchorRect = await clickChildElement(browser); await popupShownPromise; checkPopupShow(anchorRect); await checkChildFocus( browser, gInvalidFormPopup.firstElementChild.textContent ); let popupHiddenPromise = BrowserTestUtils.waitForEvent( gInvalidFormPopup, "popuphidden" ); EventUtils.synthesizeKey("KEY_Tab"); await popupHiddenPromise; gBrowser.removeCurrentTab(); }); /** * In this test, we check that the popup will hide if we move to another tab. */ add_task(async function () { incrementTest(); let uri = getDocHeader() + "
" + getDocFooter(); let browser1 = await openNewTab(uri); let popupShownPromise = BrowserTestUtils.waitForEvent( gInvalidFormPopup, "popupshown" ); let anchorRect = await clickChildElement(browser1); await popupShownPromise; checkPopupShow(anchorRect); await checkChildFocus( browser1, gInvalidFormPopup.firstElementChild.textContent ); let popupHiddenPromise = BrowserTestUtils.waitForEvent( gInvalidFormPopup, "popuphidden" ); let browser2 = await openNewTab("data:text/html,"); await popupHiddenPromise; gBrowser.removeTab(gBrowser.getTabForBrowser(browser1)); gBrowser.removeTab(gBrowser.getTabForBrowser(browser2)); }); /** * In this test, we check that the popup will hide if we navigate to another * page. */ add_task(async function () { incrementTest(); let uri = getDocHeader() + "
" + getDocFooter(); let browser = await openNewTab(uri); let popupShownPromise = BrowserTestUtils.waitForEvent( gInvalidFormPopup, "popupshown" ); let anchorRect = await clickChildElement(browser); await popupShownPromise; checkPopupShow(anchorRect); await checkChildFocus( browser, gInvalidFormPopup.firstElementChild.textContent ); let popupHiddenPromise = BrowserTestUtils.waitForEvent( gInvalidFormPopup, "popuphidden" ); BrowserTestUtils.loadURIString(browser, "data:text/html,
hello!
"); await BrowserTestUtils.browserLoaded(browser); await popupHiddenPromise; gBrowser.removeCurrentTab(); }); /** * In this test, we check that the message is correctly updated when it changes. */ add_task(async function () { incrementTest(); let uri = getDocHeader() + "
" + getDocFooter(); let browser = await openNewTab(uri); let popupShownPromise = BrowserTestUtils.waitForEvent( gInvalidFormPopup, "popupshown" ); let anchorRect = await clickChildElement(browser); await popupShownPromise; checkPopupShow(anchorRect); await checkChildFocus( browser, gInvalidFormPopup.firstElementChild.textContent ); let inputPromise = BrowserTestUtils.waitForContentEvent(browser, "input"); EventUtils.sendString("f"); await inputPromise; // Now, the element suffers from another error, the message should have // been updated. await new Promise((resolve, reject) => { // XXXndeakin This isn't really going to work when the content is another process executeSoon(function () { checkChildFocus(browser, gInvalidFormPopup.firstElementChild.textContent); resolve(); }); }); gBrowser.removeCurrentTab(); }); /** * In this test, we reload the page while the form validation popup is visible. The validation * popup should hide. */ add_task(async function () { incrementTest(); let uri = getDocHeader() + "
" + getDocFooter(); let browser = await openNewTab(uri); let popupShownPromise = BrowserTestUtils.waitForEvent( gInvalidFormPopup, "popupshown" ); let anchorRect = await clickChildElement(browser); await popupShownPromise; checkPopupShow(anchorRect); await checkChildFocus( browser, gInvalidFormPopup.firstElementChild.textContent ); let popupHiddenPromise = BrowserTestUtils.waitForEvent( gInvalidFormPopup, "popuphidden" ); BrowserReloadSkipCache(); await popupHiddenPromise; gBrowser.removeCurrentTab(); });