diff options
Diffstat (limited to '')
-rw-r--r-- | editor/libeditor/tests/test_nsIEditor_insertLineBreak.html | 416 |
1 files changed, 416 insertions, 0 deletions
diff --git a/editor/libeditor/tests/test_nsIEditor_insertLineBreak.html b/editor/libeditor/tests/test_nsIEditor_insertLineBreak.html new file mode 100644 index 0000000000..02a847b640 --- /dev/null +++ b/editor/libeditor/tests/test_nsIEditor_insertLineBreak.html @@ -0,0 +1,416 @@ +<!DOCTYPE> +<html> +<head> + <title>Test for nsIEditor.insertLineBreak()</title> + <script src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" href="/tests/SimpleTest/test.css"> +</head> +<body> +<div id="display"> +</div> +<input value="abcdef"> +<textarea>abcdef</textarea> +<div id="content" contenteditable></div> +<pre id="test"> +</pre> + +<script class="testbody" type="application/javascript"> +"use strict"; + +SimpleTest.waitForExplicitFinish(); +SimpleTest.expectAssertions(0, 2); // In a11y module +SimpleTest.waitForFocus(() => { + let input = document.getElementsByTagName("input")[0]; + let textarea = document.getElementsByTagName("textarea")[0]; + let contenteditable = document.getElementById("content"); + let selection = window.getSelection(); + + let beforeInputEvents = []; + let inputEvents = []; + function onBeforeInput(event) { + beforeInputEvents.push(event); + } + function onInput(event) { + inputEvents.push(event); + } + + function checkInputEvent(aEvent, aInputType, aTargetRanges, aDescription) { + ok(aEvent != null, `aEvent is null (${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, null, + `data of "${aEvent.type}" event should be null ${aDescription}`); + is(aEvent.dataTransfer, null, + `dataTransfer of "${aEvent.type}" event should be null ${aDescription}`); + let targetRanges = aEvent.getTargetRanges(); + if (aTargetRanges.length === 0) { + is(targetRanges.length, 0, + `getTargetRange() of "${aEvent.type}" event should return empty array: ${aDescription}`); + } else { + is(targetRanges.length, aTargetRanges.length, + `getTargetRange() of "${aEvent.type}" event should return static range array: ${aDescription}`); + if (targetRanges.length == aTargetRanges.length) { + for (let i = 0; i < targetRanges.length; i++) { + is(targetRanges[i].startContainer, aTargetRanges[i].startContainer, + `startContainer of getTargetRanges()[${i}] of "${aEvent.type}" event does not match: ${aDescription}`); + is(targetRanges[i].startOffset, aTargetRanges[i].startOffset, + `startOffset of getTargetRanges()[${i}] of "${aEvent.type}" event does not match: ${aDescription}`); + is(targetRanges[i].endContainer, aTargetRanges[i].endContainer, + `endContainer of getTargetRanges()[${i}] of "${aEvent.type}" event does not match: ${aDescription}`); + is(targetRanges[i].endOffset, aTargetRanges[i].endOffset, + `endOffset of getTargetRanges()[${i}] of "${aEvent.type}" event does not match: ${aDescription}`); + } + } + } + } + + input.focus(); + input.selectionStart = input.selectionEnd = 3; + beforeInputEvents = []; + inputEvents = []; + input.addEventListener("beforeinput", onBeforeInput); + input.addEventListener("input", onInput); + try { + getPlaintextEditor(input).insertLineBreak(); + } catch (e) { + ok(true, e.message); + } + input.removeEventListener("beforeinput", onBeforeInput); + input.removeEventListener("input", onInput); + is(input.value, "abcdef", "nsIEditor.insertLineBreak() should do nothing on single line editor"); + is(beforeInputEvents.length, 1, 'nsIEditor.insertLineBreak() should cause a "beforeinput" event on single line editor'); + checkInputEvent(beforeInputEvents[0], "insertLineBreak", [], "on single line editor"); + is(inputEvents.length, 0, 'nsIEditor.insertLineBreak() should not cause "input" event on single line editor'); + + textarea.focus(); + textarea.selectionStart = textarea.selectionEnd = 3; + beforeInputEvents = []; + inputEvents = []; + textarea.addEventListener("beforeinput", onBeforeInput); + textarea.addEventListener("input", onInput); + getPlaintextEditor(textarea).insertLineBreak(); + textarea.removeEventListener("beforeinput", onBeforeInput); + textarea.removeEventListener("input", onInput); + is(textarea.value, "abc\ndef", "nsIEditor.insertLineBreak() should insert \\n into multi-line editor"); + is(beforeInputEvents.length, 1, 'nsIEditor.insertLineBreak() should cause "beforeinput" event once on multi-line editor'); + checkInputEvent(beforeInputEvents[0], "insertLineBreak", [], "on multi-line editor"); + is(inputEvents.length, 1, 'nsIEditor.insertLineBreak() should cause "input" event once on multi-line editor'); + checkInputEvent(inputEvents[0], "insertLineBreak", [], "on multi-line editor"); + + // Note that despite of the name, insertLineBreak() should insert paragraph separator in HTMLEditor. + + document.execCommand("defaultParagraphSeparator", false, "br"); + + contenteditable.innerHTML = "abcdef"; + contenteditable.focus(); + contenteditable.scrollTop; + let selectionContainer = contenteditable.firstChild; + selection.collapse(selectionContainer, 3); + beforeInputEvents = []; + inputEvents = []; + contenteditable.addEventListener("beforeinput", onBeforeInput); + contenteditable.addEventListener("input", onInput); + getPlaintextEditor(contenteditable).insertLineBreak(); + contenteditable.removeEventListener("beforeinput", onBeforeInput); + contenteditable.removeEventListener("input", onInput); + is(contenteditable.innerHTML, "abc<br>def", + 'nsIEditor.insertLineBreak() should insert <br> element into text node when defaultParagraphSeparator is "br"'); + is(beforeInputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has only text node when defaultParagraphSeparator is "br"'); + checkInputEvent(beforeInputEvents[0], "insertParagraph", + [{startContainer: selectionContainer, startOffset: 3, + endContainer: selectionContainer, endOffset: 3}], + 'on HTMLEditor (when defaultParagraphSeparator is "br")'); + is(inputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has only text node when defaultParagraphSeparator is "br"'); + checkInputEvent(inputEvents[0], "insertParagraph", [], 'on HTMLEditor (when defaultParagraphSeparator is "br")'); + + contenteditable.innerHTML = "<p>abcdef</p>"; + contenteditable.focus(); + contenteditable.scrollTop; + selectionContainer = contenteditable.firstChild.firstChild; + selection.collapse(selectionContainer, 3); + beforeInputEvents = []; + inputEvents = []; + contenteditable.addEventListener("beforeinput", onBeforeInput); + contenteditable.addEventListener("input", onInput); + getPlaintextEditor(contenteditable).insertLineBreak(); + contenteditable.removeEventListener("beforeinput", onBeforeInput); + contenteditable.removeEventListener("input", onInput); + is(contenteditable.innerHTML, "<p>abc</p><p>def</p>", + 'nsIEditor.insertLineBreak() should add <p> element after <p> element even when defaultParagraphSeparator is "br"'); + is(beforeInputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <p> element when defaultParagraphSeparator is "br"'); + checkInputEvent(beforeInputEvents[0], "insertParagraph", + [{startContainer: selectionContainer, startOffset: 3, + endContainer: selectionContainer, endOffset: 3}], + 'in <p> element on HTMLEditor (when defaultParagraphSeparator is "br")'); + is(inputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has <p> element when defaultParagraphSeparator is "br"'); + checkInputEvent(inputEvents[0], "insertParagraph", [], 'in <p> element on HTMLEditor (when defaultParagraphSeparator is "br")'); + + contenteditable.innerHTML = "<div>abcdef</div>"; + contenteditable.focus(); + contenteditable.scrollTop; + selectionContainer = contenteditable.firstChild.firstChild; + selection.collapse(selectionContainer, 3); + beforeInputEvents = []; + inputEvents = []; + contenteditable.addEventListener("beforeinput", onBeforeInput); + contenteditable.addEventListener("input", onInput); + getPlaintextEditor(contenteditable).insertLineBreak(); + contenteditable.removeEventListener("beforeinput", onBeforeInput); + contenteditable.removeEventListener("input", onInput); + is(contenteditable.innerHTML, "<div>abc<br>def</div>", + 'nsIEditor.insertLineBreak() should insert <br> element into <div> element when defaultParagraphSeparator is "br"'); + is(beforeInputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <div> element when defaultParagraphSeparator is "br"'); + checkInputEvent(beforeInputEvents[0], "insertParagraph", + [{startContainer: selectionContainer, startOffset: 3, + endContainer: selectionContainer, endOffset: 3}], + 'in <div> element on HTMLEditor (when defaultParagraphSeparator is "br")'); + is(inputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has <div> element when defaultParagraphSeparator is "br"'); + checkInputEvent(inputEvents[0], "insertParagraph", [], 'in <div> element on HTMLEditor (when defaultParagraphSeparator is "br")'); + + contenteditable.innerHTML = "<pre>abcdef</pre>"; + contenteditable.focus(); + contenteditable.scrollTop; + selectionContainer = contenteditable.firstChild.firstChild; + selection.collapse(selectionContainer, 3); + beforeInputEvents = []; + inputEvents = []; + contenteditable.addEventListener("beforeinput", onBeforeInput); + contenteditable.addEventListener("input", onInput); + getPlaintextEditor(contenteditable).insertLineBreak(); + contenteditable.removeEventListener("beforeinput", onBeforeInput); + contenteditable.removeEventListener("input", onInput); + is(contenteditable.innerHTML, "<pre>abc<br>def</pre>", + 'nsIEditor.insertLineBreak() should insert <br> element into <pre> element when defaultParagraphSeparator is "br"'); + is(beforeInputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <pre> element when defaultParagraphSeparator is "br"'); + checkInputEvent(beforeInputEvents[0], "insertParagraph", + [{startContainer: selectionContainer, startOffset: 3, + endContainer: selectionContainer, endOffset: 3}], + 'in <pre> element on HTMLEditor (when defaultParagraphSeparator is "br")'); + is(inputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has <pre> element when defaultParagraphSeparator is "br"'); + checkInputEvent(inputEvents[0], "insertParagraph", [], 'in <pre> element on HTMLEditor (when defaultParagraphSeparator is "br")'); + + document.execCommand("defaultParagraphSeparator", false, "p"); + + contenteditable.innerHTML = "abcdef"; + contenteditable.focus(); + contenteditable.scrollTop; + selectionContainer = contenteditable.firstChild; + selection.collapse(selectionContainer, 3); + beforeInputEvents = []; + inputEvents = []; + contenteditable.addEventListener("beforeinput", onBeforeInput); + contenteditable.addEventListener("input", onInput); + getPlaintextEditor(contenteditable).insertLineBreak(); + contenteditable.removeEventListener("beforeinput", onBeforeInput); + contenteditable.removeEventListener("input", onInput); + is(contenteditable.innerHTML, "<p>abc</p><p>def</p>", + 'nsIEditor.insertLineBreak() should create <p> elements when there is only text node and defaultParagraphSeparator is "p"'); + is(beforeInputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has only text node when defaultParagraphSeparator is "p"'); + checkInputEvent(beforeInputEvents[0], "insertParagraph", + [{startContainer: selectionContainer, startOffset: 3, + endContainer: selectionContainer, endOffset: 3}], + 'on HTMLEditor (when defaultParagraphSeparator is "p")'); + is(inputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has only text node when defaultParagraphSeparator is "p"'); + checkInputEvent(inputEvents[0], "insertParagraph", [], 'on HTMLEditor (when defaultParagraphSeparator is "p")'); + + contenteditable.innerHTML = "<p>abcdef</p>"; + contenteditable.focus(); + contenteditable.scrollTop; + selectionContainer = contenteditable.firstChild.firstChild; + selection.collapse(selectionContainer, 3); + beforeInputEvents = []; + inputEvents = []; + contenteditable.addEventListener("beforeinput", onBeforeInput); + contenteditable.addEventListener("input", onInput); + getPlaintextEditor(contenteditable).insertLineBreak(); + contenteditable.removeEventListener("beforeinput", onBeforeInput); + contenteditable.removeEventListener("input", onInput); + is(contenteditable.innerHTML, "<p>abc</p><p>def</p>", + 'nsIEditor.insertLineBreak() should add <p> element after <p> element when defaultParagraphSeparator is "p"'); + is(beforeInputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <p> element when defaultParagraphSeparator is "p"'); + checkInputEvent(beforeInputEvents[0], "insertParagraph", + [{startContainer: selectionContainer, startOffset: 3, + endContainer: selectionContainer, endOffset: 3}], + 'in <p> element on HTMLEditor (when defaultParagraphSeparator is "p")'); + is(inputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has <p> element when defaultParagraphSeparator is "p"'); + checkInputEvent(inputEvents[0], "insertParagraph", [], 'in <p> element on HTMLEditor (when defaultParagraphSeparator is "p")'); + + contenteditable.innerHTML = "<div>abcdef</div>"; + contenteditable.focus(); + contenteditable.scrollTop; + selectionContainer = contenteditable.firstChild.firstChild; + selection.collapse(selectionContainer, 3); + beforeInputEvents = []; + inputEvents = []; + contenteditable.addEventListener("beforeinput", onBeforeInput); + contenteditable.addEventListener("input", onInput); + getPlaintextEditor(contenteditable).insertLineBreak(); + contenteditable.removeEventListener("beforeinput", onBeforeInput); + contenteditable.removeEventListener("input", onInput); + is(contenteditable.innerHTML, "<div>abc</div><div>def</div>", + 'nsIEditor.insertLineBreak() should add <div> element after <div> element even when defaultParagraphSeparator is "p"'); + is(beforeInputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <div> element when defaultParagraphSeparator is "p"'); + checkInputEvent(beforeInputEvents[0], "insertParagraph", + [{startContainer: selectionContainer, startOffset: 3, + endContainer: selectionContainer, endOffset: 3}], + 'in <div> element on HTMLEditor (when defaultParagraphSeparator is "p")'); + is(inputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has <div> element when defaultParagraphSeparator is "p"'); + checkInputEvent(inputEvents[0], "insertParagraph", [], 'in <div> element on HTMLEditor (when defaultParagraphSeparator is "p")'); + + contenteditable.innerHTML = "<pre>abcdef</pre>"; + contenteditable.focus(); + contenteditable.scrollTop; + selectionContainer = contenteditable.firstChild.firstChild; + selection.collapse(selectionContainer, 3); + beforeInputEvents = []; + inputEvents = []; + contenteditable.addEventListener("beforeinput", onBeforeInput); + contenteditable.addEventListener("input", onInput); + getPlaintextEditor(contenteditable).insertLineBreak(); + contenteditable.removeEventListener("beforeinput", onBeforeInput); + contenteditable.removeEventListener("input", onInput); + is(contenteditable.innerHTML, "<pre>abc<br>def</pre>", + 'nsIEditor.insertLineBreak() should insert <br> element into <pre> element when defaultParagraphSeparator is "p"'); + is(beforeInputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <pre> element when defaultParagraphSeparator is "p"'); + checkInputEvent(beforeInputEvents[0], "insertParagraph", + [{startContainer: selectionContainer, startOffset: 3, + endContainer: selectionContainer, endOffset: 3}], + 'in <pre> element on HTMLEditor (when defaultParagraphSeparator is "p")'); + is(inputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has <pre> element when defaultParagraphSeparator is "p"'); + checkInputEvent(inputEvents[0], "insertParagraph", [], 'in <pre> element on HTMLEditor (when defaultParagraphSeparator is "p")'); + + document.execCommand("defaultParagraphSeparator", false, "div"); + + contenteditable.innerHTML = "abcdef"; + contenteditable.focus(); + contenteditable.scrollTop; + selectionContainer = contenteditable.firstChild; + selection.collapse(selectionContainer, 3); + beforeInputEvents = []; + inputEvents = []; + contenteditable.addEventListener("beforeinput", onBeforeInput); + contenteditable.addEventListener("input", onInput); + getPlaintextEditor(contenteditable).insertLineBreak(); + contenteditable.removeEventListener("beforeinput", onBeforeInput); + contenteditable.removeEventListener("input", onInput); + is(contenteditable.innerHTML, "<div>abc</div><div>def</div>", + 'nsIEditor.insertLineBreak() should create <div> elements when there is only text node and defaultParagraphSeparator is "div"'); + is(beforeInputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has only text node when defaultParagraphSeparator is "div"'); + checkInputEvent(beforeInputEvents[0], "insertParagraph", + [{startContainer: selectionContainer, startOffset: 3, + endContainer: selectionContainer, endOffset: 3}], + 'on HTMLEditor (when defaultParagraphSeparator is "div")'); + is(inputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has only text node when defaultParagraphSeparator is "div"'); + checkInputEvent(inputEvents[0], "insertParagraph", [], 'on HTMLEditor (when defaultParagraphSeparator is "div")'); + + contenteditable.innerHTML = "<p>abcdef</p>"; + contenteditable.focus(); + contenteditable.scrollTop; + selectionContainer = contenteditable.firstChild.firstChild; + selection.collapse(selectionContainer, 3); + beforeInputEvents = []; + inputEvents = []; + contenteditable.addEventListener("beforeinput", onBeforeInput); + contenteditable.addEventListener("input", onInput); + getPlaintextEditor(contenteditable).insertLineBreak(); + contenteditable.removeEventListener("beforeinput", onBeforeInput); + contenteditable.removeEventListener("input", onInput); + is(contenteditable.innerHTML, "<p>abc</p><p>def</p>", + 'nsIEditor.insertLineBreak() should add <p> element after <p> element even when defaultParagraphSeparator is "div"'); + is(beforeInputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <p> element when defaultParagraphSeparator is "div"'); + checkInputEvent(beforeInputEvents[0], "insertParagraph", + [{startContainer: selectionContainer, startOffset: 3, + endContainer: selectionContainer, endOffset: 3}], + 'in <p> element on HTMLEditor (when defaultParagraphSeparator is "div")'); + is(inputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has <p> element when defaultParagraphSeparator is "div"'); + checkInputEvent(inputEvents[0], "insertParagraph", [], 'in <p> element on HTMLEditor (when defaultParagraphSeparator is "div")'); + + contenteditable.innerHTML = "<div>abcdef</div>"; + contenteditable.focus(); + contenteditable.scrollTop; + selectionContainer = contenteditable.firstChild.firstChild; + selection.collapse(selectionContainer, 3); + beforeInputEvents = []; + inputEvents = []; + contenteditable.addEventListener("beforeinput", onBeforeInput); + contenteditable.addEventListener("input", onInput); + getPlaintextEditor(contenteditable).insertLineBreak(); + contenteditable.removeEventListener("beforeinput", onBeforeInput); + contenteditable.removeEventListener("input", onInput); + is(contenteditable.innerHTML, "<div>abc</div><div>def</div>", + 'nsIEditor.insertLineBreak() should add <div> element after <div> element when defaultParagraphSeparator is "div"'); + is(beforeInputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <div> element when defaultParagraphSeparator is "div"'); + checkInputEvent(beforeInputEvents[0], "insertParagraph", + [{startContainer: selectionContainer, startOffset: 3, + endContainer: selectionContainer, endOffset: 3}], + 'in <div> element on HTMLEditor (when defaultParagraphSeparator is "div")'); + is(inputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has <div> element when defaultParagraphSeparator is "div"'); + checkInputEvent(inputEvents[0], "insertParagraph", [], 'in <div> element on HTMLEditor (when defaultParagraphSeparator is "div")'); + + contenteditable.innerHTML = "<pre>abcdef</pre>"; + contenteditable.focus(); + contenteditable.scrollTop; + selectionContainer = contenteditable.firstChild.firstChild; + selection.collapse(selectionContainer, 3); + beforeInputEvents = []; + inputEvents = []; + contenteditable.addEventListener("beforeinput", onBeforeInput); + contenteditable.addEventListener("input", onInput); + getPlaintextEditor(contenteditable).insertLineBreak(); + contenteditable.removeEventListener("beforeinput", onBeforeInput); + contenteditable.removeEventListener("input", onInput); + is(contenteditable.innerHTML, "<pre>abc<br>def</pre>", + 'nsIEditor.insertLineBreak() should insert <br> element into <pre> element when defaultParagraphSeparator is "div"'); + is(beforeInputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "beforeinput" event once on contenteditable which has <pre> element when defaultParagraphSeparator is "div"'); + checkInputEvent(beforeInputEvents[0], "insertParagraph", + [{startContainer: selectionContainer, startOffset: 3, + endContainer: selectionContainer, endOffset: 3}], + 'in <pre> element on HTMLEditor (when defaultParagraphSeparator is "div")'); + is(inputEvents.length, 1, + 'nsIEditor.insertLineBreak() should cause "input" event once on contenteditable which has <pre> element when defaultParagraphSeparator is "div"'); + checkInputEvent(inputEvents[0], "insertParagraph", [], 'in <pre> element on HTMLEditor (when defaultParagraphSeparator is "div")'); + + SimpleTest.finish(); +}); + +function getPlaintextEditor(aEditorElement) { + let editor = aEditorElement ? SpecialPowers.wrap(aEditorElement).editor : null; + if (!editor) { + editor = SpecialPowers.wrap(window).docShell.editingSession.getEditorForWindow(window); + } + return editor; +} + +</script> +</body> + +</html> |