diff options
Diffstat (limited to 'dom/html/test/browser_submission_flush.js')
-rw-r--r-- | dom/html/test/browser_submission_flush.js | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/dom/html/test/browser_submission_flush.js b/dom/html/test/browser_submission_flush.js new file mode 100644 index 0000000000..add886c6a3 --- /dev/null +++ b/dom/html/test/browser_submission_flush.js @@ -0,0 +1,97 @@ +"use strict"; +// Form submissions triggered by the Javascript 'submit' event listener are +// deferred until the event listener finishes. However, changes to specific +// attributes ("action" and "target" attributes) need to cause an immediate +// flush of any pending submission to prevent the form submission from using the +// wrong action or target. This test ensures that such flushes happen properly. + +const kTestPage = + "https://example.org/browser/dom/html/test/submission_flush.html"; +// This is the page pointed to by the form action in the test HTML page. +const kPostActionPage = + "https://example.org/browser/dom/html/test/post_action_page.html"; + +const kFormId = "test_form"; +const kFrameId = "test_frame"; +const kSubmitButtonId = "submit_button"; + +// Take in a variety of actions (in the form of setting and unsetting form +// attributes). Then submit the form in the submit event listener to cause a +// deferred form submission. Then perform the test actions and ensure that the +// form used the correct attribute values rather than the changed ones. +async function runTest(aTestActions) { + let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, kTestPage); + registerCleanupFunction(() => BrowserTestUtils.removeTab(tab)); + + /* eslint-disable no-shadow */ + let frame_url = await SpecialPowers.spawn( + gBrowser.selectedBrowser, + [{ kFormId, kFrameId, kSubmitButtonId, aTestActions }], + async function ({ kFormId, kFrameId, kSubmitButtonId, aTestActions }) { + let form = content.document.getElementById(kFormId); + + form.addEventListener( + "submit", + event => { + // Need to trigger the deferred submission by submitting in the submit + // event handler. To prevent the form from being submitted twice, the + // <form> tag contains the attribute |onsubmit="return false;"| to cancel + // the original submission. + form.submit(); + + if (aTestActions.setattr) { + for (let { attr, value } of aTestActions.setattr) { + form.setAttribute(attr, value); + } + } + if (aTestActions.unsetattr) { + for (let attr of aTestActions.unsetattr) { + form.removeAttribute(attr); + } + } + }, + { capture: true, once: true } + ); + + // Trigger the above event listener + content.document.getElementById(kSubmitButtonId).click(); + + // Test that the form was submitted to the correct target (the frame) with + // the correct action (kPostActionPage). + let frame = content.document.getElementById(kFrameId); + await new Promise(resolve => { + frame.addEventListener("load", resolve, { once: true }); + }); + return frame.contentWindow.location.href; + } + ); + /* eslint-enable no-shadow */ + is( + frame_url, + kPostActionPage, + "Form should have submitted with correct target and action" + ); +} + +add_task(async function () { + info("Changing action should flush pending submissions"); + await runTest({ setattr: [{ attr: "action", value: "about:blank" }] }); +}); + +add_task(async function () { + info("Changing target should flush pending submissions"); + await runTest({ setattr: [{ attr: "target", value: "_blank" }] }); +}); + +add_task(async function () { + info("Unsetting action should flush pending submissions"); + await runTest({ unsetattr: ["action"] }); +}); + +// On failure, this test will time out rather than failing an assert. When the +// target attribute is not set, the form will submit the active page, navigating +// it away and preventing the wait for iframe load from ever finishing. +add_task(async function () { + info("Unsetting target should flush pending submissions"); + await runTest({ unsetattr: ["target"] }); +}); |