From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../test/browser/formValidation/browser.ini | 7 + .../formValidation/browser_form_validation.js | 519 +++++++++++++++++++++ .../formValidation/browser_validation_iframe.js | 67 +++ .../formValidation/browser_validation_invisible.js | 67 +++ .../browser_validation_navigation.js | 49 ++ .../browser_validation_other_popups.js | 123 +++++ 6 files changed, 832 insertions(+) create mode 100644 browser/modules/test/browser/formValidation/browser.ini create mode 100644 browser/modules/test/browser/formValidation/browser_form_validation.js create mode 100644 browser/modules/test/browser/formValidation/browser_validation_iframe.js create mode 100644 browser/modules/test/browser/formValidation/browser_validation_invisible.js create mode 100644 browser/modules/test/browser/formValidation/browser_validation_navigation.js create mode 100644 browser/modules/test/browser/formValidation/browser_validation_other_popups.js (limited to 'browser/modules/test/browser/formValidation') diff --git a/browser/modules/test/browser/formValidation/browser.ini b/browser/modules/test/browser/formValidation/browser.ini new file mode 100644 index 0000000000..1c0b80d782 --- /dev/null +++ b/browser/modules/test/browser/formValidation/browser.ini @@ -0,0 +1,7 @@ +[browser_form_validation.js] +skip-if = true # bug 1057615 +[browser_validation_iframe.js] +skip-if = true # bug 1057615 +[browser_validation_invisible.js] +[browser_validation_navigation.js] +[browser_validation_other_popups.js] diff --git a/browser/modules/test/browser/formValidation/browser_form_validation.js b/browser/modules/test/browser/formValidation/browser_form_validation.js new file mode 100644 index 0000000000..a1cbc4d88d --- /dev/null +++ b/browser/modules/test/browser/formValidation/browser_form_validation.js @@ -0,0 +1,519 @@ +/** + * 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(); +}); diff --git a/browser/modules/test/browser/formValidation/browser_validation_iframe.js b/browser/modules/test/browser/formValidation/browser_validation_iframe.js new file mode 100644 index 0000000000..454c972f32 --- /dev/null +++ b/browser/modules/test/browser/formValidation/browser_validation_iframe.js @@ -0,0 +1,67 @@ +/** + * Make sure that the form validation error message shows even if the form is in an iframe. + */ +add_task(async function test_iframe() { + let uri = + "data:text/html;charset=utf-8," + + escape( + "
\" height=\"600\">" + ); + + 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" + ); + + await BrowserTestUtils.withNewTab(uri, async function checkTab(browser) { + let popupShownPromise = BrowserTestUtils.waitForEvent( + gInvalidFormPopup, + "popupshown" + ); + + await SpecialPowers.spawn(browser, [], async function () { + content.document + .getElementsByTagName("iframe")[0] + .contentDocument.getElementById("s") + .click(); + }); + await popupShownPromise; + + let anchorBottom = await SpecialPowers.spawn( + browser, + [], + async function () { + let childdoc = + content.document.getElementsByTagName("iframe")[0].contentDocument; + Assert.equal( + childdoc.activeElement, + childdoc.getElementById("i"), + "First invalid element should be focused" + ); + return ( + childdoc.defaultView.mozInnerScreenY + + childdoc.getElementById("i").getBoundingClientRect().bottom + ); + } + ); + + function isWithinHalfPixel(a, b) { + return Math.abs(a - b) <= 0.5; + } + + is( + isWithinHalfPixel(gInvalidFormPopup.screenY), + isWithinHalfPixel(anchorBottom), + "popup top" + ); + + ok( + gInvalidFormPopup.state == "showing" || gInvalidFormPopup.state == "open", + "The invalid form popup should be shown" + ); + }); +}); diff --git a/browser/modules/test/browser/formValidation/browser_validation_invisible.js b/browser/modules/test/browser/formValidation/browser_validation_invisible.js new file mode 100644 index 0000000000..9383ad773b --- /dev/null +++ b/browser/modules/test/browser/formValidation/browser_validation_invisible.js @@ -0,0 +1,67 @@ +"use strict"; + +var gInvalidFormPopup = + gBrowser.selectedBrowser.browsingContext.currentWindowGlobal + .getActor("FormValidation") + ._getAndMaybeCreatePanel(document); + +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"); +} + +/** + * In this test, we check that no popup appears if the element display is none. + */ +add_task(async function test_display_none() { + ok( + gInvalidFormPopup, + "The browser should have a popup to show when a form is invalid" + ); + + incrementTest(); + let testPage = + "data:text/html;charset=utf-8," + + '
'; + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, testPage); + await BrowserTestUtils.synthesizeMouse( + "#s", + 0, + 0, + {}, + gBrowser.selectedBrowser + ); + + checkPopupHide(); + BrowserTestUtils.removeTab(tab); +}); + +/** + * In this test, we check that no popup appears if the element visibility is hidden. + */ +add_task(async function test_visibility_hidden() { + incrementTest(); + let testPage = + "data:text/html;charset=utf-8," + + '
'; + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, testPage); + await BrowserTestUtils.synthesizeMouse( + "#s", + 0, + 0, + {}, + gBrowser.selectedBrowser + ); + + checkPopupHide(); + BrowserTestUtils.removeTab(tab); +}); diff --git a/browser/modules/test/browser/formValidation/browser_validation_navigation.js b/browser/modules/test/browser/formValidation/browser_validation_navigation.js new file mode 100644 index 0000000000..4dd793b983 --- /dev/null +++ b/browser/modules/test/browser/formValidation/browser_validation_navigation.js @@ -0,0 +1,49 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +/** + * Make sure that the form validation message disappears if we navigate + * immediately. + */ +add_task(async function test_navigate() { + 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" + ); + + await BrowserTestUtils.withNewTab( + "data:text/html,