summaryrefslogtreecommitdiffstats
path: root/editor/libeditor/tests/test_nsIEditorMailSupport_insertAsCitedQuotation.html
diff options
context:
space:
mode:
Diffstat (limited to 'editor/libeditor/tests/test_nsIEditorMailSupport_insertAsCitedQuotation.html')
-rw-r--r--editor/libeditor/tests/test_nsIEditorMailSupport_insertAsCitedQuotation.html322
1 files changed, 322 insertions, 0 deletions
diff --git a/editor/libeditor/tests/test_nsIEditorMailSupport_insertAsCitedQuotation.html b/editor/libeditor/tests/test_nsIEditorMailSupport_insertAsCitedQuotation.html
new file mode 100644
index 0000000000..531a8c6015
--- /dev/null
+++ b/editor/libeditor/tests/test_nsIEditorMailSupport_insertAsCitedQuotation.html
@@ -0,0 +1,322 @@
+<!DOCTYPE>
+<html>
+<head>
+ <title>Test for nsIEditorMailSupport.insertAsCitedQuotation()</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css">
+</head>
+<body>
+<div contenteditable></div>
+<script>
+"use strict";
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(() => {
+ function testInputEvents() {
+ const inReadonlyMode = getEditor().flags & SpecialPowers.Ci.nsIEditor.eEditorReadonlyMask;
+ const editorDescription = `(readonly=${!!inReadonlyMode})`;
+
+ const editor = document.querySelector("div[contenteditable]");
+ const selection = getSelection();
+
+ let beforeInputEvents = [];
+ let inputEvents = [];
+ let selectionRanges = [];
+ function onBeforeInput(aEvent) {
+ beforeInputEvents.push(aEvent);
+ 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});
+ }
+ }
+ function onInput(aEvent) {
+ inputEvents.push(aEvent);
+ }
+ editor.addEventListener("beforeinput", onBeforeInput);
+ editor.addEventListener("input", onInput);
+
+ editor.innerHTML = "";
+ editor.focus();
+ selection.collapse(editor, 0);
+
+ function checkInputEvent(aEvent, aInputType, aData, aDescription) {
+ ok(aEvent instanceof InputEvent,
+ `"${aEvent.type}" event should be dispatched with InputEvent interface ${aDescription}`);
+ // If it were cancelable whose inputType is empty string, web apps would
+ // block any Firefox specific modification whose inputType are not declared
+ // by the spec.
+ let expectedCancelable = aEvent.type === "beforeinput" && aInputType !== "";
+ is(aEvent.cancelable, expectedCancelable,
+ `"${aEvent.type}" event should ${expectedCancelable ? "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}" event should be null ${aDescription}`);
+ let targetRanges = aEvent.getTargetRanges();
+ if (aEvent.type === "beforeinput") {
+ is(targetRanges.length, selectionRanges.length,
+ `getTargetRanges() of "beforeinput" event should return selection ranges ${aDescription}`);
+ if (targetRanges.length === selectionRanges.length) {
+ for (let i = 0; i < selectionRanges.length; i++) {
+ is(targetRanges[i].startContainer, selectionRanges[i].startContainer,
+ `startContainer of getTargetRanges()[${i}] of "beforeinput" event does not match ${aDescription}`);
+ is(targetRanges[i].startOffset, selectionRanges[i].startOffset,
+ `startOffset of getTargetRanges()[${i}] of "beforeinput" event does not match ${aDescription}`);
+ is(targetRanges[i].endContainer, selectionRanges[i].endContainer,
+ `endContainer of getTargetRanges()[${i}] of "beforeinput" event does not match ${aDescription}`);
+ is(targetRanges[i].endOffset, selectionRanges[i].endOffset,
+ `endOffset of getTargetRanges()[${i}] of "beforeinput" event does not match ${aDescription}`);
+ }
+ }
+ } else {
+ is(targetRanges.length, 0,
+ `getTargetRanges() of "${aEvent.type}" event should return empty array ${aDescription}`);
+ }
+ }
+
+ // Tests when the editor is in plaintext mode.
+
+ getEditor().flags |= SpecialPowers.Ci.nsIEditor.eEditorPlaintextMask;
+
+ beforeInputEvents = [];
+ inputEvents = [];
+ getEditorMailSupport().insertAsCitedQuotation("this is quoted text\nAnd here is second line.", "this is cited text", false);
+
+ ok(
+ selection.isCollapsed,
+ `Selection should be collapsed after calling nsIEditorMailSupport.insertAsCitedQuotation() of plaintext editor ${editorDescription}`
+ );
+ is(
+ selection.focusNode,
+ editor,
+ `focus node of Selection should be a child of the editing host after calling nsIEditorMailSupport.insertAsCitedQuotation() of plaintext editor ${editorDescription}`
+ );
+ is(
+ selection.focusOffset,
+ 1,
+ `focus offset of Selection should be next to inserted <span> element after calling nsIEditorMailSupport.insertAsCitedQuotation() of plaintext editor ${editorDescription}`
+ );
+ is(
+ editor.innerHTML,
+ '<span style="white-space: pre-wrap;">&gt; this is quoted text<br>&gt; And here is second line.<br><br></span>',
+ `The quoted text should be inserted as plaintext into the plaintext editor ${editorDescription}`
+ );
+ is(
+ beforeInputEvents.length,
+ 1,
+ `One "beforeinput" event should be fired on the editing host after calling nsIEditorMailSupport.insertAsCitedQuotation() of plaintext editor ${editorDescription}`
+ );
+ checkInputEvent(
+ beforeInputEvents[0],
+ "insertText", "this is quoted text\nAnd here is second line.",
+ `after calling nsIEditorMailSupport.insertAsCitedQuotation() of plaintext editor ${editorDescription}`
+ );
+ is(
+ inputEvents.length,
+ 1,
+ `One "input" event should be fired on the editing host after calling nsIEditorMailSupport.insertAsCitedQuotation() of plaintext editor ${editorDescription}`
+ );
+ checkInputEvent(
+ inputEvents[0],
+ "insertText", "this is quoted text\nAnd here is second line.",
+ `after calling nsIEditorMailSupport.insertAsCitedQuotation() of plaintext editor ${editorDescription}`
+ );
+
+ // Tests when the editor is in HTML editor mode.
+ getEditor().flags &= ~SpecialPowers.Ci.nsIEditor.eEditorPlaintextMask;
+
+ editor.innerHTML = "";
+
+ beforeInputEvents = [];
+ inputEvents = [];
+ getEditorMailSupport().insertAsCitedQuotation("this is quoted text<br>", "this is cited text", false);
+
+ ok(
+ selection.isCollapsed,
+ `Selection should be collapsed after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as plaintext) ${editorDescription}`
+ );
+ is(
+ selection.focusNode,
+ editor,
+ `focus node of Selection should be a child of the editing host after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as plaintext) ${editorDescription}`
+ );
+ is(
+ selection.focusOffset,
+ 1,
+ `focus offset of Selection should be next to inserted <span> element after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as plaintext) ${editorDescription}`
+ );
+ is(
+ editor.innerHTML,
+ '<blockquote type="cite" cite="this is cited text">this is quoted text&lt;br&gt;</blockquote>',
+ `The quoted text should be inserted as plaintext into the HTML editor ${editorDescription}`
+ );
+ is(
+ beforeInputEvents.length,
+ 1,
+ `One "beforeinput" event should be fired on the editing host after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as plaintext) ${editorDescription}`
+ );
+ checkInputEvent(
+ beforeInputEvents[0],
+ "",
+ null,
+ `after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as plaintext) ${editorDescription}`
+ );
+ is(
+ inputEvents.length,
+ 1,
+ `One "input" event should be fired on the editing host after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as plaintext) ${editorDescription}`
+ );
+ checkInputEvent(
+ inputEvents[0],
+ "",
+ null,
+ `after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as plaintext) ${editorDescription}`
+ );
+
+ editor.innerHTML = "";
+
+ beforeInputEvents = [];
+ inputEvents = [];
+ getEditorMailSupport().insertAsCitedQuotation("this is quoted text<br>And here is second line.", "this is cited text", true);
+
+ ok(
+ selection.isCollapsed,
+ `Selection should be collapsed after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as HTML source) ${editorDescription}`
+ );
+ is(
+ selection.focusNode,
+ editor,
+ `focus node of Selection should be a child of the editing host after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as HTML source) ${editorDescription}`
+ );
+ is(
+ selection.focusOffset,
+ 1,
+ `focus offset of Selection should be next to inserted <span> element after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as HTML source) ${editorDescription}`
+ );
+ is(
+ editor.innerHTML,
+ '<blockquote type="cite" cite="this is cited text">this is quoted text<br>And here is second line.</blockquote>',
+ `The quoted text should be inserted as HTML source into the HTML editor ${editorDescription}`
+ );
+ is(
+ beforeInputEvents.length,
+ 1,
+ `One "beforeinput" event should be fired on the editing host after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as HTML source) ${editorDescription}`
+ );
+ checkInputEvent(
+ beforeInputEvents[0],
+ "",
+ null,
+ `after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as HTML source) ${editorDescription}`
+ );
+ is(
+ inputEvents.length,
+ 1,
+ `One "input" event should be fired on the editing host after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as HTML source) ${editorDescription}`
+ );
+ checkInputEvent(
+ inputEvents[0],
+ "",
+ null,
+ `after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as HTML source) ${editorDescription}`
+ );
+
+ editor.removeEventListener("beforeinput", onBeforeInput);
+ editor.removeEventListener("input", onInput);
+ }
+
+ function testStyleOfPlaintextMode() {
+ const inReadonlyMode = getEditor().flags & SpecialPowers.Ci.nsIEditor.eEditorReadonlyMask;
+ const editorDescription = `(readonly=${!!inReadonlyMode})`;
+
+ getEditor().flags |= SpecialPowers.Ci.nsIEditor.eEditorPlaintextMask;
+
+ (function testInDiv() {
+ const editor = document.querySelector("div[contenteditable]");
+ editor.innerHTML = "";
+ editor.focus();
+ getEditorMailSupport().insertAsCitedQuotation(
+ "this is quoted text.",
+ "this is cited text",
+ false
+ );
+ is(
+ editor.firstChild.tagName,
+ "SPAN",
+ `testStyleOfPlaintextMode: testInDiv: insertAsCitedQuotation should insert a <span> element ${editorDescription}`
+ );
+ const computedSpanStyle = getComputedStyle(editor.firstChild);
+ is(
+ computedSpanStyle.display,
+ "inline",
+ `testStyleOfPlaintextMode: testInDiv: The inserted <span> element should be "display: inline;" ${editorDescription}`
+ );
+ is(
+ computedSpanStyle.whiteSpace,
+ "pre-wrap",
+ `testStyleOfPlaintextMode: testInDiv: The inserted <span> element should be "white-space: pre-wrap;" ${editorDescription}`
+ );
+ })();
+
+ try {
+ document.body.contentEditable = true;
+ (function testInBody() {
+ getSelection().collapse(document.body, 0);
+ getEditorMailSupport().insertAsCitedQuotation(
+ "this is quoted text.",
+ "this is cited text",
+ false
+ );
+ is(
+ document.body.firstChild.tagName,
+ "SPAN",
+ `testStyleOfPlaintextMode: testInBody: insertAsCitedQuotation should insert a <span> element in plaintext mode and in a <body> element ${editorDescription}`
+ );
+ const computedSpanStyle = getComputedStyle(document.body.firstChild);
+ is(
+ computedSpanStyle.display,
+ "block",
+ `testStyleOfPlaintextMode: testInBody: The inserted <span> element should be "display: block;" in plaintext mode and in a <body> element ${editorDescription}`
+ );
+ is(
+ computedSpanStyle.whiteSpace,
+ "pre-wrap",
+ `testStyleOfPlaintextMode: testInBody: The inserted <span> element should be "white-space: pre-wrap;" in plaintext mode and in a <body> element ${editorDescription}`
+ );
+ document.body.firstChild.remove();
+ })();
+ } finally {
+ document.body.contentEditable = false;
+ }
+ }
+
+ testInputEvents();
+ testStyleOfPlaintextMode();
+
+ // Even if the HTMLEditor is readonly, XPCOM API should keep working.
+ getEditor().flags |= SpecialPowers.Ci.nsIEditor.eEditorReadonlyMask;
+ testInputEvents();
+ testStyleOfPlaintextMode();
+
+ SimpleTest.finish();
+});
+
+function getEditor() {
+ var editingSession = SpecialPowers.wrap(window).docShell.editingSession;
+ return editingSession.getEditorForWindow(window);
+}
+
+function getEditorMailSupport() {
+ return getEditor().QueryInterface(SpecialPowers.Ci.nsIEditorMailSupport);
+}
+
+</script>
+</body>
+
+</html>