4 <title>Test for nsIEditorMailSupport.insertAsCitedQuotation()
</title>
5 <script src=
"/tests/SimpleTest/SimpleTest.js"></script>
6 <link rel=
"stylesheet" href=
"/tests/SimpleTest/test.css">
9 <div contenteditable
></div>
13 SimpleTest
.waitForExplicitFinish();
14 SimpleTest
.waitForFocus(() => {
15 function testInputEvents() {
16 const inReadonlyMode
= getEditor().flags
& SpecialPowers
.Ci
.nsIEditor
.eEditorReadonlyMask
;
17 const editorDescription
= `(readonly=${!!inReadonlyMode})`;
19 const editor
= document
.querySelector("div[contenteditable]");
20 const selection
= getSelection();
22 let beforeInputEvents
= [];
24 let selectionRanges
= [];
25 function onBeforeInput(aEvent
) {
26 beforeInputEvents
.push(aEvent
);
28 for (let i
= 0; i
< selection
.rangeCount
; i
++) {
29 let range
= selection
.getRangeAt(i
);
30 selectionRanges
.push({startContainer
: range
.startContainer
, startOffset
: range
.startOffset
,
31 endContainer
: range
.endContainer
, endOffset
: range
.endOffset
});
34 function onInput(aEvent
) {
35 inputEvents
.push(aEvent
);
37 editor
.addEventListener("beforeinput", onBeforeInput
);
38 editor
.addEventListener("input", onInput
);
40 editor
.innerHTML
= "";
42 selection
.collapse(editor
, 0);
44 function checkInputEvent(aEvent
, aInputType
, aData
, aDescription
) {
45 ok(aEvent
instanceof InputEvent
,
46 `"${aEvent.type}" event should be dispatched with InputEvent interface ${aDescription}`);
47 // If it were cancelable whose inputType is empty string, web apps would
48 // block any Firefox specific modification whose inputType are not declared
50 let expectedCancelable
= aEvent
.type
=== "beforeinput" && aInputType
!== "";
51 is(aEvent
.cancelable
, expectedCancelable
,
52 `"${aEvent.type}" event should ${expectedCancelable ? "be" : "be never"} cancelable ${aDescription}`);
53 is(aEvent
.bubbles
, true,
54 `"${aEvent.type}" event should always bubble ${aDescription}`);
55 is(aEvent
.inputType
, aInputType
,
56 `inputType of "${aEvent.type}" event should be "${aInputType}" ${aDescription}`);
57 is(aEvent
.data
, aData
,
58 `data of "${aEvent.type}" event should be ${aData} ${aDescription}`);
59 is(aEvent
.dataTransfer
, null,
60 `dataTransfer of "${aEvent.type}" event should be null ${aDescription}`);
61 let targetRanges
= aEvent
.getTargetRanges();
62 if (aEvent
.type
=== "beforeinput") {
63 is(targetRanges
.length
, selectionRanges
.length
,
64 `getTargetRanges() of "beforeinput" event should return selection ranges ${aDescription}`);
65 if (targetRanges
.length
=== selectionRanges
.length
) {
66 for (let i
= 0; i
< selectionRanges
.length
; i
++) {
67 is(targetRanges
[i
].startContainer
, selectionRanges
[i
].startContainer
,
68 `startContainer of getTargetRanges()[${i}] of "beforeinput" event does not match ${aDescription}`);
69 is(targetRanges
[i
].startOffset
, selectionRanges
[i
].startOffset
,
70 `startOffset of getTargetRanges()[${i}] of "beforeinput" event does not match ${aDescription}`);
71 is(targetRanges
[i
].endContainer
, selectionRanges
[i
].endContainer
,
72 `endContainer of getTargetRanges()[${i}] of "beforeinput" event does not match ${aDescription}`);
73 is(targetRanges
[i
].endOffset
, selectionRanges
[i
].endOffset
,
74 `endOffset of getTargetRanges()[${i}] of "beforeinput" event does not match ${aDescription}`);
78 is(targetRanges
.length
, 0,
79 `getTargetRanges() of "${aEvent.type}" event should return empty array ${aDescription}`);
83 // Tests when the editor is in plaintext mode.
85 getEditor().flags
|= SpecialPowers
.Ci
.nsIEditor
.eEditorPlaintextMask
;
87 beforeInputEvents
= [];
89 getEditorMailSupport().insertAsCitedQuotation("this is quoted text\nAnd here is second line.", "this is cited text", false);
92 selection
.isCollapsed
,
93 `Selection should be collapsed after calling nsIEditorMailSupport.insertAsCitedQuotation() of plaintext editor ${editorDescription}`
98 `focus node of Selection should be a child of the editing host after calling nsIEditorMailSupport.insertAsCitedQuotation() of plaintext editor ${editorDescription}`
101 selection
.focusOffset
,
103 `focus offset of Selection should be next to inserted <span> element after calling nsIEditorMailSupport.insertAsCitedQuotation() of plaintext editor ${editorDescription}`
107 '<span style="white-space: pre-wrap;">> this is quoted text<br>> And here is second line.<br><br></span>',
108 `The quoted text should be inserted as plaintext into the plaintext editor ${editorDescription}`
111 beforeInputEvents
.length
,
113 `One "beforeinput" event should be fired on the editing host after calling nsIEditorMailSupport.insertAsCitedQuotation() of plaintext editor ${editorDescription}`
116 beforeInputEvents
[0],
117 "insertText", "this is quoted text\nAnd here is second line.",
118 `after calling nsIEditorMailSupport.insertAsCitedQuotation() of plaintext editor ${editorDescription}`
123 `One "input" event should be fired on the editing host after calling nsIEditorMailSupport.insertAsCitedQuotation() of plaintext editor ${editorDescription}`
127 "insertText", "this is quoted text\nAnd here is second line.",
128 `after calling nsIEditorMailSupport.insertAsCitedQuotation() of plaintext editor ${editorDescription}`
131 // Tests when the editor is in HTML editor mode.
132 getEditor().flags
&= ~SpecialPowers
.Ci
.nsIEditor
.eEditorPlaintextMask
;
134 editor
.innerHTML
= "";
136 beforeInputEvents
= [];
138 getEditorMailSupport().insertAsCitedQuotation("this is quoted text<br>", "this is cited text", false);
141 selection
.isCollapsed
,
142 `Selection should be collapsed after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as plaintext) ${editorDescription}`
147 `focus node of Selection should be a child of the editing host after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as plaintext) ${editorDescription}`
150 selection
.focusOffset
,
152 `focus offset of Selection should be next to inserted <span> element after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as plaintext) ${editorDescription}`
156 '<blockquote type="cite" cite="this is cited text">this is quoted text<br></blockquote>',
157 `The quoted text should be inserted as plaintext into the HTML editor ${editorDescription}`
160 beforeInputEvents
.length
,
162 `One "beforeinput" event should be fired on the editing host after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as plaintext) ${editorDescription}`
165 beforeInputEvents
[0],
168 `after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as plaintext) ${editorDescription}`
173 `One "input" event should be fired on the editing host after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as plaintext) ${editorDescription}`
179 `after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as plaintext) ${editorDescription}`
182 editor
.innerHTML
= "";
184 beforeInputEvents
= [];
186 getEditorMailSupport().insertAsCitedQuotation("this is quoted text<br>And here is second line.", "this is cited text", true);
189 selection
.isCollapsed
,
190 `Selection should be collapsed after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as HTML source) ${editorDescription}`
195 `focus node of Selection should be a child of the editing host after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as HTML source) ${editorDescription}`
198 selection
.focusOffset
,
200 `focus offset of Selection should be next to inserted <span> element after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as HTML source) ${editorDescription}`
204 '<blockquote type="cite" cite="this is cited text">this is quoted text<br>And here is second line.</blockquote>',
205 `The quoted text should be inserted as HTML source into the HTML editor ${editorDescription}`
208 beforeInputEvents
.length
,
210 `One "beforeinput" event should be fired on the editing host after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as HTML source) ${editorDescription}`
213 beforeInputEvents
[0],
216 `after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as HTML source) ${editorDescription}`
221 `One "input" event should be fired on the editing host after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as HTML source) ${editorDescription}`
227 `after calling nsIEditorMailSupport.insertAsCitedQuotation() of HTMLEditor editor (inserting as HTML source) ${editorDescription}`
230 editor
.removeEventListener("beforeinput", onBeforeInput
);
231 editor
.removeEventListener("input", onInput
);
234 function testStyleOfPlaintextMode() {
235 const inReadonlyMode
= getEditor().flags
& SpecialPowers
.Ci
.nsIEditor
.eEditorReadonlyMask
;
236 const editorDescription
= `(readonly=${!!inReadonlyMode})`;
238 getEditor().flags
|= SpecialPowers
.Ci
.nsIEditor
.eEditorPlaintextMask
;
240 (function testInDiv() {
241 const editor
= document
.querySelector("div[contenteditable]");
242 editor
.innerHTML
= "";
244 getEditorMailSupport().insertAsCitedQuotation(
245 "this is quoted text.",
246 "this is cited text",
250 editor
.firstChild
.tagName
,
252 `testStyleOfPlaintextMode: testInDiv: insertAsCitedQuotation should insert a <span> element ${editorDescription}`
254 const computedSpanStyle
= getComputedStyle(editor
.firstChild
);
256 computedSpanStyle
.display
,
258 `testStyleOfPlaintextMode: testInDiv: The inserted <span> element should be "display: inline;" ${editorDescription}`
261 computedSpanStyle
.whiteSpace
,
263 `testStyleOfPlaintextMode: testInDiv: The inserted <span> element should be "white-space: pre-wrap;" ${editorDescription}`
268 document
.body
.contentEditable
= true;
269 (function testInBody() {
270 getSelection().collapse(document
.body
, 0);
271 getEditorMailSupport().insertAsCitedQuotation(
272 "this is quoted text.",
273 "this is cited text",
277 document
.body
.firstChild
.tagName
,
279 `testStyleOfPlaintextMode: testInBody: insertAsCitedQuotation should insert a <span> element in plaintext mode and in a <body> element ${editorDescription}`
281 const computedSpanStyle
= getComputedStyle(document
.body
.firstChild
);
283 computedSpanStyle
.display
,
285 `testStyleOfPlaintextMode: testInBody: The inserted <span> element should be "display: block;" in plaintext mode and in a <body> element ${editorDescription}`
288 computedSpanStyle
.whiteSpace
,
290 `testStyleOfPlaintextMode: testInBody: The inserted <span> element should be "white-space: pre-wrap;" in plaintext mode and in a <body> element ${editorDescription}`
292 document
.body
.firstChild
.remove();
295 document
.body
.contentEditable
= false;
300 testStyleOfPlaintextMode();
302 // Even if the HTMLEditor is readonly, XPCOM API should keep working.
303 getEditor().flags
|= SpecialPowers
.Ci
.nsIEditor
.eEditorReadonlyMask
;
305 testStyleOfPlaintextMode();
310 function getEditor() {
311 var editingSession
= SpecialPowers
.wrap(window
).docShell
.editingSession
;
312 return editingSession
.getEditorForWindow(window
);
315 function getEditorMailSupport() {
316 return getEditor().QueryInterface(SpecialPowers
.Ci
.nsIEditorMailSupport
);