Source code

Revision control

Copy as Markdown

Other Tools

Test Info:

<!DOCTYPE html>
<!--
-->
<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>
<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>