Bug 1663793 - part 3: Use same function to check canceling "beforeinput" and not canceling it r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 27 Oct 2020 01:48:34 +0000
changeset 554809 12f9e5ca502386c4f2ddc2e366abcbb298963e37
parent 554808 8e0f42721cd778f2c3f9f78591bdf3ed48392cc6
child 554810 5363016dd24f6b73827715ac155469d86c5ce15e
push id37898
push userabutkovits@mozilla.com
push dateWed, 28 Oct 2020 09:24:21 +0000
treeherdermozilla-central@83bf4fd3b1fb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1663793
milestone84.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1663793 - part 3: Use same function to check canceling "beforeinput" and not canceling it r=m_kato So, this removes functions named as `*_and_canceling_beforeinput` and makes corresponding function take an object which has `action` and `cancelBeforeInput` to reduce dependency on wider scope variables. Depends on D94516 Differential Revision: https://phabricator.services.mozilla.com/D94517
editor/libeditor/tests/test_dom_input_event_on_htmleditor.html
editor/libeditor/tests/test_dom_input_event_on_texteditor.html
--- a/editor/libeditor/tests/test_dom_input_event_on_htmleditor.html
+++ b/editor/libeditor/tests/test_dom_input_event_on_htmleditor.html
@@ -30,16 +30,18 @@ const kIsWin = navigator.platform.indexO
 const kIsMac = navigator.platform.indexOf("Mac") == 0;
 
 async function runTests() {
   await SpecialPowers.pushPrefEnv({
     set: [["dom.input_events.beforeinput.enabled", true]],
   });
 
   const kWordSelectEatSpaceToNextWord = SpecialPowers.getBoolPref("layout.word_select.eat_space_to_next_word");
+  const kImgURL =
+    "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==";
 
   // eslint-disable-next-line complexity
   function doTests(aDocument, aWindow, aDescription) {
     aDescription += ": ";
     aWindow.focus();
 
     let body = aDocument.body;
     let selection = aWindow.getSelection();
@@ -76,28 +78,31 @@ async function runTests() {
 
     editTarget.innerHTML = "";
 
     // If the editTarget isn't its editing host, move caret to the start of it.
     if (eventTarget != editTarget) {
       aDocument.getSelection().collapse(editTarget, 0);
     }
 
+    let initializing = false;
     let beforeInputEvent = null;
     let inputEvent = null;
     let selectionRanges = [];
-    let expectedTargetRanges = [];
     function reset() {
       beforeInputEvent = null;
       inputEvent = null;
       selectionRanges = [];
     }
     let cancelBeforeInput = false;
     let action = "";
     let beforeInputHandler = (aEvent) => {
+      if (initializing) {
+        return;
+      }
       if (cancelBeforeInput) {
         aEvent.preventDefault();
       }
       ok(!beforeInputEvent,
         `${aDescription}Multiple "beforeinput" events are fired at ${action} (inputType: "${aEvent.inputType}", data: ${aEvent.data})`);
       ok(aEvent.isTrusted,
         `${aDescription}"beforeinput" event at ${action} must be trusted`);
       is(aEvent.target, eventTarget,
@@ -110,16 +115,19 @@ async function runTests() {
       selectionRanges = [];
       for (let i = 0; i < selection.rangeCount; i++) {
         let range = selection.getRangeAt(i);
         selectionRanges.push({startContainer: range.startContainer, startOffset: range.startOffset,
                               endContainer: range.endContainer, endOffset: range.endOffset});
       }
     };
     let inputHandler = (aEvent) => {
+      if (initializing) {
+        return;
+      }
       ok(!inputEvent,
         `${aDescription}Multiple "input" events are fired at ${action} (inputType: "${aEvent.inputType}", data: ${aEvent.data})`);
       ok(aEvent.isTrusted,
         `${aDescription}"input" event at ${action} must be trusted`);
       is(aEvent.target, eventTarget,
         `${aDescription}"input" event at ${action} is fired on unexpected element: ${aEvent.target.tagName}`);
       ok(aEvent instanceof InputEvent,
         `${aDescription}"input" event at ${action} should be dispatched with InputEvent interface`);
@@ -185,76 +193,92 @@ async function runTests() {
         `${aDescription}inputType of "input" event for ${action} should be "insertText"`);
       is(inputEvent.data, "a",
         `${aDescription}data of "input" event for ${action} should be "a"`);
       is(inputEvent.dataTransfer, null,
         `${aDescription}dataTransfer of "input" event for ${action} should be null`);
       checkTargetRanges(inputEvent, []);
     })();
 
-    (function test_typing_b_at_end_of_editor_and_canceling_beforeinput() {
-      reset();
-      cancelBeforeInput = true;
-      action = 'inserting "b"';
-      synthesizeKey("b", {}, aWindow);
-      is(editTarget.innerHTML, "a",
-        `${aDescription}"a" shouldn't have been modified by ${action} since "beforeinput" was canceled`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_typing_b_at_end_of_editor() {
+    function test_typing_b_at_end_of_editor(aTestData) {
       reset();
-      cancelBeforeInput = true;
-      editTarget.innerHTML = "ab";
-      selection.collapse(editTarget.firstChild, 2);
-      action = 'removing "a" with "Backspace" (with collapsed selection)';
-      synthesizeKey("KEY_Backspace", {}, aWindow);
-      is(editTarget.innerHTML, "ab",
-        `${aDescription}"a" shouldn't have been modified by ${action} since "beforeinput" was canceled`);
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      editTarget.innerHTML = "a";
+      selection.collapse(editTarget.firstChild, 1);
+      action = aTestData.action;
+      synthesizeKey("b", {}, aWindow);
+      let expectedValue = aTestData.cancelBeforeInput ? "a" : "ab";
+      is(editTarget.innerHTML, expectedValue,
+        `${aDescription}innerHTML should be"${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't been fired at ${action} since "beforeinput" was canceled`);
-    })();
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
+      ok(inputEvent,
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
+    }
+    test_typing_b_at_end_of_editor({
+      action: 'typing "b" after "a" and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_typing_b_at_end_of_editor({
+      action: 'typing "b" after "a"',
+      cancelBeforeInput: false,
+    });
 
-    (function test_typing_backspace_to_delete_last_character() {
+    function test_typing_backspace_to_delete_last_character(aTestData) {
       reset();
-      cancelBeforeInput = false;
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
       editTarget.innerHTML = "a";
       selection.collapse(editTarget.firstChild, 1);
       synthesizeKey("KEY_Backspace", {}, aWindow);
-      is(editTarget.innerHTML, "<br>",
-        `${aDescription}"a" should've been removed by ${action}`);
+      let expectedValue = aTestData.cancelBeforeInput ? "a" : "<br>";
+      is(editTarget.innerHTML, expectedValue,
+        `${aDescription}innerHTML should be"${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "deleteContentBackward",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "deleteContentBackward"`);
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "deleteContentBackward"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       checkTargetRanges(beforeInputEvent, [{startContainer: selectionRanges[0].endContainer,
                                             startOffset: selectionRanges[0].endOffset - 1,
                                             endContainer: selectionRanges[0].endContainer,
                                             endOffset: selectionRanges[0].endOffset}]);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.inputType, "deleteContentBackward",
-        `${aDescription}inputType of "input" event for ${action} should be "deleteContentBackward"`);
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "deleteContentBackward"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       checkTargetRanges(inputEvent, []);
-    })();
+    }
+    test_typing_backspace_to_delete_last_character({
+      action: 'typing "Backspace" to delete the last character and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_typing_backspace_to_delete_last_character({
+      action: 'typing "Backspace" to delete the last character',
+      cancelBeforeInput: false,
+    });
 
     (function test_typing_backspace_in_empty_editor() {
       reset();
       cancelBeforeInput = false;
       action = 'typing "Backspace" in empty editor';
       synthesizeKey("KEY_Backspace", {}, aWindow);
       is(editTarget.innerHTML, "<br>",
         `${aDescription}$shouldn't change empty editor by ${action}`);
@@ -268,154 +292,182 @@ async function runTests() {
         `${aDescription}data of "beforeinput" event for ${action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
         `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
       checkTargetRanges(beforeInputEvent, selectionRanges);
       ok(!inputEvent,
         `${aDescription}"input" event shouldn't be fired at ${action}`);
     })();
 
-    (function test_typing_B_in_empty_editor() {
+    function test_typing_enter_at_end_of_editor(aTestData) {
       reset();
-      cancelBeforeInput = false;
-      action = 'typing "B"';
-      synthesizeKey("B", {shiftKey: true}, aWindow);
-      is(editTarget.innerHTML, "B<br>",
-        `${aDescription}"B" should've been inserted by ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "insertText",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "insertText"`);
-      is(beforeInputEvent.data, "B",
-        `${aDescription}data of "beforeinput" event for ${action} should be "B"`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      checkTargetRanges(beforeInputEvent, selectionRanges);
-      ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
-      is(inputEvent.inputType, "insertText",
-        `${aDescription}inputType of "input" event for ${action} should be "insertText"`);
-      is(inputEvent.data, "B",
-        `${aDescription}data of "input" event for ${action} should be "B"`);
-      is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
-      checkTargetRanges(inputEvent, []);
-    })();
-
-    (function test_typing_enter_at_end_of_editor_and_canceling_beforeinput() {
-      reset();
-      cancelBeforeInput = true;
-      action = 'typing "Enter"';
-      synthesizeKey("KEY_Enter", {}, aWindow);
-      is(editTarget.innerHTML, "B<br>",
-        `${aDescription}shouldn't modify the editor by ${action} since "beforeinput" was canceled`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_typing_enter_at_end_of_editor() {
-      reset();
-      cancelBeforeInput = false;
-      action = 'typing "Enter"';
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
       editTarget.innerHTML = "B";
       selection.collapse(editTarget.firstChild, 1);
       synthesizeKey("KEY_Enter", {}, aWindow);
-      if (!isEditTargetIsDescendantOfEditingHost) {
+      if (aTestData.cancelBeforeInput) {
+        is(editTarget.innerHTML, "B",
+          `${aDescription}innerHTML should be "B" after ${aTestData.action}`);
+      } else if (!isEditTargetIsDescendantOfEditingHost) {
         is(editTarget.innerHTML, "<div>B</div><div><br></div>",
-          `${aDescription}should insert new paragraph by ${action}`);
+          `${aDescription}innerHTML should be "<div>B</div><div><br></div>" after ${aTestData.action}`);
       } else {
         // XXX Perhaps, this is a bug since we shouldn't change behavior when contenteditable element is <html> or <body>.
         is(editTarget.innerHTML, "B<br><br>",
-          `${aDescription}should insert new paragraph by ${action}`);
+          `${aDescription}innerHTML should be "B<br><br>" after ${aTestData.action}`);
+      }
+      is(beforeInputEvent.cancelable, true,
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
+      is(beforeInputEvent.inputType, "insertParagraph",
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "insertParagraph"`);
+      is(beforeInputEvent.data, null,
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
+      is(beforeInputEvent.dataTransfer, null,
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
+      checkTargetRanges(beforeInputEvent, selectionRanges);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
+      ok(inputEvent,
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
+      is(inputEvent.inputType, "insertParagraph",
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "insertParagraph"`);
+      is(inputEvent.data, null,
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
+      is(inputEvent.dataTransfer, null,
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
+      checkTargetRanges(inputEvent, []);
+    }
+    test_typing_enter_at_end_of_editor({
+      action: 'typing "Enter" at end of editor and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_typing_enter_at_end_of_editor({
+      action: 'typing "Enter" at end of editor',
+      cancelBeforeInput: false,
+    });
+
+    function test_typing_C_in_empty_last_line(aTestData) {
+      reset();
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
+      if (!isEditTargetIsDescendantOfEditingHost) {
+        editTarget.innerHTML = "<div>B</div><div><br></div>";
+        selection.collapse(editTarget.querySelector("div + div"), 0);
+      } else {
+        editTarget.innerHTML = "B<br><br>";
+        selection.collapse(editTarget, 2);
+      }
+      synthesizeKey("C", {shiftKey: true}, aWindow);
+      if (!isEditTargetIsDescendantOfEditingHost) {
+        let expectedValue = aTestData.cancelBeforeInput
+                              ? "<div>B</div><div><br></div>"
+                              : "<div>B</div><div>C<br></div>";
+        is(editTarget.innerHTML, expectedValue,
+          `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
+      } else {
+        let expectedValue = aTestData.cancelBeforeInput
+                              ? "B<br><br>"
+                              : "B<br>C<br>";
+        is(editTarget.innerHTML, expectedValue,
+          `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
+      }
+      is(beforeInputEvent.cancelable, true,
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
+      is(beforeInputEvent.inputType, "insertText",
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "insertText"`);
+      is(beforeInputEvent.data, "C",
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be "C"`);
+      is(beforeInputEvent.dataTransfer, null,
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
+      checkTargetRanges(beforeInputEvent, selectionRanges);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
+      ok(inputEvent,
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
+      is(inputEvent.inputType, "insertText",
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "insertText"`);
+      is(inputEvent.data, "C",
+        `${aDescription}data of "input" event for ${aTestData.action} should be "C"`);
+      is(inputEvent.dataTransfer, null,
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
+      checkTargetRanges(inputEvent, []);
+    }
+    test_typing_C_in_empty_last_line({
+      action: 'typing "C" in empty last line and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_typing_C_in_empty_last_line({
+      action: 'typing "C" in empty last line',
+      cancelBeforeInput: false,
+    });
+
+    function test_typing_enter_in_non_empty_last_line(aTestData) {
+      reset();
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
+      if (!isEditTargetIsDescendantOfEditingHost) {
+        editTarget.innerHTML = "<div>B</div><div>C<br></div>";
+        selection.collapse(editTarget.querySelector("div + div").firstChild, 1);
+      } else {
+        editTarget.innerHTML = "B<br>C<br>";
+        selection.collapse(editTarget.querySelector("br").nextSibling, 1);
+      }
+      synthesizeKey("KEY_Enter", {}, aWindow);
+      if (!isEditTargetIsDescendantOfEditingHost) {
+        let expectedValue = aTestData.cancelBeforeInput
+                              ? "<div>B</div><div>C<br></div>"
+                              : "<div>B</div><div>C</div><div><br></div>";
+        is(editTarget.innerHTML, expectedValue,
+          `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
+      } else {
+        let expectedValue = aTestData.cancelBeforeInput
+                              ? "B<br>C<br>"
+                              : "B<br>C<br><br>";
+        is(editTarget.innerHTML, expectedValue,
+          `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
       }
       is(beforeInputEvent.cancelable, true,
         `${aDescription}"beforeinput" event for ${action} should be cancelable`);
       is(beforeInputEvent.inputType, "insertParagraph",
         `${aDescription}inputType of "beforeinput" event for ${action} should be "insertParagraph"`);
       is(beforeInputEvent.data, null,
         `${aDescription}data of "beforeinput" event for ${action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
         `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
       checkTargetRanges(beforeInputEvent, selectionRanges);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
         `${aDescription}"input" event should've been fired at ${action}`);
       is(inputEvent.inputType, "insertParagraph",
         `${aDescription}inputType of "input" event for ${action} should be "insertParagraph"`);
       is(inputEvent.data, null,
         `${aDescription}data of "input" event for ${action} should be null`);
       is(inputEvent.dataTransfer, null,
         `${aDescription}dataTransfer of "input" event for ${action} should be null`);
       checkTargetRanges(inputEvent, []);
-    })();
-
-    (function test_typing_c_in_empty_last_line() {
-      reset();
-      cancelBeforeInput = false;
-      action = 'typing "C" in new paragraph';
-      synthesizeKey("C", {shiftKey: true}, aWindow);
-      if (!isEditTargetIsDescendantOfEditingHost) {
-        is(editTarget.innerHTML, "<div>B</div><div>C<br></div>",
-          `${aDescription}should insert "C" into the new paragraph by ${action}`);
-      } else {
-        is(editTarget.innerHTML, "B<br>C<br>",
-          `${aDescription}should insert "C" into the new paragraph by ${action}`);
-      }
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "insertText",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "insertText"`);
-      is(beforeInputEvent.data, "C",
-        `${aDescription}data of "beforeinput" event for ${action} should be "C"`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      checkTargetRanges(beforeInputEvent, selectionRanges);
-      ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
-      is(inputEvent.inputType, "insertText",
-        `${aDescription}inputType of "input" event for ${action} should be "insertText"`);
-      is(inputEvent.data, "C",
-        `${aDescription}data of "input" event for ${action} should be "C"`);
-      is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
-      checkTargetRanges(inputEvent, []);
-    })();
-
-    (function test_typing_enter_in_non_empty_last_line() {
-      reset();
-      cancelBeforeInput = false;
-      action = 'typing "Enter" again';
-      synthesizeKey("KEY_Enter", {}, aWindow);
-      if (!isEditTargetIsDescendantOfEditingHost) {
-        is(editTarget.innerHTML, "<div>B</div><div>C</div><div><br></div>",
-          `${aDescription}should insert new paragraph again by ${action}`);
-      } else {
-        is(editTarget.innerHTML, "B<br>C<br><br>",
-          `${aDescription}should insert new paragraph again by ${action}`);
-      }
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "insertParagraph",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "insertParagraph"`);
-      is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      checkTargetRanges(beforeInputEvent, selectionRanges);
-      ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
-      is(inputEvent.inputType, "insertParagraph",
-        `${aDescription}inputType of "input" event for ${action} should be "insertParagraph"`);
-      is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
-      is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
-      checkTargetRanges(inputEvent, []);
-    })();
+    }
+    test_typing_enter_in_non_empty_last_line({
+      action: 'typing "Enter" at end of non-empty line and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_typing_enter_in_non_empty_last_line({
+      action: 'typing "Enter" at end of non-empty line',
+      cancelBeforeInput: false,
+    });
 
     (function test_setting_innerHTML() {
       reset();
       editTarget.innerHTML = "foo-bar";
       ok(!beforeInputEvent,
         `${aDescription}"beforeinput" event should not be fired when setting value`);
       ok(!inputEvent,
         `${aDescription}"input" event should not be fired when setting value`);
@@ -425,43 +477,59 @@ async function runTests() {
       reset();
       editTarget.innerHTML = "";
       ok(!beforeInputEvent,
         `${aDescription}"beforeinput" event should not be fired when setting empty value`);
       ok(!inputEvent,
         `${aDescription}"input" event should not be fired when setting empty value`);
     })();
 
-    (function test_typing_white_space_in_empty_editor() {
+    function test_typing_white_space_in_empty_editor(aTestData) {
       reset();
-      action = 'inserting " " into empty editor';
+      editTarget.innerHTML = "";
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
       synthesizeKey(" ", {}, aWindow);
-      is(editTarget.innerHTML, "&nbsp;",
-        `${aDescription}" " should've been inserted by ${action}`);
+      let expectedValue = aTestData.cancelBeforeInput ? "" : "&nbsp;";
+      is(editTarget.innerHTML, expectedValue,
+        `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "insertText",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "insertText"`);
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "insertText"`);
       is(beforeInputEvent.data, " ",
-        `${aDescription}data of "beforeinput" event for ${action} should be " "`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be " "`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       checkTargetRanges(beforeInputEvent, selectionRanges);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.inputType, "insertText",
-        `${aDescription}inputType of "input" event for ${action} should be "insertText"`);
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "insertText"`);
       is(inputEvent.data, " ",
-        `${aDescription}data of "input" event for ${action} should be " "`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be " "`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       checkTargetRanges(inputEvent, []);
-    })();
+    }
+    test_typing_white_space_in_empty_editor({
+      action: 'typing space in empty editor and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_typing_white_space_in_empty_editor({
+      action: "typing space in empty editor",
+      cancelBeforeInput: false,
+    });
 
     (function test_typing_delete_at_end_of_editor() {
       reset();
       action = 'typing "Delete" at end';
       synthesizeKey("KEY_Delete", {}, aWindow);
       is(editTarget.innerHTML, "&nbsp;",
         `${aDescription}shouldn't modify the editor by ${action} since there is no content to remove`);
       ok(beforeInputEvent,
@@ -484,454 +552,458 @@ async function runTests() {
       action = 'typing "ArrowLeft"';
       synthesizeKey("KEY_ArrowLeft", {}, aWindow);
       ok(!beforeInputEvent,
         `${aDescription}${action} should not fire "beforeinput" event since no content has been modified`);
       ok(!inputEvent,
         `${aDescription}${action} should not fire "input" event since no content has been modified`);
     })();
 
-    (function test_typing_delete_to_delete_last_character_and_canceling_beforeinput() {
+    function test_typing_delete_to_delete_last_character(aTestData) {
       reset();
-      cancelBeforeInput = true;
-      action = 'typing "Delete"';
-      synthesizeKey("KEY_Delete", {}, aWindow);
-      is(editTarget.innerHTML, "&nbsp;",
-        `${aDescription}"\u00A0" shouldn't have been removed by ${action} since "beforeinput" was canceled`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_typing_delete_to_delete_last_character() {
-      htmlEditor.enableUndo(false);
-      htmlEditor.enableUndo(true);
-
-      reset();
-      cancelBeforeInput = false;
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
       editTarget.innerHTML = "\u00A0";
       selection.collapse(editTarget.firstChild, 0);
       synthesizeKey("KEY_Delete", {}, aWindow);
-      is(editTarget.innerHTML, "<br>",
-        `${aDescription}" " should've been removed by ${action}`);
+      let expectedValue = aTestData.cancelBeforeInput ? "&nbsp;" : "<br>";
+      is(editTarget.innerHTML, expectedValue,
+        `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "deleteContentForward",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "deleteContentForward"`);
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "deleteContentForward"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       checkTargetRanges(beforeInputEvent, [{startContainer: selectionRanges[0].startContainer,
                                             startOffset: selectionRanges[0].startOffset,
                                             endContainer: selectionRanges[0].startContainer,
                                             endOffset: selectionRanges[0].startOffset + 1}]);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.inputType, "deleteContentForward",
-        `${aDescription}inputType of "input" event for ${action} should be "deleteContentForward"`);
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "deleteContentForward"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       checkTargetRanges(inputEvent, []);
-    })();
+    }
+    test_typing_delete_to_delete_last_character({
+      action: 'typing "Delete" to delete last character (NBSP) and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_typing_delete_to_delete_last_character({
+      action: 'typing "Delete" to delete last character (NBSP)',
+      cancelBeforeInput: false,
+    });
 
-    (function test_undoing_deleting_last_character_and_canceling_beforeinput() {
+    function test_undoing_deleting_last_character(aTestData) {
       reset();
-      cancelBeforeInput = true;
-      action = 'doing "Undo"';
+      initializing = true;
+      editTarget.innerHTML = "\u00A0";
+      selection.collapse(editTarget.firstChild, 0);
+      synthesizeKey("KEY_Delete", {}, aWindow);
+      initializing = false;
+
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
       synthesizeKey("z", {accelKey: true}, aWindow);
-      is(editTarget.innerHTML, "<br>",
-        `${aDescription}" " shouldn't have been restored by ${action}`);
+      let expectedValue = aTestData.cancelBeforeInput ? "<br>" : "&nbsp;";
+      is(editTarget.innerHTML, expectedValue,
+        `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "historyUndo",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "historyUndo"`);
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "historyUndo"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       checkTargetRanges(beforeInputEvent, []);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't have been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_undoing_deleting_last_character() {
-      reset();
-      cancelBeforeInput = false;
-      action = 'doing "Undo"';
-      synthesizeKey("z", {accelKey: true}, aWindow);
-      is(editTarget.innerHTML, "&nbsp;",
-        `${aDescription}" " should've been restored by ${action}`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "historyUndo",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "historyUndo"`);
-      is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      checkTargetRanges(beforeInputEvent, []);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.inputType, "historyUndo",
-        `${aDescription}inputType of "input" event for ${action} should be "historyUndo"`);
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "historyUndo"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       checkTargetRanges(inputEvent, []);
-    })();
+    }
+    test_undoing_deleting_last_character({
+      action: 'undoing deleting last character and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_undoing_deleting_last_character({
+      action: 'undoing deleting last character',
+      cancelBeforeInput: false,
+    });
 
     (function test_undoing_without_undoable_transaction() {
       reset();
+      initializing = true;
+      htmlEditor.enableUndo(false);
+      htmlEditor.enableUndo(true);
+      editTarget.innerHTML = "\u00A0";
+      selection.collapse(editTarget.firstChild, 0);
+      synthesizeKey("KEY_Delete", {}, aWindow);
+      synthesizeKey("z", {accelKey: true}, aWindow);
+      initializing = false;
+
       action = 'doing "Undo" again';
       synthesizeKey("z", {accelKey: true}, aWindow);
       is(editTarget.innerHTML, "&nbsp;",
         `${aDescription}the editor shouldn't have been modified by ${action} since there is no undo transaction`);
       ok(!beforeInputEvent,
         `${aDescription}"beforeinput" event should've been fired at ${action} since there is no undo transaction`);
       ok(!inputEvent,
         `${aDescription}"input" event shouldn't have been fired at ${action} since there is no undo transaction`);
     })();
 
-    (function test_redoing_deleting_last_character_and_canceling_beforeinput() {
-      reset();
-      cancelBeforeInput = true;
-      action = 'doing "Redo"';
-      synthesizeKey("z", {accelKey: true, shiftKey: true}, aWindow);
-      is(editTarget.innerHTML, "&nbsp;",
-        `${aDescription}" " shouldn't have been restored by ${action}`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "historyRedo",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "historyRedo"`);
-      is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      checkTargetRanges(beforeInputEvent, []);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't have been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_redoing_deleting_last_character() {
+    function test_redoing_deleting_last_character(aTestData) {
       reset();
-      cancelBeforeInput = false;
-      action = 'doing "Redo"';
+      initializing = true;
+      htmlEditor.enableUndo(false);
+      htmlEditor.enableUndo(true);
+      editTarget.innerHTML = "\u00A0";
+      selection.collapse(editTarget.firstChild, 0);
+      synthesizeKey("KEY_Delete", {}, aWindow);
+      synthesizeKey("z", {accelKey: true}, aWindow);
+      initializing = false;
+
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
       synthesizeKey("z", {accelKey: true, shiftKey: true}, aWindow);
-      is(editTarget.innerHTML, "<br>",
-        `${aDescription}the padding <br> should've been restored by ${action}`);
+      let expectedValue = aTestData.cancelBeforeInput ? "&nbsp;" : "<br>";
+      is(editTarget.innerHTML, expectedValue,
+        `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "historyRedo",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "historyRedo"`);
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "historyRedo"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       checkTargetRanges(beforeInputEvent, []);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.inputType, "historyRedo",
-        `${aDescription}inputType of "input" event for ${action} should be "historyRedo"`);
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "historyRedo"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       checkTargetRanges(inputEvent, []);
-    })();
+    }
+    test_redoing_deleting_last_character({
+      action: 'redoing deleting last character and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_redoing_deleting_last_character({
+      action: 'redoing deleting last character',
+      cancelBeforeInput: false,
+    });
 
     (function test_redoing_without_redoable_transaction() {
       reset();
+      initializing = true;
+      htmlEditor.enableUndo(false);
+      htmlEditor.enableUndo(true);
+      editTarget.innerHTML = "\u00A0";
+      selection.collapse(editTarget.firstChild, 0);
+      synthesizeKey("KEY_Delete", {}, aWindow);
+      synthesizeKey("z", {accelKey: true}, aWindow);
+      synthesizeKey("z", {accelKey: true, shiftKey: true}, aWindow);
+      initializing = false;
+
       action = 'doing "Redo" again';
       synthesizeKey("z", {accelKey: true, shiftKey: true}, aWindow);
       is(editTarget.innerHTML, "<br>",
         `${aDescription}the editor shouldn't have been modified by ${action} since there is no redo transaction`);
       ok(!beforeInputEvent,
         `${aDescription}"beforeinput" event should've been fired at ${action} since there is no redo transaction`);
       ok(!inputEvent,
         `${aDescription}"input" event shouldn't have been fired at ${action} since there is no redo transaction`);
     })();
 
-    (function test_inserting_linebreak_and_canceling_beforeinput() {
+    function test_inserting_linebreak(aTestData) {
       reset();
-      cancelBeforeInput = true;
-      action = "inserting a line break";
-      synthesizeKey("KEY_Enter", {shiftKey: true}, aWindow);
-      is(editTarget.innerHTML, "<br>",
-        `${aDescription}shouldn't modify the editor by ${action} since "beforeinput" was canceled`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_inserting_linebreak() {
-      reset();
-      cancelBeforeInput = false;
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
       editTarget.innerHTML = "<br>";
       selection.collapse(editTarget, 0);
       synthesizeKey("KEY_Enter", {shiftKey: true}, aWindow);
-      is(editTarget.innerHTML, "<br><br>",
-        `${aDescription}should insert new <br> element by ${action}`);
+      let expectedValue = aTestData.cancelBeforeInput ? "<br>" : "<br><br>";
+      is(editTarget.innerHTML, expectedValue,
+        `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "insertLineBreak",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "insertLineBreak"`);
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "insertLineBreak"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       checkTargetRanges(beforeInputEvent, selectionRanges);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.inputType, "insertLineBreak",
-        `${aDescription}inputType of "input" event for ${action} should be "insertLineBreak"`);
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "insertLineBreak"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       checkTargetRanges(inputEvent, []);
-    })();
+    }
+    test_inserting_linebreak({
+      action: 'inserting a linebreak and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_inserting_linebreak({
+      action: "inserting a linebreak",
+      cancelBeforeInput: false,
+    });
 
-    (function test_typing_backspace_to_delete_selected_characters_and_canceling_beforeinput() {
+    function test_typing_backspace_to_delete_selected_characters(aTestData) {
       editTarget.innerHTML = "a";
       editTarget.focus();
       selection.selectAllChildren(editTarget);
       reset();
-      cancelBeforeInput = true;
-      action = 'removing "a" with "Backspace" (with selection)';
-      synthesizeKey("KEY_Backspace", {}, aWindow);
-      is(editTarget.innerHTML, "a",
-        `${aDescription}"a" shouldn't have been removed by ${action} since "beforeinput" was canceled`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_typing_backspace_to_delete_selected_characters() {
-      editTarget.innerHTML = "a";
-      editTarget.focus();
-      selection.selectAllChildren(editTarget);
-      reset();
-      cancelBeforeInput = false;
-      expectedTargetRanges = [{
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
+      let expectedTargetRanges = [{
         startContainer: editTarget.firstChild,
         startOffset: 0,
         endContainer: editTarget.firstChild,
         endOffset: editTarget.firstChild.length,
       }];
       synthesizeKey("KEY_Backspace", {}, aWindow);
-      is(editTarget.innerHTML, "<br>",
-        `${aDescription}"a" should've been removed by ${action}`);
+      let expectedValue = aTestData.cancelBeforeInput ? "a" : "<br>";
+      is(editTarget.innerHTML, expectedValue,
+        `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "deleteContentBackward",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "deleteContentBackward"`);
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "deleteContentBackward"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       checkTargetRanges(beforeInputEvent, expectedTargetRanges);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.inputType, "deleteContentBackward",
-        `${aDescription}inputType of "input" event for ${action} should be "deleteContentBackward"`);
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "deleteContentBackward"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       checkTargetRanges(inputEvent, []);
-    })();
+    }
+    test_typing_backspace_to_delete_selected_characters({
+      action: 'typing "Backspace" to delete selected characters and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_typing_backspace_to_delete_selected_characters({
+      action: 'typing "Backspace" to delete selected characters',
+      cancelBeforeInput: false,
+    });
 
-    (function test_typing_delete_to_delete_selected_characters_and_canceling_beforeinput() {
+    function test_typing_delete_to_delete_selected_characters(aTestData) {
       editTarget.innerHTML = "a";
       editTarget.focus();
       selection.selectAllChildren(editTarget);
       reset();
-      cancelBeforeInput = true;
-      action = 'removing "a" with "Delete" (with selection)';
-      expectedTargetRanges = [{
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
+      let expectedTargetRanges = [{
         startContainer: editTarget.firstChild,
         startOffset: 0,
         endContainer: editTarget.firstChild,
         endOffset: editTarget.firstChild.length,
       }];
       synthesizeKey("KEY_Delete", {}, aWindow);
-      is(editTarget.innerHTML, "a",
-        `${aDescription}"a" should've been removed by ${action} since "beforeinput" was canceled`);
+      let expectedValue = aTestData.cancelBeforeInput ? "a" : "<br>";
+      is(editTarget.innerHTML, expectedValue,
+        `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should be fired at ${action} even if it won't remove any content`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "deleteContentForward",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "deleteContentForward"`);
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "deleteContentForward"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       checkTargetRanges(beforeInputEvent, expectedTargetRanges);
-      ok(!inputEvent,
-        `${aDescription}${action} should not fire "input" event since "beforeinput" was canceled`);
-    })();
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
+      ok(inputEvent,
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
+      is(inputEvent.inputType, "deleteContentForward",
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "deleteContentForward"`);
+      is(inputEvent.data, null,
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
+      is(inputEvent.dataTransfer, null,
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
+      checkTargetRanges(inputEvent, []);
+    }
+    test_typing_delete_to_delete_selected_characters({
+      action: 'typing "Delete" to delete selected characters and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_typing_delete_to_delete_selected_characters({
+      action: 'typing "Delete" to delete selected characters',
+      cancelBeforeInput: false,
+    });
 
-    (function test_typing_delete_to_delete_selected_characters() {
-      editTarget.innerHTML = "a";
-      editTarget.focus();
-      selection.selectAllChildren(editTarget);
-      reset();
-      cancelBeforeInput = false;
-      action = 'removing "a" with "Delete" (with selection)';
-      expectedTargetRanges = [{
-        startContainer: editTarget.firstChild,
-        startOffset: 0,
-        endContainer: editTarget.firstChild,
-        endOffset: editTarget.firstChild.length,
-      }];
-      synthesizeKey("KEY_Delete", {}, aWindow);
-      is(editTarget.innerHTML, "<br>",
-        `${aDescription}" " should've been removed by ${action}`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "deleteContentForward",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "deleteContentForward"`);
-      is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      checkTargetRanges(beforeInputEvent, expectedTargetRanges);
-      ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
-      is(inputEvent.inputType, "deleteContentForward",
-        `${aDescription}inputType of "input" event for ${action} should be "deleteContentForward"`);
-      is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
-      is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
-      checkTargetRanges(inputEvent, []);
-    })();
-
-    (function test_deleting_word_backward_from_its_end_and_canceling_beforeinput() {
+    function test_deleting_word_backward_from_its_end(aTestData) {
       editTarget.innerHTML = "abc def";
       editTarget.focus();
       selection.collapse(editTarget.firstChild, "abc def".length);
       reset();
-      cancelBeforeInput = true;
-      action = 'removing last word, "def", with backward deletion from its end';
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
       SpecialPowers.doCommand(aWindow, "cmd_deleteWordBackward");
-      is(editTarget.innerHTML, "abc def",
-        `${aDescription}"def" shouldn't have been removed by ${action} since "beforeinput" was canceled`);
+      let expectedValue = aTestData.cancelBeforeInput ? "abc def" : "abc ";
+      is(editTarget.innerHTML, expectedValue,
+        `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_deleting_word_backward_from_its_end() {
-      editTarget.innerHTML = "abc def";
-      editTarget.focus();
-      selection.collapse(editTarget.firstChild, "abc def".length);
-      reset();
-      cancelBeforeInput = false;
-      SpecialPowers.doCommand(aWindow, "cmd_deleteWordBackward");
-      is(editTarget.innerHTML, "abc ",
-        `${aDescription}"def" should've been removed by ${action}`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "deleteWordBackward",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "deleteWordBackward"`);
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "deleteWordBackward"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       checkTargetRanges(beforeInputEvent, [{startContainer: selectionRanges[0].endContainer,
                                             startOffset: selectionRanges[0].endOffset - "def".length,
                                             endContainer: selectionRanges[0].endContainer,
                                             endOffset: selectionRanges[0].endOffset}]);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.inputType, "deleteWordBackward",
-        `${aDescription}inputType of "input" event for ${action} should be "deleteWordBackward"`);
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "deleteWordBackward"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       checkTargetRanges(inputEvent, []);
-    })();
+    }
+    test_deleting_word_backward_from_its_end({
+      action: 'deleting word backward from its end and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_deleting_word_backward_from_its_end({
+      action: "deleting word backward from its end",
+      cancelBeforeInput: false,
+    });
 
-    (function test_deleting_word_forward_from_its_start_and_canceling_beforeinput() {
+    function test_deleting_word_forward_from_its_start(aTestData) {
       editTarget.innerHTML = "abc def";
       editTarget.focus();
       selection.collapse(editTarget.firstChild, 0);
       reset();
-      cancelBeforeInput = true;
-      action = `removing first word, "${kWordSelectEatSpaceToNextWord ? "abc" : "abc "}", with forward deletion from its start`;
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
       SpecialPowers.doCommand(aWindow, "cmd_deleteWordForward");
-      is(editTarget.innerHTML, "abc def",
-        `${aDescription}"abc" shouldn't have been removed by ${action} since "beforeinput" was canceled`);
+      if (aTestData.cancelBeforeInput) {
+        is(editTarget.innerHTML, "abc def",
+          `${aDescription}innerHTML should be "abc def" after ${aTestData.action}`);
+      } else {
+        let expectedValue = kWordSelectEatSpaceToNextWord ? "def" : " def";
+        is(editTarget.innerHTML, expectedValue,
+          `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
+      }
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_deleting_word_forward_from_its_start() {
-      editTarget.innerHTML = "abc def";
-      editTarget.focus();
-      selection.collapse(editTarget.firstChild, 0);
-      reset();
-      cancelBeforeInput = false;
-      SpecialPowers.doCommand(aWindow, "cmd_deleteWordForward");
-      is(editTarget.innerHTML, kWordSelectEatSpaceToNextWord ? "def" : " def",
-        `${aDescription}"${kWordSelectEatSpaceToNextWord ? "abc " : "abc"}" should've been removed by ${action}`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "deleteWordForward",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "deleteWordForward"`);
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "deleteWordForward"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       checkTargetRanges(beforeInputEvent, [{startContainer: selectionRanges[0].startContainer,
                                             startOffset: selectionRanges[0].startOffset,
                                             endContainer: selectionRanges[0].startContainer,
                                             endOffset: selectionRanges[0].startOffset +
                                                 (kWordSelectEatSpaceToNextWord ? "abc ".length : "abc".length)}]);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.inputType, "deleteWordForward",
-        `${aDescription}inputType of "input" event for ${action} should be "deleteWordForward"`);
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "deleteWordForward"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       checkTargetRanges(inputEvent, []);
-    })();
+    }
+    test_deleting_word_forward_from_its_start({
+      action: 'deleting word forward from its start and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_deleting_word_forward_from_its_start({
+      action: "deleting word forward from its start",
+      cancelBeforeInput: false,
+    });
 
     (function test_deleting_word_backward_from_middle_of_second_word() {
       editTarget.innerHTML = "abc def";
       editTarget.focus();
       selection.setBaseAndExtent(editTarget.firstChild, "abc d".length, editTarget.firstChild, "abc de".length);
       reset();
       cancelBeforeInput = false;
       action = "removing characters backward from middle of second word";
@@ -1161,190 +1233,178 @@ async function runTests() {
         `${aDescription}inputType of "input" event for ${action} should be "${expectedInputType}"`);
       is(inputEvent.data, null,
         `${aDescription}data of "input" event for ${action} should be null`);
       is(inputEvent.dataTransfer, null,
         `${aDescription}dataTransfer of "input" event for ${action} should be null`);
       checkTargetRanges(inputEvent, []);
     })();
 
-    (function test_switching_text_direction_from_default_and_canceling_beforeinput() {
-      editTarget.focus();
-      reset();
-      cancelBeforeInput = true;
-      action = 'switching text direction from "ltr" to "rtl"';
-      SpecialPowers.doCommand(aWindow, "cmd_switchTextDirection");
-      // XXX If editing host is a descendant of `<body>`, this must be a bug.
-      is(body.getAttribute("dir"), null,
-        `${aDescription}dir attribute of <body> should not be set" by ${action} since "beforeinput" was canceled`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "formatSetBlockTextDirection",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "formatSetBlockTextDirection"`);
-      is(beforeInputEvent.data, "rtl",
-        `${aDescription}data of "beforeinput" event for ${action} should be "rtl"`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      checkTargetRanges(beforeInputEvent, []);
-      ok(!inputEvent,
-        `${aDescription}"input" event should not have been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_switching_text_direction_from_rtl_to_ltr_and_canceling_beforeinput() {
-      body.setAttribute("dir", "rtl");
-      htmlEditor.flags &= ~SpecialPowers.Ci.nsIEditor.eEditorLeftToRight;
-      htmlEditor.flags |= SpecialPowers.Ci.nsIEditor.eEditorRightToLeft; // XXX flags update is required, must be a bug.
-      aDocument.documentElement.scrollTop; // XXX Update the body frame
-      editTarget.focus();
-      reset();
-      cancelBeforeInput = true;
-      action = 'switching text direction from "rtl" to "ltr"';
-      SpecialPowers.doCommand(aWindow, "cmd_switchTextDirection");
-      // XXX If editing host is a descendant of `<body>`, this must be a bug.
-      is(body.getAttribute("dir"), "rtl",
-        `${aDescription}dir attribute of <body> should not have been modified by ${action} since "beforeinput" was canceled`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "formatSetBlockTextDirection",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "formatSetBlockTextDirection"`);
-      is(beforeInputEvent.data, "ltr",
-        `${aDescription}data of "beforeinput" event for ${action} should be "ltr"`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      checkTargetRanges(beforeInputEvent, []);
-      ok(!inputEvent,
-        `${aDescription}"input" event should not have been fired at ${action} since "beforeinput" was canceled`);
-    })();
+    function test_switching_text_direction_from_default(aTestData) {
+      try {
+        body.removeAttribute("dir");
+        htmlEditor.flags &= ~SpecialPowers.Ci.nsIEditor.eEditorRightToLeft;
+        htmlEditor.flags |= SpecialPowers.Ci.nsIEditor.eEditorLeftToRight; // XXX flags update is required, must be a bug.
+        aDocument.documentElement.scrollTop; // XXX Update the body frame
+        editTarget.focus();
+        reset();
+        cancelBeforeInput = aTestData.cancelBeforeInput;
+        action = aTestData.action;
+        SpecialPowers.doCommand(aWindow, "cmd_switchTextDirection");
+        // XXX If editing host is a descendant of `<body>`, this must be a bug.
+        if (aTestData.cancelBeforeInput) {
+          is(body.getAttribute("dir"), null,
+            `${aDescription}dir attribute of the element shouldn't have been set by ${aTestData.action}`);
+        } else {
+          is(body.getAttribute("dir"), "rtl",
+            `${aDescription}dir attribute of the element should've been set to "rtl" by ${aTestData.action}`);
+        }
+        ok(beforeInputEvent,
+          `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
+        is(beforeInputEvent.cancelable, true,
+          `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
+        is(beforeInputEvent.inputType, "formatSetBlockTextDirection",
+          `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "formatSetBlockTextDirection"`);
+        is(beforeInputEvent.data, "rtl",
+          `${aDescription}data of "beforeinput" event for ${aTestData.action} should be "rtl"`);
+        is(beforeInputEvent.dataTransfer, null,
+          `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
+        checkTargetRanges(beforeInputEvent, []);
+        if (aTestData.cancelBeforeInput) {
+          ok(!inputEvent,
+            `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+          return;
+        }
+        ok(inputEvent,
+          `${aDescription}"input" event should've been fired at ${aTestData.action}`);
+        is(inputEvent.inputType, "formatSetBlockTextDirection",
+          `${aDescription}inputType of "input" event for ${aTestData.action} should be "formatSetBlockTextDirection"`);
+        is(inputEvent.data, "rtl",
+          `${aDescription}data of "input" event for ${aTestData.action} should be "rtl"`);
+        is(inputEvent.dataTransfer, null,
+          `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
+        checkTargetRanges(inputEvent, []);
+      } finally {
+        body.removeAttribute("dir");
+        htmlEditor.flags &= ~SpecialPowers.Ci.nsIEditor.eEditorRightToLeft;
+        htmlEditor.flags |= SpecialPowers.Ci.nsIEditor.eEditorLeftToRight; // XXX flags update is required, must be a bug.
+        aDocument.documentElement.scrollTop; // XXX Update the body frame
+      }
+    }
+    test_switching_text_direction_from_default({
+      action: 'switching text direction from default to "rtl" and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_switching_text_direction_from_default({
+      action: 'switching text direction from default to "rtl"',
+      cancelBeforeInput: false,
+    });
 
-    (function test_switching_text_direction_from_default() {
-      body.removeAttribute("dir");
-      htmlEditor.flags &= ~SpecialPowers.Ci.nsIEditor.eEditorRightToLeft;
-      htmlEditor.flags |= SpecialPowers.Ci.nsIEditor.eEditorLeftToRight; // XXX flags update is required, must be a bug.
-      aDocument.documentElement.scrollTop; // XXX Update the body frame
-      editTarget.focus();
-      reset();
-      cancelBeforeInput = false;
-      action = 'switching text direction from "ltr" to "rtl"';
-      SpecialPowers.doCommand(aWindow, "cmd_switchTextDirection");
-      // XXX If editing host is a descendant of `<body>`, this must be a bug.
-      is(body.getAttribute("dir"), "rtl",
-        `${aDescription}dir attribute of <body> should've been set to "rtl" by ${action}`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "formatSetBlockTextDirection",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "formatSetBlockTextDirection"`);
-      is(beforeInputEvent.data, "rtl",
-        `${aDescription}data of "beforeinput" event for ${action} should be "rtl"`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      checkTargetRanges(beforeInputEvent, []);
-      ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
-      is(inputEvent.inputType, "formatSetBlockTextDirection",
-        `${aDescription}inputType of "input" event for ${action} should be "formatSetBlockTextDirection"`);
-      is(inputEvent.data, "rtl",
-        `${aDescription}data of "input" event for ${action} should be "rtl"`);
-      is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
-      checkTargetRanges(inputEvent, []);
-    })();
+    function test_switching_text_direction_from_rtl_to_ltr(aTestData) {
+      try {
+        body.setAttribute("dir", "rtl");
+        htmlEditor.flags &= ~SpecialPowers.Ci.nsIEditor.eEditorLeftToRight;
+        htmlEditor.flags |= SpecialPowers.Ci.nsIEditor.eEditorRightToLeft; // XXX flags update is required, must be a bug.
+        aDocument.documentElement.scrollTop; // XXX Update the body frame
+        editTarget.focus();
+        reset();
+        cancelBeforeInput = aTestData.cancelBeforeInput;
+        action = aTestData.action;
+        SpecialPowers.doCommand(aWindow, "cmd_switchTextDirection");
+        // XXX If editing host is a descendant of `<body>`, this must be a bug.
+        let expectedDirValue = aTestData.cancelBeforeInput ? "rtl" : "ltr";
+        is(body.getAttribute("dir"), expectedDirValue,
+          `${aDescription}dir attribute of the element should be "${expectedDirValue}" after ${aTestData.action}`);
+        ok(beforeInputEvent,
+          `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
+        is(beforeInputEvent.cancelable, true,
+          `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
+        is(beforeInputEvent.inputType, "formatSetBlockTextDirection",
+          `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "formatSetBlockTextDirection"`);
+        is(beforeInputEvent.data, "ltr",
+          `${aDescription}data of "beforeinput" event for ${aTestData.action} should be "ltr"`);
+        is(beforeInputEvent.dataTransfer, null,
+          `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
+        checkTargetRanges(beforeInputEvent, []);
+        if (aTestData.cancelBeforeInput) {
+          ok(!inputEvent,
+            `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+          return;
+        }
+        ok(inputEvent,
+          `${aDescription}"input" event should've been fired at ${aTestData.action}`);
+        is(inputEvent.inputType, "formatSetBlockTextDirection",
+          `${aDescription}inputType of "input" event for ${aTestData.action} should be "formatSetBlockTextDirection"`);
+        is(inputEvent.data, "ltr",
+          `${aDescription}data of "input" event for ${aTestData.action} should be "ltr"`);
+        is(inputEvent.dataTransfer, null,
+          `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
+        checkTargetRanges(inputEvent, []);
+      } finally {
+        body.removeAttribute("dir");
+        htmlEditor.flags &= ~SpecialPowers.Ci.nsIEditor.eEditorRightToLeft;
+        htmlEditor.flags |= SpecialPowers.Ci.nsIEditor.eEditorLeftToRight; // XXX flags update is required, must be a bug.
+        aDocument.documentElement.scrollTop; // XXX Update the body frame
+      }
+    }
+    test_switching_text_direction_from_rtl_to_ltr({
+      action: 'switching text direction from "rtl" to "ltr" and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_switching_text_direction_from_rtl_to_ltr({
+      action: 'switching text direction from "rtl" to "ltr" and canceling "beforeinput"',
+      cancelBeforeInput: false,
+    });
 
-    (function test_switching_text_direction_from_rtl_to_ltr() {
-      editTarget.focus();
-      reset();
-      cancelBeforeInput = false;
-      action = 'switching text direction from "rtl" to "ltr"';
-      SpecialPowers.doCommand(aWindow, "cmd_switchTextDirection");
-      // XXX If editing host is a descendant of `<body>`, this must be a bug.
-      is(body.getAttribute("dir"), "ltr",
-        `${aDescription}dir attribute of <body> should've been set to "ltr" by ${action}`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "formatSetBlockTextDirection",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "formatSetBlockTextDirection"`);
-      is(beforeInputEvent.data, "ltr",
-        `${aDescription}data of "beforeinput" event for ${action} should be "ltr"`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      checkTargetRanges(beforeInputEvent, []);
-      ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
-      is(inputEvent.inputType, "formatSetBlockTextDirection",
-        `${aDescription}inputType of "input" event for ${action} should be "formatSetBlockTextDirection"`);
-      is(inputEvent.data, "ltr",
-        `${aDescription}data of "input" event for ${action} should be "ltr"`);
-      is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
-      checkTargetRanges(inputEvent, []);
-    })();
 
-    (function test_inserting_link_and_canceling_beforeinput() {
+    function test_inserting_link(aTestData) {
       editTarget.innerHTML = "link";
       editTarget.focus();
       selection.selectAllChildren(editTarget);
       reset();
-      cancelBeforeInput = true;
-      action = "setting link with absolute URL";
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
       SpecialPowers.doCommand(aWindow, "cmd_insertLinkNoUI", "https://example.com/foo/bar.html");
-      is(editTarget.innerHTML, "link",
-        `${aDescription}the text should not habe been modified by ${action} since "beforeinput" was canceled`);
+      let expectedValue = aTestData.cancelBeforeInput ? "link" : '<a href="https://example.com/foo/bar.html">link</a>';
+      is(editTarget.innerHTML, expectedValue,
+        `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "insertLink",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "insertLink"`);
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "insertLink"`);
       is(beforeInputEvent.data, "https://example.com/foo/bar.html",
-        `${aDescription}data of "beforeinput" event for ${action} should be "https://example.com/foo/bar.html"`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be "https://example.com/foo/bar.html"`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       checkTargetRanges(beforeInputEvent, selectionRanges);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't have been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_inserting_link() {
-      editTarget.innerHTML = "link";
-      editTarget.focus();
-      selection.selectAllChildren(editTarget);
-      reset();
-      cancelBeforeInput = false;
-      action = "setting link with absolute URL";
-      SpecialPowers.doCommand(aWindow, "cmd_insertLinkNoUI", "https://example.com/foo/bar.html");
-      is(editTarget.innerHTML, '<a href="https://example.com/foo/bar.html">link</a>',
-        `${aDescription}the text should've been wrapped by <a href> element by ${action}`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "insertLink",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "insertLink"`);
-      is(beforeInputEvent.data, "https://example.com/foo/bar.html",
-        `${aDescription}data of "beforeinput" event for ${action} should be "https://example.com/foo/bar.html"`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      checkTargetRanges(beforeInputEvent, selectionRanges);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.inputType, "insertLink",
-        `${aDescription}inputType of "input" event for ${action} should be "insertLink"`);
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "insertLink"`);
       is(inputEvent.data, "https://example.com/foo/bar.html",
-        `${aDescription}data of "input" event for ${action} should be "https://example.com/foo/bar.html"`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be "https://example.com/foo/bar.html"`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       checkTargetRanges(inputEvent, []);
-    })();
+    }
+    test_inserting_link({
+      action: 'setting link with absolute URL and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_inserting_link({
+      action: "setting link with absolute URL",
+      cancelBeforeInput: false,
+    });
 
     (function test_inserting_link_with_relative_url() {
       editTarget.innerHTML = "link";
       selection.selectAllChildren(editTarget);
       reset();
       cancelBeforeInput = false;
       action = "setting link with relative URL";
       SpecialPowers.doCommand(aWindow, "cmd_insertLinkNoUI", "foo/bar.html");
@@ -1391,511 +1451,480 @@ async function runTests() {
                         {command: "cmd_subscript",
                         tag: "sub",
                         exclusiveTags: ["sup"],
                         inputType: "formatSubscript"},
                         {command: "cmd_superscript",
                         tag: "sup",
                         exclusiveTags: ["sub"],
                         inputType: "formatSuperscript"}]) {
-        (function test_formatting_text() {
+        function test_formatting_text(aTestData) {
           editTarget.innerHTML = "format";
           editTarget.focus();
           selection.selectAllChildren(editTarget);
           reset();
-          cancelBeforeInput = false;
-          action = `formatting with "${test.command}"`;
+          cancelBeforeInput = aTestData.cancelBeforeInput;
+          action = aTestData.action;
           SpecialPowers.doCommand(aWindow, test.command);
-          is(editTarget.innerHTML, `<${test.tag}>format</${test.tag}>`,
-            `${aDescription}all text should be wrapped with <${test.tag}> element at ${action}`);
+          let expectedValue = aTestData.cancelBeforeInput
+                                ? "format"
+                                : `<${test.tag}>format</${test.tag}>`;
+          is(editTarget.innerHTML, expectedValue,
+            `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
           ok(beforeInputEvent,
-            `${aDescription}"beforeinput" event should've been fired at ${action}`);
+            `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
           is(beforeInputEvent.cancelable, true,
-            `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-          is(beforeInputEvent.inputType, test.inputType,
-            `${aDescription}inputType of "beforeinput" event should be "${test.inputType}"`);
-          is(beforeInputEvent.data, null,
-            `${aDescription}data of "beforeinput" event for ${action} should be null`);
-          is(beforeInputEvent.dataTransfer, null,
-            `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-          checkTargetRanges(beforeInputEvent, selectionRanges);
-          ok(inputEvent,
-            `${aDescription}"input" event should've been fired at ${action}`);
-          is(inputEvent.cancelable, false,
-            `${aDescription}"input" event for ${action} should never be cancelable`);
-          is(inputEvent.inputType, test.inputType,
-            `${aDescription}inputType of "input" event should be "${test.inputType}"`);
-          is(inputEvent.data, null,
-            `${aDescription}data of "input" event for ${action} should be null`);
-          is(inputEvent.dataTransfer, null,
-            `${aDescription}dataTransfer of "input" event for ${action} should be null`);
-          checkTargetRanges(inputEvent, []);
-        })();
-
-        (function test_removing_format_text() {
-          selection.selectAllChildren(editTarget);
-          reset();
-          cancelBeforeInput = false;
-          action = `removing format with "${test.command}"`;
-          SpecialPowers.doCommand(aWindow, test.command);
-          is(editTarget.innerHTML, "format",
-            `${aDescription}<${test.tag}> element should be unwrapped by ${action}`);
-          ok(beforeInputEvent,
-            `${aDescription}"beforeinput" event should've been fired at ${action}`);
-          is(beforeInputEvent.cancelable, true,
-            `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+            `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
           is(beforeInputEvent.inputType, test.inputType,
             `${aDescription}inputType of "beforeinput" event should be "${test.inputType}"`);
           is(beforeInputEvent.data, null,
-            `${aDescription}data of "beforeinput" event for ${action} should be null`);
+            `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
           is(beforeInputEvent.dataTransfer, null,
-            `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+            `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
           checkTargetRanges(beforeInputEvent, selectionRanges);
+          if (aTestData.cancelBeforeInput) {
+            ok(!inputEvent,
+              `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+            return;
+          }
           ok(inputEvent,
-            `${aDescription}"input" event should've been fired at ${action}`);
+            `${aDescription}"input" event should've been fired at ${aTestData.action}`);
           is(inputEvent.cancelable, false,
-            `${aDescription}"input" event for ${action} should never be cancelable`);
+            `${aDescription}"input" event for ${aTestData.action} should never be cancelable`);
           is(inputEvent.inputType, test.inputType,
             `${aDescription}inputType of "input" event should be "${test.inputType}"`);
           is(inputEvent.data, null,
-            `${aDescription}data of "input" event for ${action} should be null`);
+            `${aDescription}data of "input" event for ${aTestData.action} should be null`);
           is(inputEvent.dataTransfer, null,
-            `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+            `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
           checkTargetRanges(inputEvent, []);
-        })();
+        }
+        test_formatting_text({
+          action: `formatting with "${test.command}" and canceling "beforeinput"`,
+          cancelBeforeInput: true,
+        });
+        test_formatting_text({
+          action: `formatting with "${test.command}" and canceling "beforeinput"`,
+          cancelBeforeInput: false,
+        });
 
-        (function test_formatting_text_and_canceling_beforeinput() {
+        function test_removing_format_text(aTestData) {
+          editTarget.innerHTML = `<${test.tag}>format</${test.tag}>`;
           selection.selectAllChildren(editTarget);
           reset();
-          cancelBeforeInput = true;
-          action = `formatting with "${test.command}" but "beforeinput" is canceled`;
+          cancelBeforeInput = aTestData.cancelBeforeInput;
+          action = aTestData.action;
           SpecialPowers.doCommand(aWindow, test.command);
-          is(editTarget.innerHTML, "format",
-            `${aDescription}text shouldn't have been modified at ${action}`);
+          let expectedValue = aTestData.cancelBeforeInput
+                                ? `<${test.tag}>format</${test.tag}>`
+                                : "format";
+          is(editTarget.innerHTML, expectedValue,
+            `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
           ok(beforeInputEvent,
-            `${aDescription}"beforeinput" event should've been fired at ${action}`);
+            `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
           is(beforeInputEvent.cancelable, true,
-            `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+            `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
           is(beforeInputEvent.inputType, test.inputType,
             `${aDescription}inputType of "beforeinput" event should be "${test.inputType}"`);
           is(beforeInputEvent.data, null,
-            `${aDescription}data of "beforeinput" event for ${action} should be null`);
+            `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
           is(beforeInputEvent.dataTransfer, null,
-            `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+            `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
           checkTargetRanges(beforeInputEvent, selectionRanges);
-          ok(!inputEvent,
-            `${aDescription}"input" event shouldn't have been fired at ${action}`);
-        })();
-
-        (function test_removing_format_and_canceling_beforeinput() {
-          editTarget.innerHTML = `<${test.tag}>format</${test.tag}>`;
-          editTarget.focus();
-          selection.selectAllChildren(editTarget);
-          reset();
-          cancelBeforeInput = true;
-          action = `removing format with "${test.command}" but "beforeinput" is canceled`;
-          SpecialPowers.doCommand(aWindow, test.command);
-          is(editTarget.innerHTML, `<${test.tag}>format</${test.tag}>`,
-            `${aDescription}text shouldn't have been modified at ${action}`);
-          ok(beforeInputEvent,
-            `${aDescription}"beforeinput" event should've been fired at ${action}`);
-          is(beforeInputEvent.cancelable, true,
-            `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-          is(beforeInputEvent.inputType, test.inputType,
-            `${aDescription}inputType of "beforeinput" event should be "${test.inputType}"`);
-          is(beforeInputEvent.data, null,
-            `${aDescription}data of "beforeinput" event for ${action} should be null`);
-          is(beforeInputEvent.dataTransfer, null,
-            `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-          checkTargetRanges(beforeInputEvent, selectionRanges);
-          ok(!inputEvent,
-            `${aDescription}"input" event shouldn't have been fired at ${action}`);
-        })();
+          if (aTestData.cancelBeforeInput) {
+            ok(!inputEvent,
+              `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+            return;
+          }
+          ok(inputEvent,
+            `${aDescription}"input" event should've been fired at ${aTestData.action}`);
+          is(inputEvent.cancelable, false,
+            `${aDescription}"input" event for ${aTestData.action} should never be cancelable`);
+          is(inputEvent.inputType, test.inputType,
+            `${aDescription}inputType of "input" event should be "${test.inputType}"`);
+          is(inputEvent.data, null,
+            `${aDescription}data of "input" event for ${aTestData.action} should be null`);
+          is(inputEvent.dataTransfer, null,
+            `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
+          checkTargetRanges(inputEvent, []);
+        }
+        test_removing_format_text({
+          action: `removing format with "${test.command}" and canceling "beforeinput"`,
+          cancelBeforeInput: true,
+        });
+        test_removing_format_text({
+          action: `removing format with "${test.command}" and canceling "beforeinput"`,
+          cancelBeforeInput: false,
+        });
 
         (function test_removing_format_styled_by_others() {
           if (!test.otherRemoveTags) {
             return;
           }
           for (let anotherTag of test.otherRemoveTags) {
-            (function test_removing_format_styled_by_another_element() {
-              editTarget.innerHTML = `<${anotherTag}>format</${anotherTag}>`;
-              editTarget.focus();
-              selection.selectAllChildren(editTarget);
-              reset();
-              cancelBeforeInput = false;
-              action = `removing <${anotherTag}> element with "${test.command}"`;
-              SpecialPowers.doCommand(aWindow, test.command);
-              is(editTarget.innerHTML, `format`,
-                `${aDescription}<${anotherTag}> element should be unwrapped by ${action}`);
-              ok(beforeInputEvent,
-                `${aDescription}"beforeinput" event should've been fired at ${action}`);
-              is(beforeInputEvent.cancelable, true,
-                `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-              is(beforeInputEvent.inputType, test.inputType,
-                `${aDescription}inputType of "beforeinput" event should be "${test.inputType}"`);
-              is(beforeInputEvent.data, null,
-                `${aDescription}data of "beforeinput" event for ${action} should be null`);
-              is(beforeInputEvent.dataTransfer, null,
-                `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-              checkTargetRanges(beforeInputEvent, selectionRanges);
-              ok(inputEvent,
-                `${aDescription}"input" event shouldn't have been fired at ${action}`);
-              is(inputEvent.cancelable, false,
-                `${aDescription}"input" event for ${action} should never be cancelable`);
-              is(inputEvent.inputType, test.inputType,
-                `${aDescription}inputType of "input" event should be "${test.inputType}"`);
-              is(inputEvent.data, null,
-                `${aDescription}data of "input" event for ${action} should be null`);
-              is(inputEvent.dataTransfer, null,
-                `${aDescription}dataTransfer of "input" event for ${action} should be null`);
-              checkTargetRanges(inputEvent, []);
-            })();
-
-            (function test_removing_format_styled_by_another_element_and_canceling_beforeinput() {
+            function test_removing_format_styled_by_another_element(aTestData) {
               editTarget.innerHTML = `<${anotherTag}>format</${anotherTag}>`;
               editTarget.focus();
               selection.selectAllChildren(editTarget);
               reset();
-              cancelBeforeInput = true;
-              action = `removing <${anotherTag}> element with "${test.command}" but "beforeinput" is canceled`;
+              cancelBeforeInput = aTestData.cancelBeforeInput;
+              action = aTestData.action;
               SpecialPowers.doCommand(aWindow, test.command);
-              is(editTarget.innerHTML, `<${anotherTag}>format</${anotherTag}>`,
-                `${aDescription}text shouldn't have been modified at ${action}`);
+              let expectedValue = aTestData.cancelBeforeInput
+                                    ? `<${anotherTag}>format</${anotherTag}>`
+                                    : "format";
+              is(editTarget.innerHTML, expectedValue,
+                `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
               ok(beforeInputEvent,
-                `${aDescription}"beforeinput" event should've been fired at ${action}`);
+                `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
               is(beforeInputEvent.cancelable, true,
-                `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+                `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
               is(beforeInputEvent.inputType, test.inputType,
                 `${aDescription}inputType of "beforeinput" event should be "${test.inputType}"`);
               is(beforeInputEvent.data, null,
-                `${aDescription}data of "beforeinput" event for ${action} should be null`);
+                `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
               is(beforeInputEvent.dataTransfer, null,
-                `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+                `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
               checkTargetRanges(beforeInputEvent, selectionRanges);
-              ok(!inputEvent,
-                `${aDescription}"input" event shouldn't have been fired at ${action}`);
-            })();
+              if (aTestData.cancelBeforeInput) {
+                ok(!inputEvent,
+                  `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+                return;
+              }
+              ok(inputEvent,
+                `${aDescription}"input" event shouldn't have been fired at ${aTestData.action}`);
+              is(inputEvent.cancelable, false,
+                `${aDescription}"input" event for ${aTestData.action} should never be cancelable`);
+              is(inputEvent.inputType, test.inputType,
+                `${aDescription}inputType of "input" event should be "${test.inputType}"`);
+              is(inputEvent.data, null,
+                `${aDescription}data of "input" event for ${aTestData.action} should be null`);
+              is(inputEvent.dataTransfer, null,
+                `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
+              checkTargetRanges(inputEvent, []);
+            }
+            test_removing_format_styled_by_another_element({
+              action: `removing <${anotherTag}> element with "${test.command}" and canceling "beforeinput"`,
+              cancelBeforeInput: true,
+            });
+            test_removing_format_styled_by_another_element({
+              action: `removing <${anotherTag}> element with "${test.command}"`,
+              cancelBeforeInput: false,
+            });
 
-            (function test_removing_format_styled_by_both_primary_one_and_another_one() {
+            function test_removing_format_styled_by_both_primary_one_and_another_one(aTestData) {
               editTarget.innerHTML = `<${test.tag}><${anotherTag}>format</${anotherTag}></${test.tag}>`;
               editTarget.focus();
               selection.selectAllChildren(editTarget);
               reset();
-              cancelBeforeInput = false;
-              action = `removing both <${test.tag}> and <${anotherTag}> elements with "${test.command}"`;
+              cancelBeforeInput = aTestData.cancelBeforeInput;
+              action = aTestData.action;
               SpecialPowers.doCommand(aWindow, test.command);
-              is(editTarget.innerHTML, `format`,
-                `${aDescription}Both <${test.tag}> and <${anotherTag}> elements should be unwrapped by ${action}`);
+              let expectedValue = aTestData.cancelBeforeInput
+                                    ? `<${test.tag}><${anotherTag}>format</${anotherTag}></${test.tag}>`
+                                    : "format";
+              is(editTarget.innerHTML, expectedValue,
+                `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
               ok(beforeInputEvent,
-                `${aDescription}"beforeinput" event should've been fired at ${action}`);
+                `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
               is(beforeInputEvent.cancelable, true,
-                `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+                `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
               is(beforeInputEvent.inputType, test.inputType,
                 `${aDescription}inputType of "beforeinput" event should be "${test.inputType}"`);
               is(beforeInputEvent.data, null,
-                `${aDescription}data of "beforeinput" event for ${action} should be null`);
+                `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
               is(beforeInputEvent.dataTransfer, null,
-                `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+                `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
               checkTargetRanges(beforeInputEvent, selectionRanges);
+              if (aTestData.cancelBeforeInput) {
+                ok(!inputEvent,
+                  `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+                return;
+              }
               ok(inputEvent,
-                `${aDescription}"input" event shouldn't have been fired at ${action}`);
+                `${aDescription}"input" event shouldn't have been fired at ${aTestData.action}`);
               is(inputEvent.cancelable, false,
-                `${aDescription}"input" event for ${action} should never be cancelable`);
+                `${aDescription}"input" event for ${aTestData.action} should never be cancelable`);
               is(inputEvent.inputType, test.inputType,
                 `${aDescription}inputType of "input" event should be "${test.inputType}"`);
               is(inputEvent.data, null,
-                `${aDescription}data of "input" event for ${action} should be null`);
+                `${aDescription}data of "input" event for ${aTestData.action} should be null`);
               is(inputEvent.dataTransfer, null,
-                `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+                `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
               checkTargetRanges(inputEvent, []);
-            })();
-
-            (function test_removing_format_styled_by_both_primary_one_and_another_one_and_canceling_beforeinput() {
-              editTarget.innerHTML = `<${test.tag}><${anotherTag}>format</${anotherTag}></${test.tag}>`;
-              editTarget.focus();
-              selection.selectAllChildren(editTarget);
-              reset();
-              cancelBeforeInput = true;
-              action = `removing both <${test.tag}> and <${anotherTag}> elements with "${test.command}" but "beforeinput" is canceled`;
-              SpecialPowers.doCommand(aWindow, test.command);
-              is(editTarget.innerHTML, `<${test.tag}><${anotherTag}>format</${anotherTag}></${test.tag}>`,
-                `${aDescription}text shouldn't have been modified at ${action}`);
-              ok(beforeInputEvent,
-                `${aDescription}"beforeinput" event should've been fired at ${action}`);
-              is(beforeInputEvent.cancelable, true,
-                `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-              is(beforeInputEvent.inputType, test.inputType,
-                `${aDescription}inputType of "beforeinput" event should be "${test.inputType}"`);
-              is(beforeInputEvent.data, null,
-                `${aDescription}data of "beforeinput" event for ${action} should be null`);
-              is(beforeInputEvent.dataTransfer, null,
-                `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-              checkTargetRanges(beforeInputEvent, selectionRanges);
-              ok(!inputEvent,
-                `${aDescription}"input" event shouldn't have been fired at ${action}`);
-            })();
+            }
+            test_removing_format_styled_by_both_primary_one_and_another_one({
+              action: `removing both <${test.tag}> and <${anotherTag}> elements with "${test.command}" and canceling "beforeinput"`,
+              cancelBeforeInput: true,
+            });
+            test_removing_format_styled_by_both_primary_one_and_another_one({
+              action: `removing both <${test.tag}> and <${anotherTag}> elements with "${test.command}"`,
+              cancelBeforeInput: false,
+            });
           }
         })();
         (function test_formatting_text_styled_by_exclusive_elements() {
           if (!test.exclusiveTags) {
             return;
           }
           for (let exclusiveTag of test.exclusiveTags) {
-            (function test_formatting_text_styled_by_exclusive_element() {
+            function test_formatting_text_styled_by_exclusive_element(aTestData) {
               editTarget.innerHTML = `<${exclusiveTag}>format</${exclusiveTag}>`;
               editTarget.focus();
               selection.selectAllChildren(editTarget);
               reset();
-              cancelBeforeInput = false;
-              action = `removing <${exclusiveTag}> element with formatting with "${test.command}"`;
+              cancelBeforeInput = aTestData.cancelBeforeInput;
+              action = aTestData.action;
               SpecialPowers.doCommand(aWindow, test.command);
-              is(editTarget.innerHTML, `<${test.tag}>format</${test.tag}>`,
-                `${aDescription}<${exclusiveTag}> element should be replaced with <${test.tag}> element by ${action}`);
+              let expectedValue = aTestData.cancelBeforeInput
+                                    ? `<${exclusiveTag}>format</${exclusiveTag}>`
+                                    : `<${test.tag}>format</${test.tag}>`;
+              is(editTarget.innerHTML, expectedValue,
+                `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
               ok(beforeInputEvent,
-                `${aDescription}"beforeinput" event should've been fired at ${action}`);
+                `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
               is(beforeInputEvent.cancelable, true,
-                `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+                `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
               is(beforeInputEvent.inputType, test.inputType,
                 `${aDescription}inputType of "beforeinput" event should be "${test.inputType}"`);
               is(beforeInputEvent.data, null,
-                `${aDescription}data of "beforeinput" event for ${action} should be null`);
+                `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
               is(beforeInputEvent.dataTransfer, null,
-                `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+                `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
               checkTargetRanges(beforeInputEvent, selectionRanges);
+              if (aTestData.cancelBeforeInput) {
+                ok(!inputEvent,
+                  `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+                return;
+              }
               ok(inputEvent,
-                `${aDescription}"input" event shouldn't have been fired at ${action}`);
+                `${aDescription}"input" event shouldn't have been fired at ${aTestData.action}`);
               is(inputEvent.cancelable, false,
-                `${aDescription}"input" event for ${action} should never be cancelable`);
+                `${aDescription}"input" event for ${aTestData.action} should never be cancelable`);
               is(inputEvent.inputType, test.inputType,
                 `${aDescription}inputType of "input" event should be "${test.inputType}"`);
               is(inputEvent.data, null,
-                `${aDescription}data of "input" event for ${action} should be null`);
+                `${aDescription}data of "input" event for ${aTestData.action} should be null`);
               is(inputEvent.dataTransfer, null,
-                `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+                `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
               checkTargetRanges(inputEvent, []);
-            })();
-
-            (function test_formatting_text_styled_by_exclusive_element_and_canceling_beforeinput() {
-              editTarget.innerHTML = `<${exclusiveTag}>format</${exclusiveTag}>`;
-              editTarget.focus();
-              selection.selectAllChildren(editTarget);
-              reset();
-              cancelBeforeInput = true;
-              action = `removing <${exclusiveTag}> element with formatting with "${test.command}" but "beforeinput" is canceled`;
-              SpecialPowers.doCommand(aWindow, test.command);
-              is(editTarget.innerHTML, `<${exclusiveTag}>format</${exclusiveTag}>`,
-                `${aDescription}text shouldn't have been modified at ${action}`);
-              ok(beforeInputEvent,
-                `${aDescription}"beforeinput" event should've been fired at ${action}`);
-              is(beforeInputEvent.cancelable, true,
-                `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-              is(beforeInputEvent.inputType, test.inputType,
-                `${aDescription}inputType of "beforeinput" event should be "${test.inputType}"`);
-              is(beforeInputEvent.data, null,
-                `${aDescription}data of "beforeinput" event for ${action} should be null`);
-              is(beforeInputEvent.dataTransfer, null,
-                `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-              checkTargetRanges(beforeInputEvent, selectionRanges);
-              ok(!inputEvent,
-                `${aDescription}"input" event shouldn't have been fired at ${action}`);
-            })();
+            }
+            test_formatting_text_styled_by_exclusive_element({
+              action: `removing <${exclusiveTag}> element with formatting with "${test.command}" and canceling "beforeinput"`,
+              cancelBeforeInput: true,
+            });
+            test_formatting_text_styled_by_exclusive_element({
+              action: `removing <${exclusiveTag}> element with formatting with "${test.command}"`,
+              cancelBeforeInput: false,
+            });
           }
         })();
       }
     })();
 
-    (function test_indenting_text() {
+    function test_indenting_text(aTestData) {
       editTarget.innerHTML = "format";
       editTarget.focus();
       selection.selectAllChildren(editTarget);
       reset();
-      cancelBeforeInput = false;
-      action = `indenting with "cmd_indent"`;
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
       SpecialPowers.doCommand(aWindow, "cmd_indent");
-      is(editTarget.innerHTML, `<blockquote>format</blockquote>`,
-        `${aDescription}all text should be wrapped with <blockquote> element at ${action}`);
+      let expectedValue = aTestData.cancelBeforeInput
+                            ? "format"
+                            : "<blockquote>format</blockquote>";
+      is(editTarget.innerHTML, expectedValue,
+        `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "formatIndent",
         `${aDescription}inputType of "beforeinput" event should be "formatIndent"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       checkTargetRanges(beforeInputEvent, selectionRanges);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.cancelable, false,
-        `${aDescription}"input" event for ${action} should never be cancelable`);
+        `${aDescription}"input" event for ${aTestData.action} should never be cancelable`);
       is(inputEvent.inputType, "formatIndent",
         `${aDescription}inputType of "input" event should be "formatIndent"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       checkTargetRanges(inputEvent, []);
-    })();
+    }
+    test_indenting_text({
+      action: 'indenting text and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_indenting_text({
+      action: 'indenting text',
+      cancelBeforeInput: false,
+    });
 
-    (function test_outdenting_text() {
-      selection.selectAllChildren(editTarget);
+    function test_outdenting_blockquote(aTestData) {
+      editTarget.innerHTML = "<blockquote>format</blockquote>";
+      selection.selectAllChildren(editTarget.firstChild);
       reset();
-      cancelBeforeInput = false;
-      action = `outdenting with "cmd_outdent"`;
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
       SpecialPowers.doCommand(aWindow, "cmd_outdent");
-      is(editTarget.innerHTML, "format",
-        `${aDescription}<blockquote> element should be unwrapped by ${action}`);
+      let expectedValue = aTestData.cancelBeforeInput
+                            ? "<blockquote>format</blockquote>"
+                            : "format";
+      is(editTarget.innerHTML, expectedValue,
+        `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "formatOutdent",
         `${aDescription}inputType of "beforeinput" event should be "formatOutdent"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       checkTargetRanges(beforeInputEvent, selectionRanges);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.cancelable, false,
-        `${aDescription}"input" event for ${action} should never be cancelable`);
+        `${aDescription}"input" event for ${aTestData.action} should never be cancelable`);
       is(inputEvent.inputType, "formatOutdent",
         `${aDescription}inputType of "input" event should be "formatOutdent"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       checkTargetRanges(inputEvent, []);
-    })();
-
-    (function test_indenting_text_and_canceling_beforeinput() {
-      selection.selectAllChildren(editTarget);
-      reset();
-      cancelBeforeInput = true;
-      action = `indenting with "cmd_indent" but "beforeinput" is canceled`;
-      SpecialPowers.doCommand(aWindow, "cmd_indent");
-      is(editTarget.innerHTML, "format",
-        `${aDescription}text shouldn't have been modified at ${action}`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "formatIndent",
-        `${aDescription}inputType of "beforeinput" event should be "formatIndent"`);
-      is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      checkTargetRanges(beforeInputEvent, selectionRanges);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't have been fired at ${action}`);
-    })();
+    }
+    test_outdenting_blockquote({
+      action: 'outdenting blockquote and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_outdenting_blockquote({
+      action: 'outdenting blockquote',
+      cancelBeforeInput: false,
+    });
 
-    (function test_outdenting_text_and_canceling_beforeinput() {
-      editTarget.innerHTML = `<blockquote>format</blockquote>`;
-      editTarget.focus();
-      selection.selectAllChildren(editTarget);
-      reset();
-      cancelBeforeInput = true;
-      action = `outdenting with "cmd_outdent" but "beforeinput" is canceled`;
-      SpecialPowers.doCommand(aWindow, "cmd_outdent");
-      is(editTarget.innerHTML, `<blockquote>format</blockquote>`,
-        `${aDescription}text shouldn't have been modified at ${action}`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "formatOutdent",
-        `${aDescription}inputType of "beforeinput" event should be "formatOutdent"`);
-      is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      checkTargetRanges(beforeInputEvent, selectionRanges);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't have been fired at ${action}`);
-    })();
-
-    (function test_typing_delete_to_delete_img() {
-      editTarget.innerHTML =
-        '<img src=""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==">';
+    function test_typing_delete_to_delete_img(aTestData) {
+      editTarget.innerHTML = `<img src="${kImgURL}">`;
       editTarget.focus();
       selection.collapse(editTarget, 0);
       reset();
-      cancelBeforeInput = false;
-      action = 'typing "Delete" to delete the <img> element';
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
       synthesizeKey("KEY_Delete", {}, aWindow);
-      is(editTarget.innerHTML, `<br>`,
-        `${aDescription}the <img> should be deleted and padding <br> element should've been inserted instead at ${action}`);
+      let expectedValue = aTestData.cancelBeforeInput ? `<img src="${kImgURL}">` : "<br>";
+      is(editTarget.innerHTML, expectedValue,
+        `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "deleteContentForward",
         `${aDescription}inputType of "beforeinput" event should be "deleteContentForward"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       checkTargetRanges(beforeInputEvent, [{startContainer: editTarget,
                                             startOffset: 0,
                                             endContainer: editTarget,
                                             endOffset: 1}]);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.cancelable, false,
-        `${aDescription}"input" event for ${action} should never be cancelable`);
+        `${aDescription}"input" event for ${aTestData.action} should never be cancelable`);
       is(inputEvent.inputType, "deleteContentForward",
         `${aDescription}inputType of "input" event should be "deleteContentForward"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       checkTargetRanges(inputEvent, []);
-    })();
+    }
+    test_typing_delete_to_delete_img({
+      action: 'typing "Delete" to delete the <img> element and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_typing_delete_to_delete_img({
+      action: 'typing "Delete" to delete the <img> element',
+      cancelBeforeInput: false,
+    });
 
-    (function test_typing_backspace_to_delete_img() {
-      editTarget.innerHTML =
-        '<img src=""data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAEElEQVR42mNgaGD4D8YwBgAw9AX9Y9zBwwAAAABJRU5ErkJggg==">';
+    function test_typing_backspace_to_delete_img(aTestData) {
+      editTarget.innerHTML = `<img src="${kImgURL}">`;
       editTarget.focus();
       selection.collapse(editTarget, 1);
       reset();
-      cancelBeforeInput = false;
-      action = 'typing "Backspace" to delete the <img> element';
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
       synthesizeKey("KEY_Backspace", {}, aWindow);
-      is(editTarget.innerHTML, `<br>`,
-        `${aDescription}the <img> should be deleted and padding <br> element should've been inserted instead at ${action}`);
+      let expectedValue = aTestData.cancelBeforeInput ? `<img src="${kImgURL}">` : "<br>";
+      is(editTarget.innerHTML, expectedValue,
+        `${aDescription}innerHTML should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "deleteContentBackward",
         `${aDescription}inputType of "beforeinput" event should be "deleteContentBackward"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       checkTargetRanges(beforeInputEvent, [{startContainer: editTarget,
                                             startOffset: 0,
                                             endContainer: editTarget,
                                             endOffset: 1}]);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.cancelable, false,
-        `${aDescription}"input" event for ${action} should never be cancelable`);
+        `${aDescription}"input" event for ${aTestData.action} should never be cancelable`);
       is(inputEvent.inputType, "deleteContentBackward",
         `${aDescription}inputType of "input" event should be "deleteContentBackward"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       checkTargetRanges(inputEvent, []);
-    })();
+    }
+    test_typing_backspace_to_delete_img({
+      action: 'typing "Backspace" to delete the <img> element and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_typing_backspace_to_delete_img({
+      action: 'typing "Backspace" to delete the <img> element',
+      cancelBeforeInput: false,
+    });
 
     aWindow.removeEventListener("beforeinput", beforeInputHandler, true);
     aWindow.removeEventListener("input", inputHandler, true);
   }
 
   doTests(document.getElementById("editor1").contentDocument,
           document.getElementById("editor1").contentWindow,
           "Editor1, body has contenteditable attribute");
--- a/editor/libeditor/tests/test_dom_input_event_on_texteditor.html
+++ b/editor/libeditor/tests/test_dom_input_event_on_texteditor.html
@@ -34,37 +34,44 @@ async function runTests() {
 
   const kWordSelectEatSpaceToNextWord = SpecialPowers.getBoolPref("layout.word_select.eat_space_to_next_word");
 
   function doTests(aElement, aDescription, aIsTextarea) {
     aDescription += ": ";
     aElement.focus();
     aElement.value = "";
 
+    let initializing = false;
     let cancelBeforeInput = false;
     let beforeInputEvent = null;
     let inputEvent = null;
     let action = "";
     let beforeInputHandler = (aEvent) => {
+      if (initializing) {
+        return;
+      }
       ok(!beforeInputEvent,
         `${aDescription}Multiple "beforeinput" events are fired at ${action} (inputType: "${aEvent.inputType}", data: ${aEvent.data})`);
       if (cancelBeforeInput) {
         aEvent.preventDefault();
       }
       ok(aEvent.isTrusted,
         `${aDescription}"beforeinput" event at ${action} must be trusted`);
       is(aEvent.target, aElement,
         `${aDescription}"beforeinput" event at ${action} is fired on unexpected element: ${aEvent.target.tagName}`);
       ok(aEvent instanceof InputEvent,
         `${aDescription}"beforeinput" event at ${action} should be dispatched with InputEvent interface`);
       ok(aEvent.bubbles,
         `${aDescription}"beforeinput" event at ${action} must be bubbles`);
       beforeInputEvent = aEvent;
     };
     let inputHandler = (aEvent) => {
+      if (initializing) {
+        return;
+      }
       ok(!inputEvent,
         `${aDescription}Multiple "input" events are fired at ${action} (inputType: "${aEvent.inputType}", data: ${aEvent.data})`);
       ok(aEvent.isTrusted,
         `${aDescription}"input" event at ${action} must be trusted`);
       is(aEvent.target, aElement, `"input" event at ${action} is fired on unexpected element: ${aEvent.target.tagName}`);
       ok(aEvent instanceof InputEvent,
         `${aDescription}"input" event at ${action} should be dispatched with InputEvent interface`);
       ok(!aEvent.cancelable,
@@ -76,207 +83,167 @@ async function runTests() {
         `${aDescription}perhaps, timestamp wasn't set correctly :${aEvent.timeStamp} (expected it to be within 30s of ` +
         `the current time but it differed by ${duration}ms)`);
       inputEvent = aEvent;
     };
 
     aElement.addEventListener("beforeinput", beforeInputHandler, true);
     aElement.addEventListener("input", inputHandler, true);
 
-    (function test_typing_a_in_empty_editor_and_canceling_beforeinput() {
-      cancelBeforeInput = true;
-      beforeInputEvent = null;
-      inputEvent = null;
-      action = 'typing "a"';
-      sendString("a");
-      is(aElement.value, "",
-        `${aDescription}${action} shouldn't insert "a" since "beforeinput" was canceled"`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event by ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "insertText",
-        `${aDescription}inputType of "beforeinput" event by ${action} should be "insertText"`);
-      is(beforeInputEvent.data, "a",
-        `${aDescription}data of "beforeinput" event by ${action} should be "a"`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event by ${action} should be null`);
-      is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't have been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_typing_a_in_empty_editor() {
+    function test_typing_a_in_empty_editor(aTestData) {
       aElement.value = "";
-      cancelBeforeInput = false;
+      cancelBeforeInput = aTestData.cancelBeforeInput;
       beforeInputEvent = null;
       inputEvent = null;
-      action = 'typing "a"';
+      action = aTestData.action;
       sendString("a");
-      is(aElement.value, "a",
-        `${aDescription}${action} should've inserted "a"`);
+      let expectedValue = aTestData.cancelBeforeInput ? "" : "a";
+      is(aElement.value, expectedValue,
+        `${aDescription}the value should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event by ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event by ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "insertText",
-        `${aDescription}inputType of "beforeinput" event by ${action} should be "insertText"`);
+        `${aDescription}inputType of "beforeinput" event by ${aTestData.action} should be "insertText"`);
       is(beforeInputEvent.data, "a",
-        `${aDescription}data of "beforeinput" event by ${action} should be "a"`);
+        `${aDescription}data of "beforeinput" event by ${aTestData.action} should be "a"`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event by ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event by ${aTestData.action} should be null`);
       is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
+        `${aDescription}getTargetRanges() of "beforeinput" event by ${aTestData.action} should return empty array`);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't have been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.inputType, "insertText",
-        `${aDescription}inputType of "input" event by ${action} should be "insertText"`);
+        `${aDescription}inputType of "input" event by ${aTestData.action} should be "insertText"`);
       is(inputEvent.data, "a",
-        `${aDescription}data of "input" event by ${action} should be "a"`);
+        `${aDescription}data of "input" event by ${aTestData.action} should be "a"`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event by ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event by ${aTestData.action} should be null`);
       is(inputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "input" event by ${action} should return empty array`);
-    })();
+        `${aDescription}getTargetRanges() of "input" event by ${aTestData.action} should return empty array`);
+    }
+    test_typing_a_in_empty_editor({
+      action: 'typing "a" and canceling beforeinput',
+      cancelBeforeInput: true,
+    });
+    test_typing_a_in_empty_editor({
+      action: 'typing "a"',
+      cancelBeforeInput: false,
+    });
 
-    (function test_typing_backspace_to_delete_last_character_and_canceling_beforeinput() {
-      cancelBeforeInput = true;
-      beforeInputEvent = null;
-      inputEvent = null;
-      action = 'removing "a" with "Backspace"';
-      synthesizeKey("KEY_Backspace");
-      is(aElement.value, "a",
-        `${aDescription}${action} shouldn't remove "a" since "beforeinput" was canceled"`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event by ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "deleteContentBackward",
-        `${aDescription}inputType of "beforeinput" event by ${action} should be "deleteContentBackward"`);
-      is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event by ${action} should be null`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event by ${action} should be null`);
-      is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't have been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_typing_backspace_to_delete_last_character() {
+    function test_typing_backspace_to_delete_last_character(aTestData) {
       aElement.value = "a";
       aElement.setSelectionStart = "a".length;
-      cancelBeforeInput = false;
+      cancelBeforeInput = aTestData.cancelBeforeInput;
       beforeInputEvent = null;
       inputEvent = null;
-      action = 'removing "a" with "Backspace"';
+      action = aTestData.action;
       synthesizeKey("KEY_Backspace");
-      is(aElement.value, "",
-        `${aDescription}${action} should've removed "a"`);
+      let expectedValue = aTestData.cancelBeforeInput ? "a" : "";
+      is(aElement.value, expectedValue,
+        `${aDescription}the value should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event by ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event by ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "deleteContentBackward",
-        `${aDescription}inputType of "beforeinput" event by ${action} should be "deleteContentBackward"`);
+        `${aDescription}inputType of "beforeinput" event by ${aTestData.action} should be "deleteContentBackward"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event by ${action} should be null`);
+        `${aDescription}data of "beforeinput" event by ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event by ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event by ${aTestData.action} should be null`);
       is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
+        `${aDescription}getTargetRanges() of "beforeinput" event by ${aTestData.action} should return empty array`);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't have been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.inputType, "deleteContentBackward",
-        `${aDescription}inputType of "input" event by ${action} should be "deleteContentBackward"`);
+        `${aDescription}inputType of "input" event by ${aTestData.action} should be "deleteContentBackward"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event by ${action} should be null`);
+        `${aDescription}data of "input" event by ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event by ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event by ${aTestData.action} should be null`);
       is(inputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "input" event by ${action} should return empty array`);
-    })();
+        `${aDescription}getTargetRanges() of "input" event by ${aTestData.action} should return empty array`);
+    }
+    test_typing_backspace_to_delete_last_character({
+      actin: 'typing "Backspace" to delete "a" and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_typing_backspace_to_delete_last_character({
+      actin: 'typing "Backspace" to delete "a"',
+      cancelBeforeInput: false,
+    });
 
-    (function test_typing_enter_in_empty_editor_and_canceling_beforeinput() {
-      cancelBeforeInput = true;
+    function test_typing_enter_in_empty_editor(aTestData) {
+      aElement.value = "";
+      cancelBeforeInput = aTestData.cancelBeforeInput;
       beforeInputEvent = null;
       inputEvent = null;
-      action = 'typing "Enter"';
+      action = aTestData.action;
       synthesizeKey("KEY_Enter");
       if (aIsTextarea) {
-        is(aElement.value, "",
-          `${aDescription}${action} shouldn't insert a line break since "beforeinput" was canceled"`);
+        let expectedValue = aTestData.cancelBeforeInput ? "" : "\n";
+        is(aElement.value, expectedValue,
+          `${aDescription}the value should be "${expectedValue}" after ${aTestData.action}`);
       } else {
         is(aElement.value, "",
-          `${aDescription}${action} shouldn't insert a line break since it's a single line editor"`);
+          `${aDescription}the value should be "" after ${aTestData.action}`);
       }
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event by ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event by ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "insertLineBreak",
-        `${aDescription}inputType of "beforeinput" event by ${action} should be "insertLineBreak"`);
+        `${aDescription}inputType of "beforeinput" event by ${aTestData.action} should be "insertLineBreak"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event by ${action} should be null`);
+        `${aDescription}data of "beforeinput" event by ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event by ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event by ${aTestData.action} should be null`);
       is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
+        `${aDescription}getTargetRanges() of "beforeinput" event by ${aTestData.action} should return empty array`);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't have been fired at ${aTestData.action}`);
+        return;
+      }
       if (aIsTextarea) {
-        ok(!inputEvent,
-          `${aDescription}"input" event shouldn't have been fired at ${action} since "beforeinput" was canceled`);
+        ok(inputEvent,
+          `${aDescription}"input" event should've been fired at ${aTestData.action}`);
+        is(inputEvent.inputType, "insertLineBreak",
+          `${aDescription}inputType of "input" event by ${aTestData.action} should be "insertLineBreak"`);
+        is(inputEvent.data, null,
+          `${aDescription}data of "input" event by ${aTestData.action} should be null`);
+        is(inputEvent.dataTransfer, null,
+          `${aDescription}dataTransfer of "input" event by ${aTestData.action} should be null`);
+        is(inputEvent.getTargetRanges().length, 0,
+          `${aDescription}getTargetRanges() of "input" event by ${aTestData.action} should return empty array`);
       } else {
         ok(!inputEvent,
-          `${aDescription}$"input" event shouldn't have been fired at ${action} since it's a single line editor"`);
-      }
-    })();
-
-    (function test_typing_enter_in_empty_editor() {
-      aElement.value = "";
-      cancelBeforeInput = false;
-      beforeInputEvent = null;
-      inputEvent = null;
-      action = 'typing "Enter"';
-      synthesizeKey("KEY_Enter");
-      if (aIsTextarea) {
-        is(aElement.value, "\n",
-          `${aDescription}${action} should've inserted a line break"`);
-      } else {
-        is(aElement.value, "",
-          `${aDescription}${action} shouldn't insert a line break since it's a single line editor"`);
+          `${aDescription}$"input" event shouldn't have been fired at ${aTestData.action} since it's a single line editor"`);
       }
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event by ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "insertLineBreak",
-        `${aDescription}inputType of "beforeinput" event by ${action} should be "insertLineBreak"`);
-      is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event by ${action} should be null`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event by ${action} should be null`);
-      is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
-      if (aIsTextarea) {
-        ok(inputEvent,
-          `${aDescription}"input" event should've been fired at ${action}`);
-        is(inputEvent.inputType, "insertLineBreak",
-          `${aDescription}inputType of "input" event by ${action} should be "insertLineBreak"`);
-        is(inputEvent.data, null,
-          `${aDescription}data of "input" event by ${action} should be null`);
-        is(inputEvent.dataTransfer, null,
-          `${aDescription}dataTransfer of "input" event by ${action} should be null`);
-        is(inputEvent.getTargetRanges().length, 0,
-          `${aDescription}getTargetRanges() of "input" event by ${action} should return empty array`);
-      } else {
-        ok(!inputEvent,
-          `${aDescription}$"input" event shouldn't have been fired at ${action} since it's a single line editor"`);
-      }
-    })();
+    }
+    test_typing_enter_in_empty_editor({
+      action: 'typing "Enter" in empty editor and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_typing_enter_in_empty_editor({
+      action: 'typing "Enter" in empty editor',
+      cancelBeforeInput: false,
+    });
 
     (function test_setting_value() {
       cancelBeforeInput = false;
       beforeInputEvent = null;
       inputEvent = null;
       aElement.value = "foo-bar";
       action = "setting value";
       is(aElement.value, "foo-bar",
@@ -367,433 +334,399 @@ async function runTests() {
       is(aElement.value, " ",
         `${aDescription}${action} shouldn't remove anything`);
       ok(!beforeInputEvent,
         `${aDescription}"beforeinput" event shouldn't have been fired by ${action}`);
       ok(!inputEvent,
         `${aDescription}"input" event shouldn't have been fired by ${action}`);
     })();
 
-    (function test_typing_delete_to_delete_last_character_and_canceling_beforeinput() {
-      cancelBeforeInput = true;
-      beforeInputEvent = null;
-      inputEvent = null;
-      action = 'typing "Delete"';
-      synthesizeKey("KEY_Delete");
-      is(aElement.value, " ",
-        `${aDescription}${action} shouldn't remove the content since "beforeinput" was canceled`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event by ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "deleteContentForward",
-        `${aDescription}inputType of "beforeinput" event by ${action} should be "deleteContentForward"`);
-      is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event by ${action} should be null`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event by ${action} should be null`);
-      is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't have been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_typing_delete_to_delete_last_character() {
-      aElement.value = "";
+    function test_typing_delete_to_delete_last_character(aTestData) {
       aElement.value = " ";
       aElement.selectionStart = 0;
-      cancelBeforeInput = false;
+      cancelBeforeInput = aTestData.cancelBeforeInput;
       beforeInputEvent = null;
       inputEvent = null;
-      action = 'typing "Delete"';
+      action = aTestData.action;
       synthesizeKey("KEY_Delete");
-      is(aElement.value, "",
-        `${aDescription}${action} should've removed " "`);
+      let expectedValue = aTestData.cancelBeforeInput ? " " : "";
+      is(aElement.value, expectedValue,
+        `${aDescription}the value should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event by ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event by ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "deleteContentForward",
-        `${aDescription}inputType of "beforeinput" event by ${action} should be "deleteContentForward"`);
+        `${aDescription}inputType of "beforeinput" event by ${aTestData.action} should be "deleteContentForward"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event by ${action} should be null`);
+        `${aDescription}data of "beforeinput" event by ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event by ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event by ${aTestData.action} should be null`);
       is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
+        `${aDescription}getTargetRanges() of "beforeinput" event by ${aTestData.action} should return empty array`);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't have been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.inputType, "deleteContentForward",
-        `${aDescription}inputType of "input" event by ${action} should be "deleteContentForward"`);
+        `${aDescription}inputType of "input" event by ${aTestData.action} should be "deleteContentForward"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event by ${action} should be null`);
+        `${aDescription}data of "input" event by ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event by ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event by ${aTestData.action} should be null`);
       is(inputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "input" event by ${action} should return empty array`);
-    })();
+        `${aDescription}getTargetRanges() of "input" event by ${aTestData.action} should return empty array`);
+    }
+    test_typing_delete_to_delete_last_character({
+      action: 'typing "Delete" to delete space and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_typing_delete_to_delete_last_character({
+      action: 'typing "Delete" to delete space',
+      cancelBeforeInput: false,
+    });
 
-    (function test_undoing_deleting_last_character_and_canceling_beforeinput() {
-      cancelBeforeInput = true;
+    function test_undoing_deleting_last_character(aTestData) {
+      initializing = true;
+      aElement.value = "a";
+      aElement.selectionStart = 0;
+      synthesizeKey("KEY_Delete");
+      initializing = false;
+
+      cancelBeforeInput = aTestData.cancelBeforeInput;
       beforeInputEvent = null;
       inputEvent = null;
-      action = 'doing "Undo"';
-      synthesizeKey("z", {accelKey: true});
-      is(aElement.value, "",
-        `${aDescription}${action} shouldn't restore`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "historyUndo",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "historyUndo"`);
-      is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't have been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_undoing_deleting_last_character() {
-      cancelBeforeInput = false;
-      beforeInputEvent = null;
-      inputEvent = null;
-      action = 'doing "Undo"';
+      action = aTestData.action;
       synthesizeKey("z", {accelKey: true});
-      is(aElement.value, " ",
-        `${aDescription}${action} should restore " "`);
+      let expectedValue = aTestData.cancelBeforeInput ? "" : "a";
+      is(aElement.value, expectedValue,
+        `${aDescription}the value should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "historyUndo",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "historyUndo"`);
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "historyUndo"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
+        `${aDescription}getTargetRanges() of "beforeinput" event by ${aTestData.action} should return empty array`);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't have been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.inputType, "historyUndo",
-        `${aDescription}inputType of "input" event for ${action} should be "historyUndo"`);
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "historyUndo"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "input" event by ${action} should return empty array`);
-    })();
+        `${aDescription}getTargetRanges() of "input" event by ${aTestData.action} should return empty array`);
+    }
+    test_undoing_deleting_last_character({
+      action: 'undoing deleting last character and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_undoing_deleting_last_character({
+      action: "undoing deleting last character",
+      cancelBeforeInput: false,
+    });
 
     (function test_undoing_without_undoable_transaction() {
       cancelBeforeInput = false;
       beforeInputEvent = null;
       inputEvent = null;
       action = 'doing "Undo" again';
       synthesizeKey("z", {accelKey: true});
-      is(aElement.value, " ",
+      is(aElement.value, "a",
         `${aDescription}${action} shouldn't modify the value since no undo transaction`);
       ok(!beforeInputEvent,
         `${aDescription}"beforeinput" event shouldn't have been fired at ${action} since no undo transaction`);
       ok(!inputEvent,
         `${aDescription}"input" event shouldn't have been fired at ${action} since no undo transaction`);
     })();
 
-    (function test_redoing_deleting_last_character_and_canceling_beforeinput() {
-      cancelBeforeInput = true;
-      beforeInputEvent = null;
-      inputEvent = null;
-      action = 'doing "Redo"';
-      synthesizeKey("Z", {accelKey: true, shiftKey: true});
-      is(aElement.value, " ",
-        `${aDescription}${action} shouldn't restore`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "historyRedo",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "historyRedo"`);
-      is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't have been fired at ${action} since "beforeinput" was canceled`);
-    })();
+    function test_redoing_deleting_last_character(aTestData) {
+      initializing = true;
+      aElement.value = "a";
+      aElement.selectionStart = 0;
+      synthesizeKey("KEY_Delete");
+      synthesizeKey("z", {accelKey: true});
+      initializing = false;
 
-    (function test_redoing_deleting_last_character() {
-      cancelBeforeInput = false;
+      cancelBeforeInput = aTestData.cancelBeforeInput;
       beforeInputEvent = null;
       inputEvent = null;
-      action = 'doing "Redo"';
+      action = aTestData.action;
       synthesizeKey("Z", {accelKey: true, shiftKey: true});
-      is(aElement.value, "",
-        `${aDescription}${action} should remove " "`);
+      let expectedValue = aTestData.cancelBeforeInput ? "a" : "";
+      is(aElement.value, expectedValue,
+        `${aDescription}the value should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "historyRedo",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "historyRedo"`);
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "historyRedo"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
+        `${aDescription}getTargetRanges() of "beforeinput" event by ${aTestData.action} should return empty array`);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't have been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.inputType, "historyRedo",
-        `${aDescription}inputType of "input" event for ${action} should be "historyRedo"`);
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "historyRedo"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "input" event by ${action} should return empty array`);
-    })();
+        `${aDescription}getTargetRanges() of "input" event by ${aTestData.action} should return empty array`);
+    }
+    test_redoing_deleting_last_character({
+      action: 'redoing deleting last character and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_redoing_deleting_last_character({
+      action: "redoing deleting last character",
+      cancelBeforeInput: false,
+    });
 
     (function test_redoing_without_redoable_transaction() {
       cancelBeforeInput = false;
       beforeInputEvent = null;
       inputEvent = null;
       action = 'doing "Redo" again';
       synthesizeKey("Z", {accelKey: true, shiftKey: true});
       is(aElement.value, "",
         `${aDescription}${action} shouldn't modify the value since no redo transaction`);
       ok(!beforeInputEvent,
         `${aDescription}"beforeinput" event shouldn't have been fired at ${action} since no redo transaction`);
       ok(!inputEvent,
         `${aDescription}"input" event shouldn't have been fired at ${action} since no redo transaction`);
     })();
 
-    (function test_typing_backspace_with_selecting_all_characters_and_canceling_beforeinput() {
-      aElement.value = "a";
+    function test_typing_backspace_with_selecting_all_characters(aTestData) {
+      aElement.value = "abc";
       aElement.focus();
       aElement.select();
-      cancelBeforeInput = true;
-      beforeInputEvent = null;
-      inputEvent = null;
-      action = 'removing "a" with "Backspace" (with selection)';
-      synthesizeKey("KEY_Backspace");
-      is(aElement.value, "a",
-        `${aDescription}"a" shouldn't have been removed by ${action} since "beforeinput" was canceled`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_typing_backspace_with_selecting_all_characters() {
-      aElement.value = "a";
-      aElement.focus();
-      aElement.select();
-      cancelBeforeInput = false;
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
       beforeInputEvent = null;
       inputEvent = null;
       synthesizeKey("KEY_Backspace");
-      is(aElement.value, "",
-        `${aDescription}"a" should've been removed by ${action}`);
+      let expectedValue = aTestData.cancelBeforeInput ? "abc" : "";
+      is(aElement.value, expectedValue,
+        `${aDescription}the value should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "deleteContentBackward",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "deleteContentBackward"`);
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "deleteContentBackward"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
+        `${aDescription}getTargetRanges() of "beforeinput" event by ${aTestData.action} should return empty array`);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't have been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.inputType, "deleteContentBackward",
-        `${aDescription}inputType of "input" event for ${action} should be "deleteContentBackward"`);
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "deleteContentBackward"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "input" event by ${action} should return empty array`);
-    })();
+        `${aDescription}getTargetRanges() of "input" event by ${aTestData.action} should return empty array`);
+    }
+    test_typing_backspace_with_selecting_all_characters({
+      action: 'typing "Backspace" to delete all selected characters and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_typing_backspace_with_selecting_all_characters({
+      action: 'typing "Backspace" to delete all selected characters',
+      cancelBeforeInput: false,
+    });
 
-    (function test_typing_delete_with_selecting_all_characters_and_canceling_beforeinput() {
-      aElement.value = "a";
+    function test_typing_delete_with_selecting_all_characters(aTestData) {
+      aElement.value = "abc";
       aElement.focus();
       aElement.select();
-      cancelBeforeInput = true;
+      cancelBeforeInput = aTestData.cancelBeforeInput;
       beforeInputEvent = null;
       inputEvent = null;
-      action = 'removing "a" with "Delete" (with selection)';
+      action = aTestData.action;
       synthesizeKey("KEY_Delete");
-      is(aElement.value, "a",
-        `${aDescription}"a" should've been removed by ${action} since "beforeinput" was canceled`);
+      let expectedValue = aTestData.cancelBeforeInput ? "abc" : "";
+      is(aElement.value, expectedValue,
+        `${aDescription}the value should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should be fired at ${action} even if it won't remove any content`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "deleteContentForward",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "deleteContentForward"`);
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "deleteContentForward"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
-      ok(!inputEvent,
-        `${aDescription}${action} should not fire "input" event since "beforeinput" was canceled`);
-    })();
+        `${aDescription}getTargetRanges() of "beforeinput" event by ${aTestData.action} should return empty array`);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't have been fired at ${aTestData.action}`);
+        return;
+      }
+      ok(inputEvent,
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
+      is(inputEvent.inputType, "deleteContentForward",
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "deleteContentForward"`);
+      is(inputEvent.data, null,
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
+      is(inputEvent.dataTransfer, null,
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
+      is(inputEvent.getTargetRanges().length, 0,
+        `${aDescription}getTargetRanges() of "input" event by ${aTestData.action} should return empty array`);
+    }
+    test_typing_delete_with_selecting_all_characters({
+      action: 'typing "Delete" to delete all selected characters and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_typing_delete_with_selecting_all_characters({
+      action: 'typing "Delete" to delete all selected characters and canceling "beforeinput"',
+      cancelBeforeInput: false,
+    });
 
-    (function test_typing_delete_with_selecting_all_characters() {
-      aElement.value = "a";
-      aElement.focus();
-      aElement.select();
-      cancelBeforeInput = false;
-      beforeInputEvent = null;
-      inputEvent = null;
-      action = 'removing "a" with "Delete" (with selection)';
-      synthesizeKey("KEY_Delete");
-      is(aElement.value, "",
-        `${aDescription}" " should've been removed by ${action}`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "deleteContentForward",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "deleteContentForward"`);
-      is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
-      ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
-      is(inputEvent.inputType, "deleteContentForward",
-        `${aDescription}inputType of "input" event for ${action} should be "deleteContentForward"`);
-      is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
-      is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
-      is(inputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "input" event by ${action} should return empty array`);
-    })();
-
-    (function test_deleting_word_backward_from_its_end_and_canceling_beforeinput() {
+    function test_deleting_word_backward_from_its_end(aTestData) {
       aElement.value = "abc def";
       aElement.focus();
       document.documentElement.scrollTop;  // XXX Needs reflow here for working with nsFrameSelection, must be a bug.
       aElement.setSelectionRange("abc def".length, "abc def".length);
-      cancelBeforeInput = true;
-      beforeInputEvent = null;
-      inputEvent = null;
-      action = 'removing last word, "def", with backward deletion from its end';
-      SpecialPowers.doCommand(window, "cmd_deleteWordBackward");
-      is(aElement.value, "abc def",
-        `${aDescription}"def" shouldn't have been removed by ${action} since "beforeinput" was canceled`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_deleting_word_backward_from_its_end() {
-      aElement.value = "abc def";
-      aElement.focus();
-      document.documentElement.scrollTop;  // XXX Needs reflow here for working with nsFrameSelection, must be a bug.
-      aElement.setSelectionRange("abc def".length, "abc def".length);
-      cancelBeforeInput = false;
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
       beforeInputEvent = null;
       inputEvent = null;
       SpecialPowers.doCommand(window, "cmd_deleteWordBackward");
-      is(aElement.value, "abc ",
-        `${aDescription}"def" should've been removed by ${action}`);
+      let expectedValue = aTestData.cancelBeforeInput ? "abc def" : "abc ";
+      is(aElement.value, expectedValue,
+        `${aDescription}the value should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "deleteWordBackward",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "deleteWordBackward"`);
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "deleteWordBackward"`);
       is(beforeInputEvent.data, null,
-        `${aDescription}data of "beforeinput" event for ${action} should be null`);
+        `${aDescription}data of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
+        `${aDescription}getTargetRanges() of "beforeinput" event by ${aTestData.action} should return empty array`);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't have been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.inputType, "deleteWordBackward",
-        `${aDescription}inputType of "input" event for ${action} should be "deleteWordBackward"`);
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "deleteWordBackward"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "input" event by ${action} should return empty array`);
-    })();
+        `${aDescription}getTargetRanges() of "input" event by ${aTestData.action} should return empty array`);
+    }
+    test_deleting_word_backward_from_its_end({
+      action: 'deleting word backward from its end and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_deleting_word_backward_from_its_end({
+      action: 'deleting word backward from its end',
+      cancelBeforeInput: false,
+    });
 
-    (function test_deleting_word_forward_from_its_start_and_canceling_beforeinput() {
+    function test_deleting_word_forward_from_its_start(aTestData) {
       aElement.value = "abc def";
       aElement.focus();
       document.documentElement.scrollTop;  // XXX Needs reflow here for working with nsFrameSelection, must be a bug.
       aElement.setSelectionRange(0, 0);
-      cancelBeforeInput = true;
-      beforeInputEvent = null;
-      inputEvent = null;
-      action = `removing first word, "${kWordSelectEatSpaceToNextWord ? "abc" : "abc "}", with forward deletion from its start`;
-      SpecialPowers.doCommand(window, "cmd_deleteWordForward");
-      is(aElement.value, "abc def",
-        `${aDescription}"${kWordSelectEatSpaceToNextWord ? "abc" : "abc "}" shouldn't have been removed by ${action} since "beforeinput" was canceled`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      ok(!inputEvent,
-        `${aDescription}"input" event shouldn't been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_deleting_word_forward_from_its_start() {
-      aElement.value = "abc def";
-      aElement.focus();
-      document.documentElement.scrollTop;  // XXX Needs reflow here for working with nsFrameSelection, must be a bug.
-      aElement.setSelectionRange(0, 0);
-      cancelBeforeInput = false;
+      cancelBeforeInput = aTestData.cancelBeforeInput;
+      action = aTestData.action;
       beforeInputEvent = null;
       inputEvent = null;
       SpecialPowers.doCommand(window, "cmd_deleteWordForward");
-      is(aElement.value, kWordSelectEatSpaceToNextWord ? "def" : " def",
-        `${aDescription}"${kWordSelectEatSpaceToNextWord ? "abc" : "abc "}" should've been removed by ${action}`);
+      let expectedValue;
+      if (aTestData.cancelBeforeInput) {
+        expectedValue = "abc def";
+      } else {
+        expectedValue = kWordSelectEatSpaceToNextWord ? "def" : " def";
+      }
+      is(aElement.value, expectedValue,
+        `${aDescription}the value should be "${expectedValue}" after ${aTestData.action}`);
       ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
+        `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
       is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
+        `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
       is(beforeInputEvent.inputType, "deleteWordForward",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "deleteWordForward"`);
+        `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "deleteWordForward"`);
       is(beforeInputEvent.data, null,
         `${aDescription}data of "beforeinput" event for ${action} should be null`);
       is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
       is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
+        `${aDescription}getTargetRanges() of "beforeinput" event by ${aTestData.action} should return empty array`);
+      if (aTestData.cancelBeforeInput) {
+        ok(!inputEvent,
+          `${aDescription}"input" event shouldn't have been fired at ${aTestData.action}`);
+        return;
+      }
       ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
+        `${aDescription}"input" event should've been fired at ${aTestData.action}`);
       is(inputEvent.inputType, "deleteWordForward",
-        `${aDescription}inputType of "input" event for ${action} should be "deleteWordForward"`);
+        `${aDescription}inputType of "input" event for ${aTestData.action} should be "deleteWordForward"`);
       is(inputEvent.data, null,
-        `${aDescription}data of "input" event for ${action} should be null`);
+        `${aDescription}data of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
+        `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
       is(inputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "input" event by ${action} should return empty array`);
-    })();
+        `${aDescription}getTargetRanges() of "input" event by ${aTestData.action} should return empty array`);
+    }
+    test_deleting_word_forward_from_its_start({
+      action: 'deleting word forward from its start and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_deleting_word_forward_from_its_start({
+      action: "deleting word forward from its start",
+      cancelBeforeInput: false,
+    });
 
     (function test_deleting_word_backward_from_middle_of_second_word() {
       aElement.value = "abc def";
       aElement.focus();
       document.documentElement.scrollTop;  // XXX Needs reflow here for working with nsFrameSelection, must be a bug.
       aElement.setSelectionRange("abc d".length, "abc de".length);
       cancelBeforeInput = false;
       beforeInputEvent = null;
@@ -1013,135 +946,127 @@ async function runTests() {
       is(inputEvent.data, null,
         `${aDescription}data of "input" event for ${action} should be null`);
       is(inputEvent.dataTransfer, null,
         `${aDescription}dataTransfer of "input" event for ${action} should be null`);
       is(inputEvent.getTargetRanges().length, 0,
         `${aDescription}getTargetRanges() of "input" event by ${action} should return empty array`);
     })();
 
-    (function test_switching_text_direction_from_default_and_canceling_beforeinput() {
-      aElement.focus();
-      cancelBeforeInput = true;
-      beforeInputEvent = null;
-      inputEvent = null;
-      action = 'switching text direction from "ltr" to "rtl"';
-      SpecialPowers.doCommand(window, "cmd_switchTextDirection");
-      is(aElement.getAttribute("dir"), null,
-        `${aDescription}dir attribute of the element should not be set" by ${action} since "beforeinput" was canceled`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "formatSetBlockTextDirection",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "formatSetBlockTextDirection"`);
-      is(beforeInputEvent.data, "rtl",
-        `${aDescription}data of "beforeinput" event for ${action} should be "rtl"`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
-      ok(!inputEvent,
-        `${aDescription}"input" event should not have been fired at ${action} since "beforeinput" was canceled`);
-    })();
-
-    (function test_switching_text_direction_from_rtl_to_ltr_and_canceling_beforeinput() {
-      aElement.setAttribute("dir", "rtl");
-      aElement.scrollTop; // XXX Update the root frame
-      aElement.focus();
-      cancelBeforeInput = true;
-      beforeInputEvent = null;
-      inputEvent = null;
-      action = 'switching text direction from "rtl" to "ltr"';
-      SpecialPowers.doCommand(window, "cmd_switchTextDirection");
-      is(aElement.getAttribute("dir"), "rtl",
-        `${aDescription}dir attribute of the element should not have been modified by ${action} since "beforeinput" was canceled`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "formatSetBlockTextDirection",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "formatSetBlockTextDirection"`);
-      is(beforeInputEvent.data, "ltr",
-        `${aDescription}data of "beforeinput" event for ${action} should be "ltr"`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
-      ok(!inputEvent,
-        `${aDescription}"input" event should not have been fired at ${action} since "beforeinput" was canceled`);
-    })();
+    function test_switching_text_direction_from_default(aTestData) {
+      try {
+        aElement.removeAttribute("dir");
+        aElement.scrollTop; // XXX Update the root frame
+        aElement.focus();
+        cancelBeforeInput = aTestData.cancelBeforeInput;
+        beforeInputEvent = null;
+        inputEvent = null;
+        action = aTestData.action;
+        SpecialPowers.doCommand(window, "cmd_switchTextDirection");
+        if (aTestData.cancelBeforeInput) {
+          is(aElement.getAttribute("dir"), null,
+            `${aDescription}dir attribute of the element shouldn't have been set by ${aTestData.action}`);
+        } else {
+          is(aElement.getAttribute("dir"), "rtl",
+            `${aDescription}dir attribute of the element should've been set to "rtl" by ${aTestData.action}`);
+        }
+        ok(beforeInputEvent,
+          `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
+        is(beforeInputEvent.cancelable, true,
+          `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
+        is(beforeInputEvent.inputType, "formatSetBlockTextDirection",
+          `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "formatSetBlockTextDirection"`);
+        is(beforeInputEvent.data, "rtl",
+          `${aDescription}data of "beforeinput" event for ${aTestData.action} should be "rtl"`);
+        is(beforeInputEvent.dataTransfer, null,
+          `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
+        is(beforeInputEvent.getTargetRanges().length, 0,
+          `${aDescription}getTargetRanges() of "beforeinput" event by ${aTestData.action} should return empty array`);
+        if (aTestData.cancelBeforeInput) {
+          ok(!inputEvent,
+            `${aDescription}"input" event shouldn't have been fired at ${aTestData.action}`);
+          return;
+        }
+        ok(inputEvent,
+          `${aDescription}"input" event should've been fired at ${aTestData.action}`);
+        is(inputEvent.inputType, "formatSetBlockTextDirection",
+          `${aDescription}inputType of "input" event for ${aTestData.action} should be "formatSetBlockTextDirection"`);
+        is(inputEvent.data, "rtl",
+          `${aDescription}data of "input" event for ${aTestData.action} should be "rtl"`);
+        is(inputEvent.dataTransfer, null,
+          `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
+        is(inputEvent.getTargetRanges().length, 0,
+          `${aDescription}getTargetRanges() of "input" event by ${aTestData.action} should return empty array`);
+      } finally {
+        aElement.removeAttribute("dir");
+        aElement.scrollTop; // XXX Update the root frame
+      }
+    }
+    test_switching_text_direction_from_default({
+      action: 'switching text direction from default to "rtl" and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_switching_text_direction_from_default({
+      action: 'switching text direction from default to "rtl"',
+      cancelBeforeInput: false,
+    });
 
-    (function test_switching_text_direction_from_default() {
-      aElement.removeAttribute("dir");
-      aElement.scrollTop; // XXX Update the root frame
-      aElement.focus();
-      cancelBeforeInput = false;
-      beforeInputEvent = null;
-      inputEvent = null;
-      action = 'switching text direction from "ltr" to "rtl"';
-      SpecialPowers.doCommand(window, "cmd_switchTextDirection");
-      is(aElement.getAttribute("dir"), "rtl",
-        `${aDescription}dir attribute of the element should've been set to "rtl" by ${action}`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "formatSetBlockTextDirection",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "formatSetBlockTextDirection"`);
-      is(beforeInputEvent.data, "rtl",
-        `${aDescription}data of "beforeinput" event for ${action} should be "rtl"`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
-      ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
-      is(inputEvent.inputType, "formatSetBlockTextDirection",
-        `${aDescription}inputType of "input" event for ${action} should be "formatSetBlockTextDirection"`);
-      is(inputEvent.data, "rtl",
-        `${aDescription}data of "input" event for ${action} should be "rtl"`);
-      is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
-      is(inputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "input" event by ${action} should return empty array`);
-    })();
-
-    (function test_switching_text_direction_from_rtl_to_ltr() {
-      aElement.focus();
-      cancelBeforeInput = false;
-      beforeInputEvent = null;
-      inputEvent = null;
-      action = 'switching text direction from "rtl" to "ltr"';
-      SpecialPowers.doCommand(window, "cmd_switchTextDirection");
-      is(aElement.getAttribute("dir"), "ltr",
-        `${aDescription}dir attribute of the element should've been set to "ltr" by ${action}`);
-      ok(beforeInputEvent,
-        `${aDescription}"beforeinput" event should've been fired at ${action}`);
-      is(beforeInputEvent.cancelable, true,
-        `${aDescription}"beforeinput" event for ${action} should be cancelable`);
-      is(beforeInputEvent.inputType, "formatSetBlockTextDirection",
-        `${aDescription}inputType of "beforeinput" event for ${action} should be "formatSetBlockTextDirection"`);
-      is(beforeInputEvent.data, "ltr",
-        `${aDescription}data of "beforeinput" event for ${action} should be "ltr"`);
-      is(beforeInputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "beforeinput" event for ${action} should be null`);
-      is(beforeInputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "beforeinput" event by ${action} should return empty array`);
-      ok(inputEvent,
-        `${aDescription}"input" event should've been fired at ${action}`);
-      is(inputEvent.inputType, "formatSetBlockTextDirection",
-        `${aDescription}inputType of "input" event for ${action} should be "formatSetBlockTextDirection"`);
-      is(inputEvent.data, "ltr",
-        `${aDescription}data of "input" event for ${action} should be "ltr"`);
-      is(inputEvent.dataTransfer, null,
-        `${aDescription}dataTransfer of "input" event for ${action} should be null`);
-      is(inputEvent.getTargetRanges().length, 0,
-        `${aDescription}getTargetRanges() of "input" event by ${action} should return empty array`);
-    })();
+    function test_switching_text_direction_from_rtl_to_ltr(aTestData) {
+      try {
+        aElement.setAttribute("dir", "rtl");
+        aElement.scrollTop; // XXX Update the root frame
+        aElement.focus();
+        cancelBeforeInput = aTestData.cancelBeforeInput;
+        beforeInputEvent = null;
+        inputEvent = null;
+        action = aTestData.action;
+        SpecialPowers.doCommand(window, "cmd_switchTextDirection");
+        let expectedDirValue = aTestData.cancelBeforeInput ? "rtl" : "ltr";
+        is(aElement.getAttribute("dir"), expectedDirValue,
+          `${aDescription}dir attribute of the element should be "${expectedDirValue}" after ${aTestData.action}`);
+        ok(beforeInputEvent,
+          `${aDescription}"beforeinput" event should've been fired at ${aTestData.action}`);
+        is(beforeInputEvent.cancelable, true,
+          `${aDescription}"beforeinput" event for ${aTestData.action} should be cancelable`);
+        is(beforeInputEvent.inputType, "formatSetBlockTextDirection",
+          `${aDescription}inputType of "beforeinput" event for ${aTestData.action} should be "formatSetBlockTextDirection"`);
+        is(beforeInputEvent.data, "ltr",
+          `${aDescription}data of "beforeinput" event for ${aTestData.action} should be "ltr"`);
+        is(beforeInputEvent.dataTransfer, null,
+          `${aDescription}dataTransfer of "beforeinput" event for ${aTestData.action} should be null`);
+        is(beforeInputEvent.getTargetRanges().length, 0,
+          `${aDescription}getTargetRanges() of "beforeinput" event by ${aTestData.action} should return empty array`);
+        if (aTestData.cancelBeforeInput) {
+          ok(!inputEvent,
+            `${aDescription}"input" event shouldn't have been fired at ${aTestData.action}`);
+          return;
+        }
+        ok(inputEvent,
+          `${aDescription}"input" event should've been fired at ${aTestData.action}`);
+        is(inputEvent.inputType, "formatSetBlockTextDirection",
+          `${aDescription}inputType of "input" event for ${aTestData.action} should be "formatSetBlockTextDirection"`);
+        is(inputEvent.data, "ltr",
+          `${aDescription}data of "input" event for ${aTestData.action} should be "ltr"`);
+        is(inputEvent.dataTransfer, null,
+          `${aDescription}dataTransfer of "input" event for ${aTestData.action} should be null`);
+        is(inputEvent.getTargetRanges().length, 0,
+          `${aDescription}getTargetRanges() of "input" event by ${aTestData.action} should return empty array`);
+      } finally {
+        aElement.removeAttribute("dir");
+        aElement.scrollTop; // XXX Update the root frame
+      }
+    }
+    test_switching_text_direction_from_rtl_to_ltr({
+      action: 'switching text direction from "rtl" to "ltr" and canceling "beforeinput"',
+      cancelBeforeInput: true,
+    });
+    test_switching_text_direction_from_rtl_to_ltr({
+      action: 'switching text direction from "rtl" to "ltr" and canceling "beforeinput"',
+      cancelBeforeInput: false,
+    });
 
     aElement.removeEventListener("beforeinput", beforeInputHandler, true);
     aElement.removeEventListener("input", inputHandler, true);
   }
 
   doTests(document.getElementById("input"), "<input type=\"text\">", false);
   doTests(document.getElementById("textarea"), "<textarea>", true);