diff options
Diffstat (limited to '')
-rw-r--r-- | editor/libeditor/tests/test_undo_redo_stack_after_setting_value.html | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/editor/libeditor/tests/test_undo_redo_stack_after_setting_value.html b/editor/libeditor/tests/test_undo_redo_stack_after_setting_value.html new file mode 100644 index 0000000000..6f33ccaf01 --- /dev/null +++ b/editor/libeditor/tests/test_undo_redo_stack_after_setting_value.html @@ -0,0 +1,168 @@ +<!DOCTYPE html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1473515 +--> +<html> +<head> + <title>Test for Bug 1473515</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <script src="/tests/SimpleTest/EventUtils.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1473515">Mozilla Bug 1473515</a> +<p id="display"></p> +<div id="content" style="display: none;"> + +</div> + +<input id="input"> +<textarea id="textarea"></textarea> + +<pre id="test"> + +<script class="testbody" type="application/javascript"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); +SimpleTest.expectAssertions(0, 1); // In a11y module +SimpleTest.waitForFocus(() => { + let editableElements = [ + document.getElementById("input"), + document.getElementById("textarea"), + ]; + for (let editableElement of editableElements) { + function checkInputEvent(aEvent, aInputType, aData, aDescription) { + ok(aEvent instanceof InputEvent, + `"${aEvent.type}" event should be dispatched with InputEvent interface ${aDescription}`); + is(aEvent.cancelable, aEvent.type === "beforeinput", + `"${aEvent.type}" event should ${aEvent.type === "beforeinput" ? "be" : "be never"} cancelable ${aDescription}`); + is(aEvent.bubbles, true, + `"${aEvent.type}" event should always bubble ${aDescription}`); + is(aEvent.inputType, aInputType, + `inputType of "${aEvent.type}" event should be "${aInputType}" ${aDescription}`); + is(aEvent.data, aData, + `data of "${aEvent.type}" event should be ${aData} ${aDescription}`); + is(aEvent.dataTransfer, null, + `dataTransfer of "${aEvent.type}" should be null ${aDescription}`); + is(aEvent.getTargetRanges().length, 0, + `getTargetRanges() of "${aEvent.type}" should return empty array ${aDescription}`); + } + + let beforeInputEvents = []; + let inputEvents = []; + function onBeforeInput(aEvent) { + beforeInputEvents.push(aEvent); + } + function onInput(aEvent) { + inputEvents.push(aEvent); + } + editableElement.addEventListener("beforeinput", onBeforeInput); + editableElement.addEventListener("input", onInput); + + editableElement.focus(); + + beforeInputEvents = []; + inputEvents = []; + synthesizeKey("a"); + is(beforeInputEvents.length, 1, + `Only one "beforeinput" event should be fired when inserting "a" with key on <${editableElement.tagName.toLowerCase()}> element`); + checkInputEvent(beforeInputEvents[0], "insertText", "a", `when inserting "a" with key on <${editableElement.tagName.toLowerCase()}> element`); + is(inputEvents.length, 1, + `Only one "input" event should be fired when inserting "a" with key on <${editableElement.tagName.toLowerCase()}> element`); + checkInputEvent(inputEvents[0], "insertText", "a", `when inserting "a" with key on <${editableElement.tagName.toLowerCase()}> element`); + + beforeInputEvents = []; + inputEvents = []; + synthesizeKey("c"); + is(beforeInputEvents.length, 1, + `Only one "beforeinput" event should be fired when inserting "c" with key on <${editableElement.tagName.toLowerCase()}> element`); + checkInputEvent(beforeInputEvents[0], "insertText", "c", `when inserting "c" with key on <${editableElement.tagName.toLowerCase()}> element`); + is(inputEvents.length, 1, + `Only one "input" event should be fired when inserting "c" with key on <${editableElement.tagName.toLowerCase()}> element`); + checkInputEvent(inputEvents[0], "insertText", "c", `when inserting "c" with key on <${editableElement.tagName.toLowerCase()}> element`); + + beforeInputEvents = []; + inputEvents = []; + synthesizeKey("KEY_ArrowLeft"); + is(beforeInputEvents.length, 0, + `No "beforeinput" event should be fired when pressing "ArrowLeft" key on <${editableElement.tagName.toLowerCase()}> element`); + is(inputEvents.length, 0, + `No "input" event should be fired when pressing "ArrowLeft" key on <${editableElement.tagName.toLowerCase()}> element`); + + beforeInputEvents = []; + inputEvents = []; + synthesizeKey("b"); + is(beforeInputEvents.length, 1, + `Only one "beforeinput" event should be fired when inserting "b" with key on <${editableElement.tagName.toLowerCase()}> element`); + checkInputEvent(beforeInputEvents[0], "insertText", "b", `when inserting "b" with key on <${editableElement.tagName.toLowerCase()}> element`); + is(inputEvents.length, 1, + `Only one "input" event should be fired when inserting "b" with key on <${editableElement.tagName.toLowerCase()}> element`); + checkInputEvent(inputEvents[0], "insertText", "b", `when inserting "b" with key on <${editableElement.tagName.toLowerCase()}> element`); + + let editor = SpecialPowers.wrap(editableElement).editor; + is( + editor.canUndo, + true, + `${editableElement.tagName}: Initially, the editor should have undo transactions` + ); + + beforeInputEvents = []; + inputEvents = []; + editableElement.value = "def"; + is(beforeInputEvents.length, 0, + `No "beforeinput" event should be fired when setting value of <${editableElement.tagName.toLowerCase()}> element`); + is(inputEvents.length, 0, + `No "input" event should be fired when setting value of <${editableElement.tagName.toLowerCase()}> element`); + + is( + editor.canUndo, + false, + `${editableElement.tagName}: After setting value, the editor should not have undo transactions` + ); + + beforeInputEvents = []; + inputEvents = []; + synthesizeKey("a"); + is(beforeInputEvents.length, 1, + `Only one "beforeinput" event should be fired when inserting "a" with key again on <${editableElement.tagName.toLowerCase()}> element`); + checkInputEvent(beforeInputEvents[0], "insertText", "a", `when inserting "a" with key again on <${editableElement.tagName.toLowerCase()}> element`); + is(inputEvents.length, 1, + `Only one "input" event should be fired when inserting "a" with key again on <${editableElement.tagName.toLowerCase()}> element`); + checkInputEvent(inputEvents[0], "insertText", "a", `when inserting "a" with key again on <${editableElement.tagName.toLowerCase()}> element`); + + beforeInputEvents = []; + inputEvents = []; + synthesizeKey("z", { accelKey: true }); + is(editableElement.value, "def", + editableElement.tagName + ": undo should work after setting value"); + is(beforeInputEvents.length, 1, + `Only one "beforeinput" event should be fired when undoing on <${editableElement.tagName.toLowerCase()}> element`); + checkInputEvent(beforeInputEvents[0], "historyUndo", null, `when undoing on <${editableElement.tagName.toLowerCase()}> element`); + is(inputEvents.length, 1, + `Only one "input" event should be fired when undoing on <${editableElement.tagName.toLowerCase()}> element`); + checkInputEvent(inputEvents[0], "historyUndo", null, `when undoing on <${editableElement.tagName.toLowerCase()}> element`); + + // Disable undo/redo. + editor.enableUndo(false); + is( + editor.canUndo, + false, + `${editableElement.tagName}: After calling enableUndo(false), the editor should not have undo transactions` + ); + editableElement.value = "hij"; + is( + editor.canUndo, + false, + `${editableElement.tagName}: After calling enableUndo(false), the editor should not create undo transaction for setting value` + ); + + editableElement.removeEventListener("beforeinput", onBeforeInput); + editableElement.removeEventListener("input", onInput); + } + SimpleTest.finish(); +}); +</script> +</pre> +</body> +</html> |