2 <?xml-stylesheet href=
"chrome://global/skin" type=
"text/css"?>
3 <?xml-stylesheet href=
"chrome://mochikit/content/tests/SimpleTest/test.css"
5 <window title=
"Testing composition, text and query content events"
6 xmlns:
html=
"http://www.w3.org/1999/xhtml"
7 xmlns=
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
9 <script src=
"chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
10 <script src=
"chrome://mochikit/content/tests/SimpleTest/EventUtils.js" />
11 <script src=
"chrome://mochikit/content/tests/SimpleTest/WindowSnapshot.js" />
13 <panel id=
"panel" hidden=
"true" orient=
"vertical">
15 <html:textarea id=
"textbox" cols=
"20" rows=
"4" style=
"font-size: 36px;"/>
19 <body xmlns=
"http://www.w3.org/1999/xhtml">
21 <div id=
"div" style=
"margin: 0; padding: 0; font-size: 36px;">Here is a text frame.
</div>
22 <textarea style=
"margin: 0; font-family: -moz-fixed;" id=
"textarea" cols=
"20" rows=
"4"></textarea><br/>
23 <iframe id=
"iframe" width=
"300" height=
"150"
24 src=
"data:text/html,<textarea id='textarea' cols='20' rows='4'></textarea>"></iframe><br/>
25 <iframe id=
"iframe2" width=
"300" height=
"150"
26 src=
"data:text/html,<body onload='document.designMode=%22on%22'>body content</body>"></iframe><br/>
27 <iframe id=
"iframe3" width=
"300" height=
"150"
28 src=
"data:text/html,<body onload='document.designMode=%22on%22'>body content</body>"></iframe><br/>
29 <iframe id=
"iframe4" width=
"300" height=
"150"
30 src=
"data:text/html,<div contenteditable id='contenteditable'></div>"></iframe><br/>
32 NOTE: the width for the next two iframes is chosen to be small enough to make
33 the Show Password button (for type=password) be outside the viewport so that
34 it doesn't affect the rendering compared to the type=text control.
35 But still large enough to comfortably fit the input values we test.
37 <iframe id=
"iframe5" style=
"width:10ch" height=
"50" src=
"data:text/html,<input id='input'>"></iframe>
38 <iframe id=
"iframe6" style=
"width:10ch" height=
"50" src=
"data:text/html,<input id='password' type='password'>"></iframe><br/>
39 <iframe id=
"iframe7" width=
"300" height=
"150"
40 src=
"data:text/html,<span contenteditable id='contenteditable'></span>"></iframe><br/>
41 <input id=
"input" type=
"text"/><br/>
42 <input id=
"password" type=
"password"/><br/>
44 <div id=
"content" style=
"display: none">
51 <script class=
"testbody" type=
"application/javascript">
54 function ok(aCondition, aMessage)
56 window.arguments[
0].SimpleTest.ok(aCondition, aMessage);
59 function is(aLeft, aRight, aMessage)
61 window.arguments[
0].SimpleTest.is(aLeft, aRight, aMessage);
64 function isnot(aLeft, aRight, aMessage)
66 window.arguments[
0].SimpleTest.isnot(aLeft, aRight, aMessage);
69 function isfuzzy(aLeft, aRight, aEpsilon, aMessage) {
70 window.arguments[
0].SimpleTest.isfuzzy(aLeft, aRight, aEpsilon, aMessage);
73 function todo(aCondition, aMessage)
75 window.arguments[
0].SimpleTest.todo(aCondition, aMessage);
78 function todo_is(aLeft, aRight, aMessage)
80 window.arguments[
0].SimpleTest.todo_is(aLeft, aRight, aMessage);
83 function todo_isnot(aLeft, aRight, aMessage)
85 window.arguments[
0].SimpleTest.todo_isnot(aLeft, aRight, aMessage);
88 function isSimilarTo(aLeft, aRight, aAllowedDifference, aMessage)
90 if (Math.abs(aLeft - aRight) <= aAllowedDifference) {
93 ok(false, aMessage +
", got=" + aLeft +
", expected=" + (aRight - aAllowedDifference) +
"~" + (aRight + aAllowedDifference));
97 function isGreaterThan(aLeft, aRight, aMessage)
99 ok(aLeft
> aRight, aMessage +
", got=" + aLeft +
", expected minimum value=" + aRight);
103 * synthesizeSimpleCompositionChange synthesizes a composition which has only
104 * one clause and put caret end of it.
106 * @param aComposition string or object. If string, it's treated as
107 * composition string whose attribute is
108 * COMPOSITION_ATTR_RAW_CLAUSE.
109 * If object, it must have .string whose type is
"string".
110 * Additionally, .attr can be specified if you'd like to
111 * use the other attribute instead of
112 * COMPOSITION_ATTR_RAW_CLAUSE.
114 function synthesizeSimpleCompositionChange(aComposition, aWindow, aCallback) {
115 const comp = (() =
> {
116 if (typeof aComposition ==
"string") {
117 return { string: aComposition, attr: COMPOSITION_ATTR_RAW_CLAUSE };
120 string: aComposition.string,
121 attr: aComposition.attr === undefined
122 ? COMPOSITION_ATTR_RAW_CLAUSE
126 synthesizeCompositionChange(
131 { length: comp.string.length, attr: comp.attr },
134 caret: { start: comp.string.length, length:
0 },
142 var div = document.getElementById(
"div");
143 var textarea = document.getElementById(
"textarea");
144 var panel = document.getElementById(
"panel");
145 var textbox = document.getElementById(
"textbox");
146 var iframe = document.getElementById(
"iframe");
147 var iframe2 = document.getElementById(
"iframe2");
148 var iframe3 = document.getElementById(
"iframe3");
150 var windowOfContenteditable;
151 var contenteditableBySpan;
152 var windowOfContenteditableBySpan;
153 var input = document.getElementById(
"input");
154 var password = document.getElementById(
"password");
157 const nsITextInputProcessorCallback = Ci.nsITextInputProcessorCallback;
158 const nsIInterfaceRequestor = Ci.nsIInterfaceRequestor;
159 const nsIWebNavigation = Ci.nsIWebNavigation;
160 const nsIDocShell = Ci.nsIDocShell;
161 const { AppConstants } = ChromeUtils.importESModule(
162 "resource://gre/modules/AppConstants.sys.mjs"
165 function waitForTick() {
166 return new Promise(resolve =
> { SimpleTest.executeSoon(resolve); });
169 async function waitForEventLoops(aTimes)
171 for (let i =
1; i < aTimes; i++) {
174 await new Promise(resolve =
> { setTimeout(resolve,
20); });
177 function getEditor(aNode)
182 function getHTMLEditorIMESupport(aWindow)
184 return aWindow.docShell.editor;
187 const kIsWin = (navigator.platform.indexOf(
"Win") ==
0);
188 const kIsMac = (navigator.platform.indexOf(
"Mac") ==
0);
190 const kLFLen = (kIsWin && !AppConstants.EARLY_BETA_OR_EARLIER) ?
2 :
1;
191 const kLF = (kIsWin && !AppConstants.EARLY_BETA_OR_EARLIER) ?
"\r\n" :
"\n";
193 function checkQueryContentResult(aResult, aMessage)
195 ok(aResult, aMessage +
": the result is null");
199 ok(aResult.succeeded, aMessage +
": the query content failed");
200 return aResult.succeeded;
203 function checkContent(aExpectedText, aMessage, aID)
208 let textContent = synthesizeQueryTextContent(
0,
100);
209 if (!checkQueryContentResult(textContent, aMessage +
210 ": synthesizeQueryTextContent " + aID)) {
213 is(textContent.text, aExpectedText,
214 aMessage +
": composition string is wrong " + aID);
215 return textContent.text == aExpectedText;
218 function checkContentRelativeToSelection(aRelativeOffset, aLength, aExpectedOffset, aExpectedText, aMessage, aID)
223 aMessage +=
" (aRelativeOffset=" + aRelativeOffset +
"): "
224 let textContent = synthesizeQueryTextContent(aRelativeOffset, aLength, true);
225 if (!checkQueryContentResult(textContent, aMessage +
226 "synthesizeQueryTextContent " + aID)) {
229 is(textContent.offset, aExpectedOffset,
230 aMessage +
"offset is wrong " + aID);
231 is(textContent.text, aExpectedText,
232 aMessage +
"text is wrong " + aID);
233 return textContent.offset == aExpectedOffset &&
234 textContent.text == aExpectedText;
237 function checkSelection(aExpectedOffset, aExpectedText, aMessage, aID)
242 let selectedText = synthesizeQuerySelectedText();
243 if (!checkQueryContentResult(selectedText, aMessage +
244 ": synthesizeQuerySelectedText " + aID)) {
247 if (aExpectedOffset === null) {
249 selectedText.notFound,
251 `${aMessage}: selection should not be found ${aID}`
253 return selectedText.notFound;
257 selectedText.notFound,
259 `${aMessage}: selection should be found ${aID}`
261 if (selectedText.notFound) {
267 `${aMessage}: selection offset should be ${aExpectedOffset} ${aID}`
272 `${aMessage}: selected text should be
"${aExpectedText}" ${aID}`
274 return selectedText.offset == aExpectedOffset &&
275 selectedText.text == aExpectedText;
278 function checkIMESelection(
290 aMessage +=
" (" + aSelectionType +
")";
296 let selectionType =
0;
297 switch (aSelectionType) {
299 selectionType = QUERY_CONTENT_FLAG_SELECTION_IME_RAWINPUT;
301 case
"SelectedRawClause":
302 selectionType = QUERY_CONTENT_FLAG_SELECTION_IME_SELECTEDRAWTEXT;
304 case
"ConvertedClause":
305 selectionType = QUERY_CONTENT_FLAG_SELECTION_IME_CONVERTEDTEXT;
307 case
"SelectedClause":
308 selectionType = QUERY_CONTENT_FLAG_SELECTION_IME_SELECTEDCONVERTEDTEXT;
311 ok(false, aMessage +
": invalid selection type, " + aSelectionType);
313 isnot(selectionType,
0, aMessage +
": wrong value");
314 let selectedText = synthesizeQuerySelectedText(selectionType);
315 if (!checkQueryContentResult(selectedText, aMessage +
316 ": synthesizeQuerySelectedText " + aID)) {
320 selectedText.notFound,
322 `${aMessage}: selection should ${
323 aExpectedFound ?
"" :
"not"
325 if (selectedText.notFound) {
326 return selectedText.notFound == !aExpectedFound;
332 `${aMessage}: selection offset is wrong ${aID}`
337 `${aMessage}: selected text is wrong ${aID}`
339 return selectedText.offset == aExpectedOffset &&
340 selectedText.text == aExpectedText;
343 function checkRect(aRect, aExpectedRect, aMessage)
345 is(aRect.left, aExpectedRect.left, aMessage +
": left is wrong");
346 is(aRect.top, aExpectedRect.top, aMessage +
" top is wrong");
347 is(aRect.width, aExpectedRect.width, aMessage +
": width is wrong");
348 is(aRect.height, aExpectedRect.height, aMessage +
": height is wrong");
349 return aRect.left == aExpectedRect.left &&
350 aRect.top == aExpectedRect.top &&
351 aRect.width == aExpectedRect.width &&
352 aRect.height == aExpectedRect.height;
355 function checkRectFuzzy(aRect, aExpectedRect, aEpsilon, aMessage) {
356 isfuzzy(aRect.left, aExpectedRect.left, aEpsilon.left, aMessage +
": left is wrong");
357 isfuzzy(aRect.top, aExpectedRect.top, aEpsilon.top, aMessage +
" top is wrong");
358 isfuzzy(aRect.width, aExpectedRect.width, aEpsilon.width, aMessage +
": width is wrong");
359 isfuzzy(aRect.height, aExpectedRect.height, aEpsilon.height, aMessage +
": height is wrong");
360 return (aRect.left
>= aExpectedRect.left - aEpsilon.left &&
361 aRect.left <= aExpectedRect.left + aEpsilon.left) &&
362 (aRect.top
>= aExpectedRect.top - aEpsilon.top &&
363 aRect.top <= aExpectedRect.top + aEpsilon.top) &&
364 (aRect.width
>= aExpectedRect.width - aEpsilon.width &&
365 aRect.width <= aExpectedRect.width + aEpsilon.width) &&
366 (aRect.height
>= aExpectedRect.height - aEpsilon.height &&
367 aRect.height <= aExpectedRect.height + aEpsilon.height);
370 function getRectArray(aQueryTextRectArrayResult) {
372 for (let i =
0; ; i++) {
373 let rect = { left: {}, top: {}, width: {}, height: {} };
375 aQueryTextRectArrayResult.getCharacterRect(i, rect.left, rect.top, rect.width, rect.height);
380 left: rect.left.value,
382 width: rect.width.value,
383 height: rect.height.value,
389 function checkRectArray(aQueryTextRectArrayResult, aExpectedTextRectArray, aMessage)
391 for (let i =
1; i < aExpectedTextRectArray.length; ++i) {
392 let rect = { left: {}, top: {}, width: {}, height: {} };
394 aQueryTextRectArrayResult.getCharacterRect(i, rect.left, rect.top, rect.width, rect.height);
396 ok(false, aMessage +
": failed to retrieve " + i +
"th rect (" + e +
")");
399 function toRect(aRect)
401 return { left: aRect.left.value, top: aRect.top.value, width: aRect.width.value, height: aRect.height.value };
403 if (!checkRect(toRect(rect), aExpectedTextRectArray[i], aMessage +
" " + i +
"th rect")) {
410 function checkRectContainsRect(aRect, aContainer, aMessage)
412 let container = { left: Math.ceil(aContainer.left),
413 top: Math.ceil(aContainer.top),
414 width: Math.floor(aContainer.width),
415 height: Math.floor(aContainer.height) };
417 let ret = container.left <= aRect.left &&
418 container.top <= aRect.top &&
419 container.left + container.width
>= aRect.left + aRect.width &&
420 container.top + container.height
>= aRect.top + aRect.height;
421 ret = ret && aMessage;
422 ok(ret, aMessage +
" container={ left=" + container.left +
", top=" +
423 container.top +
", width=" + container.width +
", height=" +
424 container.height +
" } rect={ left=" + aRect.left +
", top=" + aRect.top +
425 ", width=" + aRect.width +
", height=" + aRect.height +
" }");
429 // eslint-disable-next-line complexity
430 function runUndoRedoTest()
435 // input raw characters
436 synthesizeCompositionChange(
438 {
"string":
"\u306D",
441 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
444 "caret": {
"start":
1,
"length":
0 },
448 synthesizeCompositionChange(
450 {
"string":
"\u306D\u3053",
453 {
"length":
2,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
456 "caret": {
"start":
2,
"length":
0 },
461 synthesizeCompositionChange(
463 {
"string":
"\u732B",
467 "attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
470 "caret": {
"start":
1,
"length":
0 },
475 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"KEY_Enter" } });
477 // input raw characters
478 synthesizeCompositionChange(
480 {
"string":
"\u307E",
483 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
486 "caret": {
"start":
1,
"length":
0 },
490 // cancel the composition
491 synthesizeComposition({ type:
"compositioncommit", data:
"", key: { key:
"KEY_Escape" } });
493 // input raw characters
494 synthesizeCompositionChange(
496 {
"string":
"\u3080",
499 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
502 "caret": {
"start":
1,
"length":
0 },
506 synthesizeCompositionChange(
508 {
"string":
"\u3080\u3059",
511 {
"length":
2,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
514 "caret": {
"start":
2,
"length":
0 },
518 synthesizeCompositionChange(
520 {
"string":
"\u3080\u3059\u3081",
523 {
"length":
3,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
526 "caret": {
"start":
3,
"length":
0 },
531 synthesizeCompositionChange(
533 {
"string":
"\u5A18",
537 "attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
540 "caret": {
"start":
1,
"length":
0 },
545 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"KEY_Enter" } });
547 sendString(
" meant");
548 synthesizeKey(
"KEY_Backspace");
549 synthesizeKey(
"s \"cat-girl\
". She is a ");
551 // input raw characters
552 synthesizeCompositionChange(
554 {
"string":
"\u3088",
557 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
560 "caret": {
"start":
1,
"length":
0 },
564 synthesizeCompositionChange(
566 {
"string":
"\u3088\u3046",
569 {
"length":
2,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
572 "caret": {
"start":
2,
"length":
0 },
576 synthesizeCompositionChange(
578 {
"string":
"\u3088\u3046\u304b",
581 {
"length":
3,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
584 "caret": {
"start":
3,
"length":
0 },
588 synthesizeCompositionChange(
590 {
"string":
"\u3088\u3046\u304b\u3044",
593 {
"length":
4,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
596 "caret": {
"start":
4,
"length":
0 },
601 synthesizeCompositionChange(
603 {
"string":
"\u5996\u602a",
606 {
"length":
2,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
609 "caret": {
"start":
2,
"length":
0 },
614 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"Enter" } });
616 synthesizeKey(
"KEY_Backspace", {repeat:
12});
619 if (!checkContent(
"\u732B\u5A18 means \"cat-girl\
".",
620 "runUndoRedoTest",
"#" + ++i) ||
621 !checkSelection(
20,
"",
"runUndoRedoTest",
"#" + i)) {
625 synthesizeKey(
"Z", {accelKey: true});
627 if (!checkContent(
"\u732B\u5A18 means \"cat-girl\
". She is a \u5996\u602A",
628 "runUndoRedoTest",
"#" + ++i) ||
629 !checkSelection(
32,
"",
"runUndoRedoTest",
"#" + i)) {
633 synthesizeKey(
"Z", {accelKey: true});
635 if (!checkContent(
"\u732B\u5A18 means \"cat-girl\
". She is a ",
636 "runUndoRedoTest",
"#" + ++i) ||
637 !checkSelection(
30,
"",
"runUndoRedoTest",
"#" + i)) {
641 synthesizeKey(
"Z", {accelKey: true});
643 if (!checkContent(
"\u732B\u5A18 mean",
644 "runUndoRedoTest",
"#" + ++i) ||
645 !checkSelection(
7,
"",
"runUndoRedoTest",
"#" + i)) {
649 synthesizeKey(
"Z", {accelKey: true});
651 if (!checkContent(
"\u732B\u5A18 meant",
652 "runUndoRedoTest",
"#" + ++i) ||
653 !checkSelection(
8,
"",
"runUndoRedoTest",
"#" + i)) {
657 synthesizeKey(
"Z", {accelKey: true});
659 if (!checkContent(
"\u732B\u5A18",
660 "runUndoRedoTest",
"#" + ++i) ||
661 !checkSelection(
2,
"",
"runUndoRedoTest",
"#" + i)) {
665 synthesizeKey(
"Z", {accelKey: true});
667 if (!checkContent(
"\u732B",
668 "runUndoRedoTest",
"#" + ++i) ||
669 !checkSelection(
1,
"",
"runUndoRedoTest",
"#" + i)) {
673 synthesizeKey(
"Z", {accelKey: true});
675 // XXX this is unexpected behavior, see bug
258291
676 if (!checkContent(
"\u732B",
677 "runUndoRedoTest",
"#" + ++i) ||
678 !checkSelection(
1,
"",
"runUndoRedoTest",
"#" + i)) {
682 synthesizeKey(
"Z", {accelKey: true});
684 if (!checkContent(
"",
685 "runUndoRedoTest",
"#" + ++i) ||
686 !checkSelection(
0,
"",
"runUndoRedoTest",
"#" + i)) {
690 synthesizeKey(
"Z", {accelKey: true});
692 if (!checkContent(
"",
693 "runUndoRedoTest",
"#" + ++i) ||
694 !checkSelection(
0,
"",
"runUndoRedoTest",
"#" + i)) {
698 synthesizeKey(
"Z", {accelKey: true, shiftKey: true});
700 if (!checkContent(
"\u732B",
701 "runUndoRedoTest",
"#" + ++i) ||
702 !checkSelection(
1,
"",
"runUndoRedoTest",
"#" + i)) {
706 synthesizeKey(
"Z", {accelKey: true, shiftKey: true});
708 // XXX this is unexpected behavior, see bug
258291
709 if (!checkContent(
"\u732B",
710 "runUndoRedoTest",
"#" + ++i) ||
711 !checkSelection(
1,
"",
"runUndoRedoTest",
"#" + i)) {
715 synthesizeKey(
"Z", {accelKey: true, shiftKey: true});
717 if (!checkContent(
"\u732B\u5A18",
718 "runUndoRedoTest",
"#" + ++i) ||
719 !checkSelection(
2,
"",
"runUndoRedoTest",
"#" + i)) {
723 synthesizeKey(
"Z", {accelKey: true, shiftKey: true});
725 if (!checkContent(
"\u732B\u5A18 meant",
726 "runUndoRedoTest",
"#" + ++i) ||
727 !checkSelection(
8,
"",
"runUndoRedoTest",
"#" + i)) {
731 synthesizeKey(
"Z", {accelKey: true, shiftKey: true});
733 if (!checkContent(
"\u732B\u5A18 mean",
734 "runUndoRedoTest",
"#" + ++i) ||
735 !checkSelection(
7,
"",
"runUndoRedoTest",
"#" + i)) {
739 synthesizeKey(
"Z", {accelKey: true, shiftKey: true});
741 if (!checkContent(
"\u732B\u5A18 means \"cat-girl\
". She is a ",
742 "runUndoRedoTest",
"#" + ++i) ||
743 !checkSelection(
30,
"",
"runUndoRedoTest",
"#" + i)) {
747 synthesizeKey(
"Z", {accelKey: true, shiftKey: true});
749 if (!checkContent(
"\u732B\u5A18 means \"cat-girl\
". She is a \u5996\u602A",
750 "runUndoRedoTest",
"#" + ++i) ||
751 !checkSelection(
32,
"",
"runUndoRedoTest",
"#" + i)) {
755 synthesizeKey(
"Z", {accelKey: true, shiftKey: true});
757 if (!checkContent(
"\u732B\u5A18 means \"cat-girl\
".",
758 "runUndoRedoTest",
"#" + ++i) ||
759 !checkSelection(
20,
"",
"runUndoRedoTest",
"#" + i)) {
763 synthesizeKey(
"Z", {accelKey: true, shiftKey: true});
765 if (!checkContent(
"\u732B\u5A18 means \"cat-girl\
".",
766 "runUndoRedoTest",
"#" + ++i) ||
767 !checkSelection(
20,
"",
"runUndoRedoTest",
"#" + i)) {
768 // eslint-disable-next-line no-useless-return
773 function checkInputEvent(aEvent, aIsComposing, aInputType, aData, aTargetRanges, aDescription) {
774 if (aEvent.type !==
"input" && aEvent.type !==
"beforeinput") {
775 throw new Error(`${aDescription}:
"${aEvent.type}" is not InputEvent`);
777 ok(InputEvent.isInstance(aEvent), `
"${aEvent.type}" event should be dispatched with InputEvent interface: ${aDescription}`);
778 let cancelable = aEvent.type ===
"beforeinput" &&
779 aInputType !==
"insertCompositionText" &&
780 aInputType !==
"deleteCompositionText";
781 is(aEvent.cancelable, cancelable, `
"${aEvent.type}" event should ${cancelable ?
"be" :
"be never"} cancelable: ${aDescription}`);
782 is(aEvent.bubbles, true, `
"${aEvent.type}" event should always bubble: ${aDescription}`);
783 is(aEvent.isComposing, aIsComposing, `isComposing of
"${aEvent.type}" event should be ${aIsComposing}: ${aDescription}`);
784 is(aEvent.inputType, aInputType, `inputType of
"${aEvent.type}" event should be
"${aInputType}": ${aDescription}`);
785 is(aEvent.data, aData, `data of
"${aEvent.type}" event should be ${aData}: ${aDescription}`);
786 is(aEvent.dataTransfer, null, `dataTransfer of
"${aEvent.type}" event should be null: ${aDescription}`);
787 let targetRanges = aEvent.getTargetRanges();
788 if (aTargetRanges.length ===
0) {
789 is(targetRanges.length,
0,
790 `getTargetRange() of
"${aEvent.type}" event should return empty array: ${aDescription}`);
792 is(targetRanges.length, aTargetRanges.length,
793 `getTargetRange() of
"${aEvent.type}" event should return static range array: ${aDescription}`);
794 if (targetRanges.length == aTargetRanges.length) {
795 for (let i =
0; i < targetRanges.length; i++) {
796 is(targetRanges[i].startContainer, aTargetRanges[i].startContainer,
797 `startContainer of getTargetRanges()[${i}] of
"${aEvent.type}" event does not match: ${aDescription}`);
798 is(targetRanges[i].startOffset, aTargetRanges[i].startOffset,
799 `startOffset of getTargetRanges()[${i}] of
"${aEvent.type}" event does not match: ${aDescription}`);
800 is(targetRanges[i].endContainer, aTargetRanges[i].endContainer,
801 `endContainer of getTargetRanges()[${i}] of
"${aEvent.type}" event does not match: ${aDescription}`);
802 is(targetRanges[i].endOffset, aTargetRanges[i].endOffset,
803 `endOffset of getTargetRanges()[${i}] of
"${aEvent.type}" event does not match: ${aDescription}`);
809 function runCompositionCommitAsIsTest()
814 function clearResult()
819 function handler(aEvent)
824 textarea.addEventListener(
"compositionupdate", handler, true);
825 textarea.addEventListener(
"compositionend", handler, true);
826 textarea.addEventListener(
"beforeinput", handler, true);
827 textarea.addEventListener(
"input", handler, true);
828 textarea.addEventListener(
"text", handler, true);
830 // compositioncommitasis with composing string.
832 synthesizeCompositionChange(
834 {
"string":
"\u3042",
837 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
840 "caret": {
"start":
1,
"length":
0 },
843 is(textarea.value,
"\u3042",
"runCompositionCommitAsIsTest: textarea doesn't have composition string #1");
846 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"Enter" } });
849 "runCompositionCommitAsIsTest: 4 events should be fired after dispatching compositioncommitasis #1");
850 is(result[
0].type,
"text",
851 "runCompositionCommitAsIsTest: text should be fired after dispatching compositioncommitasis because it's dispatched when there is composing string #1");
852 is(result[
1].type,
"beforeinput",
853 "runCompositionCommitAsIsTest: beforeinput should be fired after dispatching compositioncommitasis because it's dispatched when there is composing string #1");
854 checkInputEvent(result[
1], true,
"insertCompositionText",
"\u3042", [],
855 "runCompositionCommitAsIsTest: after dispatching compositioncommitasis #1");
856 is(result[
2].type,
"compositionend",
857 "runCompositionCommitAsIsTest: compositionend should be fired after dispatching compositioncommitasis #1");
858 is(result[
3].type,
"input",
859 "runCompositionCommitAsIsTest: input should be fired after dispatching compositioncommitasis #1");
860 checkInputEvent(result[
3], false,
"insertCompositionText",
"\u3042", [],
861 "runCompositionCommitAsIsTest: after dispatching compositioncommitasis #1");
862 is(textarea.value,
"\u3042",
"runCompositionCommitAsIsTest: textarea doesn't have committed string #1");
864 // compositioncommitasis with committed string.
866 synthesizeCompositionChange(
868 {
"string":
"\u3042",
871 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
874 "caret": {
"start":
1,
"length":
0 },
877 is(textarea.value,
"\u3042",
"runCompositionCommitAsIsTest: textarea doesn't have composition string #2");
878 synthesizeCompositionChange(
880 {
"string":
"\u3042",
883 {
"length":
0,
"attr":
0 }
886 "caret": {
"start":
1,
"length":
0 },
887 "key": { key:
"KEY_Enter", type:
"keydown" },
889 is(textarea.value,
"\u3042",
"runCompositionCommitAsIsTest: textarea doesn't have committed string #2");
892 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"KEY_Enter", type:
"keyup" } });
895 "runCompositionCommitAsIsTest: 2 events should be fired after dispatching compositioncommitasis #2");
896 // XXX Do we need a
"beforeinput" event here? Not sure.
897 is(result[
0].type,
"compositionend",
898 "runCompositionCommitAsIsTest: compositionend should be fired after dispatching compositioncommitasis #2");
899 is(result[
1].type,
"input",
900 "runCompositionCommitAsIsTest: input should be fired after dispatching compositioncommitasis #2");
901 checkInputEvent(result[
1], false,
"insertCompositionText",
"\u3042", [],
902 "runCompositionCommitAsIsTest: after dispatching compositioncommitasis #2");
903 is(textarea.value,
"\u3042",
"runCompositionCommitAsIsTest: textarea doesn't have committed string #2");
905 // compositioncommitasis with committed string.
907 synthesizeCompositionChange(
909 {
"string":
"\u3042",
912 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
915 "caret": {
"start":
1,
"length":
0 },
918 is(textarea.value,
"\u3042",
"runCompositionCommitAsIsTest: textarea doesn't have composition string #3");
919 synthesizeCompositionChange(
924 {
"length":
0,
"attr":
0 }
927 "caret": {
"start":
0,
"length":
0 },
928 "key": { key:
"KEY_Escape", type:
"keydown" },
930 is(textarea.value,
"",
"runCompositionCommitAsIsTest: textarea has non-empty composition string #3");
933 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"KEY_Escape", type:
"keyup" } });
936 "runCompositionCommitAsIsTest: 2 events should be fired after dispatching compositioncommitasis #3");
937 // XXX Do we need a
"beforeinput" event here? Not sure.
938 is(result[
0].type,
"compositionend",
939 "runCompositionCommitAsIsTest: compositionend shouldn't be fired after dispatching compositioncommitasis #3");
940 is(result[
1].type,
"input",
941 "runCompositionCommitAsIsTest: input should be fired after dispatching compositioncommitasis #3");
942 checkInputEvent(result[
1], false,
"insertCompositionText",
"", [],
943 "runCompositionCommitAsIsTest: after dispatching compositioncommitasis #3");
944 is(textarea.value,
"",
"runCompositionCommitAsIsTest: textarea doesn't have committed string #3");
946 textarea.removeEventListener(
"compositionupdate", handler, true);
947 textarea.removeEventListener(
"compositionend", handler, true);
948 textarea.removeEventListener(
"beforeinput", handler, true);
949 textarea.removeEventListener(
"input", handler, true);
950 textarea.removeEventListener(
"text", handler, true);
953 function runCompositionCommitTest()
958 function clearResult()
963 function handler(aEvent)
968 textarea.addEventListener(
"compositionupdate", handler, true);
969 textarea.addEventListener(
"compositionend", handler, true);
970 textarea.addEventListener(
"beforeinput", handler, true);
971 textarea.addEventListener(
"input", handler, true);
972 textarea.addEventListener(
"text", handler, true);
974 // compositioncommit with different composing string.
976 synthesizeCompositionChange(
978 {
"string":
"\u3042",
981 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
984 "caret": {
"start":
1,
"length":
0 },
985 "key": { key:
"a", type:
"keydown" },
987 is(textarea.value,
"\u3042",
"runCompositionCommitTest: textarea doesn't have composition string #1");
990 synthesizeComposition({ type:
"compositioncommit", data:
"\u3043", key: { key:
"a", type:
"keyup" } });
993 "runCompositionCommitTest: 5 events should be fired after dispatching compositioncommit #1");
994 is(result[
0].type,
"compositionupdate",
995 "runCompositionCommitTest: compositionupdate should be fired after dispatching compositioncommit because it's dispatched when there is composing string #1");
996 is(result[
1].type,
"text",
997 "runCompositionCommitTest: text should be fired after dispatching compositioncommit #1");
998 is(result[
2].type,
"beforeinput",
999 "runCompositionCommitTest: beforeinput should be fired after dispatching compositioncommit because it's dispatched when there is composing string #1");
1000 checkInputEvent(result[
2], true,
"insertCompositionText",
"\u3043", [],
1001 "runCompositionCommitTest: after dispatching compositioncommit #1");
1002 is(result[
3].type,
"compositionend",
1003 "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #1");
1004 is(result[
4].type,
"input",
1005 "runCompositionCommitTest: input should be fired after dispatching compositioncommit #1");
1006 checkInputEvent(result[
4], false,
"insertCompositionText",
"\u3043", [],
1007 "runCompositionCommitTest: after dispatching compositioncommit #1");
1008 is(textarea.value,
"\u3043",
"runCompositionCommitTest: textarea doesn't have committed string #1");
1010 // compositioncommit with different committed string when there is already committed string
1011 textarea.value =
"";
1012 synthesizeCompositionChange(
1014 {
"string":
"\u3042",
1017 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1020 "caret": {
"start":
1,
"length":
0 },
1021 "key": { key:
"a" },
1023 is(textarea.value,
"\u3042",
"runCompositionCommitTest: textarea doesn't have composition string #2");
1024 synthesizeCompositionChange(
1026 {
"string":
"\u3042",
1029 {
"length":
0,
"attr":
0 }
1032 "caret": {
"start":
1,
"length":
0 },
1033 "key": { key:
"KEY_Enter", type:
"keydown" },
1035 is(textarea.value,
"\u3042",
"runCompositionCommitTest: textarea doesn't have committed string #2");
1038 synthesizeComposition({ type:
"compositioncommit", data:
"\u3043", key: { key:
"KEY_Enter", type:
"keyup" } });
1040 is(result.length,
5,
1041 "runCompositionCommitTest: 5 events should be fired after dispatching compositioncommit #2");
1042 is(result[
0].type,
"compositionupdate",
1043 "runCompositionCommitTest: compositionupdate should be fired after dispatching compositioncommit #2");
1044 is(result[
1].type,
"text",
1045 "runCompositionCommitTest: text should be fired after dispatching compositioncommit #2");
1046 is(result[
2].type,
"beforeinput",
1047 "runCompositionCommitTest: beforeinput should be fired after dispatching compositioncommit #2");
1048 checkInputEvent(result[
2], true,
"insertCompositionText",
"\u3043", [],
1049 "runCompositionCommitTest: after dispatching compositioncommit #2");
1050 is(result[
3].type,
"compositionend",
1051 "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #2");
1052 is(result[
4].type,
"input",
1053 "runCompositionCommitTest: input should be fired after dispatching compositioncommit #2");
1054 checkInputEvent(result[
4], false,
"insertCompositionText",
"\u3043", [],
1055 "runCompositionCommitTest: after dispatching compositioncommit #2");
1056 is(textarea.value,
"\u3043",
"runCompositionCommitTest: textarea doesn't have committed string #2");
1058 // compositioncommit with empty composition string.
1059 textarea.value =
"";
1060 synthesizeCompositionChange(
1062 {
"string":
"\u3042",
1065 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1068 "caret": {
"start":
1,
"length":
0 },
1069 "key": { key:
"a" },
1071 is(textarea.value,
"\u3042",
"runCompositionCommitTest: textarea doesn't have composition string #3");
1072 synthesizeCompositionChange(
1077 {
"length":
0,
"attr":
0 }
1080 "caret": {
"start":
0,
"length":
0 },
1081 "key": { key:
"KEY_Enter", type:
"keydown" },
1083 is(textarea.value,
"",
"runCompositionCommitTest: textarea has non-empty composition string #3");
1086 synthesizeComposition({ type:
"compositioncommit", data:
"\u3043", key: { key:
"KEY_Enter", type:
"keyup" } });
1088 is(result.length,
5,
1089 "runCompositionCommitTest: 5 events should be fired after dispatching compositioncommit #3");
1090 is(result[
0].type,
"compositionupdate",
1091 "runCompositionCommitTest: compositionupdate should be fired after dispatching compositioncommit #3");
1092 is(result[
1].type,
"text",
1093 "runCompositionCommitTest: text should be fired after dispatching compositioncommit #3");
1094 is(result[
2].type,
"beforeinput",
1095 "runCompositionCommitTest: beforeinput should be fired after dispatching compositioncommit #3");
1096 checkInputEvent(result[
2], true,
"insertCompositionText",
"\u3043", [],
1097 "runCompositionCommitTest: after dispatching compositioncommit #3");
1098 is(result[
3].type,
"compositionend",
1099 "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #3");
1100 is(result[
4].type,
"input",
1101 "runCompositionCommitTest: input should be fired after dispatching compositioncommit #3");
1102 checkInputEvent(result[
4], false,
"insertCompositionText",
"\u3043", [],
1103 "runCompositionCommitTest: after dispatching compositioncommit #3");
1104 is(textarea.value,
"\u3043",
"runCompositionCommitTest: textarea doesn't have committed string #3");
1106 // inserting empty string with simple composition.
1107 textarea.value =
"abc";
1108 textarea.setSelectionRange(
3,
3);
1109 synthesizeComposition({ type:
"compositionstart" });
1112 synthesizeComposition({ type:
"compositioncommit", data:
"" });
1114 is(result.length,
4,
1115 "runCompositionCommitTest: 4 events should be fired when inserting empty string with composition");
1116 is(result[
0].type,
"text",
1117 "runCompositionCommitTest: text should be fired when inserting empty string with composition");
1118 is(result[
1].type,
"beforeinput",
1119 "runCompositionCommitTest: beforeinput should be fired when inserting empty string with composition");
1120 checkInputEvent(result[
1], true,
"insertCompositionText",
"", [],
1121 "runCompositionCommitTest: when inserting empty string with composition");
1122 is(result[
2].type,
"compositionend",
1123 "runCompositionCommitTest: compositionend should be fired when inserting empty string with composition");
1124 is(result[
3].type,
"input",
1125 "runCompositionCommitTest: input should be fired when inserting empty string with composition");
1126 checkInputEvent(result[
3], false,
"insertCompositionText",
"", [],
1127 "runCompositionCommitTest: when inserting empty string with composition");
1128 is(textarea.value,
"abc",
1129 "runCompositionCommitTest: textarea should keep original value when inserting empty string with composition");
1131 // replacing selection with empty string with simple composition.
1132 textarea.value =
"abc";
1133 textarea.setSelectionRange(
0,
3);
1134 synthesizeComposition({ type:
"compositionstart" });
1137 synthesizeComposition({ type:
"compositioncommit", data:
"" });
1139 is(result.length,
4,
1140 "runCompositionCommitTest: 4 events should be fired when replacing with empty string with composition");
1141 is(result[
0].type,
"text",
1142 "runCompositionCommitTest: text should be fired when replacing with empty string with composition");
1143 is(result[
1].type,
"beforeinput",
1144 "runCompositionCommitTest: beforeinput should be fired when replacing with empty string with composition");
1145 checkInputEvent(result[
1], true,
"insertCompositionText",
"", [],
1146 "runCompositionCommitTest: when replacing with empty string with composition");
1147 is(result[
2].type,
"compositionend",
1148 "runCompositionCommitTest: compositionend should be fired when replacing with empty string with composition");
1149 is(result[
3].type,
"input",
1150 "runCompositionCommitTest: input should be fired when replacing with empty string with composition");
1151 checkInputEvent(result[
3], false,
"insertCompositionText",
"", [],
1152 "runCompositionCommitTest: when replacing with empty string with composition");
1153 is(textarea.value,
"",
1154 "runCompositionCommitTest: textarea should become empty when replacing selection with empty string with composition");
1156 // replacing selection with same string with simple composition.
1157 textarea.value =
"abc";
1158 textarea.setSelectionRange(
0,
3);
1159 synthesizeComposition({ type:
"compositionstart" });
1162 synthesizeComposition({ type:
"compositioncommit", data:
"abc" });
1164 is(result.length,
5,
1165 "runCompositionCommitTest: 5 events should be fired when replacing selection with same string with composition");
1166 is(result[
0].type,
"compositionupdate",
1167 "runCompositionCommitTest: compositionupdate should be fired when replacing selection with same string with composition");
1168 is(result[
1].type,
"text",
1169 "runCompositionCommitTest: text should be fired when replacing selection with same string with composition");
1170 is(result[
2].type,
"beforeinput",
1171 "runCompositionCommitTest: beforeinput should be fired when replacing selection with same string with composition");
1172 checkInputEvent(result[
2], true,
"insertCompositionText",
"abc", [],
1173 "runCompositionCommitTest: when replacing selection with same string with composition");
1174 is(result[
3].type,
"compositionend",
1175 "runCompositionCommitTest: compositionend should be fired when replacing selection with same string with composition");
1176 is(result[
4].type,
"input",
1177 "runCompositionCommitTest: input should be fired when replacing selection with same string with composition");
1178 checkInputEvent(result[
4], false,
"insertCompositionText",
"abc", [],
1179 "runCompositionCommitTest: when replacing selection with same string with composition");
1180 is(textarea.value,
"abc",
1181 "runCompositionCommitTest: textarea should keep same value when replacing selection with same string with composition");
1183 // compositioncommit with non-empty composition string.
1184 textarea.value =
"";
1185 synthesizeCompositionChange(
1187 {
"string":
"\u3042",
1190 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1193 "caret": {
"start":
1,
"length":
0 },
1194 "key": { key:
"a" },
1196 is(textarea.value,
"\u3042",
"runCompositionCommitTest: textarea doesn't have composition string #4");
1199 synthesizeComposition({ type:
"compositioncommit", data:
"", key: { key:
"KEY_Enter" } });
1201 is(result.length,
5,
1202 "runCompositionCommitTest: 5 events should be fired after dispatching compositioncommit #4");
1203 is(result[
0].type,
"compositionupdate",
1204 "runCompositionCommitTest: compositionupdate should be fired after dispatching compositioncommit #4");
1205 is(result[
1].type,
"text",
1206 "runCompositionCommitTest: text should be fired after dispatching compositioncommit #4");
1207 is(result[
2].type,
"beforeinput",
1208 "runCompositionCommitTest: beforeinput should be fired after dispatching compositioncommit #4");
1209 checkInputEvent(result[
2], true,
"insertCompositionText",
"", [],
1210 "runCompositionCommitTest: after dispatching compositioncommit #4");
1211 is(result[
3].type,
"compositionend",
1212 "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #4");
1213 is(result[
4].type,
"input",
1214 "runCompositionCommitTest: input should be fired after dispatching compositioncommit #4");
1215 checkInputEvent(result[
4], false,
"insertCompositionText",
"", [],
1216 "runCompositionCommitTest: after dispatching compositioncommit #4");
1217 is(textarea.value,
"",
"runCompositionCommitTest: textarea should be empty #4");
1219 // compositioncommit immediately without compositionstart
1220 textarea.value =
"";
1223 synthesizeComposition({ type:
"compositioncommit", data:
"\u3042", key: { key:
"a" } });
1225 is(result.length,
5,
1226 "runCompositionCommitTest: 5 events should be fired after dispatching compositioncommit #5");
1227 is(result[
0].type,
"compositionupdate",
1228 "runCompositionCommitTest: compositionupdate should be fired after dispatching compositioncommit #5");
1229 is(result[
1].type,
"text",
1230 "runCompositionCommitTest: text should be fired after dispatching compositioncommit #5");
1231 is(result[
2].type,
"beforeinput",
1232 "runCompositionCommitTest: beforeinput should be fired after dispatching compositioncommit #5");
1233 checkInputEvent(result[
2], true,
"insertCompositionText",
"\u3042", [],
1234 "runCompositionCommitTest: after dispatching compositioncommit #5");
1235 is(result[
3].type,
"compositionend",
1236 "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #5");
1237 is(result[
4].type,
"input",
1238 "runCompositionCommitTest: input should be fired after dispatching compositioncommit #5");
1239 checkInputEvent(result[
4], false,
"insertCompositionText",
"\u3042", [],
1240 "runCompositionCommitTest: after dispatching compositioncommit #5");
1241 is(textarea.value,
"\u3042",
"runCompositionCommitTest: textarea should be empty #5");
1243 // compositioncommit with same composition string.
1244 textarea.value =
"";
1245 synthesizeCompositionChange(
1247 {
"string":
"\u3042",
1250 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1253 "caret": {
"start":
1,
"length":
0 },
1254 "key": { key:
"a" },
1256 is(textarea.value,
"\u3042",
"runCompositionCommitTest: textarea doesn't have composition string #5");
1259 synthesizeComposition({ type:
"compositioncommit", data:
"\u3042", key: { key:
"KEY_Enter" } });
1261 is(result.length,
4,
1262 "runCompositionCommitTest: 4 events should be fired after dispatching compositioncommit #6");
1263 is(result[
0].type,
"text",
1264 "runCompositionCommitTest: text should be fired after dispatching compositioncommit #6");
1265 is(result[
1].type,
"beforeinput",
1266 "runCompositionCommitTest: beforeinput should be fired after dispatching compositioncommit #6");
1267 checkInputEvent(result[
1], true,
"insertCompositionText",
"\u3042", [],
1268 "runCompositionCommitTest: after dispatching compositioncommit #6");
1269 is(result[
2].type,
"compositionend",
1270 "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #6");
1271 is(result[
3].type,
"input",
1272 "runCompositionCommitTest: input should be fired after dispatching compositioncommit #6");
1273 checkInputEvent(result[
3], false,
"insertCompositionText",
"\u3042", [],
1274 "runCompositionCommitTest: after dispatching compositioncommit #6");
1275 is(textarea.value,
"\u3042",
"runCompositionCommitTest: textarea should have committed string #6");
1277 // compositioncommit with same composition string when there is committed string
1278 textarea.value =
"";
1279 synthesizeCompositionChange(
1281 {
"string":
"\u3042",
1284 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1287 "caret": {
"start":
1,
"length":
0 },
1288 "key": { key:
"a" },
1290 is(textarea.value,
"\u3042",
"runCompositionCommitTest: textarea doesn't have composition string #6");
1292 synthesizeCompositionChange(
1294 {
"string":
"\u3042",
1297 {
"length":
0,
"attr":
0 }
1300 "caret": {
"start":
1,
"length":
0 },
1301 "key": { key:
"KEY_Enter", type:
"keydown" },
1303 is(textarea.value,
"\u3042",
"runCompositionCommitTest: textarea doesn't have composition string #6");
1306 synthesizeComposition({ type:
"compositioncommit", data:
"\u3042", key: { key:
"KEY_Enter", type:
"keyup" } });
1308 is(result.length,
2,
1309 "runCompositionCommitTest: 2 events should be fired after dispatching compositioncommit #7");
1310 // XXX Do we need a
"beforeinput" event here? Not sure.
1311 is(result[
0].type,
"compositionend",
1312 "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #7");
1313 is(result[
1].type,
"input",
1314 "runCompositionCommitTest: input should be fired after dispatching compositioncommit #7");
1315 checkInputEvent(result[
1], false,
"insertCompositionText",
"\u3042", [],
1316 "runCompositionCommitTest: after dispatching compositioncommit #7");
1317 is(textarea.value,
"\u3042",
"runCompositionCommitTest: textarea should have committed string #6");
1319 textarea.removeEventListener(
"compositionupdate", handler, true);
1320 textarea.removeEventListener(
"compositionend", handler, true);
1321 textarea.removeEventListener(
"beforeinput", handler, true);
1322 textarea.removeEventListener(
"input", handler, true);
1323 textarea.removeEventListener(
"text", handler, true);
1326 // eslint-disable-next-line complexity
1327 async function runCompositionTest()
1329 textarea.value =
"";
1331 let caretRects = [];
1333 let caretRect = synthesizeQueryCaretRect(
0);
1334 if (!checkQueryContentResult(caretRect,
1335 "runCompositionTest: synthesizeQueryCaretRect #0")) {
1338 caretRects[
0] = caretRect;
1340 // input first character
1341 synthesizeCompositionChange(
1343 {
"string":
"\u3089",
1346 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1349 "caret": {
"start":
1,
"length":
0 },
1350 "key": { key:
"o" },
1353 if (!checkContent(
"\u3089",
"runCompositionTest",
"#1-1") ||
1354 !checkSelection(
1,
"",
"runCompositionTest",
"#1-1")) {
1358 caretRect = synthesizeQueryCaretRect(
1);
1359 if (!checkQueryContentResult(caretRect,
1360 "runCompositionTest: synthesizeQueryCaretRect #1-1")) {
1363 caretRects[
1] = caretRect;
1365 // input second character
1366 synthesizeCompositionChange(
1368 {
"string":
"\u3089\u30FC",
1371 {
"length":
2,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1374 "caret": {
"start":
2,
"length":
0 },
1375 "key": { key:
"\\", code:
"IntlYen", keyCode: KeyboardEvent.DOM_VK_BACKSLASH },
1378 if (!checkContent(
"\u3089\u30FC",
"runCompositionTest",
"#1-2") ||
1379 !checkSelection(
2,
"",
"runCompositionTest",
"#1-2")) {
1383 caretRect = synthesizeQueryCaretRect(
2);
1384 if (!checkQueryContentResult(caretRect,
1385 "runCompositionTest: synthesizeQueryCaretRect #1-2")) {
1388 caretRects[
2] = caretRect;
1390 isnot(caretRects[
2].left, caretRects[
1].left,
1391 "runCompositionTest: caret isn't moved (#1-2)");
1392 is(caretRects[
2].top, caretRects[
1].top,
1393 "runCompositionTest: caret is moved to another line (#1-2)");
1394 is(caretRects[
2].width, caretRects[
1].width,
1395 "runCompositionTest: caret width is wrong (#1-2)");
1396 is(caretRects[
2].height, caretRects[
1].height,
1397 "runCompositionTest: caret width is wrong (#1-2)");
1399 // input third character
1400 synthesizeCompositionChange(
1402 {
"string":
"\u3089\u30FC\u3081",
1405 {
"length":
3,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1408 "caret": {
"start":
3,
"length":
0 },
1409 "key": { key:
"/" },
1412 if (!checkContent(
"\u3089\u30FC\u3081",
"runCompositionTest",
"#1-3") ||
1413 !checkSelection(
3,
"",
"runCompositionTest",
"#1-3")) {
1417 caretRect = synthesizeQueryCaretRect(
3);
1418 if (!checkQueryContentResult(caretRect,
1419 "runCompositionTest: synthesizeQueryCaretRect #1-3")) {
1422 caretRects[
3] = caretRect;
1424 isnot(caretRects[
3].left, caretRects[
2].left,
1425 "runCompositionTest: caret isn't moved (#1-3)");
1426 is(caretRects[
3].top, caretRects[
2].top,
1427 "runCompositionTest: caret is moved to another line (#1-3)");
1428 is(caretRects[
3].width, caretRects[
2].width,
1429 "runCompositionTest: caret width is wrong (#1-3)");
1430 is(caretRects[
3].height, caretRects[
2].height,
1431 "runCompositionTest: caret height is wrong (#1-3)");
1433 // moves the caret left
1434 synthesizeCompositionChange(
1436 {
"string":
"\u3089\u30FC\u3081",
1439 {
"length":
3,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1442 "caret": {
"start":
2,
"length":
0 },
1443 "key": { key:
"KEY_ArrowLeft" },
1446 if (!checkContent(
"\u3089\u30FC\u3081",
"runCompositionTest",
"#1-3-1") ||
1447 !checkSelection(
2,
"",
"runCompositionTest",
"#1-3-1")) {
1452 caretRect = synthesizeQueryCaretRect(
2);
1453 if (!checkQueryContentResult(caretRect,
1454 "runCompositionTest: synthesizeQueryCaretRect #1-3-1")) {
1458 is(caretRect.left, caretRects[
2].left,
1459 "runCompositionTest: caret rects are different (#1-3-1, left)");
1460 is(caretRect.top, caretRects[
2].top,
1461 "runCompositionTest: caret rects are different (#1-3-1, top)");
1462 // by bug
335359, the caret width depends on the right side's character.
1463 is(caretRect.width, caretRects[
2].width + Math.round(window.devicePixelRatio),
1464 "runCompositionTest: caret rects are different (#1-3-1, width)");
1465 is(caretRect.height, caretRects[
2].height,
1466 "runCompositionTest: caret rects are different (#1-3-1, height)");
1468 // moves the caret left
1469 synthesizeCompositionChange(
1471 {
"string":
"\u3089\u30FC\u3081",
1474 {
"length":
3,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1477 "caret": {
"start":
1,
"length":
0 },
1478 "key": { key:
"KEY_ArrowLeft" },
1481 if (!checkContent(
"\u3089\u30FC\u3081",
"runCompositionTest",
"#1-3-2") ||
1482 !checkSelection(
1,
"",
"runCompositionTest",
"#1-3-2")) {
1487 caretRect = synthesizeQueryCaretRect(
1);
1488 if (!checkQueryContentResult(caretRect,
1489 "runCompositionTest: synthesizeQueryCaretRect #1-3-2")) {
1493 is(caretRect.left, caretRects[
1].left,
1494 "runCompositionTest: caret rects are different (#1-3-2, left)");
1495 is(caretRect.top, caretRects[
1].top,
1496 "runCompositionTest: caret rects are different (#1-3-2, top)");
1497 // by bug
335359, the caret width depends on the right side's character.
1498 is(caretRect.width, caretRects[
1].width + Math.round(window.devicePixelRatio),
1499 "runCompositionTest: caret rects are different (#1-3-2, width)");
1500 is(caretRect.height, caretRects[
1].height,
1501 "runCompositionTest: caret rects are different (#1-3-2, height)");
1503 synthesizeCompositionChange(
1505 {
"string":
"\u3089\u30FC\u3081\u3093",
1508 {
"length":
4,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1511 "caret": {
"start":
4,
"length":
0 },
1512 "key": { key:
"y" },
1515 if (!checkContent(
"\u3089\u30FC\u3081\u3093",
"runCompositionTest",
"#1-4") ||
1516 !checkSelection(
4,
"",
"runCompositionTest",
"#1-4")) {
1522 synthesizeCompositionChange(
1524 {
"string":
"\u3089\u30FC\u3081",
1527 {
"length":
3,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1530 "caret": {
"start":
3,
"length":
0 },
1531 "key": { key:
"KEY_Backspace" },
1534 if (!checkContent(
"\u3089\u30FC\u3081",
"runCompositionTest",
"#1-5") ||
1535 !checkSelection(
3,
"",
"runCompositionTest",
"#1-5")) {
1540 synthesizeCompositionChange(
1542 {
"string":
"\u3089\u30FC\u3081\u3093",
1545 {
"length":
4,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1548 "caret": {
"start":
4,
"length":
0 },
1549 "key": { key:
"y" },
1552 if (!checkContent(
"\u3089\u30FC\u3081\u3093",
"runCompositionTest",
"#1-6") ||
1553 !checkSelection(
4,
"",
"runCompositionTest",
"#1-6")) {
1557 synthesizeCompositionChange(
1559 {
"string":
"\u3089\u30FC\u3081\u3093\u3055",
1562 {
"length":
5,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1565 "caret": {
"start":
5,
"length":
0 },
1566 "key": { key:
"x" },
1569 if (!checkContent(
"\u3089\u30FC\u3081\u3093\u3055",
"runCompositionTest",
"#1-7") ||
1570 !checkSelection(
5,
"",
"runCompositionTest",
"#1-7")) {
1574 synthesizeCompositionChange(
1576 {
"string":
"\u3089\u30FC\u3081\u3093\u3055\u3044",
1579 {
"length":
6,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1582 "caret": {
"start":
6,
"length":
0 },
1583 "key": { key:
"e" },
1586 if (!checkContent(
"\u3089\u30FC\u3081\u3093\u3055\u3044",
"runCompositionTest",
"#1-8") ||
1587 !checkSelection(
6,
"",
"runCompositionTest",
"#1-8")) {
1591 synthesizeCompositionChange(
1593 {
"string":
"\u3089\u30FC\u3081\u3093\u3055\u3044\u3053",
1596 {
"length":
7,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1599 "caret": {
"start":
7,
"length":
0 },
1600 "key": { key:
"b" },
1603 if (!checkContent(
"\u3089\u30FC\u3081\u3093\u3055\u3044\u3053",
"runCompositionTest",
"#1-8") ||
1604 !checkSelection(
7,
"",
"runCompositionTest",
"#1-8")) {
1608 synthesizeCompositionChange(
1610 {
"string":
"\u3089\u30FC\u3081\u3093\u3055\u3044\u3053\u3046",
1613 {
"length":
8,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1616 "caret": {
"start":
8,
"length":
0 },
1617 "key": { key:
"4" },
1620 if (!checkContent(
"\u3089\u30FC\u3081\u3093\u3055\u3044\u3053\u3046",
1621 "runCompositionTest",
"#1-9") ||
1622 !checkSelection(
8,
"",
"runCompositionTest",
"#1-9")) {
1627 synthesizeCompositionChange(
1629 {
"string":
"\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8",
1633 "attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
1635 "attr": COMPOSITION_ATTR_CONVERTED_CLAUSE }
1638 "caret": {
"start":
4,
"length":
0 },
1639 "key": { key:
" " },
1642 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8",
1643 "runCompositionTest",
"#1-10") ||
1644 !checkSelection(
4,
"",
"runCompositionTest",
"#1-10")) {
1648 // change the selected clause
1649 synthesizeCompositionChange(
1651 {
"string":
"\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8",
1655 "attr": COMPOSITION_ATTR_CONVERTED_CLAUSE },
1657 "attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
1660 "caret": {
"start":
6,
"length":
0 },
1661 "key": { key:
"KEY_ArrowLeft", shiftKey: true },
1664 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8",
1665 "runCompositionTest",
"#1-11") ||
1666 !checkSelection(
6,
"",
"runCompositionTest",
"#1-11")) {
1671 synthesizeCompositionChange(
1673 {
"string":
"\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046",
1677 "attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
1679 "attr": COMPOSITION_ATTR_CONVERTED_CLAUSE }
1682 "caret": {
"start":
5,
"length":
0 },
1683 "key": { key:
"KEY_ArrowRight" },
1686 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046",
1687 "runCompositionTest",
"#1-12") ||
1688 !checkSelection(
5,
"",
"runCompositionTest",
"#1-12")) {
1693 let textRect1 = synthesizeQueryTextRect(
0,
1);
1694 let textRect2 = synthesizeQueryTextRect(
1,
1);
1695 if (!checkQueryContentResult(textRect1,
1696 "runCompositionTest: synthesizeQueryTextRect #1-12-1") ||
1697 !checkQueryContentResult(textRect2,
1698 "runCompositionTest: synthesizeQueryTextRect #1-12-2")) {
1702 // commit the composition string
1703 synthesizeComposition({ type:
"compositioncommitasis" });
1705 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046",
1706 "runCompositionTest",
"#1-13") ||
1707 !checkSelection(
8,
"",
"runCompositionTest",
"#1-13")) {
1711 let textRect3 = synthesizeQueryTextRect(
0,
1);
1712 let textRect4 = synthesizeQueryTextRect(
1,
1);
1714 if (!checkQueryContentResult(textRect3,
1715 "runCompositionTest: synthesizeQueryTextRect #1-13-1") ||
1716 !checkQueryContentResult(textRect4,
1717 "runCompositionTest: synthesizeQueryTextRect #1-13-2")) {
1721 checkRect(textRect3, textRect1,
"runCompositionTest: textRect #1-13-1");
1722 checkRect(textRect4, textRect2,
"runCompositionTest: textRect #1-13-2");
1724 // restart composition and input characters
1725 synthesizeCompositionChange(
1727 {
"string":
"\u3057",
1730 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1733 "caret": {
"start":
1,
"length":
0 },
1734 "key": { key:
"d" },
1737 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046\u3057",
1738 "runCompositionTest",
"#2-1") ||
1739 !checkSelection(
8 +
1,
"",
"runCompositionTest",
"#2-1")) {
1743 let textRect3QueriedWithRelativeOffset = synthesizeQueryTextRect(-
8,
1, true);
1744 let textRect4QueriedWithRelativeOffset = synthesizeQueryTextRect(-
8 +
1,
1, true);
1745 checkRect(textRect3QueriedWithRelativeOffset, textRect3,
"runCompositionTest: textRect #2-1-2");
1746 checkRect(textRect4QueriedWithRelativeOffset, textRect4,
"runCompositionTest: textRect #2-1-3");
1748 synthesizeCompositionChange(
1750 {
"string":
"\u3058",
1753 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1756 "caret": {
"start":
1,
"length":
0 },
1757 "key": { key:
"r" },
1760 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046\u3058",
1761 "runCompositionTest",
"#2-2") ||
1762 !checkSelection(
8 +
1,
"",
"runCompositionTest",
"#2-2")) {
1766 synthesizeCompositionChange(
1768 {
"string":
"\u3058\u3087",
1771 {
"length":
2,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1774 "caret": {
"start":
2,
"length":
0 },
1775 "key": { key:
")", code:
"Digit9", keyCode: KeyboardEvent.DOM_VK_9, shiftKey: true },
1778 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046\u3058\u3087",
1779 "runCompositionTest",
"#2-3") ||
1780 !checkSelection(
8 +
2,
"",
"runCompositionTest",
"#2-3")) {
1784 synthesizeCompositionChange(
1786 {
"string":
"\u3058\u3087\u3046",
1789 {
"length":
3,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1792 "caret": {
"start":
3,
"length":
0 },
1793 "key": { key:
"4" },
1796 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046\u3058\u3087\u3046",
1797 "runCompositionTest",
"#2-4") ||
1798 !checkSelection(
8 +
3,
"",
"runCompositionTest",
"#2-4")) {
1802 // commit the composition string
1803 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"KEY_Enter" } });
1805 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046\u3058\u3087\u3046",
1806 "runCompositionTest",
"#2-4") ||
1807 !checkSelection(
8 +
3,
"",
"runCompositionTest",
"#2-4")) {
1812 const selectionSetTest = await synthesizeSelectionSet(
4,
7, false);
1813 ok(selectionSetTest,
"runCompositionTest: selectionSetTest failed");
1815 if (!checkSelection(
4,
"\u3055\u884C\u3053\u3046\u3058\u3087\u3046",
"runCompositionTest",
"#3-1")) {
1819 // start composition with selection
1820 synthesizeCompositionChange(
1822 {
"string":
"\u304A",
1825 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1828 "caret": {
"start":
1,
"length":
0 },
1829 "key": { key:
"6" },
1832 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u304A",
1833 "runCompositionTest",
"#3-2") ||
1834 !checkSelection(
4 +
1,
"",
"runCompositionTest",
"#3-2")) {
1838 // remove the composition string
1839 synthesizeCompositionChange(
1844 {
"length":
0,
"attr":
0 }
1847 "caret": {
"start":
0,
"length":
0 },
1848 "key": { key:
"KEY_Backspace" },
1851 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3",
1852 "runCompositionTest",
"#3-3") ||
1853 !checkSelection(
4,
"",
"runCompositionTest",
"#3-3")) {
1857 // re-input the composition string
1858 synthesizeCompositionChange(
1860 {
"string":
"\u3046",
1863 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
1866 "caret": {
"start":
1,
"length":
0 },
1867 "key": { key:
"4" },
1870 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u3046",
1871 "runCompositionTest",
"#3-4") ||
1872 !checkSelection(
4 +
1,
"",
"runCompositionTest",
"#3-4")) {
1876 // cancel the composition
1877 synthesizeComposition({ type:
"compositioncommit", data:
"", key: { key:
"KEY_Escape" } });
1879 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3",
1880 "runCompositionTest",
"#3-5") ||
1881 !checkSelection(
4,
"",
"runCompositionTest",
"#3-5")) {
1885 // bug
271815, some Chinese IMEs for Linux make empty composition string
1886 // and compty clause information when it lists up Chinese characters on
1887 // its candidate window.
1888 synthesizeCompositionChange(
1893 {
"length":
0,
"attr":
0 }
1896 "caret": {
"start":
0,
"length":
0 },
1897 "key": { key:
"a" },
1900 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3",
1901 "runCompositionTest",
"#4-1") ||
1902 !checkSelection(
4,
"",
"runCompositionTest",
"#4-1")) {
1906 synthesizeCompositionChange(
1911 {
"length":
0,
"attr":
0 }
1914 "caret": {
"start":
0,
"length":
0 },
1915 "key": { key:
"b" },
1918 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3",
1919 "runCompositionTest",
"#4-2") ||
1920 !checkSelection(
4,
"",
"runCompositionTest",
"#4-2")) {
1924 synthesizeComposition({ type:
"compositioncommit", data:
"\u6700", key: { key:
"KEY_Enter" } });
1925 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u6700",
1926 "runCompositionTest",
"#4-3") ||
1927 !checkSelection(
5,
"",
"runCompositionTest",
"#4-3")) {
1931 // testing the canceling case
1932 synthesizeCompositionChange(
1937 {
"length":
0,
"attr":
0 }
1940 "caret": {
"start":
0,
"length":
0 },
1941 "key": { key:
"a" },
1944 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u6700",
1945 "runCompositionTest",
"#4-5") ||
1946 !checkSelection(
5,
"",
"runCompositionTest",
"#4-5")) {
1950 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"KEY_Escape" } });
1952 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u6700",
1953 "runCompositionTest",
"#4-6") ||
1954 !checkSelection(
5,
"",
"runCompositionTest",
"#4-6")) {
1958 // testing whether the empty composition string deletes selected string.
1959 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true});
1961 synthesizeCompositionChange(
1966 {
"length":
0,
"attr":
0 }
1969 "caret": {
"start":
0,
"length":
0 },
1970 "key": { key:
"a" },
1973 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3",
1974 "runCompositionTest",
"#4-8") ||
1975 !checkSelection(
4,
"",
"runCompositionTest",
"#4-8")) {
1979 synthesizeComposition({ type:
"compositioncommit", data:
"\u9AD8", key: { key:
"KEY_Enter" } });
1980 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u9AD8",
1981 "runCompositionTest",
"#4-9") ||
1982 !checkSelection(
5,
"",
"runCompositionTest",
"#4-9")) {
1986 synthesizeKey(
"KEY_Backspace");
1987 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3",
1988 "runCompositionTest",
"#4-11") ||
1989 !checkSelection(
4,
"",
"runCompositionTest",
"#4-11")) {
1993 // bug
23558, ancient Japanese IMEs on Window may send empty text event
1994 // twice at canceling composition.
1995 synthesizeCompositionChange(
1997 {
"string":
"\u6700",
2000 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
2003 "caret": {
"start":
1,
"length":
0 },
2004 "key": { key:
"a" },
2007 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u6700",
2008 "runCompositionTest",
"#5-1") ||
2009 !checkSelection(
4 +
1,
"",
"runCompositionTest",
"#5-1")) {
2013 synthesizeCompositionChange(
2018 {
"length":
0,
"attr":
0 }
2021 "caret": {
"start":
0,
"length":
0 },
2022 "key": { key:
"KEY_Backspace", type:
"keydown" },
2025 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3",
2026 "runCompositionTest",
"#5-2") ||
2027 !checkSelection(
4,
"",
"runCompositionTest",
"#5-2")) {
2031 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"KEY_Backspace", type:
"keyup" } });
2032 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3",
2033 "runCompositionTest",
"#5-3") ||
2034 !checkSelection(
4,
"",
"runCompositionTest",
"#5-3")) {
2038 // Undo tests for the testcases for bug
23558 and bug
271815
2039 synthesizeKey(
"z", { accelKey: true });
2041 // XXX this is unexpected behavior, see bug
258291
2042 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3",
2043 "runCompositionTest",
"#6-1") ||
2044 !checkSelection(
4,
"",
"runCompositionTest",
"#6-1")) {
2048 synthesizeKey(
"z", { accelKey: true });
2050 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u9AD8",
2051 "runCompositionTest",
"#6-2") ||
2052 !checkSelection(
5,
"",
"runCompositionTest",
"#6-2")) {
2056 synthesizeKey(
"z", { accelKey: true });
2058 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u6700",
2059 "runCompositionTest",
"#6-3") ||
2060 !checkSelection(
4,
"",
"runCompositionTest",
"#6-3")) {
2064 synthesizeKey(
"z", { accelKey: true });
2066 // XXX this is unexpected behavior, see bug
258291
2067 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u6700",
2068 "runCompositionTest",
"#6-4") ||
2069 !checkSelection(
5,
"",
"runCompositionTest",
"#6-4")) {
2073 synthesizeKey(
"z", { accelKey: true });
2075 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3",
2076 "runCompositionTest",
"#6-5") ||
2077 !checkSelection(
4,
"",
"runCompositionTest",
"#6-5")) {
2078 // eslint-disable-next-line no-useless-return
2083 function runCompositionEventTest()
2085 const kDescription =
"runCompositionEventTest: ";
2086 const kEvents = [
"compositionstart",
"compositionupdate",
"compositionend",
2092 let windowEventCounts = [], windowEventData = [], windowEventLocale = [];
2093 let inputEventCounts = [], inputEventData = [], inputEventLocale = [];
2094 let preventDefault = false;
2095 let stopPropagation = false;
2097 function initResults()
2099 for (let i =
0; i < kEvents.length; i++) {
2100 windowEventCounts[kEvents[i]] =
0;
2101 windowEventData[kEvents[i]] =
"";
2102 windowEventLocale[kEvents[i]] =
"";
2103 inputEventCounts[kEvents[i]] =
0;
2104 inputEventData[kEvents[i]] =
"";
2105 inputEventLocale[kEvents[i]] =
"";
2109 function compositionEventHandlerForWindow(aEvent)
2111 windowEventCounts[aEvent.type]++;
2112 windowEventData[aEvent.type] = aEvent.data;
2113 windowEventLocale[aEvent.type] = aEvent.locale;
2114 if (preventDefault) {
2115 aEvent.preventDefault();
2117 if (stopPropagation) {
2118 aEvent.stopPropagation();
2122 function formEventHandlerForWindow(aEvent)
2124 ok(aEvent.isTrusted,
"input events must be trusted events");
2125 windowEventCounts[aEvent.type]++;
2126 windowEventData[aEvent.type] = input.value;
2129 function compositionEventHandlerForInput(aEvent)
2131 inputEventCounts[aEvent.type]++;
2132 inputEventData[aEvent.type] = aEvent.data;
2133 inputEventLocale[aEvent.type] = aEvent.locale;
2134 if (preventDefault) {
2135 aEvent.preventDefault();
2137 if (stopPropagation) {
2138 aEvent.stopPropagation();
2142 function formEventHandlerForInput(aEvent)
2144 inputEventCounts[aEvent.type]++;
2145 inputEventData[aEvent.type] = input.value;
2148 window.addEventListener(
"compositionstart", compositionEventHandlerForWindow,
2150 window.addEventListener(
"compositionend", compositionEventHandlerForWindow,
2152 window.addEventListener(
"compositionupdate", compositionEventHandlerForWindow,
2154 window.addEventListener(
"input", formEventHandlerForWindow,
2157 input.addEventListener(
"compositionstart", compositionEventHandlerForInput,
2159 input.addEventListener(
"compositionend", compositionEventHandlerForInput,
2161 input.addEventListener(
"compositionupdate", compositionEventHandlerForInput,
2163 input.addEventListener(
"input", formEventHandlerForInput,
2166 // test for normal case
2169 synthesizeCompositionChange(
2171 {
"string":
"\u3089",
2174 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
2177 "caret": {
"start":
1,
"length":
0 },
2178 "key": { key:
"o" },
2181 is(windowEventCounts.compositionstart,
1,
2182 kDescription +
"compositionstart hasn't been handled by window #1");
2183 is(windowEventData.compositionstart,
"",
2184 kDescription +
"data of compositionstart isn't empty (window) #1");
2185 is(windowEventLocale.compositionstart,
"",
2186 kDescription +
"locale of compositionstart isn't empty (window) #1");
2187 is(inputEventCounts.compositionstart,
1,
2188 kDescription +
"compositionstart hasn't been handled by input #1");
2189 is(inputEventData.compositionstart,
"",
2190 kDescription +
"data of compositionstart isn't empty (input) #1");
2191 is(inputEventLocale.compositionstart,
"",
2192 kDescription +
"locale of compositionstart isn't empty (input) #1");
2194 is(windowEventCounts.compositionupdate,
1,
2195 kDescription +
"compositionupdate hasn't been handled by window #1");
2196 is(windowEventData.compositionupdate,
"\u3089",
2197 kDescription +
"data of compositionupdate doesn't match (window) #1");
2198 is(windowEventLocale.compositionupdate,
"",
2199 kDescription +
"locale of compositionupdate isn't empty (window) #1");
2200 is(inputEventCounts.compositionupdate,
1,
2201 kDescription +
"compositionupdate hasn't been handled by input #1");
2202 is(inputEventData.compositionupdate,
"\u3089",
2203 kDescription +
"data of compositionupdate doesn't match (input) #1");
2204 is(inputEventLocale.compositionupdate,
"",
2205 kDescription +
"locale of compositionupdate isn't empty (input) #1");
2207 is(windowEventCounts.compositionend,
0,
2208 kDescription +
"compositionend has been handled by window #1");
2209 is(inputEventCounts.compositionend,
0,
2210 kDescription +
"compositionend has been handled by input #1");
2212 is(windowEventCounts.input,
1,
2213 kDescription +
"input hasn't been handled by window #1");
2214 is(windowEventData.input,
"\u3089",
2215 kDescription +
"value of input element wasn't modified (window) #1");
2216 is(inputEventCounts.input,
1,
2217 kDescription +
"input hasn't been handled by input #1");
2218 is(inputEventData.input,
"\u3089",
2219 kDescription +
"value of input element wasn't modified (input) #1");
2221 synthesizeCompositionChange(
2223 {
"string":
"\u3089\u30FC",
2226 {
"length":
2,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
2229 "caret": {
"start":
2,
"length":
0 },
2230 "key": { key:
"\\", code:
"IntlYen", keyCode: KeyboardEvent.DOM_VK_BACKSLASH },
2233 is(windowEventCounts.compositionstart,
1,
2234 kDescription +
"compositionstart has been handled more than once by window #2");
2235 is(inputEventCounts.compositionstart,
1,
2236 kDescription +
"compositionstart has been handled more than once by input #2");
2238 is(windowEventCounts.compositionupdate,
2,
2239 kDescription +
"compositionupdate hasn't been handled by window #2");
2240 is(windowEventData.compositionupdate,
"\u3089\u30FC",
2241 kDescription +
"data of compositionupdate doesn't match (window) #2");
2242 is(windowEventLocale.compositionupdate,
"",
2243 kDescription +
"locale of compositionupdate isn't empty (window) #2");
2244 is(inputEventCounts.compositionupdate,
2,
2245 kDescription +
"compositionupdate hasn't been handled by input #2");
2246 is(inputEventData.compositionupdate,
"\u3089\u30FC",
2247 kDescription +
"data of compositionupdate doesn't match (input) #2");
2248 is(inputEventLocale.compositionupdate,
"",
2249 kDescription +
"locale of compositionupdate isn't empty (input) #2");
2251 is(windowEventCounts.compositionend,
0,
2252 kDescription +
"compositionend has been handled during composition by window #2");
2253 is(inputEventCounts.compositionend,
0,
2254 kDescription +
"compositionend has been handled during composition by input #2");
2256 is(windowEventCounts.input,
2,
2257 kDescription +
"input hasn't been handled by window #2");
2258 is(windowEventData.input,
"\u3089\u30FC",
2259 kDescription +
"value of input element wasn't modified (window) #2");
2260 is(inputEventCounts.input,
2,
2261 kDescription +
"input hasn't been handled by input #2");
2262 is(inputEventData.input,
"\u3089\u30FC",
2263 kDescription +
"value of input element wasn't modified (input) #2");
2265 // text event shouldn't cause composition update, e.g., at committing.
2266 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"KEY_Enter" } });
2268 is(windowEventCounts.compositionstart,
1,
2269 kDescription +
"compositionstart has been handled more than once by window #3");
2270 is(inputEventCounts.compositionstart,
1,
2271 kDescription +
"compositionstart has been handled more than once by input #3");
2273 is(windowEventCounts.compositionupdate,
2,
2274 kDescription +
"compositionupdate has been fired unexpectedly on window #3");
2275 is(inputEventCounts.compositionupdate,
2,
2276 kDescription +
"compositionupdate has been fired unexpectedly on input #3");
2278 is(windowEventCounts.compositionend,
1,
2279 kDescription +
"compositionend hasn't been handled by window #3");
2280 is(windowEventData.compositionend,
"\u3089\u30FC",
2281 kDescription +
"data of compositionend doesn't match (window) #3");
2282 is(windowEventLocale.compositionend,
"",
2283 kDescription +
"locale of compositionend isn't empty (window) #3");
2284 is(inputEventCounts.compositionend,
1,
2285 kDescription +
"compositionend hasn't been handled by input #3");
2286 is(inputEventData.compositionend,
"\u3089\u30FC",
2287 kDescription +
"data of compositionend doesn't match (input) #3");
2288 is(inputEventLocale.compositionend,
"",
2289 kDescription +
"locale of compositionend isn't empty (input) #3");
2291 is(windowEventCounts.input,
3,
2292 kDescription +
"input hasn't been handled by window #3");
2293 is(windowEventData.input,
"\u3089\u30FC",
2294 kDescription +
"value of input element wasn't modified (window) #3");
2295 is(inputEventCounts.input,
3,
2296 kDescription +
"input hasn't been handled by input #3");
2297 is(inputEventData.input,
"\u3089\u30FC",
2298 kDescription +
"value of input element wasn't modified (input) #3");
2300 // select the second character, then, data of composition start should be
2301 // the selected character.
2303 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true});
2305 synthesizeCompositionChange(
2307 {
"string":
"\u3089",
2310 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
2313 "caret": {
"start":
1,
"length":
0 },
2314 "key": { key:
"o" },
2317 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"KEY_Enter" } });
2319 is(windowEventCounts.compositionstart,
1,
2320 kDescription +
"compositionstart hasn't been handled by window #4");
2321 is(windowEventData.compositionstart,
"\u30FC",
2322 kDescription +
"data of compositionstart is empty (window) #4");
2323 is(windowEventLocale.compositionstart,
"",
2324 kDescription +
"locale of compositionstart isn't empty (window) #4");
2325 is(inputEventCounts.compositionstart,
1,
2326 kDescription +
"compositionstart hasn't been handled by input #4");
2327 is(inputEventData.compositionstart,
"\u30FC",
2328 kDescription +
"data of compositionstart is empty (input) #4");
2329 is(inputEventLocale.compositionstart,
"",
2330 kDescription +
"locale of compositionstart isn't empty (input) #4");
2332 is(windowEventCounts.compositionupdate,
1,
2333 kDescription +
"compositionupdate hasn't been handled by window #4");
2334 is(windowEventData.compositionupdate,
"\u3089",
2335 kDescription +
"data of compositionupdate doesn't match (window) #4");
2336 is(windowEventLocale.compositionupdate,
"",
2337 kDescription +
"locale of compositionupdate isn't empty (window) #4");
2338 is(inputEventCounts.compositionupdate,
1,
2339 kDescription +
"compositionupdate hasn't been handled by input #4");
2340 is(inputEventData.compositionupdate,
"\u3089",
2341 kDescription +
"data of compositionupdate doesn't match (input) #4");
2342 is(inputEventLocale.compositionupdate,
"",
2343 kDescription +
"locale of compositionupdate isn't empty (input) #4");
2345 is(windowEventCounts.compositionend,
1,
2346 kDescription +
"compositionend hasn't been handled by window #4");
2347 is(windowEventData.compositionend,
"\u3089",
2348 kDescription +
"data of compositionend doesn't match (window) #4");
2349 is(windowEventLocale.compositionend,
"",
2350 kDescription +
"locale of compositionend isn't empty (window) #4");
2351 is(inputEventCounts.compositionend,
1,
2352 kDescription +
"compositionend hasn't been handled by input #4");
2353 is(inputEventData.compositionend,
"\u3089",
2354 kDescription +
"data of compositionend doesn't match (input) #4");
2355 is(inputEventLocale.compositionend,
"",
2356 kDescription +
"locale of compositionend isn't empty (input) #4");
2358 is(windowEventCounts.input,
2,
2359 kDescription +
"input hasn't been handled by window #4");
2360 is(windowEventData.input,
"\u3089\u3089",
2361 kDescription +
"value of input element wasn't modified (window) #4");
2362 is(inputEventCounts.input,
2,
2363 kDescription +
"input hasn't been handled by input #4");
2364 is(inputEventData.input,
"\u3089\u3089",
2365 kDescription +
"value of input element wasn't modified (input) #4");
2367 // preventDefault() should effect nothing.
2368 preventDefault = true;
2371 synthesizeKey(
"a", { accelKey: true }); // Select All
2373 synthesizeCompositionChange(
2375 {
"string":
"\u306D",
2378 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
2381 "caret": {
"start":
1,
"length":
0 },
2382 "key": { key:
"," },
2385 synthesizeComposition({ type:
"compositioncommitasis" });
2387 is(windowEventCounts.compositionstart,
1,
2388 kDescription +
"compositionstart hasn't been handled by window #5");
2389 is(windowEventData.compositionstart,
"\u3089\u3089",
2390 kDescription +
"data of compositionstart is empty (window) #5");
2391 is(windowEventLocale.compositionstart,
"",
2392 kDescription +
"locale of compositionstart isn't empty (window) #5");
2393 is(inputEventCounts.compositionstart,
1,
2394 kDescription +
"compositionstart hasn't been handled by input #5");
2395 is(inputEventData.compositionstart,
"\u3089\u3089",
2396 kDescription +
"data of compositionstart is empty (input) #5");
2397 is(inputEventLocale.compositionstart,
"",
2398 kDescription +
"locale of compositionstart isn't empty (input) #5");
2400 is(windowEventCounts.compositionupdate,
1,
2401 kDescription +
"compositionupdate hasn't been handled by window #5");
2402 is(windowEventData.compositionupdate,
"\u306D",
2403 kDescription +
"data of compositionupdate doesn't match (window) #5");
2404 is(windowEventLocale.compositionupdate,
"",
2405 kDescription +
"locale of compositionupdate isn't empty (window) #5");
2406 is(inputEventCounts.compositionupdate,
1,
2407 kDescription +
"compositionupdate hasn't been handled by input #5");
2408 is(inputEventData.compositionupdate,
"\u306D",
2409 kDescription +
"data of compositionupdate doesn't match (input) #5");
2410 is(inputEventLocale.compositionupdate,
"",
2411 kDescription +
"locale of compositionupdate isn't empty (input) #5");
2413 is(windowEventCounts.compositionend,
1,
2414 kDescription +
"compositionend hasn't been handled by window #5");
2415 is(windowEventData.compositionend,
"\u306D",
2416 kDescription +
"data of compositionend doesn't match (window) #5");
2417 is(windowEventLocale.compositionend,
"",
2418 kDescription +
"locale of compositionend isn't empty (window) #5");
2419 is(inputEventCounts.compositionend,
1,
2420 kDescription +
"compositionend hasn't been handled by input #5");
2421 is(inputEventData.compositionend,
"\u306D",
2422 kDescription +
"data of compositionend doesn't match (input) #5");
2423 is(inputEventLocale.compositionend,
"",
2424 kDescription +
"locale of compositionend isn't empty (input) #5");
2426 is(windowEventCounts.input,
2,
2427 kDescription +
"input hasn't been handled by window #5");
2428 is(windowEventData.input,
"\u306D",
2429 kDescription +
"value of input element wasn't modified (window) #5");
2430 is(inputEventCounts.input,
2,
2431 kDescription +
"input hasn't been handled by input #5");
2432 is(inputEventData.input,
"\u306D",
2433 kDescription +
"value of input element wasn't modified (input) #5");
2435 preventDefault = false;
2437 // stopPropagation() should effect nothing (except event count)
2438 stopPropagation = true;
2441 synthesizeKey(
"a", { accelKey: true }); // Select All
2443 synthesizeCompositionChange(
2445 {
"string":
"\u306E",
2448 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
2451 "caret": {
"start":
1,
"length":
0 },
2452 "key": { key:
"\\", code:
"IntlRo", keyCode: KeyboardEvent.DOM_VK_BACKSLASH },
2455 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"KEY_Enter" } });
2457 is(windowEventCounts.compositionstart,
1,
2458 kDescription +
"compositionstart hasn't been handled by window #6");
2459 is(windowEventData.compositionstart,
"\u306D",
2460 kDescription +
"data of compositionstart is empty #6");
2461 is(windowEventLocale.compositionstart,
"",
2462 kDescription +
"locale of compositionstart isn't empty #6");
2463 is(inputEventCounts.compositionstart,
0,
2464 kDescription +
"compositionstart has been handled by input #6");
2466 is(windowEventCounts.compositionupdate,
1,
2467 kDescription +
"compositionupdate hasn't been handled by window #6");
2468 is(windowEventData.compositionupdate,
"\u306E",
2469 kDescription +
"data of compositionupdate doesn't match #6");
2470 is(windowEventLocale.compositionupdate,
"",
2471 kDescription +
"locale of compositionupdate isn't empty #6");
2472 is(inputEventCounts.compositionupdate,
0,
2473 kDescription +
"compositionupdate has been handled by input #6");
2475 is(windowEventCounts.compositionend,
1,
2476 kDescription +
"compositionend hasn't been handled by window #6");
2477 is(windowEventData.compositionend,
"\u306E",
2478 kDescription +
"data of compositionend doesn't match #6");
2479 is(windowEventLocale.compositionend,
"",
2480 kDescription +
"locale of compositionend isn't empty #6");
2481 is(inputEventCounts.compositionend,
0,
2482 kDescription +
"compositionend has been handled by input #6");
2484 is(windowEventCounts.input,
2,
2485 kDescription +
"input hasn't been handled by window #6");
2486 is(windowEventData.input,
"\u306E",
2487 kDescription +
"value of input element wasn't modified (window) #6");
2488 is(inputEventCounts.input,
2,
2489 kDescription +
"input hasn't been handled by input #6");
2490 is(inputEventData.input,
"\u306E",
2491 kDescription +
"value of input element wasn't modified (input) #6");
2493 stopPropagation = false;
2495 // create event and dispatch it.
2498 input.value =
"value of input";
2499 synthesizeKey(
"a", { accelKey: true }); // Select All
2501 let compositionstart = document.createEvent(
"CompositionEvent");
2502 compositionstart.initCompositionEvent(
"compositionstart",
2503 true, true, document.defaultView,
2504 "start data",
"start locale");
2505 is(compositionstart.type,
"compositionstart",
2506 kDescription +
"type doesn't match #7");
2507 is(compositionstart.data,
"start data",
2508 kDescription +
"data doesn't match #7");
2509 is(compositionstart.locale,
"start locale",
2510 kDescription +
"locale doesn't match #7");
2511 is(compositionstart.detail,
0,
2512 kDescription +
"detail isn't 0 #7");
2514 input.dispatchEvent(compositionstart);
2516 is(windowEventCounts.compositionstart,
1,
2517 kDescription +
"compositionstart hasn't been handled by window #7");
2518 is(windowEventData.compositionstart,
"start data",
2519 kDescription +
"data of compositionstart was changed (window) #7");
2520 is(windowEventLocale.compositionstart,
"start locale",
2521 kDescription +
"locale of compositionstart was changed (window) #7");
2522 is(inputEventCounts.compositionstart,
1,
2523 kDescription +
"compositionstart hasn't been handled by input #7");
2524 is(inputEventData.compositionstart,
"start data",
2525 kDescription +
"data of compositionstart was changed (input) #7");
2526 is(inputEventLocale.compositionstart,
"start locale",
2527 kDescription +
"locale of compositionstart was changed (input) #7");
2529 is(input.value,
"value of input",
2530 kDescription +
"input value was changed #7");
2532 let compositionupdate1 = document.createEvent(
"compositionevent");
2533 compositionupdate1.initCompositionEvent(
"compositionupdate",
2534 true, false, document.defaultView,
2535 "composing string",
"composing locale");
2536 is(compositionupdate1.type,
"compositionupdate",
2537 kDescription +
"type doesn't match #8");
2538 is(compositionupdate1.data,
"composing string",
2539 kDescription +
"data doesn't match #8");
2540 is(compositionupdate1.locale,
"composing locale",
2541 kDescription +
"locale doesn't match #8");
2542 is(compositionupdate1.detail,
0,
2543 kDescription +
"detail isn't 0 #8");
2545 input.dispatchEvent(compositionupdate1);
2547 is(windowEventCounts.compositionupdate,
1,
2548 kDescription +
"compositionupdate hasn't been handled by window #8");
2549 is(windowEventData.compositionupdate,
"composing string",
2550 kDescription +
"data of compositionupdate was changed (window) #8");
2551 is(windowEventLocale.compositionupdate,
"composing locale",
2552 kDescription +
"locale of compositionupdate was changed (window) #8");
2553 is(inputEventCounts.compositionupdate,
1,
2554 kDescription +
"compositionupdate hasn't been handled by input #8");
2555 is(inputEventData.compositionupdate,
"composing string",
2556 kDescription +
"data of compositionupdate was changed (input) #8");
2557 is(inputEventLocale.compositionupdate,
"composing locale",
2558 kDescription +
"locale of compositionupdate was changed (input) #8");
2560 is(input.value,
"value of input",
2561 kDescription +
"input value was changed #8");
2563 let compositionupdate2 = document.createEvent(
"compositionEvent");
2564 compositionupdate2.initCompositionEvent(
"compositionupdate",
2565 true, false, document.defaultView,
2566 "commit string",
"commit locale");
2567 is(compositionupdate2.type,
"compositionupdate",
2568 kDescription +
"type doesn't match #9");
2569 is(compositionupdate2.data,
"commit string",
2570 kDescription +
"data doesn't match #9");
2571 is(compositionupdate2.locale,
"commit locale",
2572 kDescription +
"locale doesn't match #9");
2573 is(compositionupdate2.detail,
0,
2574 kDescription +
"detail isn't 0 #9");
2576 input.dispatchEvent(compositionupdate2);
2578 is(windowEventCounts.compositionupdate,
2,
2579 kDescription +
"compositionupdate hasn't been handled by window #9");
2580 is(windowEventData.compositionupdate,
"commit string",
2581 kDescription +
"data of compositionupdate was changed (window) #9");
2582 is(windowEventLocale.compositionupdate,
"commit locale",
2583 kDescription +
"locale of compositionupdate was changed (window) #9");
2584 is(inputEventCounts.compositionupdate,
2,
2585 kDescription +
"compositionupdate hasn't been handled by input #9");
2586 is(inputEventData.compositionupdate,
"commit string",
2587 kDescription +
"data of compositionupdate was changed (input) #9");
2588 is(inputEventLocale.compositionupdate,
"commit locale",
2589 kDescription +
"locale of compositionupdate was changed (input) #9");
2591 is(input.value,
"value of input",
2592 kDescription +
"input value was changed #9");
2594 let compositionend = document.createEvent(
"Compositionevent");
2595 compositionend.initCompositionEvent(
"compositionend",
2596 true, false, document.defaultView,
2597 "end data",
"end locale");
2598 is(compositionend.type,
"compositionend",
2599 kDescription +
"type doesn't match #10");
2600 is(compositionend.data,
"end data",
2601 kDescription +
"data doesn't match #10");
2602 is(compositionend.locale,
"end locale",
2603 kDescription +
"locale doesn't match #10");
2604 is(compositionend.detail,
0,
2605 kDescription +
"detail isn't 0 #10");
2607 input.dispatchEvent(compositionend);
2609 is(windowEventCounts.compositionend,
1,
2610 kDescription +
"compositionend hasn't been handled by window #10");
2611 is(windowEventData.compositionend,
"end data",
2612 kDescription +
"data of compositionend was changed (window) #10");
2613 is(windowEventLocale.compositionend,
"end locale",
2614 kDescription +
"locale of compositionend was changed (window) #10");
2615 is(inputEventCounts.compositionend,
1,
2616 kDescription +
"compositionend hasn't been handled by input #10");
2617 is(inputEventData.compositionend,
"end data",
2618 kDescription +
"data of compositionend was changed (input) #10");
2619 is(inputEventLocale.compositionend,
"end locale",
2620 kDescription +
"locale of compositionend was changed (input) #10");
2622 is(input.value,
"value of input",
2623 kDescription +
"input value was changed #10");
2625 window.removeEventListener(
"compositionstart",
2626 compositionEventHandlerForWindow, true);
2627 window.removeEventListener(
"compositionend",
2628 compositionEventHandlerForWindow, true);
2629 window.removeEventListener(
"compositionupdate",
2630 compositionEventHandlerForWindow, true);
2631 window.removeEventListener(
"input",
2632 formEventHandlerForWindow, true);
2634 input.removeEventListener(
"compositionstart",
2635 compositionEventHandlerForInput, true);
2636 input.removeEventListener(
"compositionend",
2637 compositionEventHandlerForInput, true);
2638 input.removeEventListener(
"compositionupdate",
2639 compositionEventHandlerForInput, true);
2640 input.removeEventListener(
"input",
2641 formEventHandlerForInput, true);
2644 function runCompositionTestWhoseTextNodeModified() {
2645 const selection = windowOfContenteditable.getSelection();
2647 (function testInsertTextBeforeComposition() {
2649 "runCompositionTestWhoseTextNodeModified: testInsertTextBeforeComposition:";
2650 contenteditable.focus();
2651 contenteditable.innerHTML =
"<p>def</p>";
2652 const textNode = contenteditable.firstChild.firstChild;
2653 selection.collapse(textNode,
"def".length);
2654 // Insert composition to the end of a text node
2655 synthesizeSimpleCompositionChange(
"g");
2659 `${description} Composition should be inserted to end of the text node`
2662 // Insert a character before the composition string
2663 textNode.insertData(
0,
"c");
2669 } Composition should be shifted when a character is inserted before it`
2674 `${kLF}cdef`.length,
2678 } IME selection should be shifted when a character is inserted before it`
2681 // Update composition string (appending a character)
2682 synthesizeSimpleCompositionChange(
"gh");
2688 } Composition should be updated correctly after inserted a character before it`
2693 `${kLF}cdef`.length,
2697 } IME selection should be extended correctly at updating composition after inserted a character before it`
2700 // Insert another character before the composition
2701 textNode.insertData(
0,
"b");
2707 } Composition should be shifted when a character is inserted again before it`
2712 `${kLF}bcdef`.length,
2716 } IME selection should be shifted when a character is inserted again before it`
2719 // Update the composition string again (appending another character)
2720 synthesizeSimpleCompositionChange(
"ghi");
2726 } Composition should be updated correctly after inserted
2 characters before it`
2731 `${kLF}bcdef`.length,
2735 } IME selection should be extended correctly at updating composition after inserted
2 characters before it`
2738 // Insert a new character before the composition string
2739 textNode.insertData(
0,
"a");
2745 } Composition should be shifted when a character is inserted again and again before it`
2750 `${kLF}abcdef`.length,
2754 } IME selection should be shifted when a character is inserted again and again before it`
2757 // Commit the composition string
2758 synthesizeComposition({ type:
"compositioncommitasis" });
2764 } Composition should be committed as is`
2767 selection.focusOffset,
2769 `${description} Selection should be collapsed at end of the commit string`
2773 synthesizeKey(
"z", { accelKey: true });
2779 } Composition should be undone correctly`
2782 selection.focusOffset,
2786 } Selection should be collapsed at where the composition was after undoing`
2790 synthesizeKey(
"z", { accelKey: true, shiftKey: true });
2796 } Composition should be redone correctly`
2799 selection.focusOffset,
2803 } focus offset of Selection should be at end of the commit string after redoing`
2807 (function testInsertTextImmediatelyBeforeComposition() {
2809 "runCompositionTestWhoseTextNodeModified: testInsertTextImmediatelyBeforeComposition:";
2810 contenteditable.focus();
2811 contenteditable.innerHTML =
"<p>d</p>";
2812 const textNode = contenteditable.firstChild.firstChild;
2813 selection.collapse(textNode,
0);
2814 // Insert composition at start of the text node
2815 synthesizeSimpleCompositionChange(
"b");
2819 `${description} Composition should be inserted to start of the text node`
2822 // Insert a character before the composition string
2823 textNode.insertData(
0,
"a");
2829 } Composition should be shifted when a character is inserted immediately before it`
2838 } IME selection should be shifted when a character is inserted immediately before it`,
2840 { offset: todo_is, text: todo_is }
2843 // Update the composition string after inserting character immediately before it
2844 synthesizeSimpleCompositionChange(
"bc");
2848 `${description} Composition should be updated after the inserted character`
2857 } IME selection should be set at the composition string after the inserted character`
2861 synthesizeComposition({ type:
"compositioncommitasis" });
2867 } Composition should be committed after the inserted character`
2870 selection.focusOffset,
2872 `${description} Selection should be collapsed at end of the commit string`
2876 (function testInsertTextImmediatelyAfterComposition() {
2878 "runCompositionTestWhoseTextNodeModified: testInsertTextImmediatelyAfterComposition:";
2879 contenteditable.focus();
2880 contenteditable.innerHTML =
"<p>a</p>";
2881 const textNode = contenteditable.firstChild.firstChild;
2882 selection.collapse(textNode,
"a".length);
2883 // Insert composition at end of the text node
2884 synthesizeSimpleCompositionChange(
"b");
2888 `${description} Composition should be inserted to start of the text node`
2891 // Insert a character after the composition string
2892 textNode.insertData(
"ab".length,
"d");
2898 } Composition should stay when a character is inserted immediately after it`
2907 } IME selection should stay when a character is inserted immediately after it`
2910 // Update the composition string after inserting character immediately after it
2911 synthesizeSimpleCompositionChange(
"bc");
2915 `${description} Composition should be updated before the inserted character`
2924 } IME selection should be set at the composition string before the inserted character`
2928 synthesizeComposition({ type:
"compositioncommitasis" });
2934 } Composition should be committed before the inserted character`
2937 selection.focusOffset,
2939 `${description} Selection should be collapsed at end of the commit string`
2943 // Inserting/replacing text before the last character of composition string
2944 // should be contained by the composition, i.e., updated by next composition
2945 // update. This is Chrome compatible.
2946 (function testInsertTextMiddleOfComposition() {
2948 "runCompositionTestWhoseTextNodeModified: testInsertTextMiddleOfComposition:";
2949 contenteditable.focus();
2950 contenteditable.innerHTML =
"<p>a</p>";
2951 const textNode = contenteditable.firstChild.firstChild;
2952 selection.collapse(textNode,
"a".length);
2953 // Insert composition at middle of the text node
2954 synthesizeSimpleCompositionChange(
"bd");
2958 `${description} Composition should be inserted to end of the text node`
2961 // Insert a character before the composition string
2962 textNode.insertData(
"ab".length,
"c");
2968 } Inserted string should inserted into the middle of composition string`
2977 } IME selection should be extended when a character is inserted into middle of it`
2980 // Update the composition string after inserting character into it
2981 synthesizeSimpleCompositionChange(
"BD");
2987 } Composition should be replace the range containing the inserted character`
2996 } IME selection should be set at the updated composition string`
3000 synthesizeComposition({ type:
"compositioncommitasis" });
3006 } Composition should be committed without the inserted character`
3009 selection.focusOffset,
3011 `${description} Selection should be collapsed at end of the commit string`
3015 (function testReplaceFirstCharOfCompositionString() {
3017 "runCompositionTestWhoseTextNodeModified: testReplaceFirstCharOfCompositionString:";
3018 contenteditable.focus();
3019 contenteditable.innerHTML =
"<p>abfg</p>";
3020 const textNode = contenteditable.firstChild.firstChild;
3021 selection.collapse(textNode,
"ab".length);
3022 // Insert composition at middle of the text node
3023 synthesizeSimpleCompositionChange(
"cde");
3027 `${description} Composition should be inserted`
3030 // Replace the composition string
3031 textNode.replaceData(
"ab".length,
"c".length,
"XYZ");
3035 `${description} First character of the composition should be replaced`
3042 `${description} IME selection should contain the replace string`
3045 // Update the composition string after replaced
3046 synthesizeSimpleCompositionChange(
"CDE");
3050 `${description} Composition should update the replace string too`
3057 `${description} IME selection should update the replace string too`
3061 synthesizeComposition({ type:
"compositioncommitasis" });
3065 `${description} Composition should be committed`
3068 selection.focusOffset,
3070 `${description} Selection should be collapsed at end of the commit string`
3074 // Although Chrome commits composition if all composition string is removed,
3075 // let's keep composition for making TSF stable...
3076 (function testReplaceAllCompositionString() {
3078 "runCompositionTestWhoseTextNodeModified: testReplaceAllCompositionString:";
3079 contenteditable.focus();
3080 contenteditable.innerHTML =
"<p>abfg</p>";
3081 const textNode = contenteditable.firstChild.firstChild;
3082 selection.collapse(textNode,
"ab".length);
3083 // Insert composition at middle of the text node
3084 synthesizeSimpleCompositionChange(
"cde");
3088 `${description} Composition should be inserted to the text node`
3091 // Replace the composition string
3092 textNode.replaceData(
"ab".length,
"cde".length,
"XYZ");
3096 `${description} Composition should be replaced`
3105 } IME selection should be collapsed before the replace string`
3108 // Update the composition string after replaced
3109 synthesizeSimpleCompositionChange(
"CDE");
3113 `${description} Composition should be inserted again`
3120 `${description} IME selection should not contain the replace string`
3124 synthesizeComposition({ type:
"compositioncommitasis" });
3128 `${description} Composition should be committed`
3131 selection.focusOffset,
3133 `${description} Selection should be collapsed at end of the commit string`
3137 (function testReplaceCompositionStringAndSurroundedCharacters() {
3139 "runCompositionTestWhoseTextNodeModified: testReplaceCompositionStringAndSurroundedCharacters:";
3140 contenteditable.focus();
3141 contenteditable.innerHTML =
"<p>abfg</p>";
3142 const textNode = contenteditable.firstChild.firstChild;
3143 selection.collapse(textNode,
"ab".length);
3144 // Insert composition at middle of the text node
3145 synthesizeSimpleCompositionChange(
"cde");
3149 `${description} Composition should be inserted to the text node`
3152 // Replace the composition string
3153 textNode.replaceData(
"a".length,
"bcdef".length,
"XYZ");
3157 `${description} Composition should be replaced`
3166 } IME selection should be collapsed before the replace string`
3169 // Update the composition string after replaced
3170 synthesizeSimpleCompositionChange(
"CDE");
3174 `${description} Composition should be inserted again`
3181 `${description} IME selection should not contain the replace string`
3185 synthesizeComposition({ type:
"compositioncommitasis" });
3189 `${description} Composition should be committed`
3192 selection.focusOffset,
3194 `${description} Selection should be collapsed at end of the commit string`
3198 // If start boundary characters are replaced, the replace string should be
3199 // contained into the composition range. This is Chrome compatible.
3200 (function testReplaceStartBoundaryOfCompositionString() {
3202 "runCompositionTestWhoseTextNodeModified: testReplaceStartBoundaryOfCompositionString:";
3203 contenteditable.focus();
3204 contenteditable.innerHTML =
"<p>abfg</p>";
3205 const textNode = contenteditable.firstChild.firstChild;
3206 selection.collapse(textNode,
"ab".length);
3207 // Insert composition at middle of the text node
3208 synthesizeSimpleCompositionChange(
"cde");
3212 `${description} Composition should be inserted to the text node`
3215 // Replace some text
3216 textNode.replaceData(
"a".length,
"bc".length,
"XYZ");
3222 } Start of the composition should be replaced`
3229 `${description} IME selection should contain the replace string`
3232 // Update the replace string and remaining composition.
3233 synthesizeSimpleCompositionChange(
"CDE");
3237 `${description} Composition should update the replace string too`
3244 `${description} IME selection should contain the replace string`
3248 synthesizeComposition({ type:
"compositioncommitasis" });
3254 } Composition should be committed`
3257 selection.focusOffset,
3259 `${description} Selection should be collapsed at end of the commit string`
3263 // If start boundary characters are replaced, the replace string should NOT
3264 // be contained in the composition range. This is Chrome compatible.
3265 (function testReplaceEndBoundaryOfCompositionString() {
3267 "runCompositionTestWhoseTextNodeModified: testReplaceEndBoundaryOfCompositionString:";
3268 contenteditable.focus();
3269 contenteditable.innerHTML =
"<p>abfg</p>";
3270 const textNode = contenteditable.firstChild.firstChild;
3271 selection.collapse(textNode,
"ab".length);
3272 // Insert composition at middle of the text node
3273 synthesizeSimpleCompositionChange(
"cde");
3277 `${description} Composition should be inserted to the text node`
3280 // Replace the composition string
3281 textNode.replaceData(
"abcd".length,
"ef".length,
"XYZ");
3287 } End half of the composition should be replaced`
3296 } IME selection should be shrunken to the non-replaced part`
3299 // Update the composition string after replaced
3300 synthesizeSimpleCompositionChange(
"CDE");
3304 `${description} Only the remaining composition string should be updated`
3311 `${description} IME selection should NOT include the replace string`
3315 synthesizeComposition({ type:
"compositioncommitasis" });
3319 `${description} Composition should be committed`
3322 selection.focusOffset,
3324 `${description} Selection should be collapsed at end of the commit string`
3328 // If the last character of composition is replaced, i.e., it should NOT be
3329 // treated as a part of composition string. This is Chrome compatible.
3330 (function testReplaceLastCharOfCompositionString() {
3332 "runCompositionTestWhoseTextNodeModified: testReplaceLastCharOfCompositionString:";
3333 contenteditable.focus();
3334 contenteditable.innerHTML =
"<p>abfg</p>";
3335 const textNode = contenteditable.firstChild.firstChild;
3336 selection.collapse(textNode,
"ab".length);
3337 // Insert composition at middle of the text node
3338 synthesizeSimpleCompositionChange(
"cde");
3342 `${description} Composition should be inserted`
3345 // Replace the composition string
3346 textNode.replaceData(
"abcd".length,
"e".length,
"XYZ");
3350 `${description} Last character of the composition should be replaced`
3357 `${description} IME selection should be shrunken`
3360 // Update the composition string after replaced
3361 synthesizeSimpleCompositionChange(
"CDE");
3365 `${description} Composition should NOT update the replace string`
3372 `${description} IME selection should not contain the replace string`
3376 synthesizeComposition({ type:
"compositioncommitasis" });
3380 `${description} Composition should be committed`
3383 selection.focusOffset,
3385 `${description} Selection should be collapsed at end of the commit string`
3389 (function testReplaceMiddleCharOfCompositionString() {
3391 "runCompositionTestWhoseTextNodeModified: testReplaceMiddleCharOfCompositionString:";
3392 contenteditable.focus();
3393 contenteditable.innerHTML =
"<p>abfg</p>";
3394 const textNode = contenteditable.firstChild.firstChild;
3395 selection.collapse(textNode,
"ab".length);
3396 // Insert composition at middle of the text node
3397 synthesizeSimpleCompositionChange(
"cde");
3401 `${description} Composition should be inserted`
3404 // Replace the composition string
3405 textNode.replaceData(
"abc".length,
"d".length,
"XYZ");
3411 } Middle character of the composition should be replaced`
3418 `${description} IME selection should be extended by the replace string`
3421 // Update the composition string after replaced
3422 synthesizeSimpleCompositionChange(
"CDE");
3426 `${description} Composition should update the replace string`
3433 `${description} IME selection should be shrunken after update`
3437 synthesizeComposition({ type:
"compositioncommitasis" });
3441 `${description} Composition should be committed`
3444 selection.focusOffset,
3446 `${description} Selection should be collapsed at end of the commit string`
3451 // eslint-disable-next-line complexity
3452 function runQueryTextRectInContentEditableTest()
3454 contenteditable.focus();
3456 contenteditable.innerHTML =
"<p>abc</p><p>def</p>";
3458 // \r\n
01 234 56 789
3460 let description =
"runTextRectInContentEditableTest: \"" + contenteditable.innerHTML + "\
", ";
3463 let a = synthesizeQueryTextRect(kLFLen,
1);
3464 if (!checkQueryContentResult(a, description +
"rect for 'a'")) {
3469 let b = synthesizeQueryTextRect(kLFLen +
1,
1);
3470 if (!checkQueryContentResult(b, description +
"rect for 'b'")) {
3474 is(b.top, a.top, description +
"'a' and 'b' should be at same top");
3475 isSimilarTo(b.left, a.left + a.width,
2, description +
"left of 'b' should be at similar to right of 'a'");
3476 is(b.height, a.height, description +
"'a' and 'b' should be same height");
3479 let c = synthesizeQueryTextRect(kLFLen +
2,
1);
3480 if (!checkQueryContentResult(c, description +
"rect for 'c'")) {
3484 is(c.top, b.top, description +
"'b' and 'c' should be at same top");
3485 isSimilarTo(c.left, b.left + b.width,
2, description +
"left of 'c' should be at similar to right of 'b'");
3486 is(c.height, b.height, description +
"'b' and 'c' should be same height");
3489 let abcAsArray = synthesizeQueryTextRectArray(kLFLen,
3);
3490 if (!checkQueryContentResult(abcAsArray, description +
"rect array for 'abc'") ||
3491 !checkRectArray(abcAsArray, [a, b, c], description +
"query text rect array result of 'abc' should match with each query text rect result")) {
3495 //
2nd
<p> (can be computed with the rect of 'c')
3496 let p2 = synthesizeQueryTextRect(kLFLen +
3,
1);
3497 if (!checkQueryContentResult(p2, description +
"rect for 2nd <p>")) {
3501 is(p2.top, c.top, description +
"'c' and a line breaker caused by 2nd <p> should be at same top");
3502 isSimilarTo(p2.left, c.left + c.width,
2, description +
"left of a line breaker caused by 2nd <p> should be at similar to right of 'c'");
3503 is(p2.height, c.height, description +
"'c' and a line breaker caused by 2nd <p> should be same height");
3506 let p2AsArray = synthesizeQueryTextRectArray(kLFLen +
3,
1);
3507 if (!checkQueryContentResult(p2AsArray, description +
"2nd <p>'s line breaker as array") ||
3508 !checkRectArray(p2AsArray, [p2], description +
"query text rect array result of 2nd <p> should match with each query text rect result")) {
3514 let p2_2 = synthesizeQueryTextRect(kLFLen +
4,
1);
3515 if (!checkQueryContentResult(p2_2, description +
"rect for \\n of \\r\\n caused by 2nd <p>")) {
3519 is(p2_2.top, p2.top, description +
"'\\r' and '\\n' should be at same top");
3520 is(p2_2.left, p2.left, description +
"'\\r' and '\\n' should be at same top");
3521 is(p2_2.height, p2.height, description +
"'\\r' and '\\n' should be same height");
3522 is(p2_2.width, p2.width, description +
"'\\r' and '\\n' should be same width");
3524 // \n of \r\n as array
3525 let p2_2AsArray = synthesizeQueryTextRectArray(kLFLen +
4,
1);
3526 if (!checkQueryContentResult(p2_2AsArray, description +
"rect array for \\n of \\r\\n caused by 2nd <p>") ||
3527 !checkRectArray(p2_2AsArray, [p2_2], description +
"query text rect array result of \\n of \\r\\n caused by 2nd <p> should match with each query text rect result")) {
3533 let d = synthesizeQueryTextRect(kLFLen *
2 +
3,
1);
3534 if (!checkQueryContentResult(d, description +
"rect for 'd'")) {
3538 isGreaterThan(d.top, a.top + a.height, description +
"top of 'd' should be greater than bottom of 'a'");
3539 is(d.left, a.left, description +
"'a' and 'd' should be same at same left");
3540 is(d.height, a.height, description +
"'a' and 'd' should be same height");
3543 let e = synthesizeQueryTextRect(kLFLen *
2 +
4,
1);
3544 if (!checkQueryContentResult(e, description +
"rect for 'e'")) {
3548 is(e.top, d.top, description +
"'d' and 'd' should be at same top");
3549 isSimilarTo(e.left, d.left + d.width,
2, description +
"left of 'e' should be at similar to right of 'd'");
3550 is(e.height, d.height, description +
"'d' and 'e' should be same height");
3553 let f = synthesizeQueryTextRect(kLFLen *
2 +
5,
1);
3554 if (!checkQueryContentResult(f, description +
"rect for 'f'")) {
3558 is(f.top, e.top, description +
"'e' and 'f' should be at same top");
3559 isSimilarTo(f.left, e.left + e.width,
2, description +
"left of 'f' should be at similar to right of 'e'");
3560 is(f.height, e.height, description +
"'e' and 'f' should be same height");
3563 let defAsArray = synthesizeQueryTextRectArray(kLFLen *
2 +
3,
3);
3564 if (!checkQueryContentResult(defAsArray, description +
"rect array for 'def'") ||
3565 !checkRectArray(defAsArray, [d, e, f], description +
"query text rect array result of 'def' should match with each query text rect result")) {
3569 // next of
"f" (can be computed with rect of 'f')
3570 let next_f = synthesizeQueryTextRect(kLFLen *
2 +
6,
1);
3571 if (!checkQueryContentResult(next_f, description +
"rect for next of 'f'")) {
3575 is(next_f.top, d.top,
2, description +
"'f' and next of 'f' should be at same top");
3576 isSimilarTo(next_f.left, f.left + f.width,
2, description +
"left of next of 'f' should be at similar to right of 'f'");
3577 is(next_f.height, d.height, description +
"'f' and next of 'f' should be same height");
3579 // next of
"f" as array
3580 let next_fAsArray = synthesizeQueryTextRectArray(kLFLen *
2 +
6,
1);
3581 if (!checkQueryContentResult(next_fAsArray, description +
"rect array for next of 'f'") ||
3582 !checkRectArray(next_fAsArray, [next_f], description +
"query text rect array result of next of 'f' should match with each query text rect result")) {
3586 // too big offset for the editor
3587 let tooBigOffset = synthesizeQueryTextRect(kLFLen *
2 +
7,
1);
3588 if (!checkQueryContentResult(tooBigOffset, description +
"rect for too big offset")) {
3592 is(tooBigOffset.top, next_f.top, description +
"too big offset and next of 'f' should be at same top");
3593 is(tooBigOffset.left, next_f.left, description +
"too big offset and next of 'f' should be at same left");
3594 is(tooBigOffset.height, next_f.height, description +
"too big offset and next of 'f' should be same height");
3595 is(tooBigOffset.width, next_f.width, description +
"too big offset and next of 'f' should be same width");
3597 // too big offset for the editors as array
3598 let tooBigOffsetAsArray = synthesizeQueryTextRectArray(kLFLen *
2 +
7,
1);
3599 if (!checkQueryContentResult(tooBigOffsetAsArray, description +
"rect array for too big offset") ||
3600 !checkRectArray(tooBigOffsetAsArray, [tooBigOffset], description +
"query text rect array result with too big offset should match with each query text rect result")) {
3604 contenteditable.innerHTML =
"<p>abc</p><p>def</p><p><br></p>";
3605 // \n
0 123 4 567 8 9
3606 // \r\n
01 234 56 789 01 23
3608 description =
"runTextRectInContentEditableTest: \"" + contenteditable.innerHTML + "\
", ";
3611 f = synthesizeQueryTextRect(kLFLen *
2 +
5,
1);
3612 if (!checkQueryContentResult(f, description +
"rect for 'f'")) {
3616 is(f.top, e.top, description +
"'e' and 'f' should be at same top");
3617 is(f.height, e.height, description +
"'e' and 'f' should be same height");
3618 isSimilarTo(f.left, e.left + e.width,
2, description +
"left of 'f' should be at similar to right of 'e'");
3620 //
3rd
<p> (can be computed with rect of 'f')
3621 let p3 = synthesizeQueryTextRect(kLFLen *
2 +
6,
1);
3622 if (!checkQueryContentResult(p3, description +
"rect for 3rd <p>")) {
3626 is(p3.top, f.top, description +
"'f' and a line breaker caused by 3rd <p> should be at same top");
3627 is(p3.height, f.height, description +
"'f' and a line breaker caused by 3rd <p> should be same height");
3628 isSimilarTo(p3.left, f.left + f.width,
2, description +
"left of a line breaker caused by 3rd <p> should be similar to right of 'f'");
3631 let p3AsArray = synthesizeQueryTextRectArray(kLFLen *
2 +
6,
1);
3632 if (!checkQueryContentResult(p3AsArray, description +
"3rd <p>'s line breaker as array") ||
3633 !checkRectArray(p3AsArray, [p3], description +
"query text rect array result of 3rd <p> should match with each query text rect result")) {
3639 let p3_2 = synthesizeQueryTextRect(kLFLen *
2 +
7,
1);
3640 if (!checkQueryContentResult(p3_2, description +
"rect for \\n of \\r\\n caused by 3rd <p>")) {
3644 is(p3_2.top, p3.top, description +
"'\\r' and '\\n' should be at same top");
3645 is(p3_2.left, p3.left, description +
"'\\r' and '\\n' should be at same top");
3646 is(p3_2.height, p3.height, description +
"'\\r' and '\\n' should be same height");
3647 is(p3_2.width, p3.width, description +
"'\\r' and '\\n' should be same width");
3649 // \n of \r\n as array
3650 let p3_2AsArray = synthesizeQueryTextRectArray(kLFLen *
2 +
7,
1);
3651 if (!checkQueryContentResult(p3_2AsArray, description +
"rect array for \\n of \\r\\n caused by 3rd <p>") ||
3652 !checkRectArray(p3_2AsArray, [p3_2], description +
"query text rect array result of \\n of \\r\\n caused by 3rd <p> should match with each query text rect result")) {
3658 let br = synthesizeQueryTextRect(kLFLen *
3 +
6,
1);
3659 if (!checkQueryContentResult(br, description +
"rect for <br> in 3rd <p>")) {
3663 isGreaterThan(br.top, d.top + d.height, description +
"a line breaker caused by <br> in 3rd <p> should be greater than bottom of 'd'");
3664 isSimilarTo(br.height, d.height,
2, description +
"'d' and a line breaker caused by <br> in 3rd <p> should be similar height");
3665 is(br.left, d.left, description +
"left of a line breaker caused by <br> in 3rd <p> should be same left of 'd'");
3667 //
<br> in
3rd
<p> as array
3668 let brAsArray = synthesizeQueryTextRectArray(kLFLen *
3 +
6,
1);
3669 if (!checkQueryContentResult(brAsArray, description +
"<br> in 3rd <p> as array") ||
3670 !checkRectArray(brAsArray, [br], description +
"query text rect array result of <br> in 3rd <p> should match with each query text rect result")) {
3676 let br_2 = synthesizeQueryTextRect(kLFLen *
3 +
7,
1);
3677 if (!checkQueryContentResult(br_2, description +
"rect for \\n of \\r\\n caused by <br> in 3rd <p>")) {
3681 is(br_2.top, br.top, description +
"'\\r' and '\\n' should be at same top");
3682 is(br_2.left, br.left, description +
"'\\r' and '\\n' should be at same top");
3683 is(br_2.height, br.height, description +
"'\\r' and '\\n' should be same height");
3684 is(br_2.width, br.width, description +
"'\\r' and '\\n' should be same width");
3686 // \n of \r\n as array
3687 let br_2AsArray = synthesizeQueryTextRectArray(kLFLen *
3 +
7,
1);
3688 if (!checkQueryContentResult(br_2AsArray, description +
"rect array for \\n of \\r\\n caused by <br> in 3rd <p>") ||
3689 !checkRectArray(br_2AsArray, [br_2], description +
"query text rect array result of \\n of \\r\\n caused by <br> in 3rd <p> should match with each query text rect result")) {
3694 // next of
<br> in
3rd
<p>
3695 let next_br = synthesizeQueryTextRect(kLFLen *
4 +
6,
1);
3696 if (!checkQueryContentResult(next_br, description +
"rect for next of <br> in 3rd <p>")) {
3700 is(next_br.top, br.top, description +
"next of <br> and <br> should be at same top");
3701 is(next_br.left, br.left, description +
"next of <br> and <br> should be at same left");
3702 is(next_br.height, br.height, description +
"next of <br> and <br> should be same height");
3703 is(next_br.width, br.width, description +
"next of <br> and <br> should be same width");
3705 // next of
<br> in
3rd
<p> as array
3706 let next_brAsArray = synthesizeQueryTextRectArray(kLFLen *
4 +
6,
1);
3707 if (!checkQueryContentResult(next_brAsArray, description +
"rect array for next of <br> in 3rd <p>") ||
3708 !checkRectArray(next_brAsArray, [next_br], description +
"query text rect array result of next of <br> in 3rd <p> should match with each query text rect result")) {
3712 // too big offset for the editor
3713 tooBigOffset = synthesizeQueryTextRect(kLFLen *
4 +
7,
1);
3714 if (!checkQueryContentResult(tooBigOffset, description +
"rect for too big offset")) {
3718 is(tooBigOffset.top, next_br.top, description +
"too big offset and next of 3rd <p> should be at same top");
3719 is(tooBigOffset.left, next_br.left, description +
"too big offset and next of 3rd <p> should be at same left");
3720 is(tooBigOffset.height, next_br.height, description +
"too big offset and next of 3rd <p> should be same height");
3721 is(tooBigOffset.width, next_br.width, description +
"too big offset and next of 3rd <p> should be same width");
3723 // too big offset for the editors as array
3724 tooBigOffsetAsArray = synthesizeQueryTextRectArray(kLFLen *
4 +
7,
1);
3725 if (!checkQueryContentResult(tooBigOffsetAsArray, description +
"rect array for too big offset") ||
3726 !checkRectArray(tooBigOffsetAsArray, [tooBigOffset], description +
"query text rect array result with too big offset should match with each query text rect result")) {
3730 contenteditable.innerHTML =
"<p>abc</p><p>def</p><p></p>";
3732 // \r\n
01 234 56 789 0
3734 description =
"runTextRectInContentEditableTest: \"" + contenteditable.innerHTML + "\
", ";
3737 f = synthesizeQueryTextRect(kLFLen *
2 +
5,
1);
3738 if (!checkQueryContentResult(f, description +
"rect for 'f'")) {
3742 is(f.top, e.top, description +
"'e' and 'f' should be at same top");
3743 isSimilarTo(f.left, e.left + e.width,
2, description +
"left of 'f' should be at similar to right of 'e'");
3744 is(f.height, e.height, description +
"'e' and 'f' should be same height");
3746 //
3rd
<p> (can be computed with rect of 'f')
3747 p3 = synthesizeQueryTextRect(kLFLen *
2 +
6,
1);
3748 if (!checkQueryContentResult(p3, description +
"rect for 3rd <p>")) {
3752 is(p3.top, f.top, description +
"'f' and a line breaker caused by 3rd <p> should be at same top");
3753 is(p3.height, f.height, description +
"'f' and a line breaker caused by 3rd <p> should be same height");
3754 isSimilarTo(p3.left, f.left + f.width,
2, description +
"left of a line breaker caused by 3rd <p> should be similar to right of 'f'");
3757 p3AsArray = synthesizeQueryTextRectArray(kLFLen *
2 +
6,
1);
3758 if (!checkQueryContentResult(p3AsArray, description +
"3rd <p>'s line breaker as array") ||
3759 !checkRectArray(p3AsArray, [p3], description +
"query text rect array result of 3rd <p> should match with each query text rect result")) {
3765 let p3_2 = synthesizeQueryTextRect(kLFLen *
2 +
7,
1);
3766 if (!checkQueryContentResult(p3_2, description +
"rect for \\n of \\r\\n caused by 3rd <p>")) {
3770 is(p3_2.top, p3.top, description +
"'\\r' and '\\n' should be at same top");
3771 is(p3_2.left, p3.left, description +
"'\\r' and '\\n' should be at same top");
3772 is(p3_2.height, p3.height, description +
"'\\r' and '\\n' should be same height");
3773 is(p3_2.width, p3.width, description +
"'\\r' and '\\n' should be same width");
3775 // \n of \r\n as array
3776 let p3_2AsArray = synthesizeQueryTextRectArray(kLFLen *
2 +
7,
1);
3777 if (!checkQueryContentResult(p3_2AsArray, description +
"rect array for \\n of \\r\\n caused by 3rd <p>") ||
3778 !checkRectArray(p3_2AsArray, [p3_2], description +
"query text rect array result of \\n of \\r\\n caused by 3rd <p> should match with each query text rect result")) {
3784 let next_p3 = synthesizeQueryTextRect(kLFLen *
3 +
6,
1);
3785 if (!checkQueryContentResult(next_p3, description +
"rect for next of 3rd <p>")) {
3789 isGreaterThan(next_p3.top, d.top + d.height, description +
"top of next of 3rd <p> should equal to or be bigger than bottom of 'd'");
3790 isSimilarTo(next_p3.left, d.left,
2, description +
"left of next of 3rd <p> should be at similar to left of 'd'");
3791 isSimilarTo(next_p3.height, d.height,
2, description +
"next of 3rd <p> and 'd' should be similar height");
3793 // next of
3rd
<p> as array
3794 let next_p3AsArray = synthesizeQueryTextRectArray(kLFLen *
3 +
6,
1);
3795 if (!checkQueryContentResult(next_p3AsArray, description +
"next of 3rd <p> as array") ||
3796 !checkRectArray(next_p3AsArray, [next_p3], description +
"query text rect array result of next of 3rd <p> should match with each query text rect result")) {
3800 // too big offset for the editor
3801 tooBigOffset = synthesizeQueryTextRect(kLFLen *
3 +
7,
1);
3802 if (!checkQueryContentResult(tooBigOffset, description +
"rect for too big offset")) {
3806 is(tooBigOffset.top, next_p3.top, description +
"too big offset and next of 3rd <p> should be at same top");
3807 is(tooBigOffset.left, next_p3.left, description +
"too big offset and next of 3rd <p> should be at same left");
3808 is(tooBigOffset.height, next_p3.height, description +
"too big offset and next of 3rd <p> should be same height");
3809 is(tooBigOffset.width, next_p3.width, description +
"too big offset and next of 3rd <p> should be same width");
3811 // too big offset for the editors as array
3812 tooBigOffsetAsArray = synthesizeQueryTextRectArray(kLFLen *
3 +
7,
1);
3813 if (!checkQueryContentResult(tooBigOffsetAsArray, description +
"rect array for too big offset") ||
3814 !checkRectArray(tooBigOffsetAsArray, [tooBigOffset], description +
"query text rect array result with too big offset should match with each query text rect result")) {
3818 contenteditable.innerHTML =
"abc<br>def";
3822 description =
"runTextRectInContentEditableTest: \"" + contenteditable.innerHTML + "\
", ";
3825 a = synthesizeQueryTextRect(
0,
1);
3826 if (!checkQueryContentResult(a, description +
"rect for 'a'")) {
3831 b = synthesizeQueryTextRect(
1,
1);
3832 if (!checkQueryContentResult(b, description +
"rect for 'b'")) {
3836 is(b.top, a.top, description +
"'a' and 'b' should be at same top");
3837 isSimilarTo(b.left, a.left + a.width,
2, description +
"left of 'b' should be at similar to right of 'a'");
3838 is(b.height, a.height, description +
"'a' and 'b' should be same height");
3841 c = synthesizeQueryTextRect(
2,
1);
3842 if (!checkQueryContentResult(c, description +
"rect for 'c'")) {
3846 is(c.top, b.top, description +
"'b' and 'c' should be at same top");
3847 isSimilarTo(c.left, b.left + b.width,
2, description +
"left of 'c' should be at similar to right of 'b'");
3848 is(c.height, b.height, description +
"'b' and 'c' should be same height");
3851 abcAsArray = synthesizeQueryTextRectArray(
0,
3);
3852 if (!checkQueryContentResult(abcAsArray, description +
"rect array for 'abc'") ||
3853 !checkRectArray(abcAsArray, [a, b, c], description +
"query text rect array result of 'abc' should match with each query text rect result")) {
3857 //
<br> (can be computed with the rect of 'c')
3858 br = synthesizeQueryTextRect(
3,
1);
3859 if (!checkQueryContentResult(br, description +
"rect for <br>")) {
3863 is(br.top, c.top, description +
"'c' and a line breaker caused by <br> should be at same top");
3864 isSimilarTo(br.left, c.left + c.width,
2, description +
"left of a line breaker caused by <br> should be at similar to right of 'c'");
3865 is(br.height, c.height, description +
"'c' and a line breaker caused by <br> should be same height");
3868 brAsArray = synthesizeQueryTextRectArray(
3,
1);
3869 if (!checkQueryContentResult(brAsArray, description +
"<br>'s line breaker as array") ||
3870 !checkRectArray(brAsArray, [br], description +
"query text rect array result of <br> should match with each query text rect result")) {
3876 let br_2 = synthesizeQueryTextRect(
4,
1);
3877 if (!checkQueryContentResult(br_2, description +
"rect for \n of \r\n caused by <br>")) {
3881 is(br_2.top, br.top, description +
"'\\r' and '\\n' should be at same top");
3882 is(br_2.left, br.left, description +
"'\\r' and '\\n' should be at same top");
3883 is(br_2.height, br.height, description +
"'\\r' and '\\n' should be same height");
3884 is(br_2.width, br.width, description +
"'\\r' and '\\n' should be same width");
3886 // \n of \r\n as array
3887 let br_2AsArray = synthesizeQueryTextRectArray(
4,
1);
3888 if (!checkQueryContentResult(br_2AsArray, description +
"rect array for \\n of \\r\\n caused by <br>") ||
3889 !checkRectArray(br_2AsArray, [br_2], description +
"query text rect array result of \\n of \\r\\n caused by <br> should match with each query text rect result")) {
3895 d = synthesizeQueryTextRect(kLFLen +
3,
1);
3896 if (!checkQueryContentResult(d, description +
"rect for 'd'")) {
3900 isSimilarTo(d.top, a.top + a.height,
2, description +
"top of 'd' should be at similar to bottom of 'a'");
3901 is(d.left, a.left, description +
"'a' and 'd' should be same at same left");
3902 is(d.height, a.height, description +
"'a' and 'd' should be same height");
3905 e = synthesizeQueryTextRect(kLFLen +
4,
1);
3906 if (!checkQueryContentResult(e, description +
"rect for 'e'")) {
3910 is(e.top, d.top, description +
"'d' and 'd' should be at same top");
3911 isSimilarTo(e.left, d.left + d.width,
2, description +
"left of 'e' should be at similar to right of 'd'");
3912 is(e.height, d.height, description +
"'d' and 'e' should be same height");
3915 f = synthesizeQueryTextRect(kLFLen +
5,
1);
3916 if (!checkQueryContentResult(f, description +
"rect for 'f'")) {
3920 is(f.top, e.top, description +
"'e' and 'f' should be at same top");
3921 isSimilarTo(f.left, e.left + e.width,
2, description +
"left of 'f' should be at similar to right of 'e'");
3922 is(f.height, e.height, description +
"'e' and 'f' should be same height");
3925 defAsArray = synthesizeQueryTextRectArray(kLFLen +
3,
3);
3926 if (!checkQueryContentResult(defAsArray, description +
"rect array for 'def'") ||
3927 !checkRectArray(defAsArray, [d, e, f], description +
"query text rect array result of 'def' should match with each query text rect result")) {
3931 // next of
"f" (can be computed with rect of 'f')
3932 next_f = synthesizeQueryTextRect(kLFLen +
6,
1);
3933 if (!checkQueryContentResult(next_f, description +
"rect for next of 'f'")) {
3937 is(next_f.top, d.top,
2, description +
"'f' and next of 'f' should be at same top");
3938 isSimilarTo(next_f.left, f.left + f.width,
2, description +
"left of next of 'f' should be at similar to right of 'f'");
3939 is(next_f.height, d.height, description +
"'f' and next of 'f' should be same height");
3941 // next of
"f" as array
3942 next_fAsArray = synthesizeQueryTextRectArray(kLFLen +
6,
1);
3943 if (!checkQueryContentResult(next_fAsArray, description +
"rect array for next of 'f'") ||
3944 !checkRectArray(next_fAsArray, [next_f], description +
"query text rect array result of next of 'f' should match with each query text rect result")) {
3948 // too big offset for the editor
3949 tooBigOffset = synthesizeQueryTextRect(kLFLen +
7,
1);
3950 if (!checkQueryContentResult(tooBigOffset, description +
"rect for too big offset")) {
3954 is(tooBigOffset.top, next_f.top, description +
"too big offset and next of 'f' should be at same top");
3955 is(tooBigOffset.left, next_f.left, description +
"too big offset and next of 'f' should be at same left");
3956 is(tooBigOffset.height, next_f.height, description +
"too big offset and next of 'f' should be same height");
3957 is(tooBigOffset.width, next_f.width, description +
"too big offset and next of 'f' should be same width");
3959 // too big offset for the editors as array
3960 tooBigOffsetAsArray = synthesizeQueryTextRectArray(kLFLen +
7,
1);
3961 if (!checkQueryContentResult(tooBigOffsetAsArray, description +
"rect array for too big offset") ||
3962 !checkRectArray(tooBigOffsetAsArray, [tooBigOffset], description +
"query text rect array result with too big offset should match with each query text rect result")) {
3966 // Note that this case does not have an empty line at the end.
3967 contenteditable.innerHTML =
"abc<br>def<br>";
3971 description =
"runTextRectInContentEditableTest: \"" + contenteditable.innerHTML + "\
", ";
3974 f = synthesizeQueryTextRect(kLFLen +
5,
1);
3975 if (!checkQueryContentResult(f, description +
"rect for 'f'")) {
3979 is(f.top, e.top, description +
"'e' and 'f' should be at same top");
3980 is(f.height, e.height, description +
"'e' and 'f' should be same height");
3981 isSimilarTo(f.left, e.left + e.width,
2, description +
"left of 'f' should be at similar to right of 'e'");
3983 //
2nd
<br> (can be computed with rect of 'f')
3984 let br2 = synthesizeQueryTextRect(kLFLen +
6,
1);
3985 if (!checkQueryContentResult(br2, description +
"rect for 2nd <br>")) {
3989 is(br2.top, f.top, description +
"'f' and a line breaker caused by 2nd <br> should be at same top");
3990 is(br2.height, f.height, description +
"'f' and a line breaker caused by 2nd <br> should be same height");
3991 isSimilarTo(br2.left, f.left + f.width,
2, description +
"left of a line breaker caused by 2nd <br> should be similar to right of 'f'");
3993 //
2nd
<br> as array
3994 let br2AsArray = synthesizeQueryTextRectArray(kLFLen *
2 +
6,
1);
3995 if (!checkQueryContentResult(br2AsArray, description +
"2nd <br>'s line breaker as array") ||
3996 !checkRectArray(br2AsArray, [br2], description +
"query text rect array result of 2nd <br> should match with each query text rect result")) {
4002 let br2_2 = synthesizeQueryTextRect(kLFLen +
7,
1);
4003 if (!checkQueryContentResult(br2_2, description +
"rect for \\n of \\r\\n caused by 2nd <br>")) {
4007 is(br2_2.top, br2.top, description +
"'\\r' and '\\n' should be at same top");
4008 is(br2_2.left, br2.left, description +
"'\\r' and '\\n' should be at same top");
4009 is(br2_2.height, br2.height, description +
"'\\r' and '\\n' should be same height");
4010 is(br2_2.width, br2.width, description +
"'\\r' and '\\n' should be same width");
4012 // \n of \r\n as array
4013 let br2_2AsArray = synthesizeQueryTextRectArray(kLFLen +
7,
1);
4014 if (!checkQueryContentResult(br2_2AsArray, description +
"rect array for \\n of \\r\\n caused by 2nd <br>") ||
4015 !checkRectArray(br2_2AsArray, [br2_2], description +
"query text rect array result of \\n of \\r\\n caused by 2nd <br> should match with each query text rect result")) {
4021 let next_br2 = synthesizeQueryTextRect(kLFLen *
2 +
6,
1);
4022 if (!checkQueryContentResult(next_br2, description +
"rect for next of 2nd <br>")) {
4026 is(next_br2.top, br2.top, description +
"2nd <br> and next of 2nd <br> should be at same top");
4027 is(next_br2.left, br2.left, description +
"2nd <br> and next of 2nd <br> should be at same top");
4028 is(next_br2.height, br2.height, description +
"2nd <br> and next of 2nd <br> should be same height");
4029 is(next_br2.width, br2.width, description +
"2nd <br> and next of 2nd <br> should be same width");
4031 // next of
2nd
<br> as array
4032 let next_br2AsArray = synthesizeQueryTextRectArray(kLFLen *
2 +
6,
1);
4033 if (!checkQueryContentResult(next_br2AsArray, description +
"rect array for next of 2nd <br>") ||
4034 !checkRectArray(next_br2AsArray, [next_br2], description +
"query text rect array result of next of 2nd <br> should match with each query text rect result")) {
4038 // too big offset for the editor
4039 tooBigOffset = synthesizeQueryTextRect(kLFLen *
2 +
7,
1);
4040 if (!checkQueryContentResult(tooBigOffset, description +
"rect for too big offset")) {
4044 is(tooBigOffset.top, next_br2.top, description +
"too big offset and next of 2nd <br> should be at same top");
4045 is(tooBigOffset.left, next_br2.left, description +
"too big offset and next of 2nd <br> should be at same left");
4046 is(tooBigOffset.height, next_br2.height, description +
"too big offset and next of 2nd <br> should be same height");
4047 is(tooBigOffset.width, next_br2.width, description +
"too big offset and next of 2nd <br> should be same width");
4049 // too big offset for the editors as array
4050 tooBigOffsetAsArray = synthesizeQueryTextRectArray(kLFLen *
2 +
7,
1);
4051 if (!checkQueryContentResult(tooBigOffsetAsArray, description +
"rect array for too big offset") ||
4052 !checkRectArray(tooBigOffsetAsArray, [tooBigOffset], description +
"query text rect array result with too big offset should match with each query text rect result")) {
4056 contenteditable.innerHTML =
"abc<br>def<br><br>";
4058 // \r\n
01234 56789 01
4060 description =
"runTextRectInContentEditableTest: \"" + contenteditable.innerHTML + "\
", ";
4063 f = synthesizeQueryTextRect(kLFLen +
5,
1);
4064 if (!checkQueryContentResult(f, description +
"rect for 'f'")) {
4068 is(f.top, e.top, description +
"'e' and 'f' should be at same top");
4069 isSimilarTo(f.left, e.left + e.width,
2, description +
"left of 'f' should be at similar to right of 'e'");
4070 is(f.height, e.height, description +
"'e' and 'f' should be same height");
4073 br2 = synthesizeQueryTextRect(kLFLen +
6,
1);
4074 if (!checkQueryContentResult(br2, description +
"rect for 2nd <br>")) {
4078 is(br2.top, f.top, description +
"'f' and a line breaker caused by 2nd <br> should be at same top");
4079 is(br2.height, f.height, description +
"'f' and a line breaker caused by 2nd <br> should be same height");
4080 ok(f.left < br2.left, description +
"left of a line breaker caused by 2nd <br> should be bigger than left of 'f', f.left=" + f.left +
", br2.left=" + br2.left);
4082 //
2nd
<br> as array
4083 br2AsArray = synthesizeQueryTextRectArray(kLFLen +
6,
1);
4084 if (!checkQueryContentResult(br2AsArray, description +
"2nd <br>'s line breaker as array") ||
4085 !checkRectArray(br2AsArray, [br2], description +
"query text rect array result of 2nd <br> should match with each query text rect result")) {
4091 let br2_2 = synthesizeQueryTextRect(kLFLen +
7,
1);
4092 if (!checkQueryContentResult(br2_2, description +
"rect for \\n of \\r\\n caused by 2nd <br>")) {
4096 is(br2_2.top, br2.top, description +
"'\\r' and '\\n' should be at same top");
4097 is(br2_2.left, br2.left, description +
"'\\r' and '\\n' should be at same top");
4098 is(br2_2.height, br2.height, description +
"'\\r' and '\\n' should be same height");
4099 is(br2_2.width, br2.width, description +
"'\\r' and '\\n' should be same width");
4101 // \n of \r\n as array
4102 let br2_2AsArray = synthesizeQueryTextRectArray(kLFLen +
7,
1);
4103 if (!checkQueryContentResult(br2_2AsArray, description +
"rect array for \\n of \\r\\n caused by 2nd <br>") ||
4104 !checkRectArray(br2_2AsArray, [br2_2], description +
"query text rect array result of \\n of \\r\\n caused by 2nd <br> should match with each query text rect result")) {
4110 let br3 = synthesizeQueryTextRect(kLFLen *
2 +
7,
1);
4111 if (!checkQueryContentResult(br3, description +
"rect for next of 3rd <br>")) {
4115 isSimilarTo(br3.top, d.top + d.height,
3, description +
"top of next of 3rd <br> should at similar to bottom of 'd'");
4116 isSimilarTo(br3.left, d.left,
2, description +
"left of next of 3rd <br> should be at similar to left of 'd'");
4117 isSimilarTo(br3.height, d.height,
2, description +
"next of 3rd <br> and 'd' should be similar height");
4119 //
3rd
<br> as array
4120 let br3AsArray = synthesizeQueryTextRectArray(kLFLen +
6,
1);
4121 if (!checkQueryContentResult(br3AsArray, description +
"3rd <br>'s line breaker as array") ||
4122 !checkRectArray(br3AsArray, [br3], description +
"query text rect array result of 3rd <br> should match with each query text rect result")) {
4128 let br3_2 = synthesizeQueryTextRect(kLFLen *
2 +
7,
1);
4129 if (!checkQueryContentResult(br3_2, description +
"rect for \\n of \\r\\n caused by 3rd <br>")) {
4133 is(br3_2.top, br3.top, description +
"'\\r' and '\\n' should be at same top");
4134 is(br3_2.left, br3.left, description +
"'\\r' and '\\n' should be at same left");
4135 is(br3_2.height, br3.height, description +
"'\\r' and '\\n' should be same height");
4136 is(br3_2.width, br3.width, description +
"'\\r' and '\\n' should be same width");
4138 // \n of \r\n as array
4139 let br3_2AsArray = synthesizeQueryTextRectArray(kLFLen *
2 +
7,
1);
4140 if (!checkQueryContentResult(br3_2AsArray, description +
"rect array for \\n of \\r\\n caused by 3rd <br>") ||
4141 !checkRectArray(br3_2AsArray, [br3_2], description +
"query text rect array result of \\n of \\r\\n caused by 3rd <br> should match with each query text rect result")) {
4147 let next_br3 = synthesizeQueryTextRect(kLFLen *
3 +
6,
1);
4148 if (!checkQueryContentResult(next_br3, description +
"rect for next of 3rd <br>")) {
4152 is(next_br3.top, br3.top, description +
"3rd <br> and next of 3rd <br> should be at same top");
4153 is(next_br3.left, br3.left, description +
"3rd <br> and next of 3rd <br> should be at same left");
4154 is(next_br3.height, br3.height, description +
"3rd <br> and next of 3rd <br> should be same height");
4155 is(next_br3.width, br3.width, description +
"3rd <br> and next of 3rd <br> should be same width");
4157 // next of
3rd
<br> as array
4158 let next_br3AsArray = synthesizeQueryTextRectArray(kLFLen *
3 +
6,
1);
4159 if (!checkQueryContentResult(next_br3AsArray, description +
"rect array for next of 3rd <br>") ||
4160 !checkRectArray(next_br3AsArray, [next_br3], description +
"query text rect array result of next of 3rd <br> should match with each query text rect result")) {
4164 // too big offset for the editor
4165 tooBigOffset = synthesizeQueryTextRect(kLFLen *
3 +
7,
1);
4166 if (!checkQueryContentResult(tooBigOffset, description +
"rect for too big offset")) {
4170 is(tooBigOffset.top, next_br3.top, description +
"too big offset and next of 3rd <br> should be at same top");
4171 is(tooBigOffset.left, next_br3.left, description +
"too big offset and next of 3rd <br> should be at same left");
4172 is(tooBigOffset.height, next_br3.height, description +
"too big offset and next of 3rd <br> should be same height");
4173 is(tooBigOffset.width, next_br3.width, description +
"too big offset and next of 3rd <br> should be same width");
4175 // too big offset for the editors as array
4176 tooBigOffsetAsArray = synthesizeQueryTextRectArray(kLFLen *
2 +
7,
1);
4177 if (checkQueryContentResult(tooBigOffsetAsArray, description +
"rect array for too big offset")) {
4178 checkRectArray(tooBigOffsetAsArray, [tooBigOffset], description +
"query text rect array result with too big offset should match with each query text rect result");
4181 if (!(function test_query_text_rects_across_invisible_text() {
4182 contenteditable.innerHTML =
"<div>\n<div>abc</div></div>";
4185 description = `runQueryTextRectInContentEditableTest: test_query_text_rects_across_invisible_text:
"${
4186 contenteditable.innerHTML.replace(/\n/g, "\\n
")
4189 const rectA = synthesizeQueryTextRect(kLFLen *
3,
1);
4190 if (!checkQueryContentResult(rectA, `${description} rect of
"a"`)) {
4193 const rectArrayFromStartToA = synthesizeQueryTextRectArray(
0, kLFLen *
3 +
1);
4194 if (!checkQueryContentResult(rectArrayFromStartToA, `${description} rect array from invisible text to
"a"`)) {
4197 const fromStartToARects = getRectArray(rectArrayFromStartToA);
4199 fromStartToARects[kLFLen *
3],
4201 `${description} rect for
"a" in array should be same as the result of query only it`
4206 fromStartToARects[kLFLen *
2],
4207 fromStartToARects[
0],
4208 `${description} rect for the linebreak in invisible text node should be same as first linebreak`
4214 function test_query_text_rects_starting_from_invisible_text() {
4215 contenteditable.innerHTML =
"<div>\n<div>abc</div></div>";
4218 description = `runQueryTextRectInContentEditableTest: test_query_text_rects_starting_from_invisible_text:
"${
4219 contenteditable.innerHTML.replace(/\n/g, "\\n
")
4222 const rectA = synthesizeQueryTextRect(kLFLen *
3,
1);
4223 if (!checkQueryContentResult(rectA, `${description} rect of
"a"`)) {
4226 const rectArrayFromInvisibleToA = synthesizeQueryTextRectArray(kLFLen, kLFLen *
2 +
1);
4227 if (!checkQueryContentResult(rectArrayFromInvisibleToA, `${description} rect array from invisible text to
"a"`)) {
4230 const fromInvisibleToARects = getRectArray(rectArrayFromInvisibleToA);
4232 fromInvisibleToARects[kLFLen *
2],
4234 `${description} rect for
"a" in array should be same as the result of query only it`
4238 // For now the rect of characters in invisible text node should be caret rect
4239 // before the following line break. This is inconsistent from the result of
4240 // the query text rect array event starting from the previous visible line
4241 // break or character, but users anyway cannot insert text into the invisible
4242 // text node only with user's operation. Therefore, this won't be problem
4243 // in usual web apps.
4244 const caretRectBeforeLineBreakBeforeA = fromInvisibleToARects[kLFLen];
4246 fromInvisibleToARects[
0],
4247 caretRectBeforeLineBreakBeforeA,
4248 `${description} rect for the linebreak in invisible text node should be same as caret rect before the following visible linebreak before
"a"`
4251 if (!test_query_text_rects_starting_from_invisible_text()) {
4256 function test_query_text_rects_starting_from_middle_of_invisible_linebreak() {
4257 contenteditable.innerHTML =
"<div>\n<div>abc</div></div>";
4260 description = `runQueryTextRectInContentEditableTest: test_query_text_rects_starting_from_middle_of_invisible_linebreak:
"${
4261 contenteditable.innerHTML.replace(/\n/g, "\\n
")
4264 const rectA = synthesizeQueryTextRect(kLFLen *
3,
1);
4265 if (!checkQueryContentResult(rectA, `${description} rect of
"a"`)) {
4268 const rectArrayFromInvisibleToA = synthesizeQueryTextRectArray(kLFLen +
1,
1 + kLFLen +
1);
4269 if (!checkQueryContentResult(rectArrayFromInvisibleToA, `${description} rect array from invisible text to
"a"`)) {
4272 const fromInvisibleToARects = getRectArray(rectArrayFromInvisibleToA);
4274 fromInvisibleToARects[
1 + kLFLen],
4276 `${description} rect for
"a" in array should be same as the result of query only it`
4280 // For now the rect of characters in invisible text node should be caret rect
4281 // before the following line break. This is inconsistent from the result of
4282 // the query text rect array event starting from the previous visible line
4283 // break or character, but users anyway cannot insert text into the invisible
4284 // text node only with user's operation. Therefore, this won't be problem
4285 // in usual web apps.
4286 const caretRectBeforeLineBreakBeforeA = fromInvisibleToARects[
1];
4288 fromInvisibleToARects[
0],
4289 caretRectBeforeLineBreakBeforeA,
4290 `${description} rect for the linebreak in invisible text node should be same as caret rect before the following visible linebreak before
"a"`
4293 if (!test_query_text_rects_starting_from_middle_of_invisible_linebreak()) {
4298 function test_query_text_rects_ending_with_invisible_text() {
4299 contenteditable.innerHTML =
"<div><div>abc</div>\n</div>";
4301 // \r\n
01 23 456 78
4302 description = `runQueryTextRectInContentEditableTest: test_query_text_rects_ending_with_invisible_text:
"${
4303 contenteditable.innerHTML.replace(/\n/g, "\\n
")
4306 const rectC = synthesizeQueryTextRect(kLFLen *
2 +
2,
1);
4307 if (!checkQueryContentResult(rectC, `${description} rect of
"c"`)) {
4310 const rectArrayFromCToInvisible = synthesizeQueryTextRectArray(kLFLen *
2 +
2,
1 + kLFLen);
4311 if (!checkQueryContentResult(rectArrayFromCToInvisible, `${description} rect array from
"c" to invisible linebreak`)) {
4314 const fromCToInvisibleRects = getRectArray(rectArrayFromCToInvisible);
4316 fromCToInvisibleRects[
0],
4318 `${description} rect for
"c" in array should be same as the result of query only it`
4322 const caretRectAfterC = {
4323 left: rectC.left + rectC.width,
4326 height: rectC.height,
4328 return checkRectFuzzy(
4329 fromCToInvisibleRects[
1],
4337 `${description} rect for the linebreak in invisible text node should be same as caret rect after
"c"`
4340 if (!test_query_text_rects_ending_with_invisible_text()) {
4341 // eslint-disable-next-line no-useless-return
4346 function runCharAtPointTest(aFocusedEditor, aTargetName)
4348 aFocusedEditor.value =
"This is a test of the\nContent Events";
4349 //
012345678901234567890 12345678901234
4352 aFocusedEditor.focus();
4355 const kTestingOffset = [
0,
10,
20,
21 + kLFLen,
34 + kLFLen];
4356 const kLeftSideOffset = [ kNone,
9,
19, kNone,
33 + kLFLen];
4357 const kRightSideOffset = [
1,
11, kNone,
22 + kLFLen, kNone];
4358 const kLeftTentativeCaretOffset = [
0,
10,
20,
21 + kLFLen,
34 + kLFLen];
4359 const kRightTentativeCaretOffset = [
1,
11,
21,
22 + kLFLen,
35 + kLFLen];
4361 let editorRect = synthesizeQueryEditorRect();
4362 if (!checkQueryContentResult(editorRect,
4363 "runCharAtPointTest (" + aTargetName +
"): editorRect")) {
4367 for (let i =
0; i < kTestingOffset.length; i++) {
4368 let textRect = synthesizeQueryTextRect(kTestingOffset[i],
1);
4369 if (!checkQueryContentResult(textRect,
4370 "runCharAtPointTest (" + aTargetName +
"): textRect: i=" + i)) {
4374 checkRectContainsRect(textRect, editorRect,
4375 "runCharAtPointTest (" + aTargetName +
4376 "): the text rect isn't in the editor");
4378 // Test #
1, getting same character rect by the point near the top-left.
4379 let charAtPt1 = synthesizeCharAtPoint(textRect.left +
1,
4381 if (checkQueryContentResult(charAtPt1,
4382 "runCharAtPointTest (" + aTargetName +
"): charAtPt1: i=" + i)) {
4383 ok(!charAtPt1.notFound,
4384 "runCharAtPointTest (" + aTargetName +
"): charAtPt1 isn't found: i=" + i);
4385 if (!charAtPt1.notFound) {
4386 is(charAtPt1.offset, kTestingOffset[i],
4387 "runCharAtPointTest (" + aTargetName +
"): charAtPt1 offset is wrong: i=" + i);
4388 checkRect(charAtPt1, textRect,
"runCharAtPointTest (" + aTargetName +
4389 "): charAtPt1 left is wrong: i=" + i);
4391 ok(!charAtPt1.tentativeCaretOffsetNotFound,
4392 "runCharAtPointTest (" + aTargetName +
"): tentative caret offset for charAtPt1 isn't found: i=" + i);
4393 if (!charAtPt1.tentativeCaretOffsetNotFound) {
4394 is(charAtPt1.tentativeCaretOffset, kLeftTentativeCaretOffset[i],
4395 "runCharAtPointTest (" + aTargetName +
"): tentative caret offset for charAtPt1 is wrong: i=" + i);
4399 // Test #
2, getting same character rect by the point near the bottom-right.
4400 let charAtPt2 = synthesizeCharAtPoint(textRect.left + textRect.width -
2,
4401 textRect.top + textRect.height -
2);
4402 if (checkQueryContentResult(charAtPt2,
4403 "runCharAtPointTest (" + aTargetName +
"): charAtPt2: i=" + i)) {
4404 ok(!charAtPt2.notFound,
4405 "runCharAtPointTest (" + aTargetName +
"): charAtPt2 isn't found: i=" + i);
4406 if (!charAtPt2.notFound) {
4407 is(charAtPt2.offset, kTestingOffset[i],
4408 "runCharAtPointTest (" + aTargetName +
"): charAtPt2 offset is wrong: i=" + i);
4409 checkRect(charAtPt2, textRect,
"runCharAtPointTest (" + aTargetName +
4410 "): charAtPt1 left is wrong: i=" + i);
4412 ok(!charAtPt2.tentativeCaretOffsetNotFound,
4413 "runCharAtPointTest (" + aTargetName +
"): tentative caret offset for charAtPt2 isn't found: i=" + i);
4414 if (!charAtPt2.tentativeCaretOffsetNotFound) {
4415 is(charAtPt2.tentativeCaretOffset, kRightTentativeCaretOffset[i],
4416 "runCharAtPointTest (" + aTargetName +
"): tentative caret offset for charAtPt2 is wrong: i=" + i);
4420 // Test #
3, getting left character offset.
4421 let charAtPt3 = synthesizeCharAtPoint(textRect.left -
2,
4423 if (checkQueryContentResult(charAtPt3,
4424 "runCharAtPointTest (" + aTargetName +
"): charAtPt3: i=" + i)) {
4425 is(charAtPt3.notFound, kLeftSideOffset[i] == kNone,
4426 kLeftSideOffset[i] == kNone ?
4427 "runCharAtPointTest (" + aTargetName +
"): charAtPt3 is found: i=" + i :
4428 "runCharAtPointTest (" + aTargetName +
"): charAtPt3 isn't found: i=" + i);
4429 if (!charAtPt3.notFound) {
4430 is(charAtPt3.offset, kLeftSideOffset[i],
4431 "runCharAtPointTest (" + aTargetName +
"): charAtPt3 offset is wrong: i=" + i);
4433 if (kLeftSideOffset[i] == kNone) {
4434 // There may be no enough padding-left (depends on platform)
4436 "runCharAtPointTest (" + aTargetName +
"): tentative caret offset for charAtPt3 isn't tested: i=" + i);
4438 ok(!charAtPt3.tentativeCaretOffsetNotFound,
4439 "runCharAtPointTest (" + aTargetName +
"): tentative caret offset for charAtPt3 isn't found: i=" + i);
4440 if (!charAtPt3.tentativeCaretOffsetNotFound) {
4441 is(charAtPt3.tentativeCaretOffset, kLeftTentativeCaretOffset[i],
4442 "runCharAtPointTest (" + aTargetName +
"): tentative caret offset for charAtPt3 is wrong: i=" + i);
4447 // Test #
4, getting right character offset.
4448 let charAtPt4 = synthesizeCharAtPoint(textRect.left + textRect.width +
1,
4449 textRect.top + textRect.height -
2);
4450 if (checkQueryContentResult(charAtPt4,
4451 "runCharAtPointTest (" + aTargetName +
"): charAtPt4: i=" + i)) {
4452 is(charAtPt4.notFound, kRightSideOffset[i] == kNone,
4453 kRightSideOffset[i] == kNone ?
4454 "runCharAtPointTest (" + aTargetName +
"): charAtPt4 is found: i=" + i :
4455 "runCharAtPointTest (" + aTargetName +
"): charAtPt4 isn't found: i=" + i);
4456 if (!charAtPt4.notFound) {
4457 is(charAtPt4.offset, kRightSideOffset[i],
4458 "runCharAtPointTest (" + aTargetName +
"): charAtPt4 offset is wrong: i=" + i);
4460 ok(!charAtPt4.tentativeCaretOffsetNotFound,
4461 "runCharAtPointTest (" + aTargetName +
"): tentative caret offset for charAtPt4 isn't found: i=" + i);
4462 if (!charAtPt4.tentativeCaretOffsetNotFound) {
4463 is(charAtPt4.tentativeCaretOffset, kRightTentativeCaretOffset[i],
4464 "runCharAtPointTest (" + aTargetName +
"): tentative caret offset for charAtPt4 is wrong: i=" + i);
4470 function runCharAtPointAtOutsideTest()
4473 textarea.value =
"some text";
4474 let editorRect = synthesizeQueryEditorRect();
4475 if (!checkQueryContentResult(editorRect,
4476 "runCharAtPointAtOutsideTest: editorRect")) {
4479 // Check on a text node which is at the outside of editor.
4480 let charAtPt = synthesizeCharAtPoint(editorRect.left +
20,
4481 editorRect.top -
10);
4482 if (checkQueryContentResult(charAtPt,
4483 "runCharAtPointAtOutsideTest: charAtPt")) {
4484 ok(charAtPt.notFound,
4485 "runCharAtPointAtOutsideTest: charAtPt is found on outside of editor");
4486 ok(charAtPt.tentativeCaretOffsetNotFound,
4487 "runCharAtPointAtOutsideTest: tentative caret offset for charAtPt is found on outside of editor");
4491 async function runSetSelectionEventTest()
4493 contenteditable.focus();
4495 const selection = windowOfContenteditable.getSelection();
4498 contenteditable.innerHTML =
"abc<br>def";
4500 await synthesizeSelectionSet(
0,
100);
4501 is(selection.anchorNode, contenteditable.firstChild,
4502 "runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the first text node");
4503 is(selection.anchorOffset,
0,
4504 "runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
4505 is(selection.focusNode, contenteditable,
4506 "runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node of the editor");
4507 is(selection.focusOffset, contenteditable.childNodes.length,
4508 "runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of children");
4509 checkSelection(
0,
"abc" + kLF +
"def",
"runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\
"");
4511 await synthesizeSelectionSet(
2,
2 + kLFLen);
4512 is(selection.anchorNode, contenteditable.firstChild,
4513 "runSetSelectionEventTest #1 (2, 2+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the first text node");
4514 is(selection.anchorOffset,
2,
4515 "runSetSelectionEventTest #1 (2, 2+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 2");
4516 is(selection.focusNode, contenteditable.lastChild,
4517 "runSetSelectionEventTest #1 (2, 2+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the last text node");
4518 is(selection.focusOffset,
1,
4519 "runSetSelectionEventTest #1 (2, 2+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 1");
4520 checkSelection(
2,
"c" + kLF +
"d",
"runSetSelectionEventTest #1 (2, 2+kLFLen), \"" + contenteditable.innerHTML + "\
"");
4522 await synthesizeSelectionSet(
1,
2);
4523 is(selection.anchorNode, contenteditable.firstChild,
4524 "runSetSelectionEventTest #1 (1, 2), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the first text node");
4525 is(selection.anchorOffset,
1,
4526 "runSetSelectionEventTest #1 (1, 2), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 1");
4527 is(selection.focusNode, contenteditable.firstChild,
4528 "runSetSelectionEventTest #1 (1, 2), \"" + contenteditable.innerHTML + "\
": selection focus node should be the first text node");
4529 is(selection.focusOffset, contenteditable.firstChild.wholeText.length,
4530 "runSetSelectionEventTest #1 (1, 2), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the length of the text node");
4531 checkSelection(
1,
"bc",
"runSetSelectionEventTest #1 (1, 2), \"" + contenteditable.innerHTML + "\
"");
4533 await synthesizeSelectionSet(
3, kLFLen);
4534 is(selection.anchorNode, contenteditable.firstChild,
4535 "runSetSelectionEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the first text node");
4536 is(selection.anchorOffset, contenteditable.firstChild.wholeText.length,
4537 "runSetSelectionEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the length of the first text node");
4538 is(selection.focusNode, contenteditable,
4539 "runSetSelectionEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
4540 is(selection.focusOffset,
2,
4541 "runSetSelectionEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the index of the last text node");
4542 checkSelection(
3, kLF,
"runSetSelectionEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\
"");
4544 await synthesizeSelectionSet(
6+kLFLen,
0);
4545 is(selection.anchorNode, contenteditable.lastChild,
4546 "runSetSelectionEventTest #1 (6+kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the last text node");
4547 is(selection.anchorOffset, contenteditable.lastChild.wholeText.length,
4548 "runSetSelectionEventTest #1 (6+kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the length of the last text node");
4549 is(selection.focusNode, contenteditable.lastChild,
4550 "runSetSelectionEventTest #1 (6+kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the last text node");
4551 is(selection.anchorOffset, contenteditable.lastChild.wholeText.length,
4552 "runSetSelectionEventTest #1 (6+kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the length of the last text node");
4553 checkSelection(
6 + kLFLen,
"",
"runSetSelectionEventTest #1 (6+kLFLen, 0), \"" + contenteditable.innerHTML + "\
"");
4555 await synthesizeSelectionSet(
100,
0);
4556 is(selection.anchorNode, contenteditable,
4557 "runSetSelectionEventTest #1 (100, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node of the editor");
4558 is(selection.anchorOffset, contenteditable.childNodes.length,
4559 "runSetSelectionEventTest #1 (100, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the count of children");
4560 is(selection.focusNode, contenteditable,
4561 "runSetSelectionEventTest #1 (100, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node of the editor");
4562 is(selection.focusOffset, contenteditable.childNodes.length,
4563 "runSetSelectionEventTest #1 (100, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of children");
4564 checkSelection(
6 + kLFLen,
"",
"runSetSelectionEventTest #1 (100, 0), \"" + contenteditable.innerHTML + "\
"");
4567 contenteditable.innerHTML =
"<p>a<b>b</b>c</p><p>def</p>";
4569 await synthesizeSelectionSet(kLFLen,
4+kLFLen);
4570 is(selection.anchorNode, contenteditable.firstChild,
4571 "runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the first <p> node");
4572 is(selection.anchorOffset,
0,
4573 "runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the index of the first <p> node");
4574 is(selection.focusNode, contenteditable.lastChild.firstChild,
4575 "runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the text node in the second <p> node");
4576 is(selection.focusOffset,
1,
4577 "runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 1");
4578 checkSelection(kLFLen,
"abc" + kLF +
"d",
"runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\
"");
4580 await synthesizeSelectionSet(kLFLen,
2);
4581 is(selection.anchorNode, contenteditable.firstChild,
4582 "runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the first <p> node");
4583 is(selection.anchorOffset,
0,
4584 "runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the index of the first <p> node");
4585 is(selection.focusNode, contenteditable.firstChild.childNodes.item(
1).firstChild,
4586 "runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\
": selection focus node should be the text node in the <b> node");
4587 is(selection.focusOffset, contenteditable.firstChild.childNodes.item(
1).firstChild.wholeText.length,
4588 "runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the length of the text node in the <b> node");
4589 checkSelection(kLFLen,
"ab",
"runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\
"");
4591 await synthesizeSelectionSet(
1+kLFLen,
2);
4592 is(selection.anchorNode, contenteditable.firstChild.firstChild,
4593 "runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the first text node");
4594 is(selection.anchorOffset,
1,
4595 "runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 1");
4596 is(selection.focusNode, contenteditable.firstChild.lastChild,
4597 "runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\
": selection focus node should be the last text node in the first <p> node");
4598 is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
4599 "runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the length of the last text node in the first <p> node");
4600 checkSelection(
1+kLFLen,
"bc",
"runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\
"");
4602 await synthesizeSelectionSet(
2+kLFLen,
2+kLFLen);
4603 is(selection.anchorNode, contenteditable.firstChild.childNodes.item(
1).firstChild,
4604 "runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the text node in the <b> node");
4605 is(selection.anchorOffset, contenteditable.firstChild.childNodes.item(
1).firstChild.wholeText.length,
4606 "runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the length of the text node in the <b> node");
4607 is(selection.focusNode, contenteditable.lastChild.firstChild,
4608 "runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the text node in the last <p> node");
4609 is(selection.focusOffset,
1,
4610 "runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 1");
4611 checkSelection(
2+kLFLen,
"c" + kLF +
"d",
"runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\
"");
4613 await synthesizeSelectionSet(
3+kLFLen*
2,
1);
4614 is(selection.anchorNode, contenteditable.lastChild,
4615 "runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the second <p> node");
4616 is(selection.anchorOffset,
0,
4617 "runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the index of the second <p> node");
4618 is(selection.focusNode, contenteditable.lastChild.firstChild,
4619 "runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
": selection focus node should be the text node in the second <p> node");
4620 is(selection.focusOffset,
1,
4621 "runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 1");
4622 checkSelection(
3+kLFLen*
2,
"d",
"runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
"");
4624 await synthesizeSelectionSet(
0,
0);
4625 is(selection.anchorNode, contenteditable,
4626 "runSetSelectionEventTest #2 (0, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
4627 is(selection.anchorOffset,
0,
4628 "runSetSelectionEventTest #2 (0, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
4629 is(selection.focusNode, contenteditable,
4630 "runSetSelectionEventTest #2 (0, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
4631 is(selection.focusOffset,
0,
4632 "runSetSelectionEventTest #2 (0, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
4633 checkSelection(
0,
"",
"runSetSelectionEventTest #2 (0, 0), \"" + contenteditable.innerHTML + "\
"");
4635 await synthesizeSelectionSet(
0, kLFLen);
4636 is(selection.anchorNode, contenteditable,
4637 "runSetSelectionEventTest #2 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
4638 is(selection.anchorOffset,
0,
4639 "runSetSelectionEventTest #2 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the index of the first <p> node");
4640 is(selection.focusNode, contenteditable.firstChild,
4641 "runSetSelectionEventTest #2 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the first <p> node");
4642 is(selection.focusOffset,
0,
4643 "runSetSelectionEventTest #2 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
4644 checkSelection(
0, kLF,
"runSetSelectionEventTest #2 (0, kLFLen), \"" + contenteditable.innerHTML + "\
"");
4646 await synthesizeSelectionSet(
2+kLFLen,
1+kLFLen);
4647 is(selection.anchorNode, contenteditable.firstChild.childNodes.item(
1).firstChild,
4648 "runSetSelectionEventTest #2 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the last text node of the <b> node");
4649 is(selection.anchorOffset, contenteditable.firstChild.childNodes.item(
1).firstChild.wholeText.length,
4650 "runSetSelectionEventTest #2 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the length of the last text node of the first <b> node");
4651 is(selection.focusNode, contenteditable.lastChild,
4652 "runSetSelectionEventTest #2 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the second <p> node");
4653 is(selection.focusOffset,
0,
4654 "runSetSelectionEventTest #2 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
4655 checkSelection(
2+kLFLen,
"c" + kLF,
"runSetSelectionEventTest #2 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
"");
4657 await synthesizeSelectionSet(
3+kLFLen, kLFLen);
4658 is(selection.anchorNode, contenteditable.firstChild.lastChild,
4659 "runSetSelectionEventTest #2 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the last text node of the first <p> node");
4660 is(selection.anchorOffset, contenteditable.firstChild.lastChild.wholeText.length,
4661 "runSetSelectionEventTest #2 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the length of the last text node of the first <p> node");
4662 is(selection.focusNode, contenteditable.lastChild,
4663 "runSetSelectionEventTest #2 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the second <p> node");
4664 is(selection.focusOffset,
0,
4665 "runSetSelectionEventTest #2 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
4666 checkSelection(
3+kLFLen, kLF,
"runSetSelectionEventTest #2 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
"");
4668 await synthesizeSelectionSet(
3+kLFLen,
1+kLFLen);
4669 is(selection.anchorNode, contenteditable.firstChild.lastChild,
4670 "runSetSelectionEventTest #2 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the last text node of the first <p> node");
4671 is(selection.anchorOffset, contenteditable.firstChild.lastChild.wholeText.length,
4672 "runSetSelectionEventTest #2 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the length of the last text node of the first <p> node");
4673 is(selection.focusNode, contenteditable.lastChild.firstChild,
4674 "runSetSelectionEventTest #2 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the text node of the second <p> node");
4675 is(selection.focusOffset,
1,
4676 "runSetSelectionEventTest #2 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 1");
4677 checkSelection(
3+kLFLen, kLF +
"d",
"runSetSelectionEventTest #2 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
"");
4680 contenteditable.innerHTML =
"<div>abc<p>def</p></div>";
4682 await synthesizeSelectionSet(
1+kLFLen,
2);
4683 is(selection.anchorNode, contenteditable.firstChild.firstChild,
4684 "runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the first text node");
4685 is(selection.anchorOffset,
1,
4686 "runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 1");
4687 is(selection.focusNode, contenteditable.firstChild.firstChild,
4688 "runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\
": selection focus node should be the first text node");
4689 is(selection.focusOffset, contenteditable.firstChild.firstChild.wholeText.length,
4690 "runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the length of the first text node");
4691 checkSelection(
1+kLFLen,
"bc",
"runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\
"");
4693 await synthesizeSelectionSet(
1+kLFLen,
3+kLFLen);
4694 is(selection.anchorNode, contenteditable.firstChild.firstChild,
4695 "runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the first text node");
4696 is(selection.anchorOffset,
1,
4697 "runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 1");
4698 is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
4699 "runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the text node in the <p> node");
4700 is(selection.focusOffset,
1,
4701 "runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 1");
4702 checkSelection(
1+kLFLen,
"bc" + kLF +
"d",
"runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\
"");
4704 await synthesizeSelectionSet(
3+kLFLen,
0);
4705 is(selection.anchorNode, contenteditable.firstChild.firstChild,
4706 "runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the first text node");
4707 is(selection.anchorOffset, contenteditable.firstChild.firstChild.wholeText.length,
4708 "runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the length of the first text node");
4709 is(selection.focusNode, contenteditable.firstChild.firstChild,
4710 "runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the first text node");
4711 is(selection.focusOffset, contenteditable.firstChild.firstChild.wholeText.length,
4712 "runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the length of the first text node");
4713 checkSelection(
3+kLFLen,
"",
"runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\
"");
4715 await synthesizeSelectionSet(
0,
6+kLFLen*
2);
4716 is(selection.anchorNode, contenteditable,
4717 "runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
4718 is(selection.anchorOffset,
0,
4719 "runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
4720 is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
4721 "runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection focus node should be the last text node");
4722 is(selection.focusOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
4723 "runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the length of the last text node");
4724 checkSelection(
0, kLF +
"abc" + kLF +
"def",
"runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\
"");
4726 await synthesizeSelectionSet(
0,
100);
4727 is(selection.anchorNode, contenteditable,
4728 "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
4729 is(selection.anchorOffset,
0,
4730 "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
4731 is(selection.focusNode, contenteditable,
4732 "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
4733 is(selection.focusOffset, contenteditable.childNodes.length,
4734 "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the root's children");
4735 checkSelection(
0, kLF +
"abc" + kLF +
"def",
"runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\
"");
4737 await synthesizeSelectionSet(
4+kLFLen*
2,
2);
4738 is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
4739 "runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the last text node");
4740 is(selection.anchorOffset,
1,
4741 "runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 1");
4742 is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
4743 "runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\
": selection focus node should be the last text node");
4744 is(selection.focusOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
4745 "runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the length of the last text node");
4746 checkSelection(
4+kLFLen*
2,
"ef",
"runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\
"");
4748 await synthesizeSelectionSet(
4+kLFLen*
2,
100);
4749 is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
4750 "runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the last text node");
4751 is(selection.anchorOffset,
1,
4752 "runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 1");
4753 is(selection.focusNode, contenteditable,
4754 "runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
4755 is(selection.focusOffset, contenteditable.childNodes.length,
4756 "runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the root's children");
4757 checkSelection(
4+kLFLen*
2,
"ef",
"runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\
"");
4759 await synthesizeSelectionSet(
6+kLFLen*
2,
0);
4760 is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
4761 "runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the last text node");
4762 is(selection.anchorOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
4763 "runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the length of the last text node");
4764 is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
4765 "runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the last text node");
4766 is(selection.focusOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
4767 "runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the length of the last text node");
4768 checkSelection(
6+kLFLen*
2,
"",
"runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
"");
4770 await synthesizeSelectionSet(
6+kLFLen*
2,
1);
4771 is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
4772 "runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the last text node");
4773 is(selection.anchorOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
4774 "runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the length of the last text node");
4775 is(selection.focusNode, contenteditable,
4776 "runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
4777 is(selection.focusOffset, contenteditable.childNodes.length,
4778 "runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the root's children");
4779 checkSelection(
6+kLFLen*
2,
"",
"runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
"");
4781 await synthesizeSelectionSet(
0, kLFLen);
4782 is(selection.anchorNode, contenteditable,
4783 "runSetSelectionEventTest #3 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
4784 is(selection.anchorOffset,
0,
4785 "runSetSelectionEventTest #3 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the index of the first text node");
4786 is(selection.focusNode, contenteditable.firstChild,
4787 "runSetSelectionEventTest #3 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the <div> node");
4788 is(selection.focusOffset,
0,
4789 "runSetSelectionEventTest #3 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
4790 checkSelection(
0, kLF,
"runSetSelectionEventTest #3 (0, kLFLen), \"" + contenteditable.innerHTML + "\
"");
4792 await synthesizeSelectionSet(
0,
1+kLFLen);
4793 is(selection.anchorNode, contenteditable,
4794 "runSetSelectionEventTest #3 (0, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
4795 is(selection.anchorOffset,
0,
4796 "runSetSelectionEventTest #3 (0, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the index of the <div> node");
4797 is(selection.focusNode, contenteditable.firstChild.firstChild,
4798 "runSetSelectionEventTest #3 (0, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the first text node of the <div> node");
4799 is(selection.focusOffset,
1,
4800 "runSetSelectionEventTest #3 (0, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 1");
4801 checkSelection(
0, kLF +
"a",
"runSetSelectionEventTest #3 (0, 1+kLFLen), \"" + contenteditable.innerHTML + "\
"");
4803 await synthesizeSelectionSet(
2+kLFLen,
1+kLFLen);
4804 is(selection.anchorNode, contenteditable.firstChild.firstChild,
4805 "runSetSelectionEventTest #3 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the text node of the <div> node");
4806 is(selection.anchorOffset,
2,
4807 "runSetSelectionEventTest #3 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 2");
4808 is(selection.focusNode, contenteditable.firstChild.lastChild,
4809 "runSetSelectionEventTest #3 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the <p> node");
4810 is(selection.focusOffset,
0,
4811 "runSetSelectionEventTest #3 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
4812 checkSelection(
2+kLFLen,
"c" + kLF,
"runSetSelectionEventTest #3 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
"");
4814 await synthesizeSelectionSet(
3+kLFLen, kLFLen);
4815 is(selection.anchorNode, contenteditable.firstChild.firstChild,
4816 "runSetSelectionEventTest #3 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the text node of the <div> node");
4817 is(selection.anchorOffset, contenteditable.firstChild.firstChild.wholeText.length,
4818 "runSetSelectionEventTest #3 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the length of the text node of the <div> node");
4819 is(selection.focusNode, contenteditable.firstChild.lastChild,
4820 "runSetSelectionEventTest #3 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the <p> node");
4821 is(selection.focusOffset,
0,
4822 "runSetSelectionEventTest #3 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
4823 checkSelection(
3+kLFLen, kLF,
"runSetSelectionEventTest #3 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
"");
4825 await synthesizeSelectionSet(
3+kLFLen,
1+kLFLen);
4826 is(selection.anchorNode, contenteditable.firstChild.firstChild,
4827 "runSetSelectionEventTest #3 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the text node of the <div> node");
4828 is(selection.anchorOffset, contenteditable.firstChild.firstChild.wholeText.length,
4829 "runSetSelectionEventTest #3 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the length of the text node of the <div> node");
4830 is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
4831 "runSetSelectionEventTest #3 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the text node of the <p> node");
4832 is(selection.focusOffset,
1,
4833 "runSetSelectionEventTest #3 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 1");
4834 checkSelection(
3+kLFLen, kLF +
"d",
"runSetSelectionEventTest #3 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
"");
4837 contenteditable.innerHTML =
"<div><p>abc</p>def</div>";
4839 await synthesizeSelectionSet(
1+kLFLen*
2,
2);
4840 is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
4841 "runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the text node in the <p> node");
4842 is(selection.anchorOffset,
1,
4843 "runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 1");
4844 is(selection.focusNode, contenteditable.firstChild.firstChild.firstChild,
4845 "runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\
": selection focus node should be the text node in the <p> node");
4846 is(selection.focusOffset, contenteditable.firstChild.firstChild.firstChild.wholeText.length,
4847 "runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the length of the text node in the <p> node");
4848 checkSelection(
1+kLFLen*
2,
"bc",
"runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\
"");
4850 await synthesizeSelectionSet(
1+kLFLen*
2,
3);
4851 is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
4852 "runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the text node in the <p> node");
4853 is(selection.anchorOffset,
1,
4854 "runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 1");
4855 is(selection.focusNode, contenteditable.firstChild.lastChild,
4856 "runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\
": selection focus node should be the last text node");
4857 is(selection.focusOffset,
1,
4858 "runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 1");
4859 checkSelection(
1+kLFLen*
2,
"bcd",
"runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\
"");
4861 await synthesizeSelectionSet(
3+kLFLen*
2,
0);
4862 is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
4863 "runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the text node in the <p> node");
4864 is(selection.anchorOffset, contenteditable.firstChild.firstChild.firstChild.wholeText.length,
4865 "runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the length of the text node in the <p> node");
4866 is(selection.focusNode, contenteditable.firstChild.firstChild.firstChild,
4867 "runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the text node in the <p> node");
4868 is(selection.focusOffset, contenteditable.firstChild.firstChild.firstChild.wholeText.length,
4869 "runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the length of the text node in the <p> node");
4870 checkSelection(
3+kLFLen*
2,
"",
"runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
"");
4872 await synthesizeSelectionSet(
0,
6+kLFLen*
2);
4873 is(selection.anchorNode, contenteditable,
4874 "runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
4875 is(selection.anchorOffset,
0,
4876 "runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
4877 is(selection.focusNode, contenteditable.firstChild.lastChild,
4878 "runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection focus node should be the last text node");
4879 is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
4880 "runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the length of the last text node");
4881 checkSelection(
0, kLF + kLF +
"abcdef",
"runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\
"");
4883 await synthesizeSelectionSet(
0,
100);
4884 is(selection.anchorNode, contenteditable,
4885 "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
4886 is(selection.anchorOffset,
0,
4887 "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
4888 is(selection.focusNode, contenteditable,
4889 "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
4890 is(selection.focusOffset, contenteditable.childNodes.length,
4891 "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the root's children");
4892 checkSelection(
0, kLF + kLF +
"abcdef",
"runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\
"");
4894 await synthesizeSelectionSet(
4+kLFLen*
2,
2);
4895 is(selection.anchorNode, contenteditable.firstChild.lastChild,
4896 "runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the last text node");
4897 is(selection.anchorOffset,
1,
4898 "runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 1");
4899 is(selection.focusNode, contenteditable.firstChild.lastChild,
4900 "runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\
": selection focus node should be the last text node");
4901 is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
4902 "runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the length of the last text node");
4903 checkSelection(
4+kLFLen*
2,
"ef",
"runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\
"");
4905 await synthesizeSelectionSet(
4+kLFLen*
2,
100);
4906 is(selection.anchorNode, contenteditable.firstChild.lastChild,
4907 "runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the last text node");
4908 is(selection.anchorOffset,
1,
4909 "runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 1");
4910 is(selection.focusNode, contenteditable,
4911 "runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
4912 is(selection.focusOffset, contenteditable.childNodes.length,
4913 "runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the root's children");
4914 checkSelection(
4+kLFLen*
2,
"ef",
"runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\
"");
4916 await synthesizeSelectionSet(
6+kLFLen*
2,
0);
4917 is(selection.anchorNode, contenteditable.firstChild.lastChild,
4918 "runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the last text node");
4919 is(selection.anchorOffset, contenteditable.firstChild.lastChild.wholeText.length,
4920 "runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the length of the last text node");
4921 is(selection.focusNode, contenteditable.firstChild.lastChild,
4922 "runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the last text node");
4923 is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
4924 "runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the length of the last text node");
4925 checkSelection(
6+kLFLen*
2,
"",
"runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
"");
4927 await synthesizeSelectionSet(
6+kLFLen*
2,
1);
4928 is(selection.anchorNode, contenteditable.firstChild.lastChild,
4929 "runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the last text node");
4930 is(selection.anchorOffset, contenteditable.firstChild.lastChild.wholeText.length,
4931 "runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the length of the last text node");
4932 is(selection.focusNode, contenteditable,
4933 "runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
4934 is(selection.focusOffset, contenteditable.childNodes.length,
4935 "runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the root's children");
4936 checkSelection(
6+kLFLen*
2,
"",
"runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
"");
4938 await synthesizeSelectionSet(
0, kLFLen);
4939 is(selection.anchorNode, contenteditable,
4940 "runSetSelectionEventTest #4 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
4941 is(selection.anchorOffset,
0,
4942 "runSetSelectionEventTest #4 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the index of the <div> node");
4943 is(selection.focusNode, contenteditable.firstChild,
4944 "runSetSelectionEventTest #4 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the <div> node");
4945 is(selection.focusOffset,
0,
4946 "runSetSelectionEventTest #4 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
4947 checkSelection(
0, kLF,
"runSetSelectionEventTest #4 (0, kLFLen), \"" + contenteditable.innerHTML + "\
"");
4949 await synthesizeSelectionSet(
0, kLFLen*
2);
4950 is(selection.anchorNode, contenteditable,
4951 "runSetSelectionEventTest #4 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
4952 is(selection.anchorOffset,
0,
4953 "runSetSelectionEventTest #4 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the index of the <div> node");
4954 is(selection.focusNode, contenteditable.firstChild.firstChild,
4955 "runSetSelectionEventTest #4 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection focus node should be the <p> node");
4956 is(selection.focusOffset,
0,
4957 "runSetSelectionEventTest #4 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
4958 checkSelection(
0, kLF + kLF,
"runSetSelectionEventTest #4 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
"");
4960 await synthesizeSelectionSet(
0,
1+kLFLen*
2);
4961 is(selection.anchorNode, contenteditable,
4962 "runSetSelectionEventTest #4 (0, 1+kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
4963 is(selection.anchorOffset,
0,
4964 "runSetSelectionEventTest #4 (0, 1+kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the index of the <div> node");
4965 is(selection.focusNode, contenteditable.firstChild.firstChild.firstChild,
4966 "runSetSelectionEventTest #4 (0, 1+kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection focus node should be the text node in the <p> node");
4967 is(selection.focusOffset,
1,
4968 "runSetSelectionEventTest #4 (0, 1+kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 1");
4969 checkSelection(
0, kLF + kLF +
"a",
"runSetSelectionEventTest #4 (0, 1+kLFLen*2), \"" + contenteditable.innerHTML + "\
"");
4971 await synthesizeSelectionSet(kLFLen,
0);
4972 is(selection.anchorNode, contenteditable.firstChild,
4973 "runSetSelectionEventTest #4 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the <div> node");
4974 is(selection.anchorOffset,
0,
4975 "runSetSelectionEventTest #4 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
4976 is(selection.focusNode, contenteditable.firstChild,
4977 "runSetSelectionEventTest #4 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the <div> node");
4978 is(selection.focusOffset,
0,
4979 "runSetSelectionEventTest #4 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
4980 checkSelection(kLFLen,
"",
"runSetSelectionEventTest #4 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
"");
4982 await synthesizeSelectionSet(kLFLen, kLFLen);
4983 is(selection.anchorNode, contenteditable.firstChild,
4984 "runSetSelectionEventTest #4 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the <div> node");
4985 is(selection.anchorOffset,
0,
4986 "runSetSelectionEventTest #4 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the index of the <p> node");
4987 is(selection.focusNode, contenteditable.firstChild.firstChild,
4988 "runSetSelectionEventTest #4 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the <p> node");
4989 is(selection.focusOffset,
0,
4990 "runSetSelectionEventTest #4 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
4991 checkSelection(kLFLen, kLF,
"runSetSelectionEventTest #4 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
"");
4993 await synthesizeSelectionSet(kLFLen,
1+kLFLen);
4994 is(selection.anchorNode, contenteditable.firstChild,
4995 "runSetSelectionEventTest #4 (kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the <div> node");
4996 is(selection.anchorOffset,
0,
4997 "runSetSelectionEventTest #4 (kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the index of the <p> node");
4998 is(selection.focusNode, contenteditable.firstChild.firstChild.firstChild,
4999 "runSetSelectionEventTest #4 (kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the text node in the <p> node");
5000 is(selection.focusOffset,
1,
5001 "runSetSelectionEventTest #4 (kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 1");
5002 checkSelection(kLFLen, kLF +
"a",
"runSetSelectionEventTest #4 (kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
"");
5005 contenteditable.innerHTML =
"<br>";
5007 await synthesizeSelectionSet(
0,
0);
5008 is(selection.anchorNode, contenteditable,
5009 "runSetSelectionEventTest #5 (0, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
5010 is(selection.anchorOffset,
0,
5011 "runSetSelectionEventTest #5 (0, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5012 is(selection.focusNode, contenteditable,
5013 "runSetSelectionEventTest #5 (0, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
5014 is(selection.focusOffset,
0,
5015 "runSetSelectionEventTest #5 (0, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
5016 checkSelection(
0,
"",
"runSetSelectionEventTest #5 (0, 0), \"" + contenteditable.innerHTML + "\
"");
5018 await synthesizeSelectionSet(
0, kLFLen);
5019 is(selection.anchorNode, contenteditable,
5020 "runSetSelectionEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
5021 is(selection.anchorOffset,
0,
5022 "runSetSelectionEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5023 is(selection.focusNode, contenteditable,
5024 "runSetSelectionEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
5025 is(selection.focusOffset, contenteditable.childNodes.length,
5026 "runSetSelectionEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the root's children");
5027 checkSelection(
0, kLF,
"runSetSelectionEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5029 await synthesizeSelectionSet(kLFLen,
0);
5030 is(selection.anchorNode, contenteditable,
5031 "runSetSelectionEventTest #5 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
5032 is(selection.anchorOffset, contenteditable.childNodes.length,
5033 "runSetSelectionEventTest #5 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the count of the root's children");
5034 is(selection.focusNode, contenteditable,
5035 "runSetSelectionEventTest #5 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
5036 is(selection.focusOffset, contenteditable.childNodes.length,
5037 "runSetSelectionEventTest #5 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the root's children");
5038 checkSelection(kLFLen,
"",
"runSetSelectionEventTest #5 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
"");
5040 await synthesizeSelectionSet(kLFLen,
1);
5041 is(selection.anchorNode, contenteditable,
5042 "runSetSelectionEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
5043 is(selection.anchorOffset, contenteditable.childNodes.length,
5044 "runSetSelectionEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the count of the root's children");
5045 is(selection.focusNode, contenteditable,
5046 "runSetSelectionEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
5047 is(selection.focusOffset, contenteditable.childNodes.length,
5048 "runSetSelectionEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the root's children");
5049 checkSelection(kLFLen,
"",
"runSetSelectionEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\
"");
5052 contenteditable.innerHTML =
"<p><br></p>";
5054 await synthesizeSelectionSet(kLFLen, kLFLen);
5055 is(selection.anchorNode, contenteditable.firstChild,
5056 "runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the <p> node");
5057 is(selection.anchorOffset,
0,
5058 "runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 1");
5059 is(selection.focusNode, contenteditable.firstChild,
5060 "runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the <p> node");
5061 is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
5062 "runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the <p>'s children");
5063 checkSelection(kLFLen, kLF,
"runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5065 await synthesizeSelectionSet(kLFLen*
2,
0);
5066 is(selection.anchorNode, contenteditable.firstChild,
5067 "runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the <p> node");
5068 is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
5069 "runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the count of the <p>'s children");
5070 is(selection.focusNode, contenteditable.firstChild,
5071 "runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the <p> node");
5072 is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
5073 "runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the <p>'s children");
5074 checkSelection(kLFLen*
2,
"",
"runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
"");
5076 await synthesizeSelectionSet(kLFLen*
2,
1);
5077 is(selection.anchorNode, contenteditable.firstChild,
5078 "runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the <p> node");
5079 is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
5080 "runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the count of the root's children");
5081 is(selection.focusNode, contenteditable,
5082 "runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
5083 is(selection.focusOffset, contenteditable.childNodes.length,
5084 "runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the root's children");
5085 checkSelection(kLFLen*
2,
"",
"runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
"");
5087 await synthesizeSelectionSet(
0, kLFLen);
5088 is(selection.anchorNode, contenteditable,
5089 "runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
5090 is(selection.anchorOffset,
0,
5091 "runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5092 is(selection.focusNode, contenteditable.firstChild,
5093 "runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the <p> node");
5094 is(selection.focusOffset,
0,
5095 "runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
5096 checkSelection(
0, kLF,
"runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5098 await synthesizeSelectionSet(
0, kLFLen*
2);
5099 is(selection.anchorNode, contenteditable,
5100 "runSetSelectionEventTest #6 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
5101 is(selection.anchorOffset,
0,
5102 "runSetSelectionEventTest #6 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5103 is(selection.focusNode, contenteditable.firstChild,
5104 "runSetSelectionEventTest #6 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection focus node should be the <p> node");
5105 is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
5106 "runSetSelectionEventTest #6 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the <p>'s children");
5107 checkSelection(
0, kLF + kLF,
"runSetSelectionEventTest #6 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
"");
5109 await synthesizeSelectionSet(kLFLen,
0);
5110 is(selection.anchorNode, contenteditable.firstChild,
5111 "runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the <p> node");
5112 is(selection.anchorOffset,
0,
5113 "runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5114 is(selection.focusNode, contenteditable.firstChild,
5115 "runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the <p> node");
5116 is(selection.focusOffset,
0,
5117 "runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
5118 checkSelection(kLFLen,
"",
"runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
"");
5121 contenteditable.innerHTML =
"<br><br>";
5123 await synthesizeSelectionSet(
0, kLFLen);
5124 is(selection.anchorNode, contenteditable,
5125 "runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
5126 is(selection.anchorOffset,
0,
5127 "runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5128 is(selection.focusNode, contenteditable,
5129 "runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
5130 is(selection.focusOffset,
1,
5131 "runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 1");
5132 checkSelection(
0, kLF,
"runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5134 await synthesizeSelectionSet(
0, kLFLen *
2);
5135 is(selection.anchorNode, contenteditable,
5136 "runSetSelectionEventTest #7 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
5137 is(selection.anchorOffset,
0,
5138 "runSetSelectionEventTest #7 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5139 is(selection.focusNode, contenteditable,
5140 "runSetSelectionEventTest #7 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
5141 is(selection.focusOffset, contenteditable.childNodes.length,
5142 "runSetSelectionEventTest #7 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the root's children");
5143 checkSelection(
0, kLF + kLF,
"runSetSelectionEventTest #7 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
"");
5145 await synthesizeSelectionSet(kLFLen,
0);
5146 is(selection.anchorNode, contenteditable,
5147 "runSetSelectionEventTest #7 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
5148 is(selection.anchorOffset,
1,
5149 "runSetSelectionEventTest #7 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 1");
5150 is(selection.focusNode, contenteditable,
5151 "runSetSelectionEventTest #7 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
5152 is(selection.focusOffset,
1,
5153 "runSetSelectionEventTest #7 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 1");
5154 checkSelection(kLFLen,
"",
"runSetSelectionEventTest #7 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
"");
5156 await synthesizeSelectionSet(kLFLen, kLFLen);
5157 is(selection.anchorNode, contenteditable,
5158 "runSetSelectionEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
5159 is(selection.anchorOffset,
1,
5160 "runSetSelectionEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 1");
5161 is(selection.focusNode, contenteditable,
5162 "runSetSelectionEventTest #7 (kLFLen, kLFLen) selection focus node should be the root node");
5163 is(selection.focusOffset, contenteditable.childNodes.length,
5164 "runSetSelectionEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the root's children");
5165 checkSelection(kLFLen, kLF,
"runSetSelectionEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5167 await synthesizeSelectionSet(kLFLen *
2,
0);
5168 is(selection.anchorNode, contenteditable,
5169 "runSetSelectionEventTest #7 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
5170 is(selection.anchorOffset, contenteditable.childNodes.length,
5171 "runSetSelectionEventTest #7 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the count of the root's children");
5172 is(selection.focusNode, contenteditable,
5173 "runSetSelectionEventTest #7 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
5174 is(selection.focusOffset, contenteditable.childNodes.length,
5175 "runSetSelectionEventTest #7 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the root's children");
5176 checkSelection(kLFLen *
2,
"",
"runSetSelectionEventTest #7 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
"");
5179 contenteditable.innerHTML =
"<p><br><br></p>";
5181 await synthesizeSelectionSet(kLFLen, kLFLen);
5182 is(selection.anchorNode, contenteditable.firstChild,
5183 "runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the <p> node");
5184 is(selection.anchorOffset,
0,
5185 "runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5186 is(selection.focusNode, contenteditable.firstChild,
5187 "runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the <p> node");
5188 is(selection.focusOffset,
1,
5189 "runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 1");
5190 checkSelection(kLFLen, kLF,
"runSetSelectionEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5192 await synthesizeSelectionSet(kLFLen, kLFLen *
2);
5193 is(selection.anchorNode, contenteditable.firstChild,
5194 "runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the <p> node");
5195 is(selection.anchorOffset,
0,
5196 "runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5197 is(selection.focusNode, contenteditable.firstChild,
5198 "runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection focus node should be the <p> node");
5199 is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
5200 "runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the <p>'s children");
5201 checkSelection(kLFLen, kLF + kLF,
"runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\
"");
5203 await synthesizeSelectionSet(kLFLen*
2,
0);
5204 is(selection.anchorNode, contenteditable.firstChild,
5205 "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the <p> node");
5206 is(selection.anchorOffset,
1,
5207 "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 1");
5208 is(selection.focusNode, contenteditable.firstChild,
5209 "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the <p> node");
5210 is(selection.focusOffset,
1,
5211 "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 1");
5212 checkSelection(kLFLen*
2,
"",
"runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\
"");
5214 await synthesizeSelectionSet(kLFLen*
2, kLFLen);
5215 is(selection.anchorNode, contenteditable.firstChild,
5216 "runSetSelectionEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the <p> node");
5217 is(selection.anchorOffset,
1,
5218 "runSetSelectionEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 1");
5219 is(selection.focusNode, contenteditable.firstChild,
5220 "runSetSelectionEventTest #8 (kLFLen*2, kLFLen) selection focus node should be the <p> node");
5221 is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
5222 "runSetSelectionEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the <p>'s children");
5223 checkSelection(kLFLen*
2, kLF,
"runSetSelectionEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5225 await synthesizeSelectionSet(kLFLen*
3,
0);
5226 is(selection.anchorNode, contenteditable.firstChild,
5227 "runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the <p> node");
5228 is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
5229 "runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the count of the <p>'s children");
5230 is(selection.focusNode, contenteditable.firstChild,
5231 "runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the <p> node");
5232 is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
5233 "runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the <p>'s children");
5234 checkSelection(kLFLen*
3,
"",
"runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\
"");
5236 // #
9 (ContentEventHandler cannot distinguish if
<p> can have children, so, the result is same as case #
5,
"<br>")
5237 contenteditable.innerHTML =
"<p></p>";
5239 await synthesizeSelectionSet(kLFLen,
0);
5240 is(selection.anchorNode, contenteditable,
5241 "runSetSelectionEventTest #9 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
5242 is(selection.anchorOffset,
1,
5243 "runSetSelectionEventTest #9 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the index of the <p> node + 1");
5244 is(selection.focusNode, contenteditable,
5245 "runSetSelectionEventTest #9 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the <p> node");
5246 is(selection.focusOffset,
1,
5247 "runSetSelectionEventTest #9 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the index of the <p> node + 1");
5248 checkSelection(kLFLen,
"",
"runSetSelectionEventTest #9 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
"");
5250 await synthesizeSelectionSet(kLFLen,
1);
5251 is(selection.anchorNode, contenteditable,
5252 "runSetSelectionEventTest #9 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
5253 is(selection.anchorOffset,
1,
5254 "runSetSelectionEventTest #9 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be the index of the <p> node + 1");
5255 is(selection.focusNode, contenteditable,
5256 "runSetSelectionEventTest #9 (kLFLen, 1), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
5257 is(selection.focusOffset, contenteditable.childNodes.length,
5258 "runSetSelectionEventTest #9 (kLFLen, 1), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the root's children");
5259 checkSelection(kLFLen,
"",
"runSetSelectionEventTest #9 (kLFLen, 0), \"" + contenteditable.innerHTML + "\
"");
5262 contenteditable.innerHTML =
"";
5264 await synthesizeSelectionSet(
0,
0);
5265 is(selection.anchorNode, contenteditable,
5266 "runSetSelectionEventTest #10 (0, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
5267 is(selection.anchorOffset,
0,
5268 "runSetSelectionEventTest #10 (0, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5269 is(selection.focusNode, contenteditable,
5270 "runSetSelectionEventTest #10 (0, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
5271 is(selection.focusOffset,
0,
5272 "runSetSelectionEventTest #10 (0, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
5273 checkSelection(
0,
"",
"runSetSelectionEventTest #10 (0, 0), \"" + contenteditable.innerHTML + "\
"");
5275 await synthesizeSelectionSet(
0,
1);
5276 is(selection.anchorNode, contenteditable,
5277 "runSetSelectionEventTest #10 (0, 1), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
5278 is(selection.anchorOffset,
0,
5279 "runSetSelectionEventTest #10 (0, 1), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5280 is(selection.focusNode, contenteditable,
5281 "runSetSelectionEventTest #10 (0, 1), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
5282 is(selection.focusOffset,
0,
5283 "runSetSelectionEventTest #10 (0, 1), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
5284 checkSelection(
0,
"",
"runSetSelectionEventTest #10 (0, 1), \"" + contenteditable.innerHTML + "\
"");
5287 contenteditable.innerHTML =
"<span></span><i><u></u></i>";
5289 await synthesizeSelectionSet(
0,
0);
5290 is(selection.anchorNode, contenteditable,
5291 "runSetSelectionEventTest #11 (0, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
5292 is(selection.anchorOffset,
0,
5293 "runSetSelectionEventTest #11 (0, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5294 is(selection.focusNode, contenteditable,
5295 "runSetSelectionEventTest #11 (0, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
5296 is(selection.focusOffset,
0,
5297 "runSetSelectionEventTest #11 (0, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
5298 checkSelection(
0,
"",
"runSetSelectionEventTest #11 (0, 0), \"" + contenteditable.innerHTML + "\
"");
5300 await synthesizeSelectionSet(
0,
1);
5301 is(selection.anchorNode, contenteditable,
5302 "runSetSelectionEventTest #11 (0, 1), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the root node");
5303 is(selection.anchorOffset,
0,
5304 "runSetSelectionEventTest #11 (0, 1), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5305 is(selection.focusNode, contenteditable,
5306 "runSetSelectionEventTest #11 (0, 1), \"" + contenteditable.innerHTML + "\
": selection focus node should be the root node");
5307 is(selection.focusOffset, contenteditable.childNodes.length,
5308 "runSetSelectionEventTest #11 (0, 1), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the count of the root's children");
5309 checkSelection(
0,
"",
"runSetSelectionEventTest #11 (0, 1), \"" + contenteditable.innerHTML + "\
"");
5312 contenteditable.innerHTML =
"<span>abc</span><i><u></u></i>";
5313 selection.selectAllChildren(contenteditable);
5315 await synthesizeSelectionSet(
0,
0);
5316 is(selection.anchorNode, contenteditable.firstChild.firstChild,
5317 "runSetSelectionEventTest #12 (0, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the text node");
5318 is(selection.anchorOffset,
0,
5319 "runSetSelectionEventTest #12 (0, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5320 is(selection.focusNode, contenteditable.firstChild.firstChild,
5321 "runSetSelectionEventTest #12 (0, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the text node");
5322 is(selection.focusOffset,
0,
5323 "runSetSelectionEventTest #12 (0, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
5324 checkSelection(
0,
"",
"runSetSelectionEventTest #12 (0, 0), \"" + contenteditable.innerHTML + "\
"");
5327 contenteditable.innerHTML =
"<span></span><i>abc<u></u></i>";
5328 selection.selectAllChildren(contenteditable);
5330 await synthesizeSelectionSet(
0,
0);
5331 is(selection.anchorNode, contenteditable.childNodes.item(
1).firstChild,
5332 "runSetSelectionEventTest #13 (0, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the text node");
5333 is(selection.anchorOffset,
0,
5334 "runSetSelectionEventTest #13 (0, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5335 is(selection.focusNode, contenteditable.childNodes.item(
1).firstChild,
5336 "runSetSelectionEventTest #13 (0, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the text node");
5337 is(selection.focusOffset,
0,
5338 "runSetSelectionEventTest #13 (0, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
5339 checkSelection(
0,
"",
"runSetSelectionEventTest #13 (0, 0), \"" + contenteditable.innerHTML + "\
"");
5342 contenteditable.innerHTML =
"<span></span><i><u>abc</u></i>";
5343 selection.selectAllChildren(contenteditable);
5345 await synthesizeSelectionSet(
0,
0);
5346 is(selection.anchorNode, contenteditable.childNodes.item(
1).firstChild.firstChild,
5347 "runSetSelectionEventTest #14 (0, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the text node");
5348 is(selection.anchorOffset,
0,
5349 "runSetSelectionEventTest #14 (0, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5350 is(selection.focusNode, contenteditable.childNodes.item(
1).firstChild.firstChild,
5351 "runSetSelectionEventTest #14 (0, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the text node");
5352 is(selection.focusOffset,
0,
5353 "runSetSelectionEventTest #14 (0, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
5354 checkSelection(
0,
"",
"runSetSelectionEventTest #14 (0, 0), \"" + contenteditable.innerHTML + "\
"");
5357 contenteditable.innerHTML =
"<span></span><i><u></u>abc</i>";
5358 selection.selectAllChildren(contenteditable);
5360 await synthesizeSelectionSet(
0,
0);
5361 is(selection.anchorNode, contenteditable.childNodes.item(
1).lastChild,
5362 "runSetSelectionEventTest #15 (0, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the text node");
5363 is(selection.anchorOffset,
0,
5364 "runSetSelectionEventTest #15 (0, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5365 is(selection.focusNode, contenteditable.childNodes.item(
1).lastChild,
5366 "runSetSelectionEventTest #15 (0, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the text node");
5367 is(selection.focusOffset,
0,
5368 "runSetSelectionEventTest #15 (0, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
5369 checkSelection(
0,
"",
"runSetSelectionEventTest #15 (0, 0), \"" + contenteditable.innerHTML + "\
"");
5372 contenteditable.innerHTML =
"a<blink>b</blink>c";
5373 await synthesizeSelectionSet(
0,
3);
5374 is(selection.anchorNode, contenteditable.firstChild,
5375 "runSetSelectionEventTest #16 (0, 3), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the first text node");
5376 is(selection.anchorOffset,
0,
5377 "runSetSelectionEventTest #16 (0, 3), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5378 is(selection.focusNode, contenteditable.lastChild,
5379 "runSetSelectionEventTest #16 (0, 3), \"" + contenteditable.innerHTML + "\
": selection focus node should be the last text node");
5380 is(selection.focusOffset, contenteditable.lastChild.wholeText.length,
5381 "runSetSelectionEventTest #16 (0, 3), \"" + contenteditable.innerHTML + "\
": selection focus offset should be the length of the last text node");
5382 checkSelection(
0,
"abc",
"runSetSelectionEventTest #16 (0, 3), \"" + contenteditable.innerHTML + "\
"");
5384 // #
17 (bug
1319660 - incorrect adjustment of content iterator last node)
5385 contenteditable.innerHTML =
"<div>a</div><div><br></div>";
5387 await synthesizeSelectionSet(kLFLen,
1+kLFLen);
5388 is(selection.anchorNode, contenteditable.firstChild,
5389 "runSetSelectionEventTest #17 (kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the first <div> element");
5390 is(selection.anchorOffset,
0,
5391 "runSetSelectionEventTest #17 (kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5392 is(selection.focusNode, contenteditable.lastChild,
5393 "runSetSelectionEventTest #17 (kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the second <div> element");
5394 is(selection.focusOffset,
0,
5395 "runSetSelectionEventTest #17 (kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
5396 checkSelection(kLFLen,
"a" + kLF,
"runSetSelectionEventTest #17 (kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
"");
5398 await synthesizeSelectionSet(
1+
2*kLFLen,
0);
5399 is(selection.anchorNode, contenteditable.lastChild,
5400 "runSetSelectionEventTest #17 (1+2*kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the second <div> element");
5401 is(selection.anchorOffset,
0,
5402 "runSetSelectionEventTest #17 (1+2*kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 0");
5403 is(selection.focusNode, contenteditable.lastChild,
5404 "runSetSelectionEventTest #17 (1+2*kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection focus node should be the second <div> element");
5405 is(selection.focusOffset,
0,
5406 "runSetSelectionEventTest #17 (1+2*kLFLen, 0), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
5407 checkSelection(
1+
2*kLFLen,
"",
"runSetSelectionEventTest #17 (1+2*kLFLen, 0), \"" + contenteditable.innerHTML + "\
"");
5409 // #
18 (bug
1319660 - content iterator start node regression)
5410 contenteditable.innerHTML =
"<div><br></div><div><br></div>";
5412 await synthesizeSelectionSet(
2*kLFLen, kLFLen);
5413 is(selection.anchorNode, contenteditable.firstChild,
5414 "runSetSelectionEventTest #18 (2*kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor node should be the first <div> element");
5415 is(selection.anchorOffset,
1,
5416 "runSetSelectionEventTest #18 (2*kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection anchor offset should be 1");
5417 is(selection.focusNode, contenteditable.lastChild,
5418 "runSetSelectionEventTest #18 (2*kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus node should be the second <div> element");
5419 is(selection.focusOffset,
0,
5420 "runSetSelectionEventTest #18 (2*kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
": selection focus offset should be 0");
5421 checkSelection(
2*kLFLen, kLF,
"runSetSelectionEventTest #18 (2*kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5424 function runQueryTextContentEventTest()
5426 contenteditable.focus();
5431 contenteditable.innerHTML =
"abc<br>def";
5433 result = synthesizeQueryTextContent(
0,
6 + kLFLen);
5434 is(result.text,
"abc" + kLF +
"def",
"runQueryTextContentEventTest #1 (0, 6+kLFLen), \"" + contenteditable.innerHTML + "\
"");
5436 result = synthesizeQueryTextContent(
0,
100);
5437 is(result.text,
"abc" + kLF +
"def",
"runQueryTextContentEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\
"");
5439 result = synthesizeQueryTextContent(
2,
2 + kLFLen);
5440 is(result.text,
"c" + kLF +
"d",
"runQueryTextContentEventTest #1 (2, 2+kLFLen), \"" + contenteditable.innerHTML + "\
"");
5442 result = synthesizeQueryTextContent(
1,
2);
5443 is(result.text,
"bc",
"runQueryTextContentEventTest #1 (1, 2), \"" + contenteditable.innerHTML + "\
"");
5445 result = synthesizeQueryTextContent(
3, kLFLen);
5446 is(result.text, kLF,
"runQueryTextContentEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5448 result = synthesizeQueryTextContent(
6 + kLFLen,
1);
5449 is(result.text,
"",
"runQueryTextContentEventTest #1 (6 + kLFLen, 0), \"" + contenteditable.innerHTML + "\
"");
5452 contenteditable.innerHTML =
"<p>a<b>b</b>c</p><p>def</p>";
5454 result = synthesizeQueryTextContent(kLFLen,
4+kLFLen);
5455 is(result.text,
"abc" + kLF +
"d",
"runQueryTextContentEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\
"");
5457 result = synthesizeQueryTextContent(kLFLen,
2);
5458 is(result.text,
"ab",
"runQueryTextContentEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\
"");
5460 result = synthesizeQueryTextContent(
1+kLFLen,
2);
5461 is(result.text,
"bc",
"runQueryTextContentEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\
"");
5463 result = synthesizeQueryTextContent(
2+kLFLen,
2+kLFLen);
5464 is(result.text,
"c" + kLF +
"d",
"runQueryTextContentEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\
"");
5466 result = synthesizeQueryTextContent(
3+kLFLen*
2,
1);
5467 is(result.text,
"d",
"runQueryTextContentEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
"");
5469 result = synthesizeQueryTextContent(
0, kLFLen);
5470 is(result.text, kLF,
"runQueryTextContentEventTest #2 (0, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5472 result = synthesizeQueryTextContent(
2+kLFLen,
1+kLFLen);
5473 is(result.text,
"c" + kLF,
"runQueryTextContentEventTest #2 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
"");
5475 result = synthesizeQueryTextContent(
3+kLFLen, kLFLen);
5476 is(result.text, kLF,
"runQueryTextContentEventTest #2 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5478 result = synthesizeQueryTextContent(
3+kLFLen,
1+kLFLen);
5479 is(result.text, kLF +
"d",
"runQueryTextContentEventTest #2 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
"");
5482 contenteditable.innerHTML =
"<div>abc<p>def</p></div>";
5484 result = synthesizeQueryTextContent(
1+kLFLen,
2);
5485 is(result.text,
"bc",
"runQueryTextContentEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\
"");
5487 result = synthesizeQueryTextContent(
1+kLFLen,
3+kLFLen);
5488 is(result.text,
"bc" + kLF +
"d",
"runQueryTextContentEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\
"");
5490 result = synthesizeQueryTextContent(
3+kLFLen*
2,
1);
5491 is(result.text,
"d",
"runQueryTextContentEventTest #3 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
"");
5493 result = synthesizeQueryTextContent(
0,
6+kLFLen*
2);
5494 is(result.text, kLF +
"abc" + kLF +
"def",
"runQueryTextContentEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\
"");
5496 result = synthesizeQueryTextContent(
0,
100);
5497 is(result.text, kLF +
"abc" + kLF +
"def",
"runQueryTextContentEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\
"");
5499 result = synthesizeQueryTextContent(
4+kLFLen*
2,
2);
5500 is(result.text,
"ef",
"runQueryTextContentEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\
"");
5502 result = synthesizeQueryTextContent(
4+kLFLen*
2,
100);
5503 is(result.text,
"ef",
"runQueryTextContentEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\
"");
5505 result = synthesizeQueryTextContent(
6+kLFLen*
2,
1);
5506 is(result.text,
"",
"runQueryTextContentEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
"");
5508 result = synthesizeQueryTextContent(
0, kLFLen);
5509 is(result.text, kLF,
"runQueryTextContentEventTest #3 (0, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5511 result = synthesizeQueryTextContent(
0,
1+kLFLen);
5512 is(result.text, kLF +
"a",
"runQueryTextContentEventTest #3 (0, 1+kLFLen), \"" + contenteditable.innerHTML + "\
"");
5514 result = synthesizeQueryTextContent(
2+kLFLen,
1+kLFLen);
5515 is(result.text,
"c" + kLF,
"runQueryTextContentEventTest #3 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
"");
5517 result = synthesizeQueryTextContent(
3+kLFLen, kLFLen);
5518 is(result.text, kLF,
"runQueryTextContentEventTest #3 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5520 result = synthesizeQueryTextContent(
3+kLFLen,
1+kLFLen);
5521 is(result.text, kLF +
"d",
"runQueryTextContentEventTest #3 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\
"");
5524 contenteditable.innerHTML =
"<div><p>abc</p>def</div>";
5526 result = synthesizeQueryTextContent(
1+kLFLen*
2,
2);
5527 is(result.text,
"bc",
"runQueryTextContentEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\
"");
5529 result = synthesizeQueryTextContent(
1+kLFLen*
2,
3);
5530 is(result.text,
"bcd",
"runQueryTextContentEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\
"");
5532 result = synthesizeQueryTextContent(
3+kLFLen*
2,
1);
5533 is(result.text,
"d",
"runQueryTextContentEventTest #4 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
"");
5535 result = synthesizeQueryTextContent(
0,
6+kLFLen*
2);
5536 is(result.text, kLF + kLF +
"abcdef",
"runQueryTextContentEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\
"");
5538 result = synthesizeQueryTextContent(
0,
100);
5539 is(result.text, kLF + kLF +
"abcdef",
"runQueryTextContentEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\
"");
5541 result = synthesizeQueryTextContent(
4+kLFLen*
2,
2);
5542 is(result.text,
"ef",
"runQueryTextContentEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\
"");
5544 result = synthesizeQueryTextContent(
4+kLFLen*
2,
100);
5545 is(result.text,
"ef",
"runQueryTextContentEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\
"");
5547 result = synthesizeQueryTextContent(
6+kLFLen*
2,
1);
5548 is(result.text,
"",
"runQueryTextContentEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
"");
5550 result = synthesizeQueryTextContent(
0, kLFLen);
5551 is(result.text, kLF,
"runQueryTextContentEventTest #4 (0, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5553 result = synthesizeQueryTextContent(
0, kLFLen*
2);
5554 is(result.text, kLF + kLF,
"runQueryTextContentEventTest #4 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
"");
5556 result = synthesizeQueryTextContent(
0,
1+kLFLen*
2);
5557 is(result.text, kLF + kLF +
"a",
"runQueryTextContentEventTest #4 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
"");
5559 result = synthesizeQueryTextContent(kLFLen, kLFLen);
5560 is(result.text, kLF,
"runQueryTextContentEventTest #4 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5562 result = synthesizeQueryTextContent(kLFLen,
1+kLFLen);
5563 is(result.text, kLF +
"a",
"runQueryTextContentEventTest #4 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5566 contenteditable.innerHTML =
"<br>";
5568 result = synthesizeQueryTextContent(
0, kLFLen);
5569 is(result.text, kLF,
"runQueryTextContentEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5571 result = synthesizeQueryTextContent(kLFLen,
1);
5572 is(result.text,
"",
"runQueryTextContentEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\
"");
5575 contenteditable.innerHTML =
"<p><br></p>";
5577 result = synthesizeQueryTextContent(kLFLen, kLFLen);
5578 is(result.text, kLF,
"runQueryTextContentEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5580 result = synthesizeQueryTextContent(kLFLen*
2,
1);
5581 is(result.text,
"",
"runQueryTextContentEventTest #5 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
"");
5583 result = synthesizeQueryTextContent(
0, kLFLen);
5584 is(result.text, kLF,
"runQueryTextContentEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5586 result = synthesizeQueryTextContent(
0, kLFLen*
2);
5587 is(result.text, kLF + kLF,
"runQueryTextContentEventTest #6 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
"");
5590 contenteditable.innerHTML =
"<br><br>";
5592 result = synthesizeQueryTextContent(
0, kLFLen);
5593 is(result.text, kLF,
"runQueryTextContentEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5595 result = synthesizeQueryTextContent(
0, kLFLen *
2);
5596 is(result.text, kLF + kLF,
"runQueryTextContentEventTest #7 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\
"");
5598 result = synthesizeQueryTextContent(kLFLen, kLFLen);
5599 is(result.text, kLF,
"runQueryTextContentEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5601 result = synthesizeQueryTextContent(kLFLen *
2,
1);
5602 is(result.text,
"",
"runQueryTextContentEventTest #7 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\
"");
5605 contenteditable.innerHTML =
"<p><br><br></p>";
5607 result = synthesizeQueryTextContent(kLFLen, kLFLen);
5608 is(result.text, kLF,
"runQueryTextContentEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5610 result = synthesizeQueryTextContent(kLFLen, kLFLen *
2);
5611 is(result.text, kLF + kLF,
"runQueryTextContentEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\
"");
5613 result = synthesizeQueryTextContent(kLFLen*
2, kLFLen);
5614 is(result.text, kLF,
"runQueryTextContentEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\
"");
5616 result = synthesizeQueryTextContent(kLFLen*
3,
1);
5617 is(result.text,
"",
"runQueryTextContentEventTest #8 (kLFLen*3, 1), \"" + contenteditable.innerHTML + "\
"");
5620 contenteditable.innerHTML =
"a<blink>b</blink>c";
5622 result = synthesizeQueryTextContent(
0,
3);
5623 is(result.text,
"abc",
"runQueryTextContentEventTest #16 (0, 3), \"" + contenteditable.innerHTML + "\
"");
5626 function runQuerySelectionEventTest()
5628 contenteditable.focus();
5630 let selection = windowOfContenteditable.getSelection();
5633 contenteditable.innerHTML =
"<br/>a";
5634 selection.setBaseAndExtent(
5635 contenteditable.firstChild,
5637 contenteditable.lastChild,
5643 `runQuerySelectionEventTest #
1,
"${contenteditable.innerHTML}"`
5647 contenteditable.innerHTML =
"<p></p><p>abc</p>";
5648 selection.setBaseAndExtent(
5649 contenteditable.firstChild,
5651 contenteditable.lastChild.firstChild,
5657 `runQuerySelectionEventTest #
2,
"${contenteditable.innerHTML}"`
5661 contenteditable.innerHTML =
"<p>abc</p><p>def</p>";
5662 selection.setBaseAndExtent(
5663 contenteditable.firstChild,
5665 contenteditable.lastChild.firstChild,
5671 `runQuerySelectionEventTest #
3,
"${contenteditable.innerHTML}"`
5675 contenteditable.innerHTML =
"<p>abc</p>";
5676 selection.removeAllRanges();
5680 `runQuerySelectionEventTest #
4,
"${contenteditable.innerHTML}"`
5684 function runQueryIMESelectionTest()
5687 textarea.value =
"before after";
5688 let startoffset = textarea.selectionStart = textarea.selectionEnd =
"before ".length;
5690 if (!checkIMESelection(
"RawClause", false,
0,
"",
"runQueryIMESelectionTest: before starting composition") ||
5691 !checkIMESelection(
"SelectedRawClause", false,
0,
"",
"runQueryIMESelectionTest: before starting composition") ||
5692 !checkIMESelection(
"ConvertedClause", false,
0,
"",
"runQueryIMESelectionTest: before starting composition") ||
5693 !checkIMESelection(
"SelectedClause", false,
0,
"",
"runQueryIMESelectionTest: before starting composition")) {
5694 synthesizeComposition({ type:
"compositioncommitasis" });
5698 synthesizeCompositionChange(
5703 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
5706 "caret": {
"start":
1,
"length":
0 }
5709 if (!checkIMESelection(
"RawClause", true, startoffset,
"a",
"runQueryIMESelectionTest: inputting raw text") ||
5710 !checkIMESelection(
"SelectedRawClause", false,
0,
"",
"runQueryIMESelectionTest: inputting raw text") ||
5711 !checkIMESelection(
"ConvertedClause", false,
0,
"",
"runQueryIMESelectionTest: inputting raw text") ||
5712 !checkIMESelection(
"SelectedClause", false,
0,
"",
"runQueryIMESelectionTest: inputting raw text")) {
5713 synthesizeComposition({ type:
"compositioncommitasis" });
5717 synthesizeCompositionChange(
5719 {
"string":
"abcdefgh",
5722 {
"length":
8,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
5725 "caret": {
"start":
8,
"length":
0 }
5728 if (!checkIMESelection(
"RawClause", true, startoffset,
"abcdefgh",
"runQueryIMESelectionTest: updating raw text") ||
5729 !checkIMESelection(
"SelectedRawClause", false,
0,
"",
"runQueryIMESelectionTest: updating raw text") ||
5730 !checkIMESelection(
"ConvertedClause", false,
0,
"",
"runQueryIMESelectionTest: updating raw text") ||
5731 !checkIMESelection(
"SelectedClause", false,
0,
"",
"runQueryIMESelectionTest: updating raw text")) {
5732 synthesizeComposition({ type:
"compositioncommitasis" });
5736 synthesizeCompositionChange(
5738 {
"string":
"ABCDEFGH",
5741 {
"length":
2,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
5742 {
"length":
3,
"attr": COMPOSITION_ATTR_CONVERTED_CLAUSE },
5743 {
"length":
3,
"attr": COMPOSITION_ATTR_CONVERTED_CLAUSE },
5746 "caret": {
"start":
2,
"length":
0 }
5749 if (!checkIMESelection(
"RawClause", false,
0,
"",
"runQueryIMESelectionTest: starting to convert") ||
5750 !checkIMESelection(
"SelectedRawClause", false,
0,
"",
"runQueryIMESelectionTest: starting to convert") ||
5751 !checkIMESelection(
"ConvertedClause", true, startoffset +
2,
"CDE",
"runQueryIMESelectionTest: starting to convert") ||
5752 !checkIMESelection(
"SelectedClause", true, startoffset,
"AB",
"runQueryIMESelectionTest: starting to convert")) {
5753 synthesizeComposition({ type:
"compositioncommitasis" });
5757 synthesizeCompositionChange(
5759 {
"string":
"ABCDEFGH",
5762 {
"length":
2,
"attr": COMPOSITION_ATTR_CONVERTED_CLAUSE },
5763 {
"length":
3,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
5764 {
"length":
3,
"attr": COMPOSITION_ATTR_CONVERTED_CLAUSE },
5767 "caret": {
"start":
5,
"length":
0 }
5770 if (!checkIMESelection(
"RawClause", false,
0,
"",
"runQueryIMESelectionTest: changing selected clause") ||
5771 !checkIMESelection(
"SelectedRawClause", false,
0,
"",
"runQueryIMESelectionTest: changing selected clause") ||
5772 !checkIMESelection(
"ConvertedClause", true, startoffset,
"AB",
"runQueryIMESelectionTest: changing selected clause") ||
5773 !checkIMESelection(
"SelectedClause", true, startoffset +
2,
"CDE",
"runQueryIMESelectionTest: changing selected clause")) {
5774 synthesizeComposition({ type:
"compositioncommitasis" });
5778 synthesizeComposition({ type:
"compositioncommitasis" });
5780 if (!checkIMESelection(
"RawClause", false,
0,
"",
"runQueryIMESelectionTest: after committing composition") ||
5781 !checkIMESelection(
"SelectedRawClause", false,
0,
"",
"runQueryIMESelectionTest: after committing composition") ||
5782 !checkIMESelection(
"ConvertedClause", false,
0,
"",
"runQueryIMESelectionTest: after committing composition") ||
5783 !checkIMESelection(
"SelectedClause", false,
0,
"",
"runQueryIMESelectionTest: after committing composition")) {
5787 startoffset = textarea.selectionStart;
5789 synthesizeCompositionChange(
5791 {
"string":
"abcdefgh",
5794 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE },
5795 {
"length":
1,
"attr": COMPOSITION_ATTR_SELECTED_RAW_CLAUSE },
5796 {
"length":
1,
"attr": COMPOSITION_ATTR_CONVERTED_CLAUSE },
5797 {
"length":
1,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
5798 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE },
5799 {
"length":
1,
"attr": COMPOSITION_ATTR_SELECTED_RAW_CLAUSE },
5800 {
"length":
1,
"attr": COMPOSITION_ATTR_CONVERTED_CLAUSE },
5801 {
"length":
1,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
5804 "caret": {
"start":
8,
"length":
0 }
5807 if (!checkIMESelection(
"RawClause", true, startoffset,
"a",
"runQueryIMESelectionTest: unrealistic testcase") ||
5808 !checkIMESelection(
"SelectedRawClause", true, startoffset +
1,
"b",
"runQueryIMESelectionTest: unrealistic testcase") ||
5809 !checkIMESelection(
"ConvertedClause", true, startoffset +
2,
"c",
"runQueryIMESelectionTest: unrealistic testcase") ||
5810 !checkIMESelection(
"SelectedClause", true, startoffset +
3,
"d",
"runQueryIMESelectionTest: unrealistic testcase")) {
5811 synthesizeComposition({ type:
"compositioncommitasis" });
5815 synthesizeComposition({ type:
"compositioncommitasis" });
5818 function runQueryPasswordTest() {
5819 function checkRange(aOffset, aLength, aExpectedResult, aDescription) {
5821 let result = synthesizeQueryTextContent(aOffset, aLength);
5822 is(result.text, aExpectedResult,
5823 `${aDescription}: synthesizeQueryTextContent(${aOffset}, ${aLength})`);
5824 password.setSelectionRange(aOffset, aOffset + aLength);
5825 result = synthesizeQuerySelectedText();
5826 is(result.text, aExpectedResult,
5827 `${aDescription}: synthesizeQuerySelectedText(${aOffset}, ${aLength})`);
5830 let editor = password.editor;
5831 const kMask = editor.passwordMask;
5832 password.value =
"abcdef";
5835 checkRange(
0,
6, `${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}`,
5836 "runQueryPasswordTest: unmasked range is not specified #1");
5837 checkRange(
0,
3, `${kMask}${kMask}${kMask}`,
5838 "runQueryPasswordTest: unmasked range is not specified #2");
5839 checkRange(
3,
3, `${kMask}${kMask}${kMask}`,
5840 "runQueryPasswordTest: unmasked range is not specified #3");
5841 checkRange(
2,
2, `${kMask}${kMask}`,
5842 "runQueryPasswordTest: unmasked range is not specified #4");
5844 editor.unmask(
0,
6);
5845 checkRange(
0,
6,
"abcdef",
5846 "runQueryPasswordTest: unmasked range 0-6 #1");
5847 checkRange(
0,
3,
"abc",
5848 "runQueryPasswordTest: unmasked range 0-6 #2");
5849 checkRange(
3,
3,
"def",
5850 "runQueryPasswordTest: unmasked range 0-6 #3");
5851 checkRange(
2,
2,
"cd",
5852 "runQueryPasswordTest: unmasked range 0-6 #4");
5854 editor.unmask(
0,
3);
5855 checkRange(
0,
6, `abc${kMask}${kMask}${kMask}`,
5856 "runQueryPasswordTest: unmasked range 0-3 #1");
5857 checkRange(
0,
3,
"abc",
5858 "runQueryPasswordTest: unmasked range 0-3 #2");
5859 checkRange(
3,
3, `${kMask}${kMask}${kMask}`,
5860 "runQueryPasswordTest: unmasked range 0-3 #3");
5861 checkRange(
2,
2, `c${kMask}`,
5862 "runQueryPasswordTest: unmasked range 0-3 #4");
5864 editor.unmask(
3,
6);
5865 checkRange(
0,
6, `${kMask}${kMask}${kMask}def`,
5866 "runQueryPasswordTest: unmasked range 3-6 #1");
5867 checkRange(
0,
3, `${kMask}${kMask}${kMask}`,
5868 "runQueryPasswordTest: unmasked range 3-6 #2");
5869 checkRange(
3,
3, `def`,
5870 "runQueryPasswordTest: unmasked range 3-6 #3");
5871 checkRange(
2,
2, `${kMask}d`,
5872 "runQueryPasswordTest: unmasked range 3-6 #4");
5874 editor.unmask(
2,
4);
5875 checkRange(
0,
6, `${kMask}${kMask}cd${kMask}${kMask}`,
5876 "runQueryPasswordTest: unmasked range 3-4 #1");
5877 checkRange(
1,
2, `${kMask}c`,
5878 "runQueryPasswordTest: unmasked range 3-4 #2");
5879 checkRange(
1,
3, `${kMask}cd`,
5880 "runQueryPasswordTest: unmasked range 3-4 #3");
5881 checkRange(
1,
4, `${kMask}cd${kMask}`,
5882 "runQueryPasswordTest: unmasked range 3-4 #4");
5883 checkRange(
2,
2,
"cd",
5884 "runQueryPasswordTest: unmasked range 3-4 #5");
5885 checkRange(
2,
3, `cd${kMask}`,
5886 "runQueryPasswordTest: unmasked range 3-4 #6");
5889 const kEmoji = String.fromCodePoint(
0x1f914);
5890 password.value = `${kEmoji}${kEmoji}${kEmoji}`
5893 checkRange(
0,
6, `${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}`,
5894 "runQueryPasswordTest: Emojis in password, unmasked range is not specified");
5896 editor.unmask(
0,
2);
5897 checkRange(
0,
6, `${kEmoji}${kMask}${kMask}${kMask}${kMask}`,
5898 "runQueryPasswordTest: Emojis in password, unmasked range 0-2 #1");
5899 checkRange(
0,
2, `${kEmoji}`,
5900 "runQueryPasswordTest: Emojis in password, unmasked range 0-2 #2");
5901 checkRange(
2,
2, `${kMask}${kMask}`,
5902 "runQueryPasswordTest: Emojis in password, unmasked range 0-2 #3");
5903 checkRange(
4,
2, `${kMask}${kMask}`,
5904 "runQueryPasswordTest: Emojis in password, unmasked range 0-2 #4");
5906 editor.unmask(
2,
4);
5907 checkRange(
0,
6, `${kMask}${kMask}${kEmoji}${kMask}${kMask}`,
5908 "runQueryPasswordTest: Emojis in password, unmasked range 2-4 #1");
5909 checkRange(
0,
2, `${kMask}${kMask}`,
5910 "runQueryPasswordTest: Emojis in password, unmasked range 2-4 #2");
5911 checkRange(
2,
2, `${kEmoji}`,
5912 "runQueryPasswordTest: Emojis in password, unmasked range 2-4 #3");
5913 checkRange(
4,
2, `${kMask}${kMask}`,
5914 "runQueryPasswordTest: Emojis in password, unmasked range 2-4 #4");
5916 editor.unmask(
4,
6);
5917 checkRange(
0,
6, `${kMask}${kMask}${kMask}${kMask}${kEmoji}`,
5918 "runQueryPasswordTest: Emojis in password, unmasked range 4-6 #1");
5919 checkRange(
0,
2, `${kMask}${kMask}`,
5920 "runQueryPasswordTest: Emojis in password, unmasked range 4-6 #2");
5921 checkRange(
2,
2, `${kMask}${kMask}`,
5922 "runQueryPasswordTest: Emojis in password, unmasked range 4-6 #3");
5923 checkRange(
4,
2, `${kEmoji}`,
5924 "runQueryPasswordTest: Emojis in password, unmasked range 4-6 #4");
5926 editor.unmask(
0,
1);
5927 checkRange(
0,
6, `${kEmoji}${kMask}${kMask}${kMask}${kMask}`,
5928 "runQueryPasswordTest: Emojis in password, unmasked range 0-1");
5930 editor.unmask(
1,
2);
5931 checkRange(
0,
6, `${kEmoji}${kMask}${kMask}${kMask}${kMask}`,
5932 "runQueryPasswordTest: Emojis in password, unmasked range 1-2");
5934 editor.unmask(
2,
3);
5935 checkRange(
0,
6, `${kMask}${kMask}${kEmoji}${kMask}${kMask}`,
5936 "runQueryPasswordTest: Emojis in password, unmasked range 2-3");
5938 editor.unmask(
3,
4);
5939 checkRange(
0,
6, `${kMask}${kMask}${kEmoji}${kMask}${kMask}`,
5940 "runQueryPasswordTest: Emojis in password, unmasked range 3-4");
5942 editor.unmask(
4,
5);
5943 checkRange(
0,
6, `${kMask}${kMask}${kMask}${kMask}${kEmoji}`,
5944 "runQueryPasswordTest: Emojis in password, unmasked range 4-5");
5946 editor.unmask(
5,
6);
5947 checkRange(
0,
6, `${kMask}${kMask}${kMask}${kMask}${kEmoji}`,
5948 "runQueryPasswordTest: Emojis in password, unmasked range 5-6");
5951 const kEmojiSuperhero = String.fromCodePoint(
0x1f9b8);
5952 const kEmojiMediumSkinTone = String.fromCodePoint(
0x1f3fd);
5953 const kZeroWidthJoiner =
"\u200d";
5954 const kFemaleSign =
"\u2640";
5955 const kVariationSelector16 =
"\ufe0f";
5956 const kComplicatedEmoji = `${kEmojiSuperhero}${kEmojiMediumSkinTone}${kZeroWidthJoiner}${kFemaleSign}${kVariationSelector16}`;
5957 password.value = `${kComplicatedEmoji}${kComplicatedEmoji}${kComplicatedEmoji}`
5959 checkRange(
0,
21, `${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}`,
5960 "runQueryPasswordTest: Complicated emojis in password, unmasked range is not specified");
5962 editor.unmask(
0,
7);
5963 checkRange(
0,
21, `${kComplicatedEmoji}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}`,
5964 "runQueryPasswordTest: Complicated emojis in password, unmasked range 0-7 #1");
5965 checkRange(
0,
7, `${kComplicatedEmoji}`,
5966 "runQueryPasswordTest: Complicated emojis in password, unmasked range 0-7 #2");
5967 checkRange(
7,
7, `${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}`,
5968 "runQueryPasswordTest: Complicated emojis in password, unmasked range 0-7 #3");
5969 checkRange(
14,
7, `${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}`,
5970 "runQueryPasswordTest: Complicated emojis in password, unmasked range 0-7 #4");
5972 editor.unmask(
7,
14);
5973 checkRange(
0,
21, `${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kComplicatedEmoji}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}`,
5974 "runQueryPasswordTest: Complicated emojis in password, unmasked range 7-14 #1");
5975 checkRange(
0,
7, `${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}`,
5976 "runQueryPasswordTest: Complicated emojis in password, unmasked range 7-14 #2");
5977 checkRange(
7,
7, `${kComplicatedEmoji}`,
5978 "runQueryPasswordTest: Complicated emojis in password, unmasked range 7-14 #3");
5979 checkRange(
14,
7, `${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}`,
5980 "runQueryPasswordTest: Complicated emojis in password, unmasked range 7-14 #4");
5982 editor.unmask(
14,
21);
5983 checkRange(
0,
21, `${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kComplicatedEmoji}`,
5984 "runQueryPasswordTest: Complicated emojis in password, unmasked range 14-21 #1");
5985 checkRange(
0,
7, `${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}`,
5986 "runQueryPasswordTest: Complicated emojis in password, unmasked range 14-21 #2");
5987 checkRange(
7,
7, `${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}`,
5988 "runQueryPasswordTest: Complicated emojis in password, unmasked range 14-21 #3");
5989 checkRange(
14,
7, `${kComplicatedEmoji}`,
5990 "runQueryPasswordTest: Complicated emojis in password, unmasked range 14-21 #4");
5992 password.value = `${kComplicatedEmoji}`
5993 editor.unmask(
0,
1);
5994 checkRange(
0,
7, `${kEmojiSuperhero}${kMask}${kMask}${kMask}${kMask}${kMask}`,
5995 "runQueryPasswordTest: Complicated emoji in password, unmasked range 0-1");
5997 editor.unmask(
1,
2);
5998 checkRange(
0,
7, `${kEmojiSuperhero}${kMask}${kMask}${kMask}${kMask}${kMask}`,
5999 "runQueryPasswordTest: Complicated emoji in password, unmasked range 1-2");
6001 editor.unmask(
2,
3);
6002 checkRange(
0,
7, `${kMask}${kMask}${kEmojiMediumSkinTone}${kMask}${kMask}${kMask}`,
6003 "runQueryPasswordTest: Complicated emoji in password, unmasked range 2-3");
6005 editor.unmask(
3,
4);
6006 checkRange(
0,
7, `${kMask}${kMask}${kEmojiMediumSkinTone}${kMask}${kMask}${kMask}`,
6007 "runQueryPasswordTest: Complicated emoji in password, unmasked range 3-4");
6009 editor.unmask(
4,
5);
6010 checkRange(
0,
7, `${kMask}${kMask}${kMask}${kMask}${kZeroWidthJoiner}${kMask}${kMask}`,
6011 "runQueryPasswordTest: Complicated emoji in password, unmasked range 4-5");
6013 editor.unmask(
5,
6);
6014 checkRange(
0,
7, `${kMask}${kMask}${kMask}${kMask}${kMask}${kFemaleSign}${kMask}`,
6015 "runQueryPasswordTest: Complicated emoji in password, unmasked range 5-6");
6017 editor.unmask(
6,
7);
6018 checkRange(
0,
7, `${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kVariationSelector16}`,
6019 "runQueryPasswordTest: Complicated emoji in password, unmasked range 6-7");
6022 const kKanji =
"\u8fba";
6023 const kIVS = String.fromCodePoint(
0xe0101);
6024 const kKanjiWithIVS = `${kKanji}${kIVS}`;
6025 password.value = `${kKanjiWithIVS}${kKanjiWithIVS}${kKanjiWithIVS}`
6028 checkRange(
0,
9, `${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}`,
6029 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range is not specified");
6031 editor.unmask(
0,
3);
6032 checkRange(
0,
9, `${kKanjiWithIVS}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}`,
6033 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 1-3 #1");
6034 checkRange(
0,
3, `${kKanjiWithIVS}`,
6035 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 1-3 #2");
6036 checkRange(
1,
3, `${kIVS}${kMask}`,
6037 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 1-3 #3");
6038 checkRange(
0,
1, `${kKanji}`,
6039 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 1-3 #4");
6040 checkRange(
1,
2, `${kIVS}`,
6041 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 1-3 #5");
6042 checkRange(
3,
1, `${kMask}`,
6043 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 1-3 #6");
6044 checkRange(
4,
2, `${kMask}${kMask}`,
6045 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 1-3 #7");
6046 checkRange(
6,
1, `${kMask}`,
6047 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 1-3 #8");
6048 checkRange(
7,
2, `${kMask}${kMask}`,
6049 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 1-3 #9");
6051 editor.unmask(
0,
1);
6052 checkRange(
0,
9, `${kKanji}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}`,
6053 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 0-1 #1");
6054 checkRange(
0,
1, `${kKanji}`,
6055 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 0-1 #2");
6056 checkRange(
1,
2, `${kMask}${kMask}`,
6057 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 0-1 #3");
6058 checkRange(
3,
1, `${kMask}`,
6059 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 0-1 #4");
6060 checkRange(
4,
2, `${kMask}${kMask}`,
6061 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 0-1 #5");
6062 checkRange(
6,
1, `${kMask}`,
6063 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 0-1 #6");
6064 checkRange(
7,
2, `${kMask}${kMask}`,
6065 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 0-1 #7");
6067 editor.unmask(
1,
3);
6068 checkRange(
0,
9, `${kMask}${kIVS}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}`,
6069 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 1-3 #1");
6070 checkRange(
0,
1, `${kMask}`,
6071 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 1-3 #2");
6072 checkRange(
1,
2, `${kIVS}`,
6073 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 1-3 #3");
6074 checkRange(
3,
1, `${kMask}`,
6075 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 1-3 #4");
6076 checkRange(
4,
2, `${kMask}${kMask}`,
6077 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 1-3 #5");
6078 checkRange(
6,
1, `${kMask}`,
6079 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 1-3 #6");
6080 checkRange(
7,
2, `${kMask}${kMask}`,
6081 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 1-3 #7");
6083 editor.unmask(
3,
6);
6084 checkRange(
0,
9, `${kMask}${kMask}${kMask}${kKanjiWithIVS}${kMask}${kMask}${kMask}`,
6085 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 3-6 #1");
6086 checkRange(
3,
3, `${kKanjiWithIVS}`,
6087 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 3-6 #2");
6088 checkRange(
4,
3, `${kIVS}${kMask}`,
6089 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 3-6 #3");
6090 checkRange(
0,
1, `${kMask}`,
6091 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 3-6 #4");
6092 checkRange(
1,
2, `${kMask}${kMask}`,
6093 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 3-6 #5");
6094 checkRange(
3,
1, `${kKanji}`,
6095 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 3-6 #6");
6096 checkRange(
4,
2, `${kIVS}`,
6097 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 3-6 #7");
6098 checkRange(
6,
1, `${kMask}`,
6099 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 3-6 #8");
6100 checkRange(
7,
2, `${kMask}${kMask}`,
6101 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 3-6 #9");
6103 editor.unmask(
3,
4);
6104 checkRange(
0,
9, `${kMask}${kMask}${kMask}${kKanji}${kMask}${kMask}${kMask}${kMask}${kMask}`,
6105 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 3-4 #1");
6106 checkRange(
0,
1, `${kMask}`,
6107 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 3-4 #2");
6108 checkRange(
1,
2, `${kMask}${kMask}`,
6109 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 3-4 #3");
6110 checkRange(
3,
1, `${kKanji}`,
6111 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 3-4 #4");
6112 checkRange(
4,
2, `${kMask}${kMask}`,
6113 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 3-4 #5");
6114 checkRange(
6,
1, `${kMask}`,
6115 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 3-4 #6");
6116 checkRange(
7,
2, `${kMask}${kMask}`,
6117 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 3-4 #7");
6119 editor.unmask(
4,
6);
6120 checkRange(
0,
9, `${kMask}${kMask}${kMask}${kMask}${kIVS}${kMask}${kMask}${kMask}`,
6121 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 4-6 #1");
6122 checkRange(
0,
1, `${kMask}`,
6123 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 4-6 #2");
6124 checkRange(
1,
2, `${kMask}${kMask}`,
6125 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 4-6 #3");
6126 checkRange(
3,
1, `${kMask}`,
6127 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 4-6 #4");
6128 checkRange(
4,
2, `${kIVS}`,
6129 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 4-6 #5");
6130 checkRange(
6,
1, `${kMask}`,
6131 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 4-6 #6");
6132 checkRange(
7,
2, `${kMask}${kMask}`,
6133 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 4-6 #7");
6135 editor.unmask(
6,
9);
6136 checkRange(
0,
9, `${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kKanjiWithIVS}`,
6137 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 6-9 #1");
6138 checkRange(
6,
3, `${kKanjiWithIVS}`,
6139 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 6-9 #2");
6140 checkRange(
4,
3, `${kMask}${kMask}${kKanji}`,
6141 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 6-9 #3");
6142 checkRange(
0,
1, `${kMask}`,
6143 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 6-9 #4");
6144 checkRange(
1,
2, `${kMask}${kMask}`,
6145 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 6-9 #5");
6146 checkRange(
3,
1, `${kMask}`,
6147 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 6-9 #6");
6148 checkRange(
4,
2, `${kMask}${kMask}`,
6149 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 6-9 #7");
6150 checkRange(
6,
1, `${kKanji}`,
6151 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 6-9 #8");
6152 checkRange(
7,
2, `${kIVS}`,
6153 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 6-9 #9");
6155 editor.unmask(
6,
7);
6156 checkRange(
0,
9, `${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kKanji}${kMask}${kMask}`,
6157 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 6-7 #1");
6158 checkRange(
0,
1, `${kMask}`,
6159 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 6-7 #2");
6160 checkRange(
1,
2, `${kMask}${kMask}`,
6161 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 6-7 #3");
6162 checkRange(
3,
1, `${kMask}`,
6163 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 6-7 #4");
6164 checkRange(
4,
2, `${kMask}${kMask}`,
6165 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 6-7 #5");
6166 checkRange(
6,
1, `${kKanji}`,
6167 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 6-7 #6");
6168 checkRange(
7,
2, `${kMask}${kMask}`,
6169 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 6-7 #7");
6171 editor.unmask(
7,
9);
6172 checkRange(
0,
9, `${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kMask}${kIVS}`,
6173 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 7-9 #1");
6174 checkRange(
0,
1, `${kMask}`,
6175 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 7-9 #2");
6176 checkRange(
1,
2, `${kMask}${kMask}`,
6177 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 7-9 #3");
6178 checkRange(
3,
1, `${kMask}`,
6179 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 7-9 #4");
6180 checkRange(
4,
2, `${kMask}${kMask}`,
6181 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 7-9 #5");
6182 checkRange(
6,
1, `${kMask}`,
6183 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 7-9 #6");
6184 checkRange(
7,
2, `${kIVS}`,
6185 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 7-9 #7");
6187 password.value = `${kKanjiWithIVS}${kKanjiWithIVS}`;
6188 editor.unmask(
0,
2);
6189 checkRange(
0,
6, `${kKanjiWithIVS}${kMask}${kMask}${kMask}`,
6190 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 0-2");
6192 editor.unmask(
1,
2);
6193 checkRange(
0,
6, `${kMask}${kIVS}${kMask}${kMask}${kMask}`,
6194 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 1-2");
6196 editor.unmask(
2,
3);
6197 checkRange(
0,
6, `${kMask}${kIVS}${kMask}${kMask}${kMask}`,
6198 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 2-3");
6200 editor.unmask(
3,
5);
6201 checkRange(
0,
6, `${kMask}${kMask}${kMask}${kKanjiWithIVS}`,
6202 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 3-5");
6204 editor.unmask(
4,
5);
6205 checkRange(
0,
6, `${kMask}${kMask}${kMask}${kMask}${kIVS}`,
6206 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 4-5");
6208 editor.unmask(
5,
6);
6209 checkRange(
0,
6, `${kMask}${kMask}${kMask}${kMask}${kIVS}`,
6210 "runQueryPasswordTest: Pairs of Kanji and IVS in password, unmasked range 5-6");
6215 function runQueryContentEventRelativeToInsertionPoint()
6218 textarea.value =
"0123456789";
6221 let startOffset = textarea.selectionStart = textarea.selectionEnd =
0;
6222 if (!checkContentRelativeToSelection(
0,
1,
0,
"0",
"runQueryContentEventRelativeToInsertionPoint[0-0]",
"#1") ||
6223 !checkContentRelativeToSelection(-
1,
1,
0,
"0",
"runQueryContentEventRelativeToInsertionPoint[0-0]",
"#2") ||
6224 !checkContentRelativeToSelection(
1,
1,
1,
"1",
"runQueryContentEventRelativeToInsertionPoint[0-0]",
"#3") ||
6225 !checkContentRelativeToSelection(
5,
10,
5,
"56789",
"runQueryContentEventRelativeToInsertionPoint[0-0]",
"#4") ||
6226 !checkContentRelativeToSelection(
10,
1,
10,
"",
"runQueryContentEventRelativeToInsertionPoint[0-0]",
"#5")) {
6231 textarea.selectionEnd =
5;
6232 if (!checkContentRelativeToSelection(
0,
1,
0,
"0",
"runQueryContentEventRelativeToInsertionPoint[0-5]",
"#1") ||
6233 !checkContentRelativeToSelection(-
1,
1,
0,
"0",
"runQueryContentEventRelativeToInsertionPoint[0-5]",
"#2") ||
6234 !checkContentRelativeToSelection(
1,
1,
1,
"1",
"runQueryContentEventRelativeToInsertionPoint[0-5]",
"#3") ||
6235 !checkContentRelativeToSelection(
5,
10,
5,
"56789",
"runQueryContentEventRelativeToInsertionPoint[0-5]",
"#4") ||
6236 !checkContentRelativeToSelection(
10,
1,
10,
"",
"runQueryContentEventRelativeToInsertionPoint[0-5]",
"#5")) {
6241 startOffset = textarea.selectionStart = textarea.selectionEnd =
4;
6242 if (!checkContentRelativeToSelection(
0,
1, startOffset +
0,
"4",
"runQueryContentEventRelativeToInsertionPoint[4-4]",
"#1") ||
6243 !checkContentRelativeToSelection(-
1,
1, startOffset -
1,
"3",
"runQueryContentEventRelativeToInsertionPoint[4-4]",
"#2") ||
6244 !checkContentRelativeToSelection(
1,
1, startOffset +
1,
"5",
"runQueryContentEventRelativeToInsertionPoint[4-4]",
"#3") ||
6245 !checkContentRelativeToSelection(
5,
10, startOffset +
5,
"9",
"runQueryContentEventRelativeToInsertionPoint[4-4]",
"#4") ||
6246 !checkContentRelativeToSelection(
10,
1,
10,
"",
"runQueryContentEventRelativeToInsertionPoint[4-4]",
"#5")) {
6250 synthesizeCompositionChange(
6255 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
6258 "caret": {
"start":
1,
"length":
0 }
6261 if (!checkContentRelativeToSelection(
0,
1, startOffset +
0,
"a",
"runQueryContentEventRelativeToInsertionPoint[composition at 4]",
"#1") ||
6262 !checkContentRelativeToSelection(-
1,
1, startOffset -
1,
"3",
"runQueryContentEventRelativeToInsertionPoint[composition at 4]",
"#2") ||
6263 !checkContentRelativeToSelection(
1,
1, startOffset +
1,
"4",
"runQueryContentEventRelativeToInsertionPoint[composition at 4]",
"#3") ||
6264 !checkContentRelativeToSelection(
5,
10, startOffset +
5,
"89",
"runQueryContentEventRelativeToInsertionPoint[composition at 4]",
"#4") ||
6265 !checkContentRelativeToSelection(
11,
1,
11,
"",
"runQueryContentEventRelativeToInsertionPoint[composition at 4]")) {
6266 synthesizeComposition({ type:
"compositioncommitasis" });
6270 synthesizeComposition({ type:
"compositioncommitasis" });
6272 // Move start of composition at first compositionupdate event.
6273 function onCompositionUpdate(aEvent)
6275 startOffset = textarea.selectionStart = textarea.selectionEnd = textarea.selectionStart -
1;
6276 textarea.removeEventListener(
"compositionupdate", onCompositionUpdate);
6278 textarea.addEventListener(
"compositionupdate", onCompositionUpdate);
6280 synthesizeCompositionChange(
6285 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
6288 "caret": {
"start":
1,
"length":
0 }
6291 if (!checkContentRelativeToSelection(
0,
1, startOffset +
0,
"b",
"runQueryContentEventRelativeToInsertionPoint[composition at 3]",
"#1") ||
6292 !checkContentRelativeToSelection(-
1,
1, startOffset -
1,
"3",
"runQueryContentEventRelativeToInsertionPoint[composition at 3]",
"#2") ||
6293 !checkContentRelativeToSelection(
1,
1, startOffset +
1,
"a",
"runQueryContentEventRelativeToInsertionPoint[composition at 3]",
"#3") ||
6294 !checkContentRelativeToSelection(
5,
10, startOffset +
5,
"789",
"runQueryContentEventRelativeToInsertionPoint[composition at 3]",
"#4") ||
6295 !checkContentRelativeToSelection(
12,
1,
12,
"",
"runQueryContentEventRelativeToInsertionPoint[composition at 3]",
"#5")) {
6296 synthesizeComposition({ type:
"compositioncommitasis" });
6300 synthesizeComposition({ type:
"compositioncommitasis" });
6303 function runBug1375825Test()
6305 contenteditable.focus();
6308 contenteditable.innerHTML =
"abc<span contenteditable=\"false\
">defgh</span>";
6310 let ret = synthesizeQueryTextRect(
2,
1);
6311 if (!checkQueryContentResult(ret,
"runBug1375825Test #1 (2, 1), \"" + contenteditable.innerHTML + "\
"")) {
6314 is(ret.text,
"c",
"runBug1375825Test #1 (2, 1), \"" + contenteditable.innerHTML + "\
": should have queried a rect for 'c'");
6316 ret = synthesizeQueryTextRect(
3,
1);
6317 if (!checkQueryContentResult(ret,
"runBug1375825Test #1 (3, 1), \"" + contenteditable.innerHTML + "\
"")) {
6320 is(ret.text,
"d",
"runBug1375825Test #1 (3, 1), \"" + contenteditable.innerHTML + "\
": should have queried a rect for 'd'");
6322 ret = synthesizeQueryTextRect(
4,
1);
6323 if (!checkQueryContentResult(ret,
"runBug1375825Test #1 (4, 1), \"" + contenteditable.innerHTML + "\
"")) {
6326 is(ret.text,
"e",
"runBug1375825Test #1 (4, 1), \"" + contenteditable.innerHTML + "\
": should have queried a rect for 'e'");
6328 ret = synthesizeQueryTextRect(
5,
1);
6329 if (!checkQueryContentResult(ret,
"runBug1375825Test #1 (5, 1), \"" + contenteditable.innerHTML + "\
"")) {
6332 is(ret.text,
"f",
"runBug1375825Test #1 (5, 1), \"" + contenteditable.innerHTML + "\
": should have queried a rect for 'f'");
6334 ret = synthesizeQueryTextRect(
6,
1);
6335 if (!checkQueryContentResult(ret,
"runBug1375825Test #1 (6, 1), \"" + contenteditable.innerHTML + "\
"")) {
6338 is(ret.text,
"g",
"runBug1375825Test #1 (6, 1), \"" + contenteditable.innerHTML + "\
": should have queried a rect for 'g'");
6340 ret = synthesizeQueryTextRect(
7,
1);
6341 if (!checkQueryContentResult(ret,
"runBug1375825Test #1 (7, 1), \"" + contenteditable.innerHTML + "\
"")) {
6344 is(ret.text,
"h",
"runBug1375825Test #1 (7, 1), \"" + contenteditable.innerHTML + "\
": should have queried a rect for 'h'");
6347 contenteditable.innerHTML =
"abc<span style=\"user-select: all;\
">defgh</span>";
6349 ret = synthesizeQueryTextRect(
2,
1);
6350 if (!checkQueryContentResult(ret,
"runBug1375825Test #2 (2, 1), \"" + contenteditable.innerHTML + "\
"")) {
6353 is(ret.text,
"c",
"runBug1375825Test #2 (2, 1), \"" + contenteditable.innerHTML + "\
": should have queried a rect for 'c'");
6355 ret = synthesizeQueryTextRect(
3,
1);
6356 if (!checkQueryContentResult(ret,
"runBug1375825Test #2 (3, 1), \"" + contenteditable.innerHTML + "\
"")) {
6359 is(ret.text,
"d",
"runBug1375825Test #2 (3, 1), \"" + contenteditable.innerHTML + "\
": should have queried a rect for 'd'");
6361 ret = synthesizeQueryTextRect(
4,
1);
6362 if (!checkQueryContentResult(ret,
"runBug1375825Test #2 (4, 1), \"" + contenteditable.innerHTML + "\
"")) {
6365 is(ret.text,
"e",
"runBug1375825Test #2 (4, 1), \"" + contenteditable.innerHTML + "\
": should have queried a rect for 'e'");
6367 ret = synthesizeQueryTextRect(
5,
1);
6368 if (!checkQueryContentResult(ret,
"runBug1375825Test #2 (5, 1), \"" + contenteditable.innerHTML + "\
"")) {
6371 is(ret.text,
"f",
"runBug1375825Test #2 (5, 1), \"" + contenteditable.innerHTML + "\
": should have queried a rect for 'f'");
6373 ret = synthesizeQueryTextRect(
6,
1);
6374 if (!checkQueryContentResult(ret,
"runBug1375825Test #2 (6, 1), \"" + contenteditable.innerHTML + "\
"")) {
6377 is(ret.text,
"g",
"runBug1375825Test #2 (6, 1), \"" + contenteditable.innerHTML + "\
": should have queried a rect for 'g'");
6379 ret = synthesizeQueryTextRect(
7,
1);
6380 if (!checkQueryContentResult(ret,
"runBug1375825Test #2 (7, 1), \"" + contenteditable.innerHTML + "\
"")) {
6383 is(ret.text,
"h",
"runBug1375825Test #2 (7, 1), \"" + contenteditable.innerHTML + "\
": should have queried a rect for 'h'");
6386 function runBug1530649Test()
6388 // Vietnamese IME on macOS commits composition with typing space key.
6389 // Then, typing new word shouldn't trim the trailing whitespace.
6390 contenteditable.focus();
6391 contenteditable.innerHTML =
"";
6392 synthesizeCompositionChange(
6393 {composition: {string:
"abc", clauses: [{length:
3, attr: COMPOSITION_ATTR_RAW_CLAUSE}]},
6394 caret: {start:
3, length:
0}});
6395 synthesizeComposition({type:
"compositioncommit", data:
"abc ", key:
" "});
6397 is(contenteditable.innerHTML,
"abc <br>",
6398 "runBug1530649Test: The trailing space shouldn't be removed");
6400 synthesizeCompositionChange(
6401 {composition: {string:
"d", clauses: [{length:
1, attr: COMPOSITION_ATTR_RAW_CLAUSE}]},
6402 caret: {start:
1, length:
0}});
6404 is(contenteditable.innerHTML,
"abc d<br>",
6405 "runBug1530649Test: The new composition string shouldn't remove the last space");
6407 synthesizeComposition({type:
"compositioncommitasis", key:
"KEY_Enter"});
6409 is(contenteditable.innerHTML,
"abc d<br>",
6410 "runBug1530649Test: Committing the new composition string shouldn't remove the last space");
6413 function runBug1571375Test()
6415 let selection = windowOfContenteditableBySpan.getSelection();
6416 let doc = document.getElementById(
"iframe7").contentDocument;
6418 contenteditableBySpan.focus();
6420 contenteditableBySpan.innerHTML =
"hello world";
6421 let range = doc.createRange();
6422 range.setStart(contenteditableBySpan.firstChild,
6);
6423 range.setEnd(contenteditableBySpan.firstChild,
11);
6424 selection.removeAllRanges();
6425 selection.addRange(range);
6427 synthesizeCompositionChange({
6428 composition: {string:
"world", clauses: [{length:
5, attr: COMPOSITION_ATTR_RAW_CLAUSE}]},
6429 caret: { start:
5, length:
0 },
6431 synthesizeComposition({type:
"compositioncommit", data:
"world", key:
" "});
6432 is(contenteditableBySpan.innerHTML,
"hello world",
6433 "runBug1571375Test: space must not be removed by commit");
6435 contenteditableBySpan.innerHTML =
"hello world";
6436 range = doc.createRange();
6437 range.setStart(contenteditableBySpan.firstChild,
0);
6438 range.setEnd(contenteditableBySpan.firstChild,
5);
6439 selection.removeAllRanges();
6440 selection.addRange(range);
6442 synthesizeCompositionChange({
6443 composition: {string:
"hello", clauses: [{length:
5, attr: COMPOSITION_ATTR_RAW_CLAUSE}]},
6444 caret: { start:
5, length:
0 },
6446 synthesizeComposition({type:
"compositioncommit", data:
"hello", key:
" "});
6447 is(contenteditableBySpan.innerHTML,
"hello world",
6448 "runBug1571375Test: space must not be removed by commit");
6450 contenteditableBySpan.innerHTML =
"hello world<div>.</div>";
6451 range = doc.createRange();
6452 range.setStart(contenteditableBySpan.firstChild,
6);
6453 range.setEnd(contenteditableBySpan.firstChild,
11);
6454 selection.removeAllRanges();
6455 selection.addRange(range);
6457 synthesizeCompositionChange({
6458 composition: {string:
"world", clauses: [{length:
5, attr: COMPOSITION_ATTR_RAW_CLAUSE}]},
6459 caret: {start:
0, length:
0}}
6461 synthesizeComposition({type:
"compositioncommit", data:
"world", key:
" "});
6462 is(contenteditableBySpan.innerHTML,
"hello world<div>.</div>",
6463 "runBug1571375Test: space must not be removed by commit");
6466 async function runBug1584901Test()
6468 contenteditableBySpan.focus();
6469 contenteditableBySpan.innerHTML =
"";
6471 // XXX synthesizeCompositionChange won't work without wait.
6472 await waitForTick();
6474 synthesizeCompositionChange({
6475 composition: {string:
"a ", clauses: [{length:
2, attr: COMPOSITION_ATTR_RAW_CLAUSE}]},
6477 synthesizeComposition({type:
"compositioncommitasis", key:
" "});
6479 is(contenteditableBySpan.innerHTML,
"a ",
6480 "runBug1584901Test: space must not be removed by composition change");
6482 synthesizeCompositionChange({
6483 composition: {string:
"b ", clauses: [{length:
2, attr: COMPOSITION_ATTR_RAW_CLAUSE}]},
6485 synthesizeComposition({type:
"compositioncommitasis", key:
" "});
6487 is(contenteditableBySpan.innerHTML,
"a b ",
6488 "runBug1584901Test: space must not be removed by composition change");
6491 function runBug1675313Test()
6497 function handler() {
6502 input.addEventListener(
"keydown", handler);
6503 input.addEventListener(
"keyup", handler);
6505 synthesizeCompositionChange({
6508 clauses: [{length:
1, attr: COMPOSITION_ATTR_RAW_CLAUSE}],
6509 key: { key:
"a", type:
"keyup" },
6512 synthesizeCompositionChange({
6515 clauses: [{length:
1, attr: COMPOSITION_ATTR_RAW_CLAUSE}],
6516 key: { key:
"b", type:
"keyup" },
6519 synthesizeComposition({type:
"compositioncommitasis"});
6521 is(count,
6,
"runBug1675313Test: keydown event and keyup event are fired correctly");
6522 is(input.value,
"b",
6523 "runBug1675313Test: re-focus element doesn't commit composition if re-focus isn't click by user");
6525 input.removeEventListener(
"keyup", handler);
6528 function runCommitCompositionWithSpaceKey()
6530 contenteditable.focus();
6531 contenteditable.innerHTML =
"";
6533 // Last white space might be
if last child is no
<br>
6534 // Actually, our implementation will insert
<br> element at last child, so
6535 // white space will be ASCII space.
6537 synthesizeCompositionChange({
6538 composition: {string:
"a", clauses: [{length:
1, attr: COMPOSITION_ATTR_RAW_CLAUSE}]},
6540 synthesizeComposition({type:
"compositioncommit", data:
"a"});
6543 is(contenteditable.innerHTML,
"a <br>",
6544 "runCommitCompositionWithSpaceKey: last single space should be kept");
6546 synthesizeCompositionChange({
6547 composition: {string:
"b", clauses: [{length:
1, attr: COMPOSITION_ATTR_RAW_CLAUSE}]},
6549 synthesizeComposition({type:
"compositioncommit", data:
"b"});
6552 is(contenteditable.innerHTML,
"a b <br>",
6553 "runCommitCompositionWithSpaceKey: inserting composition shouldn't remove last single space.");
6555 synthesizeCompositionChange({
6556 composition: {string:
"c", clauses: [{length:
1, attr: COMPOSITION_ATTR_RAW_CLAUSE}]},
6558 synthesizeComposition({type:
"compositioncommit", data:
"c"});
6561 is(contenteditable.innerHTML,
"a b c <br>",
6562 "runCommitCompositionWithSpaceKey: inserting composition shouldn't remove last single space.");
6564 contenteditable.innerHTML =
"a";
6565 windowOfContenteditable.getSelection().collapse(contenteditable.firstChild, contenteditable.firstChild.length);
6566 is(contenteditable.innerHTML,
"a",
6567 "runCommitCompositionWithSpaceKey: contenteditable should be initialized with text ending with a space and without following <br> element");
6569 synthesizeCompositionChange({
6570 composition: {string:
"b", clauses: [{length:
1, attr: COMPOSITION_ATTR_RAW_CLAUSE}]},
6572 synthesizeComposition({type:
"compositioncommit", data:
"b ", key: { key:
" ", code:
"Space" }});
6574 is(contenteditable.innerHTML,
"ab <br>",
6575 "runCommitCompositionWithSpaceKey: contenteditable should end with a padding <br> element after inserting commit string ending with a space");
6578 function runCSSTransformTest()
6581 textarea.value =
"some text";
6582 textarea.selectionStart = textarea.selectionEnd = textarea.value.length;
6583 let editorRect = synthesizeQueryEditorRect();
6584 if (!checkQueryContentResult(editorRect,
6585 "runCSSTransformTest: editorRect")) {
6588 let firstCharRect = synthesizeQueryTextRect(
0,
1);
6589 if (!checkQueryContentResult(firstCharRect,
6590 "runCSSTransformTest: firstCharRect")) {
6593 let lastCharRect = synthesizeQueryTextRect(textarea.value.length -
1, textarea.value.length);
6594 if (!checkQueryContentResult(lastCharRect,
6595 "runCSSTransformTest: lastCharRect")) {
6598 let caretRect = synthesizeQueryCaretRect(textarea.selectionStart);
6599 if (!checkQueryContentResult(caretRect,
6600 "runCSSTransformTest: caretRect")) {
6603 let caretRectBeforeFirstChar = synthesizeQueryCaretRect(
0);
6604 if (!checkQueryContentResult(caretRectBeforeFirstChar,
6605 "runCSSTransformTest: caretRectBeforeFirstChar")) {
6610 textarea.style.transform =
"translate(10px, 15px)";
6611 function movedRect(aRect, aCSS_CX, aCSS_CY)
6614 left: aRect.left + Math.round(aCSS_CX * window.devicePixelRatio),
6615 top: aRect.top + Math.round(aCSS_CY * window.devicePixelRatio),
6617 height: aRect.height
6621 let editorRectTranslated = synthesizeQueryEditorRect();
6622 if (!checkQueryContentResult(editorRectTranslated,
6623 "runCSSTransformTest: editorRectTranslated, " + textarea.style.transform) ||
6624 !checkRectFuzzy(editorRectTranslated, movedRect(editorRect,
10,
15), {left:
1, top:
1, width:
1, height:
1},
6625 "runCSSTransformTest: editorRectTranslated, " + textarea.style.transform)) {
6628 let firstCharRectTranslated = synthesizeQueryTextRect(
0,
1);
6629 if (!checkQueryContentResult(firstCharRectTranslated,
6630 "runCSSTransformTest: firstCharRectTranslated, " + textarea.style.transform) ||
6631 !checkRectFuzzy(firstCharRectTranslated, movedRect(firstCharRect,
10,
15), {left:
1, top:
1, width:
1, height:
1},
6632 "runCSSTransformTest: firstCharRectTranslated, " + textarea.style.transform)) {
6635 let lastCharRectTranslated = synthesizeQueryTextRect(textarea.value.length -
1, textarea.value.length);
6636 if (!checkQueryContentResult(lastCharRectTranslated,
6637 "runCSSTransformTest: lastCharRectTranslated, " + textarea.style.transform) ||
6638 !checkRectFuzzy(lastCharRectTranslated, movedRect(lastCharRect,
10,
15), {left:
1, top:
1, width:
1, height:
1},
6639 "runCSSTransformTest: lastCharRectTranslated, " + textarea.style.transform)) {
6642 let caretRectTranslated = synthesizeQueryCaretRect(textarea.selectionStart);
6643 if (!checkQueryContentResult(caretRectTranslated,
6644 "runCSSTransformTest: caretRectTranslated, " + textarea.style.transform) ||
6645 !checkRectFuzzy(caretRectTranslated, movedRect(caretRect,
10,
15), {left:
1, top:
1, width:
1, height:
1},
6646 "runCSSTransformTest: caretRectTranslated, " + textarea.style.transform)) {
6649 let caretRectBeforeFirstCharTranslated = synthesizeQueryCaretRect(
0);
6650 if (!checkQueryContentResult(caretRectBeforeFirstCharTranslated,
6651 "runCSSTransformTest: caretRectBeforeFirstCharTranslated, " + textarea.style.transform) ||
6652 !checkRectFuzzy(caretRectBeforeFirstCharTranslated, movedRect(caretRectBeforeFirstChar,
10,
15), {left:
1, top:
1, width:
1, height:
1},
6653 "runCSSTransformTest: caretRectBeforeFirstCharTranslated, " + textarea.style.transform)) {
6656 let firstCharRectTranslatedAsArray = synthesizeQueryTextRectArray(
0,
1);
6657 if (!checkQueryContentResult(firstCharRectTranslatedAsArray,
"runCSSTransformTest: firstCharRectTranslatedAsArray, " + textarea.style.transform) ||
6658 !checkRectArray(firstCharRectTranslatedAsArray, [firstCharRectTranslated],
"runCSSTransformTest: firstCharRectTranslatedAsArray, " + textarea.style.transform)) {
6661 let lastCharRectTranslatedAsArray = synthesizeQueryTextRectArray(textarea.value.length -
1, textarea.value.length);
6662 if (!checkQueryContentResult(lastCharRectTranslatedAsArray,
"runCSSTransformTest: lastCharRectTranslatedAsArray, " + textarea.style.transform) ||
6663 !checkRectArray(lastCharRectTranslatedAsArray, [lastCharRectTranslated],
"runCSSTransformTest: lastCharRectTranslatedAsArray, " + textarea.style.transform)) {
6667 // XXX It's too difficult to check the result with scale and rotate...
6668 // For now, let's check if query text rect and query text rect array returns same rect.
6669 textarea.style.transform =
"scale(1.5)";
6670 firstCharRectTranslated = synthesizeQueryTextRect(
0,
1);
6671 if (!checkQueryContentResult(firstCharRectTranslated,
6672 "runCSSTransformTest: firstCharRectTranslated, " + textarea.style.transform)) {
6675 lastCharRectTranslated = synthesizeQueryTextRect(textarea.value.length -
1, textarea.value.length);
6676 if (!checkQueryContentResult(lastCharRectTranslated,
6677 "runCSSTransformTest: lastCharRectTranslated, " + textarea.style.transform)) {
6680 firstCharRectTranslatedAsArray = synthesizeQueryTextRectArray(
0,
1);
6681 if (!checkQueryContentResult(firstCharRectTranslatedAsArray,
"runCSSTransformTest: firstCharRectTranslatedAsArray, " + textarea.style.transform) ||
6682 !checkRectArray(firstCharRectTranslatedAsArray, [firstCharRectTranslated],
"runCSSTransformTest: firstCharRectTranslatedAsArray, " + textarea.style.transform)) {
6685 lastCharRectTranslatedAsArray = synthesizeQueryTextRectArray(textarea.value.length -
1, textarea.value.length);
6686 if (!checkQueryContentResult(lastCharRectTranslatedAsArray,
"runCSSTransformTest: lastCharRectTranslatedAsArray, " + textarea.style.transform) ||
6687 !checkRectArray(lastCharRectTranslatedAsArray, [lastCharRectTranslated],
"runCSSTransformTest: lastCharRectTranslatedAsArray, " + textarea.style.transform)) {
6691 textarea.style.transform =
"rotate(30deg)";
6692 firstCharRectTranslated = synthesizeQueryTextRect(
0,
1);
6693 if (!checkQueryContentResult(firstCharRectTranslated,
6694 "runCSSTransformTest: firstCharRectTranslated, " + textarea.style.transform)) {
6697 lastCharRectTranslated = synthesizeQueryTextRect(textarea.value.length -
1, textarea.value.length);
6698 if (!checkQueryContentResult(lastCharRectTranslated,
6699 "runCSSTransformTest: lastCharRectTranslated, " + textarea.style.transform)) {
6702 firstCharRectTranslatedAsArray = synthesizeQueryTextRectArray(
0,
1);
6703 if (!checkQueryContentResult(firstCharRectTranslatedAsArray,
"runCSSTransformTest: firstCharRectTranslatedAsArray, " + textarea.style.transform) ||
6704 !checkRectArray(firstCharRectTranslatedAsArray, [firstCharRectTranslated],
"runCSSTransformTest: firstCharRectTranslatedAsArray, " + textarea.style.transform)) {
6707 lastCharRectTranslatedAsArray = synthesizeQueryTextRectArray(textarea.value.length -
1, textarea.value.length);
6708 if (!checkQueryContentResult(lastCharRectTranslatedAsArray,
"runCSSTransformTest: lastCharRectTranslatedAsArray, " + textarea.style.transform) ||
6709 !checkRectArray(lastCharRectTranslatedAsArray, [lastCharRectTranslated],
"runCSSTransformTest: lastCharRectTranslatedAsArray, " + textarea.style.transform)) {
6713 textarea.style.transform =
"";
6717 function runBug722639Test()
6720 textarea.value =
"\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
6721 textarea.value += textarea.value;
6722 textarea.value += textarea.value; //
80 characters
6724 let firstLine = synthesizeQueryTextRect(
0,
1);
6725 if (!checkQueryContentResult(firstLine,
6726 "runBug722639Test: firstLine")) {
6729 ok(true,
"runBug722639Test: 1st line, top=" + firstLine.top +
", left=" + firstLine.left);
6730 let firstLineAsArray = synthesizeQueryTextRectArray(
0,
1);
6731 if (!checkQueryContentResult(firstLineAsArray,
"runBug722639Test: 1st line as array") ||
6732 !checkRectArray(firstLineAsArray, [firstLine],
"runBug722639Test: 1st line as array should match with text rect result")) {
6736 let firstLineLF = synthesizeQueryTextRect(
1,
1);
6737 if (!checkQueryContentResult(firstLineLF,
6738 "runBug722639Test: firstLineLF")) {
6741 is(firstLineLF.top, firstLine.top,
"runBug722639Test: 1st line's \\n rect should be same as 1st line's \\r rect");
6742 is(firstLineLF.left, firstLine.left,
"runBug722639Test: 1st line's \\n rect should be same as 1st line's \\r rect");
6743 isfuzzy(firstLineLF.height, firstLine.height,
1,
6744 "runBug722639Test: 1st line's \\n rect should be same as 1st line's \\r rect");
6745 is(firstLineLF.width, firstLine.width,
"runBug722639Test: 1st line's \\n rect should be same as 1st line's \\r rect");
6746 let firstLineLFAsArray = synthesizeQueryTextRectArray(
1,
1);
6747 if (!checkQueryContentResult(firstLineLFAsArray,
"runBug722639Test: 1st line's \\n rect as array") ||
6748 !checkRectArray(firstLineLFAsArray, [firstLineLF],
"runBug722639Test: 1st line's rect as array should match with text rect result")) {
6752 let secondLine = synthesizeQueryTextRect(kLFLen,
1);
6753 if (!checkQueryContentResult(secondLine,
6754 "runBug722639Test: secondLine")) {
6757 ok(true,
"runBug722639Test: 2nd line, top=" + secondLine.top +
", left=" + secondLine.left);
6758 let secondLineAsArray = synthesizeQueryTextRectArray(kLFLen,
1);
6759 if (!checkQueryContentResult(secondLineAsArray,
"runBug722639Test: 2nd line as array") ||
6760 !checkRectArray(secondLineAsArray, [secondLine],
"runBug722639Test: 2nd line as array should match with text rect result")) {
6764 let secondLineLF = synthesizeQueryTextRect(kLFLen +
1,
1);
6765 if (!checkQueryContentResult(secondLineLF,
6766 "runBug722639Test: secondLineLF")) {
6769 is(secondLineLF.top, secondLine.top,
"runBug722639Test: 2nd line's \\n rect should be same as 2nd line's \\r rect");
6770 is(secondLineLF.left, secondLine.left,
"runBug722639Test: 2nd line's \\n rect should be same as 2nd line's \\r rect");
6771 isfuzzy(secondLineLF.height, secondLine.height,
1,
6772 "runBug722639Test: 2nd line's \\n rect should be same as 2nd line's \\r rect");
6773 is(secondLineLF.width, secondLine.width,
"runBug722639Test: 2nd line's \\n rect should be same as 2nd line's \\r rect");
6774 let secondLineLFAsArray = synthesizeQueryTextRectArray(kLFLen +
1,
1);
6775 if (!checkQueryContentResult(secondLineLFAsArray,
"runBug722639Test: 2nd line's \\n rect as array") ||
6776 !checkRectArray(secondLineLFAsArray, [secondLineLF],
"runBug722639Test: 2nd line's rect as array should match with text rect result")) {
6780 let lineHeight = secondLine.top - firstLine.top;
6782 "runBug722639Test: lineHeight must be positive");
6783 is(secondLine.left, firstLine.left,
6784 "runBug722639Test: the left value must be always same value");
6785 isfuzzy(secondLine.height, firstLine.height,
1,
6786 "runBug722639Test: the height must be always same value");
6787 let previousTop = secondLine.top;
6788 for (let i =
3; i <= textarea.value.length +
1; i++) {
6789 let currentLine = synthesizeQueryTextRect(kLFLen * (i -
1),
1);
6790 if (!checkQueryContentResult(currentLine,
6791 "runBug722639Test: " + i +
"th currentLine")) {
6794 ok(true,
"runBug722639Test: " + i +
"th line, top=" + currentLine.top +
", left=" + currentLine.left);
6795 let currentLineAsArray = synthesizeQueryTextRectArray(kLFLen * (i -
1),
1);
6796 if (!checkQueryContentResult(currentLineAsArray,
"runBug722639Test: " + i +
"th line as array") ||
6797 !checkRectArray(currentLineAsArray, [currentLine],
"runBug722639Test: " + i +
"th line as array should match with text rect result")) {
6800 // NOTE: the top position may be
1px larger or smaller than other lines
6801 // due to sub pixel positioning.
6802 if (Math.abs(currentLine.top - (previousTop + lineHeight)) <=
1) {
6803 ok(true,
"runBug722639Test: " + i +
"th line's top is expected");
6805 is(currentLine.top, previousTop + lineHeight,
6806 "runBug722639Test: " + i +
"th line's top is unexpected");
6808 is(currentLine.left, firstLine.left,
6809 "runBug722639Test: " + i +
"th line's left is unexpected");
6810 isfuzzy(currentLine.height, firstLine.height,
1,
6811 `runBug722639Test: ${i}th line's height is unexpected`);
6813 let currentLineLF = synthesizeQueryTextRect(kLFLen * (i -
1) +
1,
1);
6814 if (!checkQueryContentResult(currentLineLF,
6815 "runBug722639Test: " + i +
"th currentLineLF")) {
6818 is(currentLineLF.top, currentLine.top,
"runBug722639Test: " + i +
"th line's \\n rect should be same as same line's \\r rect");
6819 is(currentLineLF.left, currentLine.left,
"runBug722639Test: " + i +
"th line's \\n rect should be same as same line's \\r rect");
6820 isfuzzy(currentLineLF.height, currentLine.height,
1,
6821 `runBug722639Test: ${i}th line's \\n rect should be same as same line's \\r rect`);
6822 is(currentLineLF.width, currentLine.width,
"runBug722639Test: " + i +
"th line's \\n rect should be same as same line's \\r rect");
6823 let currentLineLFAsArray = synthesizeQueryTextRectArray(kLFLen * (i -
1) +
1,
1);
6824 if (!checkQueryContentResult(currentLineLFAsArray,
"runBug722639Test: " + i +
"th line's \\n rect as array") ||
6825 !checkRectArray(currentLineLFAsArray, [currentLineLF],
"runBug722639Test: " + i +
"th line's rect as array should match with text rect result")) {
6829 previousTop = currentLine.top;
6833 function runCompositionWithSelectionChange() {
6834 function doTest(aEditor, aDescription) {
6836 const isHTMLEditor =
6837 aEditor.nodeName.toLowerCase() !=
"input" && aEditor.nodeName.toLowerCase() !=
"textarea";
6838 const win = isHTMLEditor ? windowOfContenteditable : window;
6839 function getValue() {
6840 return isHTMLEditor ? aEditor.innerHTML : aEditor.value;
6842 function setSelection(aStart, aLength) {
6844 win.getSelection().setBaseAndExtent(aEditor.firstChild, aStart, aEditor.firstChild, aStart + aLength);
6846 aEditor.setSelectionRange(aStart, aStart + aLength);
6851 aEditor.innerHTML =
"abcxyz";
6853 aEditor.value =
"abcxyz";
6855 setSelection(
"abc".length,
0);
6857 synthesizeCompositionChange({
6860 clauses: [{ length:
1, attr: COMPOSITION_ATTR_RAW_CLAUSE}],
6861 caret: { start:
1, length:
0 },
6865 is(getValue(),
"abc1xyz",
6866 `${aDescription}: First composing character should be inserted middle of the text`);
6868 aEditor.addEventListener(
"compositionupdate", () =
> {
6869 setSelection(
"abc".length,
"1".length);
6872 synthesizeCompositionChange({
6875 clauses: [{ length:
2, attr: COMPOSITION_ATTR_RAW_CLAUSE}],
6876 caret: { start:
2, length:
0 },
6880 is(getValue(),
"abc12xyz",
6881 `${aDescription}: Only composition string should be updated even if selection range is updated by
"compositionupdate" event listener`);
6883 aEditor.addEventListener(
"compositionupdate", () =
> {
6884 setSelection(
"abc1".length,
"2d".length);
6887 synthesizeCompositionChange({
6890 clauses: [{ length:
3, attr: COMPOSITION_ATTR_RAW_CLAUSE}],
6891 caret: { start:
3, length:
0 },
6895 is(getValue(),
"abc123xyz",
6896 `${aDescription}: Only composition string should be updated even if selection range wider than composition string is updated by
"compositionupdate" event listener`);
6898 aEditor.addEventListener(
"compositionupdate", () =
> {
6899 setSelection(
"ab".length,
"c123d".length);
6902 synthesizeCompositionChange({
6905 clauses: [{ length:
3, attr: COMPOSITION_ATTR_RAW_CLAUSE}],
6906 caret: { start:
3, length:
0 },
6910 is(getValue(),
"abc456xyz",
6911 `${aDescription}: Only composition string should be updated even if selection range which covers all over the composition string is updated by
"compositionupdate" event listener`);
6913 aEditor.addEventListener(
"beforeinput", () =
> {
6914 setSelection(
"abc456d".length,
0);
6917 synthesizeComposition({ type:
"compositioncommitasis" });
6919 is(getValue(),
"abc456xyz",
6920 `${aDescription}: Only composition string should be updated when committing composition but selection is updated by
"beforeinput" event listener`);
6922 is(win.getSelection().focusNode, aEditor.firstChild,
6923 `${aDescription}: The focus node after composition should be the text node`);
6924 is(win.getSelection().focusOffset,
"abc456".length,
6925 `${aDescription}: The focus offset after composition should be end of the composition string`);
6926 is(win.getSelection().anchorNode, aEditor.firstChild,
6927 `${aDescription}: The anchor node after composition should be the text node`);
6928 is(win.getSelection().anchorOffset,
"abc456".length,
6929 `${aDescription}: The anchor offset after composition should be end of the composition string`);
6931 is(aEditor.selectionStart,
"abc456".length,
6932 `${aDescription}: The selectionStart after composition should be end of the composition string`);
6933 is(aEditor.selectionEnd,
"abc456".length,
6934 `${aDescription}: The selectionEnd after composition should be end of the composition string`);
6937 doTest(textarea,
"runCompositionWithSelectionChange(textarea)");
6938 doTest(input,
"runCompositionWithSelectionChange(input)");
6939 doTest(contenteditable,
"runCompositionWithSelectionChange(contenteditable)");
6942 function runForceCommitTest()
6945 function eventHandler(aEvent)
6947 events.push(aEvent);
6949 window.addEventListener(
"compositionstart", eventHandler, true);
6950 window.addEventListener(
"compositionupdate", eventHandler, true);
6951 window.addEventListener(
"compositionend", eventHandler, true);
6952 window.addEventListener(
"beforeinput", eventHandler, true);
6953 window.addEventListener(
"input", eventHandler, true);
6954 window.addEventListener(
"text", eventHandler, true);
6956 // Make the composition in textarea commit by click in the textarea
6958 textarea.value =
"";
6961 synthesizeCompositionChange(
6963 {
"string":
"\u306E",
6966 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
6969 "caret": {
"start":
1,
"length":
0 }
6972 is(events.length,
5,
6973 "runForceCommitTest: wrong event count #1");
6974 is(events[
0].type,
"compositionstart",
6975 "runForceCommitTest: the 1st event must be compositionstart #1");
6976 is(events[
1].type,
"compositionupdate",
6977 "runForceCommitTest: the 2nd event must be compositionupdate #1");
6978 is(events[
2].type,
"text",
6979 "runForceCommitTest: the 3rd event must be text #1");
6980 is(events[
3].type,
"beforeinput",
6981 "runForceCommitTest: the 4th event must be beforeinput #1");
6982 checkInputEvent(events[
3], true,
"insertCompositionText",
"\u306E", [],
6983 "runForceCommitTest #1");
6984 is(events[
4].type,
"input",
6985 "runForceCommitTest: the 5th event must be input #1");
6986 checkInputEvent(events[
4], true,
"insertCompositionText",
"\u306E", [],
6987 "runForceCommitTest #1");
6990 synthesizeMouseAtCenter(textarea, {});
6992 is(events.length,
4,
6993 "runForceCommitTest: wrong event count #2");
6994 is(events[
0].type,
"text",
6995 "runForceCommitTest: the 1st event must be text #2");
6996 is(events[
0].target, textarea,
6997 `runForceCommitTest: The
"${events[0].type}" event was fired on wrong event target #
2`);
6998 is(events[
1].type,
"beforeinput",
6999 "runForceCommitTest: the 2nd event must be beforeinput #2");
7000 is(events[
1].target, textarea,
7001 `runForceCommitTest: The
"${events[1].type}" event was fired on wrong event target #
2`);
7002 checkInputEvent(events[
1], true,
"insertCompositionText",
"\u306E", [],
7003 "runForceCommitTest #2");
7004 is(events[
2].type,
"compositionend",
7005 "runForceCommitTest: the 3rd event must be compositionend #2");
7006 is(events[
2].target, textarea,
7007 `runForceCommitTest: The
"${events[2].type}" event was fired on wrong event target #
2`);
7008 is(events[
2].data,
"\u306E",
7009 "runForceCommitTest: compositionend has wrong data #2");
7010 is(events[
3].type,
"input",
7011 "runForceCommitTest: the 4th event must be input #2");
7012 is(events[
3].target, textarea,
7013 `runForceCommitTest: The
"${events[3].type}" event was fired on wrong event target #
2`);
7014 checkInputEvent(events[
3], false,
"insertCompositionText",
"\u306E", [],
7015 "runForceCommitTest #2");
7016 ok(!getEditor(textarea).isComposing,
7017 "runForceCommitTest: the textarea still has composition #2");
7018 is(textarea.value,
"\u306E",
7019 "runForceCommitTest: the textarea doesn't have the committed text #2");
7021 // Make the composition in textarea commit by click in another editor (input)
7023 textarea.value =
"";
7026 synthesizeCompositionChange(
7028 {
"string":
"\u306E",
7031 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7034 "caret": {
"start":
1,
"length":
0 }
7038 synthesizeMouseAtCenter(input, {});
7040 is(events.length,
4,
7041 "runForceCommitTest: wrong event count #3");
7042 is(events[
0].type,
"text",
7043 "runForceCommitTest: the 1st event must be text #3");
7044 is(events[
0].target, textarea,
7045 `runForceCommitTest: The
"${events[0].type}" event was fired on wrong event target #
3`);
7046 is(events[
1].type,
"beforeinput",
7047 "runForceCommitTest: the 2nd event must be beforeinput #3");
7048 is(events[
1].target, textarea,
7049 `runForceCommitTest: The
"${events[1].type}" event was fired on wrong event target #
3`);
7050 checkInputEvent(events[
1], true,
"insertCompositionText",
"\u306E", [],
7051 "runForceCommitTest #3");
7052 is(events[
2].type,
"compositionend",
7053 "runForceCommitTest: the 3rd event must be compositionend #3");
7054 is(events[
2].target, textarea,
7055 `runForceCommitTest: The
"${events[2].type}" event was fired on wrong event target #
3`);
7056 is(events[
2].data,
"\u306E",
7057 "runForceCommitTest: compositionend has wrong data #3");
7058 is(events[
3].type,
"input",
7059 "runForceCommitTest: the 4th event must be input #3");
7060 is(events[
3].target, textarea,
7061 `runForceCommitTest: The
"${events[3].type}" event was fired on wrong event target #
3`);
7062 checkInputEvent(events[
3], false,
"insertCompositionText",
"\u306E", [],
7063 "runForceCommitTest #3");
7064 ok(!getEditor(textarea).isComposing,
7065 "runForceCommitTest: the textarea still has composition #3");
7066 ok(!getEditor(input).isComposing,
7067 "runForceCommitTest: the input has composition #3");
7068 is(textarea.value,
"\u306E",
7069 "runForceCommitTest: the textarea doesn't have the committed text #3");
7071 "runForceCommitTest: the input has the committed text? #3");
7073 // Make the composition in textarea commit by blur()
7075 textarea.value =
"";
7077 synthesizeCompositionChange(
7079 {
"string":
"\u306E",
7082 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7085 "caret": {
"start":
1,
"length":
0 }
7091 is(events.length,
4,
7092 "runForceCommitTest: wrong event count #4");
7093 is(events[
0].type,
"text",
7094 "runForceCommitTest: the 1st event must be text #4");
7095 is(events[
0].target, textarea,
7096 `runForceCommitTest: The
"${events[0].type}" event was fired on wrong event target #
4`);
7097 is(events[
1].type,
"beforeinput",
7098 "runForceCommitTest: the 2nd event must be beforeinput #4");
7099 is(events[
1].target, textarea,
7100 `runForceCommitTest: The
"${events[1].type}" event was fired on wrong event target #
4`);
7101 checkInputEvent(events[
1], true,
"insertCompositionText",
"\u306E", [],
7102 "runForceCommitTest #4");
7103 is(events[
2].type,
"compositionend",
7104 "runForceCommitTest: the 3rd event must be compositionend #4");
7105 is(events[
2].target, textarea,
7106 `runForceCommitTest: The
"${events[2].type}" event was fired on wrong event target #
4`);
7107 is(events[
2].data,
"\u306E",
7108 "runForceCommitTest: compositionend has wrong data #4");
7109 is(events[
3].type,
"input",
7110 "runForceCommitTest: the 4th event must be input #4");
7111 is(events[
3].target, textarea,
7112 `runForceCommitTest: The
"${events[3].type}" event was fired on wrong event target #
4`);
7113 checkInputEvent(events[
3], false,
"insertCompositionText",
"\u306E", [],
7114 "runForceCommitTest #4");
7115 ok(!getEditor(textarea).isComposing,
7116 "runForceCommitTest: the textarea still has composition #4");
7117 is(textarea.value,
"\u306E",
7118 "runForceCommitTest: the textarea doesn't have the committed text #4");
7120 // Make the composition in textarea commit by input.focus()
7122 textarea.value =
"";
7125 synthesizeCompositionChange(
7127 {
"string":
"\u306E",
7130 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7133 "caret": {
"start":
1,
"length":
0 }
7139 is(events.length,
4,
7140 "runForceCommitTest: wrong event count #5");
7141 is(events[
0].type,
"text",
7142 "runForceCommitTest: the 1st event must be text #5");
7143 is(events[
0].target, textarea,
7144 `runForceCommitTest: The
"${events[0].type}" event was fired on wrong event target #
5`);
7145 is(events[
1].type,
"beforeinput",
7146 "runForceCommitTest: the 2nd event must be beforeinput #5");
7147 is(events[
1].target, textarea,
7148 `runForceCommitTest: The
"${events[1].type}" event was fired on wrong event target #
5`);
7149 checkInputEvent(events[
1], true,
"insertCompositionText",
"\u306E", [],
7150 "runForceCommitTest #5");
7151 is(events[
2].type,
"compositionend",
7152 "runForceCommitTest: the 3rd event must be compositionend #5");
7153 is(events[
2].target, textarea,
7154 `runForceCommitTest: The
"${events[2].type}" event was fired on wrong event target #
5`);
7155 is(events[
2].data,
"\u306E",
7156 "runForceCommitTest: compositionend has wrong data #5");
7157 is(events[
3].type,
"input",
7158 "runForceCommitTest: the 4th event must be input #5");
7159 is(events[
3].target, textarea,
7160 `runForceCommitTest: The
"${events[3].type}" event was fired on wrong event target #
5`);
7161 checkInputEvent(events[
3], false,
"insertCompositionText",
"\u306E", [],
7162 "runForceCommitTest #5");
7163 ok(!getEditor(textarea).isComposing,
7164 "runForceCommitTest: the textarea still has composition #5");
7165 ok(!getEditor(input).isComposing,
7166 "runForceCommitTest: the input has composition #5");
7167 is(textarea.value,
"\u306E",
7168 "runForceCommitTest: the textarea doesn't have the committed text #5");
7170 "runForceCommitTest: the input has the committed text? #5");
7172 // Make the composition in textarea commit by click in another document's editor
7174 textarea.value =
"";
7175 textareaInFrame.value =
"";
7177 synthesizeCompositionChange(
7179 {
"string":
"\u306E",
7182 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7185 "caret": {
"start":
1,
"length":
0 }
7189 synthesizeMouseAtCenter(textareaInFrame, {}, iframe.contentWindow);
7191 is(events.length,
4,
7192 "runForceCommitTest: wrong event count #6");
7193 is(events[
0].type,
"text",
7194 "runForceCommitTest: the 1st event must be text #6");
7195 is(events[
0].target, textarea,
7196 `runForceCommitTest: The
"${events[0].type}" event was fired on wrong event target #
6`);
7197 is(events[
1].type,
"beforeinput",
7198 "runForceCommitTest: the 2nd event must be beforeinput #6");
7199 is(events[
1].target, textarea,
7200 `runForceCommitTest: The
"${events[1].type}" event was fired on wrong event target #
6`);
7201 checkInputEvent(events[
1], true,
"insertCompositionText",
"\u306E", [],
7202 "runForceCommitTest #6");
7203 is(events[
2].type,
"compositionend",
7204 "runForceCommitTest: the 3rd event must be compositionend #6");
7205 is(events[
2].target, textarea,
7206 `runForceCommitTest: The
"${events[2].type}" event was fired on wrong event target #
6`);
7207 is(events[
2].data,
"\u306E",
7208 "runForceCommitTest: compositionend has wrong data #6");
7209 is(events[
3].type,
"input",
7210 "runForceCommitTest: the 4th event must be input #6");
7211 is(events[
3].target, textarea,
7212 `runForceCommitTest: The
"${events[3].type}" event was fired on wrong event target #
6`);
7213 checkInputEvent(events[
3], false,
"insertCompositionText",
"\u306E", [],
7214 "runForceCommitTest #6");
7215 ok(!getEditor(textarea).isComposing,
7216 "runForceCommitTest: the textarea still has composition #6");
7217 ok(!getEditor(textareaInFrame).isComposing,
7218 "runForceCommitTest: the textarea in frame has composition #6");
7219 is(textarea.value,
"\u306E",
7220 "runForceCommitTest: the textarea doesn't have the committed text #6");
7221 is(textareaInFrame.value,
"",
7222 "runForceCommitTest: the textarea in frame has the committed text? #6");
7224 // Make the composition in textarea commit by another document's editor's focus()
7226 textarea.value =
"";
7227 textareaInFrame.value =
"";
7229 synthesizeCompositionChange(
7231 {
"string":
"\u306E",
7234 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7237 "caret": {
"start":
1,
"length":
0 }
7241 textareaInFrame.focus();
7243 is(events.length,
4,
7244 "runForceCommitTest: wrong event count #7");
7245 is(events[
0].type,
"text",
7246 "runForceCommitTest: the 1st event must be text #7");
7247 is(events[
0].target, textarea,
7248 `runForceCommitTest: The
"${events[0].type}" event was fired on wrong event target #
7`);
7249 is(events[
1].type,
"beforeinput",
7250 "runForceCommitTest: the 2nd event must be beforeinput #7");
7251 is(events[
1].target, textarea,
7252 `runForceCommitTest: The
"${events[1].type}" event was fired on wrong event target #
7`);
7253 checkInputEvent(events[
1], true,
"insertCompositionText",
"\u306E", [],
7254 "runForceCommitTest #7");
7255 is(events[
2].type,
"compositionend",
7256 "runForceCommitTest: the 3rd event must be compositionend #7");
7257 is(events[
2].target, textarea,
7258 `runForceCommitTest: The
"${events[2].type}" event was fired on wrong event target #
7`);
7259 is(events[
2].data,
"\u306E",
7260 "runForceCommitTest: compositionend has wrong data #7");
7261 is(events[
3].type,
"input",
7262 "runForceCommitTest: the 4th event must be input #7");
7263 is(events[
3].target, textarea,
7264 `runForceCommitTest: The
"${events[3].type}" event was fired on wrong event target #
7`);
7265 checkInputEvent(events[
3], false,
"insertCompositionText",
"\u306E", [],
7266 "runForceCommitTest #7");
7267 ok(!getEditor(textarea).isComposing,
7268 "runForceCommitTest: the textarea still has composition #7");
7269 ok(!getEditor(textareaInFrame).isComposing,
7270 "runForceCommitTest: the textarea in frame has composition #7");
7271 is(textarea.value,
"\u306E",
7272 "runForceCommitTest: the textarea doesn't have the committed text #7");
7273 is(textareaInFrame.value,
"",
7274 "runForceCommitTest: the textarea in frame has the committed text? #7");
7276 // Make the composition in a textarea commit by click in another editable document
7278 textarea.value =
"";
7279 iframe2.contentDocument.body.innerHTML =
"Text in the Body";
7280 let iframe2BodyInnerHTML = iframe2.contentDocument.body.innerHTML;
7282 synthesizeCompositionChange(
7284 {
"string":
"\u306E",
7287 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7290 "caret": {
"start":
1,
"length":
0 }
7294 synthesizeMouseAtCenter(iframe2.contentDocument.body, {}, iframe2.contentWindow);
7296 is(events.length,
4,
7297 "runForceCommitTest: wrong event count #8");
7298 is(events[
0].type,
"text",
7299 "runForceCommitTest: the 1st event must be text #8");
7300 is(events[
0].target, textarea,
7301 `runForceCommitTest: The ${events[
0].type} event was fired on wrong event target #
8`);
7302 is(events[
1].type,
"beforeinput",
7303 "runForceCommitTest: the 2nd event must be beforeinput #8");
7304 is(events[
1].target, textarea,
7305 `runForceCommitTest: The ${events[
1].type} event was fired on wrong event target #
8`);
7306 checkInputEvent(events[
1], true,
"insertCompositionText",
"\u306E", [],
7307 "runForceCommitTest #8");
7308 is(events[
2].type,
"compositionend",
7309 "runForceCommitTest: the 3rd event must be compositionend #8");
7310 is(events[
2].target, textarea,
7311 `runForceCommitTest: The ${events[
2].type} event was fired on wrong event target #
8`);
7312 is(events[
2].data,
"\u306E",
7313 "runForceCommitTest: compositionend has wrong data #8");
7314 is(events[
3].type,
"input",
7315 "runForceCommitTest: the 4th event must be input #8");
7316 is(events[
3].target, textarea,
7317 `runForceCommitTest: The ${events[
3].type} event was fired on wrong event target #
8`);
7318 checkInputEvent(events[
3], false,
"insertCompositionText",
"\u306E", [],
7319 "runForceCommitTest #8");
7320 ok(!getEditor(textarea).isComposing,
7321 "runForceCommitTest: the textarea still has composition #8");
7322 ok(!getHTMLEditorIMESupport(iframe2.contentWindow).isComposing,
7323 "runForceCommitTest: the editable document has composition #8");
7324 is(textarea.value,
"\u306E",
7325 "runForceCommitTest: the textarea doesn't have the committed text #8");
7326 is(iframe2.contentDocument.body.innerHTML, iframe2BodyInnerHTML,
7327 "runForceCommitTest: the editable document has the committed text? #8");
7329 // Make the composition in an editable document commit by click in it
7330 iframe2.contentWindow.focus();
7331 iframe2.contentDocument.body.innerHTML =
"Text in the Body";
7332 iframe2BodyInnerHTML = iframe2.contentDocument.body.innerHTML;
7334 synthesizeCompositionChange(
7336 {
"string":
"\u306E",
7339 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7342 "caret": {
"start":
1,
"length":
0 }
7343 }, iframe2.contentWindow);
7346 synthesizeMouseAtCenter(iframe2.contentDocument.body, {}, iframe2.contentWindow);
7348 is(events.length,
4,
7349 "runForceCommitTest: wrong event count #9");
7350 is(events[
0].type,
"text",
7351 "runForceCommitTest: the 1st event must be text #9");
7352 is(events[
0].target, iframe2.contentDocument.body,
7353 `runForceCommitTest: The
"${events[0].type}" event was fired on wrong event target #
9`);
7354 is(events[
1].type,
"beforeinput",
7355 "runForceCommitTest: the 2nd event must be beforeinput #9");
7356 is(events[
1].target, iframe2.contentDocument.body,
7357 `runForceCommitTest: The
"${events[1].type}" event was fired on wrong event target #
9`);
7358 checkInputEvent(events[
1], true,
"insertCompositionText",
"\u306E",
7359 [{startContainer: iframe2.contentDocument.body.firstChild,
7360 startOffset: iframe2.contentDocument.body.firstChild.wholeText.indexOf(
"\u306E"),
7361 endContainer: iframe2.contentDocument.body.firstChild,
7362 endOffset: iframe2.contentDocument.body.firstChild.wholeText.indexOf(
"\u306E") +
1}],
7363 "runForceCommitTest #9");
7364 is(events[
2].type,
"compositionend",
7365 "runForceCommitTest: the 3rd event must be compositionend #9");
7366 is(events[
2].target, iframe2.contentDocument.body,
7367 `runForceCommitTest: The
"${events[2].type}" event was fired on wrong event target #
9`);
7368 is(events[
2].data,
"\u306E",
7369 "runForceCommitTest: compositionend has wrong data #9");
7370 is(events[
3].type,
"input",
7371 "runForceCommitTest: the 4th event must be input #9");
7372 is(events[
3].target, iframe2.contentDocument.body,
7373 `runForceCommitTest: The
"${events[3].type}" event was fired on wrong event target #
9`);
7374 checkInputEvent(events[
3], false,
"insertCompositionText",
"\u306E", [],
7375 "runForceCommitTest #9");
7376 ok(!getHTMLEditorIMESupport(iframe2.contentWindow).isComposing,
7377 "runForceCommitTest: the editable document still has composition #9");
7378 ok(iframe2.contentDocument.body.innerHTML != iframe2BodyInnerHTML &&
7379 iframe2.contentDocument.body.innerHTML.includes(
"\u306E"),
7380 "runForceCommitTest: the editable document doesn't have the committed text #9");
7382 // Make the composition in an editable document commit by click in another document's editor
7383 textarea.value =
"";
7384 iframe2.contentWindow.focus();
7385 iframe2.contentDocument.body.innerHTML =
"Text in the Body";
7386 iframe2BodyInnerHTML = iframe2.contentDocument.body.innerHTML;
7388 synthesizeCompositionChange(
7390 {
"string":
"\u306E",
7393 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7396 "caret": {
"start":
1,
"length":
0 }
7397 }, iframe2.contentWindow);
7400 synthesizeMouseAtCenter(textarea, {});
7402 is(events.length,
4,
7403 "runForceCommitTest: wrong event count #10");
7404 is(events[
0].type,
"text",
7405 "runForceCommitTest: the 1st event must be text #10");
7406 is(events[
0].target, iframe2.contentDocument.body,
7407 `runForceCommitTest: The ${events[
0].type} event was fired on wrong event target #
10`);
7408 is(events[
1].type,
"beforeinput",
7409 "runForceCommitTest: the 2nd event must be beforeinput #10");
7410 is(events[
1].target, iframe2.contentDocument.body,
7411 `runForceCommitTest: The ${events[
1].type} event was fired on wrong event target #
10`);
7412 checkInputEvent(events[
1], true,
"insertCompositionText",
"\u306E",
7413 [{startContainer: iframe2.contentDocument.body.firstChild,
7414 startOffset: iframe2.contentDocument.body.firstChild.wholeText.indexOf(
"\u306E"),
7415 endContainer: iframe2.contentDocument.body.firstChild,
7416 endOffset: iframe2.contentDocument.body.firstChild.wholeText.indexOf(
"\u306E") +
1}],
7417 "runForceCommitTest #10");
7418 is(events[
2].type,
"compositionend",
7419 "runForceCommitTest: the 3rd event must be compositionend #10");
7420 is(events[
2].target, iframe2.contentDocument.body,
7421 `runForceCommitTest: The ${events[
2].type} event was fired on wrong event target #
10`);
7422 is(events[
2].data,
"\u306E",
7423 "runForceCommitTest: compositionend has wrong data #10");
7424 is(events[
3].type,
"input",
7425 "runForceCommitTest: the 4th event must be input #10");
7426 is(events[
3].target, iframe2.contentDocument.body,
7427 `runForceCommitTest: The ${events[
3].type} event was fired on wrong event target #
10`);
7428 checkInputEvent(events[
3], false,
"insertCompositionText",
"\u306E", [],
7429 "runForceCommitTest #10");
7430 ok(!getHTMLEditorIMESupport(iframe2.contentWindow).isComposing,
7431 "runForceCommitTest: the editable document still has composition #10");
7432 ok(!getEditor(textarea).isComposing,
7433 "runForceCommitTest: the textarea has composition #10");
7434 ok(iframe2.contentDocument.body.innerHTML != iframe2BodyInnerHTML &&
7435 iframe2.contentDocument.body.innerHTML.includes(
"\u306E"),
7436 "runForceCommitTest: the editable document doesn't have the committed text #10");
7437 is(textarea.value,
"",
7438 "runForceCommitTest: the textarea has the committed text? #10");
7440 // Make the composition in an editable document commit by click in the another editable document
7441 iframe2.contentWindow.focus();
7442 iframe2.contentDocument.body.innerHTML =
"Text in the Body";
7443 iframe2BodyInnerHTML = iframe2.contentDocument.body.innerHTML;
7444 iframe3.contentDocument.body.innerHTML =
"Text in the Body";
7445 let iframe3BodyInnerHTML = iframe2.contentDocument.body.innerHTML;
7447 synthesizeCompositionChange(
7449 {
"string":
"\u306E",
7452 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7455 "caret": {
"start":
1,
"length":
0 }
7456 }, iframe2.contentWindow);
7459 synthesizeMouseAtCenter(iframe3.contentDocument.body, {}, iframe3.contentWindow);
7461 is(events.length,
4,
7462 "runForceCommitTest: wrong event count #11");
7463 is(events[
0].type,
"text",
7464 "runForceCommitTest: the 1st event must be text #11");
7465 is(events[
0].target, iframe2.contentDocument.body,
7466 `runForceCommitTest: The
"${events[0].type}" event was fired on wrong event target #
11`);
7467 is(events[
1].type,
"beforeinput",
7468 "runForceCommitTest: the 2nd event must be beforeinput #11");
7469 is(events[
1].target, iframe2.contentDocument.body,
7470 `runForceCommitTest: The
"${events[1].type}" event was fired on wrong event target #
11`);
7471 checkInputEvent(events[
1], true,
"insertCompositionText",
"\u306E",
7472 [{startContainer: iframe2.contentDocument.body.firstChild,
7473 startOffset: iframe2.contentDocument.body.firstChild.wholeText.indexOf(
"\u306E"),
7474 endContainer: iframe2.contentDocument.body.firstChild,
7475 endOffset: iframe2.contentDocument.body.firstChild.wholeText.indexOf(
"\u306E") +
1}],
7476 "runForceCommitTest #11");
7477 is(events[
2].type,
"compositionend",
7478 "runForceCommitTest: the 3rd event must be compositionend #11");
7479 is(events[
2].target, iframe2.contentDocument.body,
7480 `runForceCommitTest: The
"${events[2].type}" event was fired on wrong event target #
11`);
7481 is(events[
2].data,
"\u306E",
7482 "runForceCommitTest: compositionend has wrong data #11");
7483 is(events[
3].type,
"input",
7484 "runForceCommitTest: the 4th event must be input #11");
7485 is(events[
3].target, iframe2.contentDocument.body,
7486 `runForceCommitTest: The
"${events[3].type}" event was fired on wrong event target #
11`);
7487 checkInputEvent(events[
3], false,
"insertCompositionText",
"\u306E", [],
7488 "runForceCommitTest #11");
7489 ok(!getHTMLEditorIMESupport(iframe2.contentWindow).isComposing,
7490 "runForceCommitTest: the editable document still has composition #11");
7491 ok(!getHTMLEditorIMESupport(iframe3.contentWindow).isComposing,
7492 "runForceCommitTest: the other editable document has composition #11");
7493 ok(iframe2.contentDocument.body.innerHTML != iframe2BodyInnerHTML &&
7494 iframe2.contentDocument.body.innerHTML.includes(
"\u306E"),
7495 "runForceCommitTest: the editable document doesn't have the committed text #11");
7496 is(iframe3.contentDocument.body.innerHTML, iframe3BodyInnerHTML,
7497 "runForceCommitTest: the other editable document has the committed text? #11");
7502 synthesizeCompositionChange(
7504 {
"string":
"\u306E",
7507 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7510 "caret": {
"start":
1,
"length":
0 }
7514 input.value =
"set value";
7516 is(events.length,
4,
7517 "runForceCommitTest: wrong event count #12");
7518 is(events[
0].type,
"text",
7519 "runForceCommitTest: the 1st event must be text #12");
7520 is(events[
0].target, input,
7521 `runForceCommitTest: The
"${events[0].type}" event was fired on wrong event target #
12`);
7522 is(events[
1].type,
"beforeinput",
7523 "runForceCommitTest: the 2nd event must be beforeinput #12");
7524 is(events[
1].target, input,
7525 `runForceCommitTest: The
"${events[1].type}" event was fired on wrong event target #
12`);
7526 checkInputEvent(events[
1], true,
"insertCompositionText",
"\u306E", [],
7527 "runForceCommitTest #12");
7528 is(events[
2].type,
"compositionend",
7529 "runForceCommitTest: the 3rd event must be compositionend #12");
7530 is(events[
2].target, input,
7531 `runForceCommitTest: The
"${events[2].type}" event was fired on wrong event target #
12`);
7532 is(events[
2].data,
"\u306E",
7533 "runForceCommitTest: compositionend has wrong data #12");
7534 is(events[
3].type,
"input",
7535 "runForceCommitTest: the 4th event must be input #12");
7536 is(events[
3].target, input,
7537 `runForceCommitTest: The
"${events[3].type}" event was fired on wrong event target #
12`);
7538 checkInputEvent(events[
3], false,
"insertCompositionText",
"\u306E", [],
7539 "runForceCommitTest #12");
7540 ok(!getEditor(input).isComposing,
7541 "runForceCommitTest: the input still has composition #12");
7542 is(input.value,
"set value",
7543 "runForceCommitTest: the input doesn't have the set text #12");
7546 textarea.value =
"";
7548 synthesizeCompositionChange(
7550 {
"string":
"\u306E",
7553 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7556 "caret": {
"start":
1,
"length":
0 }
7560 textarea.value =
"set value";
7562 is(events.length,
4,
7563 "runForceCommitTest: wrong event count #13");
7564 is(events[
0].type,
"text",
7565 "runForceCommitTest: the 1st event must be text #13");
7566 is(events[
0].target, textarea,
7567 `runForceCommitTest: The
"${events[0].type}" event was fired on wrong event target #
13`);
7568 is(events[
1].type,
"beforeinput",
7569 "runForceCommitTest: the 2nd event must be beforeinput #13");
7570 is(events[
1].target, textarea,
7571 `runForceCommitTest: The
"${events[1].type}" event was fired on wrong event target #
13`);
7572 checkInputEvent(events[
1], true,
"insertCompositionText",
"\u306E", [],
7573 "runForceCommitTest #13");
7574 is(events[
2].type,
"compositionend",
7575 "runForceCommitTest: the 3rd event must be compositionend #13");
7576 is(events[
2].target, textarea,
7577 `runForceCommitTest: The
"${events[2].type}" event was fired on wrong event target #
13`);
7578 is(events[
2].data,
"\u306E",
7579 "runForceCommitTest: compositionend has wrong data #13");
7580 is(events[
3].type,
"input",
7581 "runForceCommitTest: the 4th event must be input #13");
7582 is(events[
3].target, textarea,
7583 `runForceCommitTest: The
"${events[3].type}" event was fired on wrong event target #
13`);
7584 checkInputEvent(events[
3], false,
"insertCompositionText",
"\u306E", [],
7585 "runForceCommitTest #13");
7586 ok(!getEditor(textarea).isComposing,
7587 "runForceCommitTest: the textarea still has composition #13");
7588 is(textarea.value,
"set value",
7589 "runForceCommitTest: the textarea doesn't have the set text #13");
7594 synthesizeCompositionChange(
7596 {
"string":
"\u306E",
7599 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7602 "caret": {
"start":
1,
"length":
0 }
7606 input.value +=
" appended value";
7608 is(events.length,
4,
7609 "runForceCommitTest: wrong event count #14");
7610 is(events[
0].type,
"text",
7611 "runForceCommitTest: the 1st event must be text #14");
7612 is(events[
0].target, input,
7613 `runForceCommitTest: The
"${events[0].type}" event was fired on wrong event target #
14`);
7614 is(events[
1].type,
"beforeinput",
7615 "runForceCommitTest: the 2nd event must be beforeinput #14");
7616 is(events[
1].target, input,
7617 `runForceCommitTest: The
"${events[1].type}" event was fired on wrong event target #
14`);
7618 checkInputEvent(events[
1], true,
"insertCompositionText",
"\u306E", [],
7619 "runForceCommitTest #14");
7620 is(events[
2].type,
"compositionend",
7621 "runForceCommitTest: the 3rd event must be compositionend #14");
7622 is(events[
2].target, input,
7623 `runForceCommitTest: The
"${events[2].type}" event was fired on wrong event target #
14`);
7624 is(events[
2].data,
"\u306E",
7625 "runForceCommitTest: compositionend has wrong data #14");
7626 is(events[
3].type,
"input",
7627 "runForceCommitTest: the 4th event must be input #14");
7628 is(events[
3].target, input,
7629 `runForceCommitTest: The
"${events[3].type}" event was fired on wrong event target #
14`);
7630 checkInputEvent(events[
3], false,
"insertCompositionText",
"\u306E", [],
7631 "runForceCommitTest #14");
7632 ok(!getEditor(input).isComposing,
7633 "runForceCommitTest: the input still has composition #14");
7634 is(input.value,
"\u306E appended value",
7635 "runForceCommitTest: the input should have both composed text and appended text #14");
7638 input.value =
"abcd";
7640 synthesizeCompositionChange(
7642 {
"string":
"\u306E",
7645 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7648 "caret": {
"start":
1,
"length":
0 }
7652 input.value =
"abcd\u306E";
7654 is(events.length,
0,
7655 "runForceCommitTest: setting same value to input with composition shouldn't cause any events #15");
7656 is(input.value,
"abcd\u306E",
7657 "runForceCommitTest: the input has unexpected value #15");
7659 input.blur(); // commit composition
7662 textarea.value =
"abcd";
7664 synthesizeCompositionChange(
7666 {
"string":
"\u306E",
7669 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7672 "caret": {
"start":
1,
"length":
0 }
7676 textarea.value =
"abcd\u306E";
7678 is(events.length,
0,
7679 "runForceCommitTest: setting same value to textarea with composition shouldn't cause any events #16");
7680 is(textarea.value,
"abcd\u306E",
7681 "runForceCommitTest: the input has unexpected value #16");
7683 textarea.blur(); // commit composition
7685 window.removeEventListener(
"compositionstart", eventHandler, true);
7686 window.removeEventListener(
"compositionupdate", eventHandler, true);
7687 window.removeEventListener(
"compositionend", eventHandler, true);
7688 window.removeEventListener(
"beforeinput", eventHandler, true);
7689 window.removeEventListener(
"input", eventHandler, true);
7690 window.removeEventListener(
"text", eventHandler, true);
7693 function runNestedSettingValue()
7695 let isTesting = false;
7697 function eventHandler(aEvent)
7699 events.push(aEvent);
7701 aEvent.target.value += aEvent.type +
", ";
7704 window.addEventListener(
"compositionstart", eventHandler, true);
7705 window.addEventListener(
"compositionupdate", eventHandler, true);
7706 window.addEventListener(
"compositionend", eventHandler, true);
7707 window.addEventListener(
"beforeinput", eventHandler, true);
7708 window.addEventListener(
"input", eventHandler, true);
7709 window.addEventListener(
"text", eventHandler, true);
7712 textarea.value =
"";
7714 synthesizeCompositionChange(
7716 {
"string":
"\u306E",
7719 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7722 "caret": {
"start":
1,
"length":
0 }
7727 textarea.value =
"first setting value, ";
7730 is(events.length,
4,
7731 "runNestedSettingValue: wrong event count #1");
7732 is(events[
0].type,
"text",
7733 "runNestedSettingValue: the 1st event must be text #1");
7734 is(events[
0].target, textarea,
7735 `runNestedSettingValue: The
"${events[0].type}" event was fired on wrong event target #
1`);
7736 is(events[
1].type,
"beforeinput",
7737 "runNestedSettingValue: the 2nd event must be beforeinput #1");
7738 is(events[
1].target, textarea,
7739 `runNestedSettingValue: The
"${events[1].type}" event was fired on wrong event target #
1`);
7740 checkInputEvent(events[
1], true,
"insertCompositionText",
"\u306E", [],
7741 "runNestedSettingValue #1");
7742 is(events[
2].type,
"compositionend",
7743 "runNestedSettingValue: the 3rd event must be compositionend #1");
7744 is(events[
2].target, textarea,
7745 `runNestedSettingValue: The
"${events[2].type}" event was fired on wrong event target #
1`);
7746 is(events[
2].data,
"\u306E",
7747 "runNestedSettingValue: compositionend has wrong data #1");
7748 is(events[
3].type,
"input",
7749 "runNestedSettingValue: the 4th event must be input #1");
7750 is(events[
3].target, textarea,
7751 `runNestedSettingValue: The
"${events[3].type}" event was fired on wrong event target #
1`);
7752 checkInputEvent(events[
3], false,
"insertCompositionText",
"\u306E", [],
7753 "runNestedSettingValue #1");
7754 ok(!getEditor(textarea).isComposing,
7755 "runNestedSettingValue: the textarea still has composition #1");
7756 is(textarea.value,
"first setting value, text, beforeinput, compositionend, input, ",
7757 "runNestedSettingValue: the textarea should have all string set to value attribute");
7762 synthesizeCompositionChange(
7764 {
"string":
"\u306E",
7767 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7770 "caret": {
"start":
1,
"length":
0 }
7775 input.value =
"first setting value, ";
7778 is(events.length,
4,
7779 "runNestedSettingValue: wrong event count #2");
7780 is(events[
0].type,
"text",
7781 "runNestedSettingValue: the 1st event must be text #2");
7782 is(events[
0].target, input,
7783 `runNestedSettingValue: The
"${events[0].type}" event was fired on wrong event target #
2`);
7784 is(events[
1].type,
"beforeinput",
7785 "runNestedSettingValue: the 2nd event must be beforeinput #2");
7786 is(events[
1].target, input,
7787 `runNestedSettingValue: The
"${events[1].type}" event was fired on wrong event target #
2`);
7788 checkInputEvent(events[
1], true,
"insertCompositionText",
"\u306E", [],
7789 "runNestedSettingValue #2");
7790 is(events[
2].type,
"compositionend",
7791 "runNestedSettingValue: the 3rd event must be compositionend #2");
7792 is(events[
2].target, input,
7793 `runNestedSettingValue: The
"${events[2].type}" event was fired on wrong event target #
2`);
7794 is(events[
2].data,
"\u306E",
7795 "runNestedSettingValue: compositionend has wrong data #2");
7796 is(events[
3].type,
"input",
7797 "runNestedSettingValue: the 4th event must be input #2");
7798 is(events[
3].target, input,
7799 `runNestedSettingValue: The
"${events[3].type}" event was fired on wrong event target #
2`);
7800 checkInputEvent(events[
3], false,
"insertCompositionText",
"\u306E", [],
7801 "runNestedSettingValue #2");
7802 ok(!getEditor(input).isComposing,
7803 "runNestedSettingValue: the input still has composition #2");
7804 is(textarea.value,
"first setting value, text, beforeinput, compositionend, input, ",
7805 "runNestedSettingValue: the input should have all string set to value attribute #2");
7808 textarea.value =
"";
7810 synthesizeCompositionChange(
7812 {
"string":
"\u306E",
7815 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7818 "caret": {
"start":
1,
"length":
0 }
7823 textarea.setRangeText(
"first setting value, ");
7826 is(events.length,
4,
7827 "runNestedSettingValue: wrong event count #3");
7828 is(events[
0].type,
"text",
7829 "runNestedSettingValue: the 1st event must be text #3");
7830 is(events[
0].target, textarea,
7831 `runNestedSettingValue: The ${events[
0].type} event was fired on wrong event target #
3`);
7832 is(events[
1].type,
"beforeinput",
7833 "runNestedSettingValue: the 2nd event must be beforeinput #3");
7834 is(events[
1].target, textarea,
7835 `runNestedSettingValue: The ${events[
1].type} event was fired on wrong event target #
3`);
7836 checkInputEvent(events[
1], true,
"insertCompositionText",
"\u306E", [],
7837 "runNestedSettingValue #3");
7838 is(events[
2].type,
"compositionend",
7839 "runNestedSettingValue: the 3rd event must be compositionend #3");
7840 is(events[
2].target, textarea,
7841 `runNestedSettingValue: The ${events[
2].type} event was fired on wrong event target #
3`);
7842 is(events[
2].data,
"\u306E",
7843 "runNestedSettingValue: compositionend has wrong data #3");
7844 is(events[
3].type,
"input",
7845 "runNestedSettingValue: the 4th event must be input #3");
7846 is(events[
3].target, textarea,
7847 `runNestedSettingValue: The ${events[
3].type} event was fired on wrong event target #
3`);
7848 checkInputEvent(events[
3], false,
"insertCompositionText",
"\u306E", [],
7849 "runNestedSettingValue #3");
7850 ok(!getEditor(textarea).isComposing,
7851 "runNestedSettingValue: the textarea still has composition #3");
7852 is(textarea.value,
"\u306Efirst setting value, text, beforeinput, compositionend, input, ",
7853 "runNestedSettingValue: the textarea should have appended by setRangeText() and all string set to value attribute #3");
7858 synthesizeCompositionChange(
7860 {
"string":
"\u306E",
7863 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7866 "caret": {
"start":
1,
"length":
0 }
7871 input.setRangeText(
"first setting value, ");
7874 is(events.length,
4,
7875 "runNestedSettingValue: wrong event count #4");
7876 is(events[
0].type,
"text",
7877 "runNestedSettingValue: the 1st event must be text #4");
7878 is(events[
0].target, input,
7879 `runNestedSettingValue: The
"${events[0].type}" event was fired on wrong event target #
4`);
7880 is(events[
1].type,
"beforeinput",
7881 "runNestedSettingValue: the 2nd event must be beforeinput #4");
7882 is(events[
1].target, input,
7883 `runNestedSettingValue: The
"${events[1].type}" event was fired on wrong event target #
4`);
7884 checkInputEvent(events[
1], true,
"insertCompositionText",
"\u306E", [],
7885 "runNestedSettingValue #4");
7886 is(events[
2].type,
"compositionend",
7887 "runNestedSettingValue: the 3rd event must be compositionend #4");
7888 is(events[
2].target, input,
7889 `runNestedSettingValue: The
"${events[2].type}" event was fired on wrong event target #
4`);
7890 is(events[
2].data,
"\u306E",
7891 "runNestedSettingValue: compositionend has wrong data #4");
7892 is(events[
3].type,
"input",
7893 "runNestedSettingValue: the 4th event must be input #4");
7894 is(events[
3].target, input,
7895 `runNestedSettingValue: The
"${events[3].type}" event was fired on wrong event target #
4`);
7896 checkInputEvent(events[
3], false,
"insertCompositionText",
"\u306E", [],
7897 "runNestedSettingValue #4");
7898 ok(!getEditor(input).isComposing,
7899 "runNestedSettingValue: the input still has composition #4");
7900 is(textarea.value,
"\u306Efirst setting value, text, beforeinput, compositionend, input, ",
7901 "runNestedSettingValue: the input should have all string appended by setRangeText() and set to value attribute #4");
7903 window.removeEventListener(
"compositionstart", eventHandler, true);
7904 window.removeEventListener(
"compositionupdate", eventHandler, true);
7905 window.removeEventListener(
"compositionend", eventHandler, true);
7906 window.removeEventListener(
"beforeinput", eventHandler, true);
7907 window.removeEventListener(
"input", eventHandler, true);
7908 window.removeEventListener(
"text", eventHandler, true);
7912 async function runAsyncForceCommitTest()
7915 function eventHandler(aEvent)
7917 events.push(aEvent);
7920 // If IME commits composition for a request, TextComposition commits
7921 // composition automatically because most web apps must expect that active
7922 // composition should be committed synchronously. Therefore, in this case,
7923 // a click during composition should cause committing composition
7924 // synchronously and delayed commit shouldn't cause composition events.
7925 let commitRequested = false;
7926 let onFinishTest = null;
7927 function callback(aTIP, aNotification)
7929 ok(true, aNotification.type);
7930 if (aNotification.type !=
"request-to-commit") {
7933 commitRequested = true;
7935 let resolve = onFinishTest;
7936 onFinishTest = null;
7938 SimpleTest.executeSoon(() =
> {
7940 aTIP.commitComposition();
7942 is(events.length,
0,
7943 "runAsyncForceCommitTest: composition events shouldn't been fired by asynchronous call of nsITextInputProcessor.commitComposition()");
7945 SimpleTest.executeSoon(resolve);
7951 function promiseCleanUp() {
7952 return new Promise(resolve =
> { onFinishTest = resolve; });
7955 window.addEventListener(
"compositionstart", eventHandler, true);
7956 window.addEventListener(
"compositionupdate", eventHandler, true);
7957 window.addEventListener(
"compositionend", eventHandler, true);
7958 window.addEventListener(
"beforeinput", eventHandler, true);
7959 window.addEventListener(
"input", eventHandler, true);
7960 window.addEventListener(
"text", eventHandler, true);
7962 // Make the composition in textarea commit by click in the textarea
7964 textarea.value =
"";
7967 synthesizeCompositionChange(
7969 {
"string":
"\u306E",
7972 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
7975 "caret": {
"start":
1,
"length":
0 }
7976 }, window, callback);
7978 is(events.length,
5,
7979 "runAsyncForceCommitTest: wrong event count #1");
7980 is(events[
0].type,
"compositionstart",
7981 "runAsyncForceCommitTest: the 1st event must be compositionstart #1");
7982 is(events[
1].type,
"compositionupdate",
7983 "runAsyncForceCommitTest: the 2nd event must be compositionupdate #1");
7984 is(events[
2].type,
"text",
7985 "runAsyncForceCommitTest: the 3rd event must be text #1");
7986 is(events[
3].type,
"beforeinput",
7987 "runAsyncForceCommitTest: the 4th event must be beforeinput #1");
7988 checkInputEvent(events[
3], true,
"insertCompositionText",
"\u306E", [],
7989 "runAsyncForceCommitTest #1");
7990 is(events[
4].type,
"input",
7991 "runAsyncForceCommitTest: the 5th event must be input #1");
7992 checkInputEvent(events[
4], true,
"insertCompositionText",
"\u306E", [],
7993 "runAsyncForceCommitTest #1");
7996 let waitCleanState = promiseCleanUp();
7998 synthesizeMouseAtCenter(textarea, {});
8001 "runAsyncForceCommitTest: \"request-to-commit\
" should've been notified");
8002 is(events.length,
4,
8003 "runAsyncForceCommitTest: wrong event count #2");
8004 is(events[
0].type,
"text",
8005 "runAsyncForceCommitTest: the 1st event must be text #2");
8006 is(events[
0].target, textarea,
8007 `runAsyncForceCommitTest: The
"${events[0].type}" event was fired on wrong event target #
2`);
8008 is(events[
1].type,
"beforeinput",
8009 "runAsyncForceCommitTest: the 2nd event must be beforeinput #2");
8010 is(events[
1].target, textarea,
8011 `runAsyncForceCommitTest: The
"${events[1].type}" event was fired on wrong event target #
2`);
8012 checkInputEvent(events[
1], true,
"insertCompositionText",
"\u306E", [],
8013 "runAsyncForceCommitTest #2");
8014 is(events[
2].type,
"compositionend",
8015 "runAsyncForceCommitTest: the 3rd event must be compositionend #2");
8016 is(events[
2].target, textarea,
8017 `runAsyncForceCommitTest: The
"${events[2].type}" event was fired on wrong event target #
2`);
8018 is(events[
2].data,
"\u306E",
8019 "runAsyncForceCommitTest: compositionend has wrong data #2");
8020 is(events[
3].type,
"input",
8021 "runAsyncForceCommitTest: the 4th event must be input #2");
8022 is(events[
3].target, textarea,
8023 `runAsyncForceCommitTest: The
"${events[3].type}" event was fired on wrong event target #
2`);
8024 checkInputEvent(events[
3], false,
"insertCompositionText",
"\u306E", [],
8025 "runAsyncForceCommitTest #2");
8026 ok(!getEditor(textarea).isComposing,
8027 "runAsyncForceCommitTest: the textarea still has composition #2");
8028 is(textarea.value,
"\u306E",
8029 "runAsyncForceCommitTest: the textarea doesn't have the committed text #2");
8031 await waitCleanState;
8033 window.removeEventListener(
"compositionstart", eventHandler, true);
8034 window.removeEventListener(
"compositionupdate", eventHandler, true);
8035 window.removeEventListener(
"compositionend", eventHandler, true);
8036 window.removeEventListener(
"beforeinput", eventHandler, true);
8037 window.removeEventListener(
"input", eventHandler, true);
8038 window.removeEventListener(
"text", eventHandler, true);
8041 function runBug811755Test()
8043 iframe2.contentDocument.body.innerHTML =
"<div>content<br/></div>";
8044 iframe2.contentWindow.focus();
8046 let textContent = synthesizeQueryTextContent(
0,
10);
8047 if (!checkQueryContentResult(textContent,
"runBug811755Test: synthesizeQueryTextContent #1")) {
8050 // Query everything but specify exact end offset, which should be immediately after the
<br> node
8051 // If PreContentIterator is used, the next node after
<br> is the node after
</div>.
8052 // If ContentIterator is used, the next node is the
<div> node itself. In this case, the end
8053 // node ends up being before the start node, and an empty string is returned.
8054 let queryContent = synthesizeQueryTextContent(
0, textContent.text.length);
8055 if (!checkQueryContentResult(queryContent,
"runBug811755Test: synthesizeQueryTextContent #2")) {
8058 is(queryContent.text, textContent.text,
"runBug811755Test: two queried texts don't match");
8061 function runIsComposingTest()
8063 let expectedIsComposing = false;
8064 let description =
"";
8066 function eventHandler(aEvent)
8068 if (aEvent.type ==
"keydown" || aEvent.type ==
"keyup") {
8069 is(aEvent.isComposing, expectedIsComposing,
8070 "runIsComposingTest: " + description +
" (type=" + aEvent.type +
", key=" + aEvent.key +
")");
8071 } else if (aEvent.type ==
"keypress") {
8072 // keypress event shouldn't be fired during composition so that isComposing should be always false.
8073 is(aEvent.isComposing, false,
8074 "runIsComposingTest: " + description +
" (type=" + aEvent.type +
")");
8076 checkInputEvent(aEvent, expectedIsComposing,
"insertCompositionText",
"\u3042", [],
8077 `runIsComposingTest: ${description}`);
8081 function onComposition(aEvent)
8083 if (aEvent.type ==
"compositionstart") {
8084 expectedIsComposing = true;
8085 } else if (aEvent.type ==
"compositionend") {
8086 expectedIsComposing = false;
8090 textarea.addEventListener(
"keydown", eventHandler, true);
8091 textarea.addEventListener(
"keypress", eventHandler, true);
8092 textarea.addEventListener(
"keyup", eventHandler, true);
8093 textarea.addEventListener(
"beforeinput", eventHandler, true);
8094 textarea.addEventListener(
"input", eventHandler, true);
8095 textarea.addEventListener(
"compositionstart", onComposition, true);
8096 textarea.addEventListener(
"compositionend", onComposition, true);
8099 textarea.value =
"";
8101 // XXX These cases shouldn't occur in actual native key events because we
8102 // don't dispatch key events while composition (bug
354358).
8103 description =
"events before dispatching compositionstart";
8104 synthesizeKey(
"KEY_ArrowLeft");
8106 description =
"events after dispatching compositionchange";
8107 synthesizeCompositionChange(
8109 {
"string":
"\u3042",
8112 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
8115 "caret": {
"start":
1,
"length":
0 },
8116 "key": { key:
"a", code:
"KeyA", keyCode: KeyboardEvent.DOM_VK_A },
8119 // Although, firing keypress event during composition is a bug.
8120 synthesizeKey(
"KEY_Insert");
8122 description =
"events for committing composition string";
8124 synthesizeComposition({ type:
"compositioncommitasis",
8125 key: { key:
"KEY_Enter", code:
"Enter", type:
"keydown" } });
8127 // input event will be fired by synthesizing compositionend event.
8128 // Then, its isComposing should be false.
8129 description =
"events after dispatching compositioncommitasis";
8130 synthesizeKey(
"KEY_Enter", {type:
"keyup"});
8132 textarea.removeEventListener(
"keydown", eventHandler, true);
8133 textarea.removeEventListener(
"keypress", eventHandler, true);
8134 textarea.removeEventListener(
"keyup", eventHandler, true);
8135 textarea.removeEventListener(
"beforeinput", eventHandler, true);
8136 textarea.removeEventListener(
"input", eventHandler, true);
8137 textarea.removeEventListener(
"compositionstart", onComposition, true);
8138 textarea.removeEventListener(
"compositionend", onComposition, true);
8140 textarea.value =
"";
8143 function runRedundantChangeTest()
8148 function clearResult()
8153 function handler(aEvent)
8155 result.push(aEvent);
8158 textarea.addEventListener(
"compositionupdate", handler, true);
8159 textarea.addEventListener(
"compositionend", handler, true);
8160 textarea.addEventListener(
"beforeinput", handler, true);
8161 textarea.addEventListener(
"input", handler, true);
8162 textarea.addEventListener(
"text", handler, true);
8164 textarea.value =
"";
8166 // synthesize change event
8168 synthesizeCompositionChange(
8170 {
"string":
"\u3042",
8173 {
"length":
1,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
8176 "caret": {
"start":
1,
"length":
0 }
8179 is(result.length,
4,
8180 "runRedundantChangeTest: 4 events should be fired after synthesizing composition change #1");
8181 is(result[
0].type,
"compositionupdate",
8182 "runRedundantChangeTest: compositionupdate should be fired after synthesizing composition change #1");
8183 is(result[
1].type,
"text",
8184 "runRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string #1");
8185 is(result[
2].type,
"beforeinput",
8186 "runRedundantChangeTest: beforeinput should be fired after synthesizing composition change #1");
8187 checkInputEvent(result[
2], true,
"insertCompositionText",
"\u3042", [],
8188 "runRedundantChangeTest: after synthesizing composition change #1");
8189 is(result[
3].type,
"input",
8190 "runRedundantChangeTest: input should be fired after synthesizing composition change #1");
8191 checkInputEvent(result[
3], true,
"insertCompositionText",
"\u3042", [],
8192 "runRedundantChangeTest: after synthesizing composition change #1");
8193 is(textarea.value,
"\u3042",
"runRedundantChangeTest: textarea has uncommitted string #1");
8195 // synthesize another change event
8197 synthesizeCompositionChange(
8199 {
"string":
"\u3042\u3044",
8202 {
"length":
2,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
8205 "caret": {
"start":
2,
"length":
0 }
8208 is(result.length,
4,
8209 "runRedundantChangeTest: 4 events should be fired after synthesizing composition change #2");
8210 is(result[
0].type,
"compositionupdate",
8211 "runRedundantChangeTest: compositionupdate should be fired after synthesizing composition change #2");
8212 is(result[
1].type,
"text",
8213 "runRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string #2");
8214 is(result[
2].type,
"beforeinput",
8215 "runRedundantChangeTest: beforeinput should be fired after synthesizing composition change #2");
8216 checkInputEvent(result[
2], true,
"insertCompositionText",
"\u3042\u3044", [],
8217 "runRedundantChangeTest: after synthesizing composition change #2");
8218 is(result[
3].type,
"input",
8219 "runRedundantChangeTest: input should be fired after synthesizing composition change #2");
8220 checkInputEvent(result[
3], true,
"insertCompositionText",
"\u3042\u3044", [],
8221 "runRedundantChangeTest: after synthesizing composition change #2");
8222 is(textarea.value,
"\u3042\u3044",
"runRedundantChangeTest: textarea has uncommitted string #2");
8224 // synthesize same change event again
8226 synthesizeCompositionChange(
8228 {
"string":
"\u3042\u3044",
8231 {
"length":
2,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
8234 "caret": {
"start":
2,
"length":
0 }
8237 is(result.length,
0,
"runRedundantChangeTest: no events should be fired after synthesizing composition change again");
8238 is(textarea.value,
"\u3042\u3044",
"runRedundantChangeTest: textarea has uncommitted string #3");
8240 // synthesize commit-as-is
8242 synthesizeComposition({ type:
"compositioncommitasis" });
8243 is(result.length,
4,
8244 "runRedundantChangeTest: 4 events should be fired after synthesizing composition commit-as-is");
8245 is(result[
0].type,
"text",
8246 "runRedundantChangeTest: text should be fired after synthesizing composition commit-as-is for removing the ranges");
8247 is(result[
1].type,
"beforeinput",
8248 "runRedundantChangeTest: beforeinput should be fired after synthesizing composition commit-as-is for removing the ranges");
8249 checkInputEvent(result[
1], true,
"insertCompositionText",
"\u3042\u3044", [],
8250 "runRedundantChangeTest: at synthesizing commit-as-is");
8251 is(result[
2].type,
"compositionend",
8252 "runRedundantChangeTest: compositionend should be fired after synthesizing composition commit-as-is");
8253 is(result[
3].type,
"input",
8254 "runRedundantChangeTest: input should be fired before compositionend at synthesizing commit-as-is");
8255 checkInputEvent(result[
3], false,
"insertCompositionText",
"\u3042\u3044", [],
8256 "runRedundantChangeTest: at synthesizing commit-as-is");
8257 is(textarea.value,
"\u3042\u3044",
"runRedundantChangeTest: textarea has the commit string");
8259 textarea.removeEventListener(
"compositionupdate", handler, true);
8260 textarea.removeEventListener(
"compositionend", handler, true);
8261 textarea.removeEventListener(
"beforeinput", handler, true);
8262 textarea.removeEventListener(
"input", handler, true);
8263 textarea.removeEventListener(
"text", handler, true);
8266 function runNotRedundantChangeTest()
8271 function clearResult()
8276 function handler(aEvent)
8278 result.push(aEvent);
8281 textarea.addEventListener(
"compositionupdate", handler, true);
8282 textarea.addEventListener(
"compositionend", handler, true);
8283 textarea.addEventListener(
"beforeinput", handler, true);
8284 textarea.addEventListener(
"input", handler, true);
8285 textarea.addEventListener(
"text", handler, true);
8287 textarea.value =
"abcde";
8289 // synthesize change event with non-null ranges
8291 synthesizeCompositionChange(
8293 {
"string":
"ABCDE",
8296 {
"length":
5,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
8299 "caret": {
"start":
5,
"length":
0 }
8302 is(result.length,
4,
8303 "runNotRedundantChangeTest: 4 events should be fired after synthesizing composition change with non-null ranges");
8304 is(result[
0].type,
"compositionupdate",
8305 "runNotRedundantChangeTest: compositionupdate should be fired after synthesizing composition change with non-null ranges");
8306 is(result[
1].type,
"text",
8307 "runNotRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string with non-null ranges");
8308 is(result[
2].type,
"beforeinput",
8309 "runNotRedundantChangeTest: beforeinput should be fired after synthesizing composition change with non-null ranges");
8310 checkInputEvent(result[
2], true,
"insertCompositionText",
"ABCDE", [],
8311 "runNotRedundantChangeTest: after synthesizing composition change with non-null ranges");
8312 is(result[
3].type,
"input",
8313 "runNotRedundantChangeTest: input should be fired after synthesizing composition change with non-null ranges");
8314 checkInputEvent(result[
3], true,
"insertCompositionText",
"ABCDE", [],
8315 "runNotRedundantChangeTest: after synthesizing composition change with non-null ranges");
8316 is(textarea.value,
"abcdeABCDE",
"runNotRedundantChangeTest: textarea has uncommitted string #1");
8318 // synthesize change event with null ranges
8320 synthesizeCompositionChange(
8322 {
"string":
"ABCDE",
8325 {
"length":
0,
"attr":
0 }
8329 is(result.length,
3,
8330 "runNotRedundantChangeTest: 3 events should be fired after synthesizing composition change with null ranges after non-null ranges");
8331 is(result[
0].type,
"text",
8332 "runNotRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string with null ranges after non-null ranges");
8333 is(result[
1].type,
"beforeinput",
8334 "runNotRedundantChangeTest: beforeinput should be fired after synthesizing composition change because it's dispatched when there is composing string with null ranges after non-null ranges");
8335 checkInputEvent(result[
1], true,
"insertCompositionText",
"ABCDE", [],
8336 "runNotRedundantChangeTest: after synthesizing composition change with null ranges after non-null ranges");
8337 is(result[
2].type,
"input",
8338 "runNotRedundantChangeTest: input should be fired after synthesizing composition change with null ranges after non-null ranges");
8339 checkInputEvent(result[
2], true,
"insertCompositionText",
"ABCDE", [],
8340 "runNotRedundantChangeTest: after synthesizing composition change with null ranges after non-null ranges");
8341 is(textarea.value,
"abcdeABCDE",
"runNotRedundantChangeTest: textarea has uncommitted string #2");
8343 // synthesize change event with non-null ranges
8345 synthesizeCompositionChange(
8347 {
"string":
"ABCDE",
8350 {
"length":
5,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
8353 "caret": {
"start":
5,
"length":
0 }
8356 is(result.length,
3,
8357 "runNotRedundantChangeTest: 3 events should be fired after synthesizing composition change with null ranges after non-null ranges");
8358 is(result[
0].type,
"text",
8359 "runNotRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string with non-null ranges after null ranges");
8360 is(result[
1].type,
"beforeinput",
8361 "runNotRedundantChangeTest: beforeinput should be fired after synthesizing composition change because it's dispatched when there is composing string with non-null ranges after null ranges");
8362 checkInputEvent(result[
1], true,
"insertCompositionText",
"ABCDE", [],
8363 "runNotRedundantChangeTest: after synthesizing composition change with non-null ranges after null ranges");
8364 is(result[
2].type,
"input",
8365 "runNotRedundantChangeTest: input should be fired after synthesizing composition change with non-null ranges after null ranges");
8366 checkInputEvent(result[
2], true,
"insertCompositionText",
"ABCDE", [],
8367 "runNotRedundantChangeTest: after synthesizing composition change with non-null ranges after null ranges");
8368 is(textarea.value,
"abcdeABCDE",
"runNotRedundantChangeTest: textarea has uncommitted string #3");
8370 // synthesize change event with empty data and null ranges
8372 synthesizeCompositionChange(
8377 {
"length":
0,
"attr":
0 }
8381 is(result.length,
4,
8382 "runNotRedundantChangeTest: 4 events should be fired after synthesizing composition change with empty data and null ranges after non-null ranges");
8383 is(result[
0].type,
"compositionupdate",
8384 "runNotRedundantChangeTest: compositionupdate should be fired after synthesizing composition change with empty data and null ranges after non-null ranges");
8385 is(result[
1].type,
"text",
8386 "runNotRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string with empty data and null ranges after non-null ranges");
8387 is(result[
2].type,
"beforeinput",
8388 "runNotRedundantChangeTest: beforeinput should be fired after synthesizing composition change with empty data and null ranges after non-null ranges");
8389 checkInputEvent(result[
2], true,
"insertCompositionText",
"", [],
8390 "runNotRedundantChangeTest: after synthesizing composition change with empty data and null ranges after non-null ranges");
8391 is(result[
3].type,
"input",
8392 "runNotRedundantChangeTest: input should be fired after synthesizing composition change with empty data and null ranges after non-null ranges");
8393 checkInputEvent(result[
3], true,
"insertCompositionText",
"", [],
8394 "runNotRedundantChangeTest: after synthesizing composition change with empty data and null ranges after non-null ranges");
8395 is(textarea.value,
"abcde",
"runNotRedundantChangeTest: textarea doesn't have uncommitted string #1");
8397 // synthesize change event with non-null ranges
8399 synthesizeCompositionChange(
8401 {
"string":
"ABCDE",
8404 {
"length":
5,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
8407 "caret": {
"start":
5,
"length":
0 }
8410 is(result.length,
4,
8411 "runNotRedundantChangeTest: 4 events should be fired after synthesizing composition change with non-null ranges after empty data and null ranges");
8412 is(result[
0].type,
"compositionupdate",
8413 "runNotRedundantChangeTest: compositionupdate should be fired after synthesizing composition change with non-null ranges after empty data and null ranges");
8414 is(result[
1].type,
"text",
8415 "runNotRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string with non-null ranges after empty data and null ranges");
8416 is(result[
2].type,
"beforeinput",
8417 "runNotRedundantChangeTest: beforeinput should be fired after synthesizing composition change with non-null ranges after empty data and null ranges");
8418 checkInputEvent(result[
2], true,
"insertCompositionText",
"ABCDE", [],
8419 "runNotRedundantChangeTest: after synthesizing composition change with non-null ranges after empty data and null ranges");
8420 is(result[
3].type,
"input",
8421 "runNotRedundantChangeTest: input should be fired after synthesizing composition change with non-null ranges after empty data and null ranges");
8422 checkInputEvent(result[
3], true,
"insertCompositionText",
"ABCDE", [],
8423 "runNotRedundantChangeTest: after synthesizing composition change with non-null ranges after empty data and null ranges");
8424 is(textarea.value,
"abcdeABCDE",
"runNotRedundantChangeTest: textarea has uncommitted string #4");
8427 synthesizeComposition({ type:
"compositioncommit", data:
"" });
8429 is(result.length,
5,
8430 "runNotRedundantChangeTest: 5 events should be fired after synthesizing composition commit with empty data after non-empty data");
8431 is(result[
0].type,
"compositionupdate",
8432 "runNotRedundantChangeTest: compositionupdate should be fired after synthesizing composition commit with empty data after non-empty data");
8433 is(result[
1].type,
"text",
8434 "runNotRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string with empty data after non-empty data");
8435 is(result[
2].type,
"beforeinput",
8436 "runNotRedundantChangeTest: beforeinput should be fired after synthesizing composition commit with empty data after non-empty data");
8437 checkInputEvent(result[
2], true,
"insertCompositionText",
"", [],
8438 "runNotRedundantChangeTest: after synthesizing composition change with empty data after non-empty data");
8439 is(result[
3].type,
"compositionend",
8440 "runNotRedundantChangeTest: compositionend should be fired after synthesizing composition commit with empty data after non-empty data");
8441 is(result[
4].type,
"input",
8442 "runNotRedundantChangeTest: input should be fired after compositionend after synthesizing composition change with empty data after non-empty data");
8443 checkInputEvent(result[
4], false,
"insertCompositionText",
"", [],
8444 "runNotRedundantChangeTest: after synthesizing composition change with empty data after non-empty data");
8445 is(textarea.value,
"abcde",
"runNotRedundantChangeTest: textarea doesn't have uncommitted string #2");
8447 textarea.removeEventListener(
"compositionupdate", handler, true);
8448 textarea.removeEventListener(
"compositionend", handler, true);
8449 textarea.removeEventListener(
"beforeinput", handler, true);
8450 textarea.removeEventListener(
"input", handler, true);
8451 textarea.removeEventListener(
"text", handler, true);
8454 function runNativeLineBreakerTest()
8459 function clearResult()
8461 result = { compositionupdate: null, compositionend: null };
8464 function handler(aEvent)
8466 result[aEvent.type] = aEvent.data;
8469 Services.prefs.setBoolPref(
"dom.compositionevent.allow_control_characters", false);
8471 textarea.addEventListener(
"compositionupdate", handler, true);
8472 textarea.addEventListener(
"compositionend", handler, true);
8474 // '\n' in composition string shouldn't be changed.
8476 textarea.value =
"";
8477 let clauses = [
"abc\n",
"def\n\ng",
"hi\n",
"\njkl" ];
8478 let caret = clauses[
0] + clauses[
1] + clauses[
2];
8479 synthesizeCompositionChange(
8481 {
"string": clauses.join(''),
8484 {
"length": clauses[
0].length,
8485 "attr": COMPOSITION_ATTR_RAW_CLAUSE },
8486 {
"length": clauses[
1].length,
8487 "attr": COMPOSITION_ATTR_SELECTED_RAW_CLAUSE },
8488 {
"length": clauses[
2].length,
8489 "attr": COMPOSITION_ATTR_CONVERTED_CLAUSE },
8490 {
"length": clauses[
3].length,
8491 "attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
8494 "caret": {
"start": caret.length,
"length":
0 }
8497 checkSelection(caret.replace(/\n/g,
"\n").length + (kLFLen -
1) *
4,
"",
"runNativeLineBreakerTest",
"#1");
8498 checkIMESelection(
"RawClause", true,
0, clauses[
0].replace(/\n/g, kLF),
"runNativeLineBreakerTest: \\n shouldn't be replaced with any character #1");
8499 checkIMESelection(
"SelectedRawClause", true, clauses[
0].replace(/\n/g, kLF).length, clauses[
1].replace(/\n/g, kLF),
"runNativeLineBreakerTest: \\n shouldn't be replaced with any character #1");
8500 checkIMESelection(
"ConvertedClause", true, (clauses[
0] + clauses[
1]).replace(/\n/g, kLF).length, clauses[
2].replace(/\n/g, kLF),
"runNativeLineBreakerTest: \\n shouldn't be replaced with any character #1");
8501 checkIMESelection(
"SelectedClause", true, (clauses[
0] + clauses[
1] + clauses[
2]).replace(/\n/g, kLF).length, clauses[
3].replace(/\n/g, kLF),
"runNativeLineBreakerTest: \\n shouldn't be replaced with any character #1");
8502 is(result.compositionupdate, clauses.join('').replace(/\n/g,
"\n"),
"runNativeLineBreakerTest: \\n in compositionupdate.data shouldn't be removed nor replaced with other characters #1");
8503 is(textarea.value, clauses.join('').replace(/\n/g,
"\n"),
"runNativeLineBreakerTest: \\n in textarea.value shouldn't be removed nor replaced with other characters #1");
8505 synthesizeComposition({ type:
"compositioncommit", data: clauses.join('') });
8506 checkSelection(clauses.join('').replace(/\n/g,
"\n").length + (kLFLen -
1) *
5,
"",
"runNativeLineBreakerTest",
"#2");
8507 is(result.compositionend, clauses.join('').replace(/\n/g,
"\n"),
"runNativeLineBreakerTest: \\n in compositionend.data shouldn't be removed nor replaced with other characters #2");
8508 is(textarea.value, clauses.join('').replace(/\n/g,
"\n"),
"runNativeLineBreakerTest: \\n in textarea.value shouldn't be removed nor replaced with other characters #2");
8510 // \r\n in composition string should be replaced with \n.
8512 textarea.value =
"";
8513 clauses = [
"abc\r\n",
"def\r\n\r\ng",
"hi\r\n",
"\r\njkl" ];
8514 caret = clauses[
0] + clauses[
1] + clauses[
2];
8515 synthesizeCompositionChange(
8517 {
"string": clauses.join(''),
8520 {
"length": clauses[
0].length,
8521 "attr": COMPOSITION_ATTR_RAW_CLAUSE },
8522 {
"length": clauses[
1].length,
8523 "attr": COMPOSITION_ATTR_SELECTED_RAW_CLAUSE },
8524 {
"length": clauses[
2].length,
8525 "attr": COMPOSITION_ATTR_CONVERTED_CLAUSE },
8526 {
"length": clauses[
3].length,
8527 "attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
8530 "caret": {
"start": caret.length,
"length":
0 }
8533 checkSelection(caret.replace(/\r\n/g,
"\n").length + (kLFLen -
1) *
4,
"",
"runNativeLineBreakerTest",
"#3");
8534 checkIMESelection(
"RawClause", true,
0, clauses[
0].replace(/\r\n/g, kLF),
"runNativeLineBreakerTest: \\r\\n should be replaced with \\n #3");
8535 checkIMESelection(
"SelectedRawClause", true, clauses[
0].replace(/\r\n/g, kLF).length, clauses[
1].replace(/\r\n/g, kLF),
"runNativeLineBreakerTest: \\r\\n should be replaced with \\n #3");
8536 checkIMESelection(
"ConvertedClause", true, (clauses[
0] + clauses[
1]).replace(/\r\n/g, kLF).length, clauses[
2].replace(/\r\n/g, kLF),
"runNativeLineBreakerTest: \\r\\n should be replaced with \\n #3");
8537 checkIMESelection(
"SelectedClause", true, (clauses[
0] + clauses[
1] + clauses[
2]).replace(/\r\n/g, kLF).length, clauses[
3].replace(/\r\n/g, kLF),
"runNativeLineBreakerTest: \\r\\n should be replaced with \\n #3");
8538 is(result.compositionupdate, clauses.join('').replace(/\r\n/g,
"\n"),
"runNativeLineBreakerTest: \\r\\n in compositionudpate.data should be replaced with \\n #3");
8539 is(textarea.value, clauses.join('').replace(/\r\n/g,
"\n"),
"runNativeLineBreakerTest: \\r\\n in textarea.value should be replaced with \\n #3");
8541 synthesizeComposition({ type:
"compositioncommit", data: clauses.join('') });
8542 checkSelection(clauses.join('').replace(/\r\n/g,
"\n").length + (kLFLen -
1) *
5,
"",
"runNativeLineBreakerTest",
"#4");
8543 is(result.compositionend, clauses.join('').replace(/\r\n/g,
"\n"),
"runNativeLineBreakerTest: \\r\\n in compositionend.data should be replaced with \\n #4");
8544 is(textarea.value, clauses.join('').replace(/\r\n/g,
"\n"),
"runNativeLineBreakerTest: \\r\\n in textarea.value should be replaced with \\n #4");
8546 // \r (not followed by \n) in composition string should be replaced with \n.
8548 textarea.value =
"";
8549 clauses = [
"abc\r",
"def\r\rg",
"hi\r",
"\rjkl" ];
8550 caret = clauses[
0] + clauses[
1] + clauses[
2];
8551 synthesizeCompositionChange(
8553 {
"string": clauses.join(''),
8556 {
"length": clauses[
0].length,
8557 "attr": COMPOSITION_ATTR_RAW_CLAUSE },
8558 {
"length": clauses[
1].length,
8559 "attr": COMPOSITION_ATTR_SELECTED_RAW_CLAUSE },
8560 {
"length": clauses[
2].length,
8561 "attr": COMPOSITION_ATTR_CONVERTED_CLAUSE },
8562 {
"length": clauses[
3].length,
8563 "attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
8566 "caret": {
"start": caret.length,
"length":
0 }
8569 checkSelection(caret.replace(/\r/g,
"\n").length + (kLFLen -
1) *
4,
"",
"runNativeLineBreakerTest",
"#5");
8570 checkIMESelection(
"RawClause", true,
0, clauses[
0].replace(/\r/g, kLF),
"runNativeLineBreakerTest: \\r should be replaced with \\n #5");
8571 checkIMESelection(
"SelectedRawClause", true, clauses[
0].replace(/\r/g, kLF).length, clauses[
1].replace(/\r/g, kLF),
"runNativeLineBreakerTest: \\r should be replaced with \\n #5");
8572 checkIMESelection(
"ConvertedClause", true, (clauses[
0] + clauses[
1]).replace(/\r/g, kLF).length, clauses[
2].replace(/\r/g, kLF),
"runNativeLineBreakerTest: \\r should be replaced with \\n #5");
8573 checkIMESelection(
"SelectedClause", true, (clauses[
0] + clauses[
1] + clauses[
2]).replace(/\r/g, kLF).length, clauses[
3].replace(/\r/g, kLF),
"runNativeLineBreakerTest: \\r should be replaced with \\n #5");
8574 is(result.compositionupdate, clauses.join('').replace(/\r/g,
"\n"),
"runNativeLineBreakerTest: \\r in compositionupdate.data should be replaced with \\n #5");
8575 is(textarea.value, clauses.join('').replace(/\r/g,
"\n"),
"runNativeLineBreakerTest: \\r in textarea.value should be replaced with \\n #5");
8577 synthesizeComposition({ type:
"compositioncommit", data: clauses.join('') });
8578 checkSelection(clauses.join('').replace(/\r/g,
"\n").length + (kLFLen -
1) *
5,
"",
"runNativeLineBreakerTest",
"#6");
8579 is(result.compositionend, clauses.join('').replace(/\r/g,
"\n"),
"runNativeLineBreakerTest: \\r in compositionend.data should be replaced with \\n #6");
8580 is(textarea.value, clauses.join('').replace(/\r/g,
"\n"),
"runNativeLineBreakerTest: \\r in textarea.value should be replaced with \\n #6");
8582 textarea.removeEventListener(
"compositionupdate", handler, true);
8583 textarea.removeEventListener(
"compositionend", handler, true);
8585 Services.prefs.clearUserPref(
"dom.compositionevent.allow_control_characters");
8588 function runControlCharTest()
8593 function clearResult()
8595 result = { compositionupdate: null, compositionend: null };
8598 function handler(aEvent)
8600 result[aEvent.type] = aEvent.data;
8603 textarea.addEventListener(
"compositionupdate", handler, true);
8604 textarea.addEventListener(
"compositionend", handler, true);
8606 textarea.value =
"";
8608 let controlChars = String.fromCharCode.apply(null, Object.keys(Array.from({length:
0x20}))) +
"\x7F";
8609 let allowedChars =
"\t\n\n";
8611 let data =
"AB" + controlChars +
"CD" + controlChars +
"EF";
8612 let removedData =
"AB" + allowedChars +
"CD" + allowedChars +
"EF";
8614 let DIndex = data.indexOf(
"D");
8615 let removedDIndex = removedData.indexOf(
"D");
8617 // input string contains control characters
8619 synthesizeCompositionChange(
8625 "attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
8626 {
"length": data.length - DIndex,
8627 "attr": COMPOSITION_ATTR_CONVERTED_CLAUSE }
8630 "caret": {
"start": DIndex,
"length":
0 }
8633 checkSelection(removedDIndex + (kLFLen -
1) *
2,
"",
"runControlCharTest",
"#1")
8635 is(result.compositionupdate, removedData,
"runControlCharTest: control characters in event.data should be removed in compositionupdate event #1");
8636 is(textarea.value, removedData,
"runControlCharTest: control characters should not appear in textarea #1");
8638 synthesizeComposition({ type:
"compositioncommit", data });
8640 is(result.compositionend, removedData,
"runControlCharTest: control characters in event.data should be removed in compositionend event #2");
8641 is(textarea.value, removedData,
"runControlCharTest: control characters should not appear in textarea #2");
8643 textarea.value =
"";
8647 Services.prefs.setBoolPref(
"dom.compositionevent.allow_control_characters", true);
8649 // input string contains control characters, allowing control characters
8651 synthesizeCompositionChange(
8657 "attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
8658 {
"length": data.length - DIndex,
8659 "attr": COMPOSITION_ATTR_CONVERTED_CLAUSE }
8662 "caret": {
"start": DIndex,
"length":
0 }
8665 checkSelection(DIndex + (kLFLen -
1) *
2,
"",
"runControlCharTest",
"#3")
8667 is(result.compositionupdate, data.replace(/\r/g,
"\n"),
"runControlCharTest: control characters in event.data should not be removed in compositionupdate event #3");
8668 is(textarea.value, data.replace(/\r/g,
"\n"),
"runControlCharTest: control characters should appear in textarea #3");
8670 synthesizeComposition({ type:
"compositioncommit", data });
8672 is(result.compositionend, data.replace(/\r/g,
"\n"),
"runControlCharTest: control characters in event.data should not be removed in compositionend event #4");
8673 is(textarea.value, data.replace(/\r/g,
"\n"),
"runControlCharTest: control characters should appear in textarea #4");
8675 Services.prefs.clearUserPref(
"dom.compositionevent.allow_control_characters");
8677 textarea.removeEventListener(
"compositionupdate", handler, true);
8678 textarea.removeEventListener(
"compositionend", handler, true);
8681 async function runRemoveContentTest()
8684 function eventHandler(aEvent)
8686 events.push(aEvent);
8688 textarea.addEventListener(
"compositionstart", eventHandler, true);
8689 textarea.addEventListener(
"compositionupdate", eventHandler, true);
8690 textarea.addEventListener(
"compositionend", eventHandler, true);
8691 textarea.addEventListener(
"beforeinput", eventHandler, true);
8692 textarea.addEventListener(
"input", eventHandler, true);
8693 textarea.addEventListener(
"text", eventHandler, true);
8696 textarea.value =
"";
8698 synthesizeCompositionChange(
8700 {
"string":
"\u306E",
8703 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
8706 "caret": {
"start":
1,
"length":
0 }
8709 let nextSibling = textarea.nextSibling;
8710 let parent = textarea.parentElement;
8713 parent.removeChild(textarea);
8715 await waitForEventLoops(
50);
8717 // XXX Currently,
"input" event and
"beforeinput" event are not fired on removed content.
8718 is(events.length,
3,
8719 "runRemoveContentTest: wrong event count #1");
8720 is(events[
0].type,
"compositionupdate",
8721 "runRemoveContentTest: the 1st event must be compositionupdate #1");
8722 is(events[
0].target, textarea,
8723 `runRemoveContentTest: The
"${events[0].type}" event was fired on wrong event target #
1`);
8724 is(events[
0].data,
"",
8725 "runRemoveContentTest: compositionupdate has wrong data #1");
8726 is(events[
1].type,
"text",
8727 "runRemoveContentTest: the 2nd event must be text #1");
8728 is(events[
1].target, textarea,
8729 `runRemoveContentTest: The
"${events[1].type}" event was fired on wrong event target #
1`);
8730 todo_is(events[
2].type,
"beforeinput",
8731 "runRemoveContentTest: the 3rd event must be beforeinput #1");
8732 // is(events[
2].target, textarea,
8733 // `runRemoveContentTest: The
"${events[2].type}" event was fired on wrong event target #
1`);
8734 // checkInputEvent(events[
2], true,
"insertCompositionText",
"", [],
8735 //
"runRemoveContentTest: #1");
8736 is(events[
2].type,
"compositionend",
8737 "runRemoveContentTest: the 4th event must be compositionend #1");
8738 is(events[
2].target, textarea,
8739 `runRemoveContentTest: The
"${events[2].type}" event was fired on wrong event target #
1`);
8740 is(events[
2].data,
"",
8741 "runRemoveContentTest: compositionend has wrong data #1");
8742 ok(!getEditor(textarea).isComposing,
8743 "runRemoveContentTest: the textarea still has composition #1");
8744 todo_is(textarea.value,
"",
8745 "runRemoveContentTest: the textarea has the committed text? #1");
8747 parent.insertBefore(textarea, nextSibling);
8750 textarea.value =
"";
8752 synthesizeComposition({ type:
"compositionstart" });
8755 parent.removeChild(textarea);
8757 await waitForEventLoops(
50);
8759 // XXX Currently,
"input" event and
"beforeinput" event are not fired on removed content.
8760 is(events.length,
2,
8761 "runRemoveContentTest: wrong event count #2");
8762 is(events[
0].type,
"text",
8763 "runRemoveContentTest: the 1st event must be text #2");
8764 is(events[
0].target, textarea,
8765 `runRemoveContentTest: The ${events[
0].type} event was fired on wrong event target #
2`);
8766 todo_is(events[
1].type,
"beforeinput",
8767 "runRemoveContentTest: the 2nd event must be beforeinput #2");
8768 // is(events[
1].target, textarea,
8769 // `runRemoveContentTest: The ${events[
1].type} event was fired on wrong event target #
2`);
8770 // checkInputEvent(events[
1], true,
"insertCompositionText",
"", [],
8771 //
"runRemoveContentTest: #2");
8772 is(events[
1].type,
"compositionend",
8773 "runRemoveContentTest: the 3rd event must be compositionend #2");
8774 is(events[
1].target, textarea,
8775 `runRemoveContentTest: The ${events[
1].type} event was fired on wrong event target #
2`);
8776 is(events[
1].data,
"",
8777 "runRemoveContentTest: compositionupdate has wrong data #2");
8778 ok(!getEditor(textarea).isComposing,
8779 "runRemoveContentTest: the textarea still has composition #2");
8780 is(textarea.value,
"",
8781 "runRemoveContentTest: the textarea has the committed text? #2");
8783 parent.insertBefore(textarea, nextSibling);
8785 textarea.removeEventListener(
"compositionstart", eventHandler, true);
8786 textarea.removeEventListener(
"compositionupdate", eventHandler, true);
8787 textarea.removeEventListener(
"compositionend", eventHandler, true);
8788 textarea.removeEventListener(
"beforeinput", eventHandler, true);
8789 textarea.removeEventListener(
"input", eventHandler, true);
8790 textarea.removeEventListener(
"text", eventHandler, true);
8792 await waitForTick();
8795 function runTestOnAnotherContext(aPanelOrFrame, aFocusedEditor, aTestName)
8797 aFocusedEditor.value =
"";
8799 // The frames and panel are cross-origin, and we no longer
8800 // propagate flushes to parent cross-origin iframes explicitly,
8801 // so flush our own layout here so the positions are correct.
8802 document.documentElement.getBoundingClientRect();
8804 let editorRect = synthesizeQueryEditorRect();
8805 if (!checkQueryContentResult(editorRect, aTestName +
": editorRect")) {
8809 let r = aPanelOrFrame.getBoundingClientRect();
8811 left: r.left * window.devicePixelRatio,
8812 top: r.top * window.devicePixelRatio,
8813 width: (r.right - r.left) * window.devicePixelRatio,
8814 height: (r.bottom - r.top) * window.devicePixelRatio,
8816 checkRectContainsRect(editorRect, parentRect, aTestName +
8817 ": the editor rect coordinates are wrong");
8820 synthesizeCompositionChange(
8822 {
"string":
"\u3078\u3093\u3057\u3093",
8825 {
"length":
4,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
8828 "caret": {
"start":
4,
"length":
0 }
8831 if (!checkContent(
"\u3078\u3093\u3057\u3093", aTestName,
"#1-1") ||
8832 !checkSelection(
4,
"", aTestName,
"#1-1")) {
8837 synthesizeCompositionChange(
8839 {
"string":
"\u8FD4\u4FE1",
8843 "attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
8846 "caret": {
"start":
2,
"length":
0 }
8849 if (!checkContent(
"\u8FD4\u4FE1", aTestName,
"#1-2") ||
8850 !checkSelection(
2,
"", aTestName,
"#1-2")) {
8855 synthesizeCompositionChange(
8857 {
"string":
"\u5909\u8EAB",
8861 "attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
8864 "caret": {
"start":
2,
"length":
0 }
8867 if (!checkContent(
"\u5909\u8EAB", aTestName,
"#1-3") ||
8868 !checkSelection(
2,
"", aTestName,
"#1-3")) {
8873 synthesizeComposition({ type:
"compositioncommitasis" });
8874 if (!checkContent(
"\u5909\u8EAB", aTestName,
"#1-4") ||
8875 !checkSelection(
2,
"", aTestName,
"#1-4")) {
8879 is(aFocusedEditor.value,
"\u5909\u8EAB",
8880 aTestName +
": composition isn't in the focused editor");
8881 if (aFocusedEditor.value !=
"\u5909\u8EAB") {
8885 let textRect = synthesizeQueryTextRect(
0,
1);
8886 let caretRect = synthesizeQueryCaretRect(
2);
8887 if (!checkQueryContentResult(textRect,
8888 aTestName +
": synthesizeQueryTextRect") ||
8889 !checkQueryContentResult(caretRect,
8890 aTestName +
": synthesizeQueryCaretRect")) {
8893 checkRectContainsRect(textRect, editorRect, aTestName +
":testRect");
8894 checkRectContainsRect(caretRect, editorRect, aTestName +
":caretRect");
8897 function runFrameTest()
8899 textareaInFrame.focus();
8900 runTestOnAnotherContext(iframe, textareaInFrame,
"runFrameTest");
8901 runCharAtPointTest(textareaInFrame,
"textarea in the iframe");
8904 async function runPanelTest()
8906 panel.hidden = false;
8907 let waitOpenPopup = new Promise(resolve =
> {
8908 panel.addEventListener(
"popupshown", resolve, {once: true});
8910 let waitFocusTextBox = new Promise(resolve =
> {
8911 textbox.addEventListener(
"focus", resolve, {once: true});
8913 panel.openPopupAtScreen(window.screenX + window.outerWidth,
0, false);
8914 await waitOpenPopup;
8916 await waitFocusTextBox;
8917 is(panel.state,
"open",
"The panel should be open (after textbox.focus())");
8918 await waitForTick();
8919 is(panel.state,
"open",
"The panel should be open (after waitForTick())");
8920 runTestOnAnotherContext(panel, textbox,
"runPanelTest");
8921 is(panel.state,
"open",
"The panel should be open (after runTestOnAnotherContext())");
8922 runCharAtPointTest(textbox,
"textbox in the panel");
8923 is(panel.state,
"open",
"The panel should be open (after runCharAtPointTest())");
8924 let waitClosePopup = new Promise(resolve =
> {
8925 panel.addEventListener(
"popuphidden", resolve, {once: true});
8928 await waitClosePopup;
8929 await waitForTick();
8932 // eslint-disable-next-line complexity
8933 function runMaxLengthTest()
8935 input.maxLength =
1;
8939 let kDesc =
"runMaxLengthTest";
8941 // input first character
8942 synthesizeCompositionChange(
8944 {
"string":
"\u3089",
8947 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
8950 "caret": {
"start":
1,
"length":
0 }
8953 if (!checkContent(
"\u3089", kDesc,
"#1-1") ||
8954 !checkSelection(
1,
"", kDesc,
"#1-1")) {
8958 // input second character
8959 synthesizeCompositionChange(
8961 {
"string":
"\u3089\u30FC",
8964 {
"length":
2,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
8967 "caret": {
"start":
2,
"length":
0 }
8970 if (!checkContent(
"\u3089\u30FC", kDesc,
"#1-2") ||
8971 !checkSelection(
2,
"", kDesc,
"#1-2")) {
8975 // input third character
8976 synthesizeCompositionChange(
8978 {
"string":
"\u3089\u30FC\u3081",
8981 {
"length":
3,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
8984 "caret": {
"start":
3,
"length":
0 }
8987 if (!checkContent(
"\u3089\u30FC\u3081", kDesc,
"#1-3") ||
8988 !checkSelection(
3,
"", kDesc,
"#1-3")) {
8992 // input fourth character
8993 synthesizeCompositionChange(
8995 {
"string":
"\u3089\u30FC\u3081\u3093",
8998 {
"length":
4,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9001 "caret": {
"start":
4,
"length":
0 }
9004 if (!checkContent(
"\u3089\u30FC\u3081\u3093", kDesc,
"#1-4") ||
9005 !checkSelection(
4,
"", kDesc,
"#1-4")) {
9011 synthesizeCompositionChange(
9013 {
"string":
"\u3089\u30FC\u3081",
9016 {
"length":
3,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9019 "caret": {
"start":
3,
"length":
0 }
9022 if (!checkContent(
"\u3089\u30FC\u3081", kDesc,
"#1-5") ||
9023 !checkSelection(
3,
"", kDesc,
"#1-5")) {
9028 synthesizeCompositionChange(
9030 {
"string":
"\u3089\u30FC\u3081\u3093",
9033 {
"length":
4,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9036 "caret": {
"start":
4,
"length":
0 }
9039 if (!checkContent(
"\u3089\u30FC\u3081\u3093", kDesc,
"#1-6") ||
9040 !checkSelection(
4,
"", kDesc,
"#1-6")) {
9044 synthesizeCompositionChange(
9046 {
"string":
"\u3089\u30FC\u3081\u3093\u3055",
9049 {
"length":
5,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9052 "caret": {
"start":
5,
"length":
0 }
9055 if (!checkContent(
"\u3089\u30FC\u3081\u3093\u3055", kDesc,
"#1-7") ||
9056 !checkSelection(
5,
"", kDesc,
"#1-7")) {
9060 synthesizeCompositionChange(
9062 {
"string":
"\u3089\u30FC\u3081\u3093\u3055\u3044",
9065 {
"length":
6,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9068 "caret": {
"start":
6,
"length":
0 }
9071 if (!checkContent(
"\u3089\u30FC\u3081\u3093\u3055\u3044", kDesc,
"#1-8") ||
9072 !checkSelection(
6,
"", kDesc,
"#1-8")) {
9076 synthesizeCompositionChange(
9078 {
"string":
"\u3089\u30FC\u3081\u3093\u3055\u3044\u3053",
9081 {
"length":
7,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9084 "caret": {
"start":
7,
"length":
0 }
9087 if (!checkContent(
"\u3089\u30FC\u3081\u3093\u3055\u3044\u3053",
9089 !checkSelection(
7,
"", kDesc,
"#1-8")) {
9093 synthesizeCompositionChange(
9095 {
"string":
"\u3089\u30FC\u3081\u3093\u3055\u3044\u3053\u3046",
9098 {
"length":
8,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9101 "caret": {
"start":
8,
"length":
0 }
9104 if (!checkContent(
"\u3089\u30FC\u3081\u3093\u3055\u3044\u3053\u3046",
9106 !checkSelection(
8,
"", kDesc,
"#1-9")) {
9111 synthesizeCompositionChange(
9113 {
"string":
"\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8",
9117 "attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
9119 "attr": COMPOSITION_ATTR_CONVERTED_CLAUSE }
9122 "caret": {
"start":
4,
"length":
0 }
9125 if (!checkContent(
"\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8", kDesc,
"#1-10") ||
9126 !checkSelection(
4,
"", kDesc,
"#1-10")) {
9130 // commit the composition string
9131 synthesizeComposition({ type:
"compositioncommitasis" });
9132 if (!checkContent(
"\u30E9", kDesc,
"#1-11") ||
9133 !checkSelection(
1,
"", kDesc,
"#1-11")) {
9138 synthesizeCompositionChange(
9140 {
"string":
"\u3057",
9143 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9146 "caret": {
"start":
1,
"length":
0 }
9149 if (!checkContent(
"\u30E9\u3057", kDesc,
"#2-1") ||
9150 !checkSelection(
1 +
1,
"", kDesc,
"#2-1")) {
9154 // commit the composition string
9155 synthesizeComposition({ type:
"compositioncommit", data:
"\u3058" });
9156 if (!checkContent(
"\u30E9", kDesc,
"#2-2") ||
9157 !checkSelection(
1 +
0,
"", kDesc,
"#2-2")) {
9162 synthesizeKey(
"Z", {accelKey: true});
9164 // XXX this is unexpected behavior, see bug
258291
9165 if (!checkContent(
"\u30E9", kDesc,
"#3-1") ||
9166 !checkSelection(
1 +
0,
"", kDesc,
"#3-1")) {
9171 synthesizeKey(
"Z", {accelKey: true});
9172 if (!checkContent(
"", kDesc,
"#3-2") ||
9173 !checkSelection(
0,
"", kDesc,
"#3-2")) {
9178 synthesizeKey(
"Z", {accelKey: true, shiftKey: true});
9179 if (!checkContent(
"\u30E9", kDesc,
"#3-3") ||
9180 !checkSelection(
1,
"", kDesc,
"#3-3")) {
9185 synthesizeKey(
"Z", {accelKey: true, shiftKey: true});
9186 if (!checkContent(
"\u30E9", kDesc,
"#3-4") ||
9187 !checkSelection(
1 +
0,
"", kDesc,
"#3-4")) {
9191 // The input element whose content length is already maxlength and
9192 // the carest is at start of the content.
9194 input.selectionStart = input.selectionEnd =
0;
9197 synthesizeCompositionChange(
9199 {
"string":
"\u9B54",
9202 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9205 "caret": {
"start":
1,
"length":
0 }
9208 if (!checkContent(
"\u9B54X", kDesc,
"#4-1") ||
9209 !checkSelection(
1,
"", kDesc,
"#4-1")) {
9213 // commit the composition string
9214 synthesizeComposition({ type:
"compositioncommitasis" });
9216 // The input text must be discarded. Then, the caret position shouldn't be
9217 // updated from its position at compositionstart.
9218 if (!checkContent(
"X", kDesc,
"#4-2") ||
9219 !checkSelection(
0,
"", kDesc,
"#4-2")) {
9224 synthesizeCompositionChange(
9226 {
"string":
"\u9B54\u6CD5",
9229 {
"length":
2,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9232 "caret": {
"start":
2,
"length":
0 }
9235 if (!checkContent(
"\u9B54\u6CD5X", kDesc,
"#5-1") ||
9236 !checkSelection(
2,
"", kDesc,
"#5-1")) {
9240 // commit the composition string
9241 synthesizeComposition({ type:
"compositioncommitasis" });
9243 if (checkContent(
"X", kDesc,
"#5-2")) {
9244 checkSelection(
0,
"", kDesc,
"#5-2");
9248 async function runEditorReframeTests()
9250 async function runEditorReframeTest(aEditor, aWindow, aEventType)
9254 return aEditor == contenteditable ?
9255 aEditor.innerHTML.replace(
"<br>",
"") : aEditor.value;
9258 let description =
"runEditorReframeTest(" + aEditor.id +
", \"" + aEventType + "\
"): ";
9262 synthesizeCompositionChange(
9267 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9270 "caret": {
"start":
1,
"length":
0 }
9274 is(getValue(aEditor),
"a", description +
"Typing 'a'");
9278 synthesizeCompositionChange(
9283 {
"length":
2,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9286 "caret": {
"start":
2,
"length":
0 }
9290 is(getValue(aEditor),
"ab", description +
"Typing 'b' next to 'a'");
9294 synthesizeCompositionChange(
9299 {
"length":
3,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9302 "caret": {
"start":
3,
"length":
0 }
9306 is(getValue(aEditor),
"abc", description +
"Typing 'c' next to 'ab'");
9310 synthesizeCompositionChange(
9315 {
"length":
2,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
9316 {
"length":
1,
"attr": COMPOSITION_ATTR_CONVERTED_CLAUSE }
9319 "caret": {
"start":
2,
"length":
0 }
9323 is(getValue(aEditor),
"abc", description +
"Starting to convert 'ab][c'");
9327 synthesizeCompositionChange(
9332 {
"length":
2,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
9333 {
"length":
1,
"attr": COMPOSITION_ATTR_CONVERTED_CLAUSE }
9336 "caret": {
"start":
2,
"length":
0 }
9340 is(getValue(aEditor),
"ABc", description +
"Starting to convert 'AB][c'");
9344 synthesizeCompositionChange(
9349 {
"length":
2,
"attr": COMPOSITION_ATTR_CONVERTED_CLAUSE },
9350 {
"length":
1,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
9353 "caret": {
"start":
3,
"length":
0 }
9357 is(getValue(aEditor),
"ABC", description +
"Starting to convert 'AB][C'");
9361 // Commit composition
9362 synthesizeComposition({ type:
"compositioncommitasis" });
9365 is(getValue(aEditor),
"ABC", description +
"Committed as 'ABC'");
9369 synthesizeCompositionChange(
9374 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9377 "caret": {
"start":
1,
"length":
0 }
9381 is(getValue(aEditor),
"ABCd", description +
"Typing 'd' next to ABC");
9385 synthesizeCompositionChange(
9390 {
"length":
2,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9393 "caret": {
"start":
2,
"length":
0 }
9397 is(getValue(aEditor),
"ABCde", description +
"Typing 'e' next to ABCd");
9401 synthesizeCompositionChange(
9406 {
"length":
3,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9409 "caret": {
"start":
3,
"length":
0 }
9413 is(getValue(aEditor),
"ABCdef", description +
"Typing 'f' next to ABCde");
9417 // Commit composition
9418 synthesizeComposition({ type:
"compositioncommitasis" });
9421 is(getValue(aEditor),
"ABCdef", description +
"Commit 'def' without convert");
9426 synthesizeKey(
"KEY_ArrowLeft");
9427 synthesizeKey(
"KEY_ArrowLeft");
9428 synthesizeKey(
"KEY_Shift", {type:
"keydown", shiftKey: true});
9429 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true});
9430 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true});
9431 synthesizeKey(
"KEY_Shift", {type:
"keyup"});
9437 synthesizeCompositionChange(
9442 {
"length":
1,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9445 "caret": {
"start":
1,
"length":
0 }
9449 is(getValue(aEditor),
"ABgef", description +
"Typing 'g' next to AB");
9453 synthesizeCompositionChange(
9458 {
"length":
2,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9461 "caret": {
"start":
2,
"length":
0 }
9465 is(getValue(aEditor),
"ABghef", description +
"Typing 'h' next to ABg");
9469 synthesizeCompositionChange(
9474 {
"length":
3,
"attr": COMPOSITION_ATTR_RAW_CLAUSE }
9477 "caret": {
"start":
3,
"length":
0 }
9481 is(getValue(aEditor),
"ABghief", description +
"Typing 'i' next to ABgh");
9485 synthesizeCompositionChange(
9490 {
"length":
3,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
9493 "caret": {
"start":
3,
"length":
0 }
9497 is(getValue(aEditor),
"ABGHIef", description +
"Convert 'ghi' to 'GHI'");
9501 // Commit composition
9502 synthesizeComposition({ type:
"compositioncommitasis" });
9505 is(getValue(aEditor),
"ABGHIef", description +
"Commit 'GHI'");
9510 function doReframe(aEvent)
9512 aEvent.target.style.overflow =
9513 aEvent.target.style.overflow !=
"hidden" ?
"hidden" :
"auto";
9516 aEditor.addEventListener(aEventType, doReframe);
9518 for (const currentTest of tests) {
9520 await waitForEventLoops(
20);
9521 currentTest.check();
9522 await waitForTick();
9525 await new Promise(resolve =
> {
9526 aEditor.style.overflow =
"auto";
9527 aEditor.removeEventListener(aEventType, doReframe);
9528 requestAnimationFrame(() =
> { SimpleTest.executeSoon(resolve); });
9532 // TODO: Add
"beforeinput" case.
9534 await runEditorReframeTest(input, window,
"input");
9536 await runEditorReframeTest(input, window,
"compositionupdate");
9537 textarea.value =
"";
9538 await runEditorReframeTest(textarea, window,
"input");
9539 textarea.value =
"";
9540 await runEditorReframeTest(textarea, window,
"compositionupdate");
9541 contenteditable.innerHTML =
"";
9542 await runEditorReframeTest(contenteditable, windowOfContenteditable,
"input");
9543 contenteditable.innerHTML =
"";
9544 await runEditorReframeTest(contenteditable, windowOfContenteditable,
"compositionupdate");
9547 async function runIMEContentObserverTest()
9549 let notifications = [];
9550 let onReceiveNotifications = null;
9551 function callback(aTIP, aNotification)
9553 if (aNotification.type !=
"notify-end-input-transaction") {
9554 notifications.push(aNotification);
9556 switch (aNotification.type) {
9557 case
"request-to-commit":
9558 aTIP.commitComposition();
9560 case
"request-to-cancel":
9561 aTIP.cancelComposition();
9564 if (onReceiveNotifications) {
9565 let resolve = onReceiveNotifications;
9566 onReceiveNotifications = null;
9567 SimpleTest.executeSoon(() =
> {
9574 function dumpUnexpectedNotifications(aDescription, aExpectedCount)
9576 if (notifications.length <= aExpectedCount) {
9579 for (let i = aExpectedCount; i < notifications.length; i++) {
9581 aDescription +
" caused unexpected notification: " + notifications[i].type);
9585 function promiseReceiveNotifications()
9588 return new Promise(resolve =
> {
9589 onReceiveNotifications = resolve;
9593 function flushNotifications()
9595 return new Promise(resolve =
> {
9596 // FYI: Dispatching non-op keyboard events causes forcibly flushing pending
9598 synthesizeKey(
"KEY_Unidentified", { code:
"" });
9599 SimpleTest.executeSoon(()=
>{
9606 function ensureToRemovePrecedingPositionChangeNotification(aDescription)
9608 if (!notifications.length) {
9611 if (notifications[
0].type !=
"notify-position-change") {
9614 // Sometimes, notify-position-change is notified first separately if
9615 // the operation causes scroll or something. Tests can ignore this.
9616 ok(true,
"notify-position-change", aDescription +
"Unnecessary notify-position-change occurred, ignoring it");
9617 notifications.shift();
9620 // Bug
1374057 - On ubuntu
16.04 there are notify-position-change events that are
9621 // recorded after all the other events so we remove them through this function.
9622 function ensureToRemovePostPositionChangeNotification(aDescription, expectedCount)
9624 if (!notifications.length) {
9627 if (notifications.length <= expectedCount) {
9630 if (notifications[notifications.length-
1].type !=
"notify-position-change") {
9633 ok(true,
"notify-position-change", aDescription +
"Unnecessary notify-position-change occurred, ignoring it");
9634 notifications.pop();
9637 function getNativeText(aXPText)
9642 return aXPText.replace(/\n/g, kLF);
9645 function checkPositionChangeNotification(aNotification, aDescription)
9647 is(!aNotification || aNotification.type,
"notify-position-change",
9648 aDescription +
" should cause position change notification");
9651 function checkSelectionChangeNotification(aNotification, aDescription, aExpected)
9653 is(!aNotification || aNotification.type,
"notify-selection-change",
9654 aDescription +
" should cause selection change notification");
9655 if (!aNotification || (aNotification.type !=
"notify-selection-change")) {
9658 is(aNotification.offset, aExpected.offset,
9659 aDescription +
" should cause selection change notification whose offset is " + aExpected.offset);
9660 is(aNotification.text, aExpected.text,
9661 aDescription +
" should cause selection change notification whose text is '" + aExpected.text +
"'");
9662 is(aNotification.collapsed, !aExpected.text.length,
9663 aDescription +
" should cause selection change notification whose collapsed is " + (!aExpected.text.length));
9664 is(aNotification.length, aExpected.text.length,
9665 aDescription +
" should cause selection change notification whose length is " + aExpected.text.length);
9666 is(aNotification.reversed, aExpected.reversed || false,
9667 aDescription +
" should cause selection change notification whose reversed is " + (aExpected.reversed || false));
9668 is(aNotification.writingMode, aExpected.writingMode ||
"horizontal-tb",
9669 aDescription +
" should cause selection change notification whose writingMode is '" + (aExpected.writingMode ||
"horizontal-tb"));
9672 function checkTextChangeNotification(aNotification, aDescription, aExpected)
9674 is(!aNotification || aNotification.type,
"notify-text-change",
9675 aDescription +
" should cause text change notification");
9676 if (!aNotification || aNotification.type !=
"notify-text-change") {
9679 is(aNotification.offset, aExpected.offset,
9680 aDescription +
" should cause text change notification whose offset is " + aExpected.offset);
9681 is(aNotification.removedLength, aExpected.removedLength,
9682 aDescription +
" should cause text change notification whose removedLength is " + aExpected.removedLength);
9683 is(aNotification.addedLength, aExpected.addedLength,
9684 aDescription +
" should cause text change notification whose addedLength is " + aExpected.addedLength);
9687 async function testWithPlaintextEditor(aDescription, aElement, aTestLineBreaker)
9689 aElement.value =
"";
9691 let doc = aElement.ownerDocument;
9692 let win = doc.defaultView;
9694 await flushNotifications();
9697 let description = aDescription +
"typing 'a'";
9698 let waitNotifications = promiseReceiveNotifications();
9699 synthesizeKey(
"a", {}, win, callback);
9700 await waitNotifications;
9701 ensureToRemovePrecedingPositionChangeNotification();
9702 checkTextChangeNotification(notifications[
0], description, { offset:
0, removedLength:
0, addedLength:
1 });
9703 checkSelectionChangeNotification(notifications[
1], description, { offset:
1, text:
"" });
9704 checkPositionChangeNotification(notifications[
2], description);
9705 ensureToRemovePostPositionChangeNotification(description,
3);
9706 dumpUnexpectedNotifications(description,
3);
9709 description = aDescription +
"typing 'b'";
9710 waitNotifications = promiseReceiveNotifications();
9711 synthesizeKey(
"b", {}, win, callback);
9712 await waitNotifications;
9713 ensureToRemovePrecedingPositionChangeNotification();
9714 checkTextChangeNotification(notifications[
0], description, { offset:
1, removedLength:
0, addedLength:
1 });
9715 checkSelectionChangeNotification(notifications[
1], description, { offset:
2, text:
"" });
9716 checkPositionChangeNotification(notifications[
2], description);
9717 ensureToRemovePostPositionChangeNotification(description,
3);
9718 dumpUnexpectedNotifications(description,
3);
9721 description = aDescription +
"typing 'c'";
9722 waitNotifications = promiseReceiveNotifications();
9723 synthesizeKey(
"c", {}, win, callback);
9724 await waitNotifications;
9725 ensureToRemovePrecedingPositionChangeNotification();
9726 checkTextChangeNotification(notifications[
0], description, { offset:
2, removedLength:
0, addedLength:
1 });
9727 checkSelectionChangeNotification(notifications[
1], description, { offset:
3, text:
"" });
9728 checkPositionChangeNotification(notifications[
2], description);
9729 ensureToRemovePostPositionChangeNotification(description,
3);
9730 dumpUnexpectedNotifications(description,
3);
9733 description = aDescription +
"selecting 'c' with pressing Shift+ArrowLeft";
9734 waitNotifications = promiseReceiveNotifications();
9735 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
9736 await waitNotifications;
9737 ensureToRemovePrecedingPositionChangeNotification();
9738 checkSelectionChangeNotification(notifications[
0], description, { offset:
2, text:
"c", reversed: true });
9739 ensureToRemovePostPositionChangeNotification(description,
1);
9740 dumpUnexpectedNotifications(description,
1);
9743 description = aDescription +
"selecting 'bc' with pressing Shift+ArrowLeft";
9744 waitNotifications = promiseReceiveNotifications();
9745 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
9746 await waitNotifications;
9747 ensureToRemovePrecedingPositionChangeNotification();
9748 checkSelectionChangeNotification(notifications[
0], description, { offset:
1, text:
"bc", reversed: true });
9749 ensureToRemovePostPositionChangeNotification(description,
1);
9750 dumpUnexpectedNotifications(description,
1);
9753 description = aDescription +
"selecting 'bc' with pressing Shift+ArrowLeft";
9754 waitNotifications = promiseReceiveNotifications();
9755 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
9756 await waitNotifications;
9757 ensureToRemovePrecedingPositionChangeNotification();
9758 checkSelectionChangeNotification(notifications[
0], description, { offset:
0, text:
"abc", reversed: true });
9759 ensureToRemovePostPositionChangeNotification(description,
1);
9760 dumpUnexpectedNotifications(description,
1);
9763 description = aDescription +
"collapsing selection to the left-most with pressing ArrowLeft";
9764 waitNotifications = promiseReceiveNotifications();
9765 synthesizeKey(
"KEY_ArrowLeft", {}, win, callback);
9766 await waitNotifications;
9767 ensureToRemovePrecedingPositionChangeNotification();
9768 checkSelectionChangeNotification(notifications[
0], description, { offset:
0, text:
"" });
9769 ensureToRemovePostPositionChangeNotification(description,
1);
9770 dumpUnexpectedNotifications(description,
1);
9773 description = aDescription +
"selecting 'a' with pressing Shift+ArrowRight";
9774 waitNotifications = promiseReceiveNotifications();
9775 synthesizeKey(
"KEY_ArrowRight", {shiftKey: true}, win, callback);
9776 await waitNotifications;
9777 ensureToRemovePrecedingPositionChangeNotification();
9778 checkSelectionChangeNotification(notifications[
0], description, { offset:
0, text:
"a" });
9779 ensureToRemovePostPositionChangeNotification(description,
1);
9780 dumpUnexpectedNotifications(description,
1);
9783 description = aDescription +
"selecting 'ab' with pressing Shift+ArrowRight";
9784 waitNotifications = promiseReceiveNotifications();
9785 synthesizeKey(
"KEY_ArrowRight", {shiftKey: true}, win, callback);
9786 await waitNotifications;
9787 ensureToRemovePrecedingPositionChangeNotification();
9788 checkSelectionChangeNotification(notifications[
0], description, { offset:
0, text:
"ab" });
9789 ensureToRemovePostPositionChangeNotification(description,
1);
9790 dumpUnexpectedNotifications(description,
1);
9793 description = aDescription +
"deleting 'ab' with pressing Delete";
9794 waitNotifications = promiseReceiveNotifications();
9795 synthesizeKey(
"KEY_Delete", {}, win, callback);
9796 await waitNotifications;
9797 ensureToRemovePrecedingPositionChangeNotification();
9798 checkTextChangeNotification(notifications[
0], description, { offset:
0, removedLength:
2, addedLength:
0 });
9799 checkSelectionChangeNotification(notifications[
1], description, { offset:
0, text:
"" });
9800 checkPositionChangeNotification(notifications[
2], description);
9801 ensureToRemovePostPositionChangeNotification(description,
3);
9802 dumpUnexpectedNotifications(description,
3);
9805 description = aDescription +
"deleting following 'c' with pressing Delete";
9806 waitNotifications = promiseReceiveNotifications();
9807 synthesizeKey(
"KEY_Delete", {}, win, callback);
9808 await waitNotifications;
9809 ensureToRemovePrecedingPositionChangeNotification();
9810 checkTextChangeNotification(notifications[
0], description, { offset:
0, removedLength:
1, addedLength:
0 });
9811 checkPositionChangeNotification(notifications[
1], description);
9812 ensureToRemovePostPositionChangeNotification(description,
2);
9813 dumpUnexpectedNotifications(description,
2);
9816 synthesizeKey(
"a", {}, win, callback);
9817 synthesizeKey(
"b", {}, win, callback);
9818 synthesizeKey(
"c", {}, win, callback);
9819 await flushNotifications();
9822 description = aDescription +
"deleting 'c' with pressing Backspace";
9823 waitNotifications = promiseReceiveNotifications();
9824 synthesizeKey(
"KEY_Backspace", {}, win, callback);
9825 await waitNotifications;
9826 ensureToRemovePrecedingPositionChangeNotification();
9827 checkTextChangeNotification(notifications[
0], description, { offset:
2, removedLength:
1, addedLength:
0 });
9828 checkSelectionChangeNotification(notifications[
1], description, { offset:
2, text:
"" });
9829 checkPositionChangeNotification(notifications[
2], description);
9830 ensureToRemovePostPositionChangeNotification(description,
3);
9831 dumpUnexpectedNotifications(description,
3);
9834 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
9835 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
9836 await flushNotifications();
9839 description = aDescription +
"deleting 'ab' with pressing Backspace";
9840 waitNotifications = promiseReceiveNotifications();
9841 synthesizeKey(
"KEY_Backspace", {}, win, callback);
9842 await waitNotifications;
9843 ensureToRemovePrecedingPositionChangeNotification();
9844 checkTextChangeNotification(notifications[
0], description, { offset:
0, removedLength:
2, addedLength:
0 });
9845 checkSelectionChangeNotification(notifications[
1], description, { offset:
0, text:
"" });
9846 checkPositionChangeNotification(notifications[
2], description);
9847 ensureToRemovePostPositionChangeNotification(description,
3);
9848 dumpUnexpectedNotifications(description,
3);
9851 synthesizeKey(
"a", {}, win, callback);
9852 synthesizeKey(
"b", {}, win, callback);
9853 synthesizeKey(
"c", {}, win, callback);
9854 synthesizeKey(
"d", {}, win, callback);
9855 await flushNotifications();
9858 synthesizeKey(
"KEY_ArrowLeft", {}, win, callback);
9859 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
9860 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
9861 await flushNotifications();
9864 description = aDescription +
"deleting 'bc' with pressing Backspace";
9865 waitNotifications = promiseReceiveNotifications();
9866 synthesizeKey(
"KEY_Backspace", {}, win, callback);
9867 await waitNotifications;
9868 ensureToRemovePrecedingPositionChangeNotification();
9869 checkTextChangeNotification(notifications[
0], description, { offset:
1, removedLength:
2, addedLength:
0 });
9870 checkSelectionChangeNotification(notifications[
1], description, { offset:
1, text:
"" });
9871 checkPositionChangeNotification(notifications[
2], description);
9872 ensureToRemovePostPositionChangeNotification(description,
3);
9873 dumpUnexpectedNotifications(description,
3);
9876 synthesizeKey(
"b", {}, win, callback);
9877 synthesizeKey(
"c", {}, win, callback);
9878 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
9879 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
9880 await flushNotifications();
9883 description = aDescription +
"replacing 'bc' with 'B' with pressing Shift+B";
9884 waitNotifications = promiseReceiveNotifications();
9885 synthesizeKey(
"B", {shiftKey: true}, win, callback);
9886 await waitNotifications;
9887 ensureToRemovePrecedingPositionChangeNotification();
9888 checkTextChangeNotification(notifications[
0], description, { offset:
1, removedLength:
2, addedLength:
1 });
9889 checkSelectionChangeNotification(notifications[
1], description, { offset:
2, text:
"" });
9890 checkPositionChangeNotification(notifications[
2], description);
9891 ensureToRemovePostPositionChangeNotification(description,
3);
9892 dumpUnexpectedNotifications(description,
3);
9894 if (!aTestLineBreaker) {
9899 description = aDescription +
"inserting a line break after 'B' with pressing Enter";
9900 waitNotifications = promiseReceiveNotifications();
9901 synthesizeKey(
"KEY_Enter", {}, win, callback);
9902 await waitNotifications;
9903 ensureToRemovePrecedingPositionChangeNotification();
9904 checkTextChangeNotification(notifications[
0], description, { offset:
2, removedLength:
0, addedLength: kLFLen });
9905 checkSelectionChangeNotification(notifications[
1], description, { offset: getNativeText(
"aB\n").length, text:
"" });
9906 checkPositionChangeNotification(notifications[
2], description);
9907 ensureToRemovePostPositionChangeNotification(description,
3);
9908 dumpUnexpectedNotifications(description,
3);
9911 description = aDescription +
"removing a line break after 'B' with pressing Backspace";
9912 waitNotifications = promiseReceiveNotifications();
9913 synthesizeKey(
"KEY_Backspace", {}, win, callback);
9914 await waitNotifications;
9915 ensureToRemovePrecedingPositionChangeNotification();
9916 checkTextChangeNotification(notifications[
0], description, { offset:
2, removedLength: kLFLen, addedLength:
0 });
9917 checkSelectionChangeNotification(notifications[
1], description, { offset:
2, text:
"" });
9918 checkPositionChangeNotification(notifications[
2], description);
9919 ensureToRemovePostPositionChangeNotification(description,
3);
9920 dumpUnexpectedNotifications(description,
3);
9923 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
9924 await flushNotifications();
9927 description = aDescription +
"replacing 'B' with a line break with pressing Enter";
9928 waitNotifications = promiseReceiveNotifications();
9929 synthesizeKey(
"KEY_Enter", {}, win, callback);
9930 await waitNotifications;
9931 ensureToRemovePrecedingPositionChangeNotification();
9932 checkTextChangeNotification(notifications[
0], description, { offset:
1, removedLength:
1, addedLength: kLFLen });
9933 checkSelectionChangeNotification(notifications[
1], description, { offset: getNativeText(
"a\n").length, text:
"" });
9934 checkPositionChangeNotification(notifications[
2], description);
9935 ensureToRemovePostPositionChangeNotification(description,
3);
9936 dumpUnexpectedNotifications(description,
3);
9939 description = aDescription +
"selecting '\n' with pressing Shift+ArrowLeft";
9940 waitNotifications = promiseReceiveNotifications();
9941 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
9942 await waitNotifications;
9943 ensureToRemovePrecedingPositionChangeNotification();
9944 checkSelectionChangeNotification(notifications[
0], description, { offset:
1, text: kLF, reversed: true });
9945 ensureToRemovePostPositionChangeNotification(description,
1);
9946 dumpUnexpectedNotifications(description,
1);
9949 description = aDescription +
"removing selected '\n' with pressing Delete";
9950 waitNotifications = promiseReceiveNotifications();
9951 synthesizeKey(
"KEY_Delete", {shiftKey: true}, win, callback);
9952 await waitNotifications;
9953 ensureToRemovePrecedingPositionChangeNotification();
9954 checkTextChangeNotification(notifications[
0], description, { offset:
1, removedLength: kLFLen, addedLength:
0 });
9955 checkSelectionChangeNotification(notifications[
1], description, { offset:
1, text:
"" });
9956 checkPositionChangeNotification(notifications[
2], description);
9957 ensureToRemovePostPositionChangeNotification(description,
3);
9958 dumpUnexpectedNotifications(description,
3);
9960 // ab\ncd\nef\ngh\n[]
9961 description = aDescription +
"setting the value property to 'ab\ncd\nef\ngh\n'";
9962 waitNotifications = promiseReceiveNotifications();
9963 aElement.value =
"ab\ncd\nef\ngh\n";
9964 await waitNotifications;
9965 ensureToRemovePrecedingPositionChangeNotification();
9966 checkTextChangeNotification(notifications[
0], description, { offset:
0, removedLength:
2, addedLength: getNativeText(
"ab\ncd\nef\ngh\n").length });
9967 checkSelectionChangeNotification(notifications[
1], description, { offset: getNativeText(
"ab\ncd\nef\ngh\n").length, text:
"" });
9968 checkPositionChangeNotification(notifications[
2], description);
9969 ensureToRemovePostPositionChangeNotification(description,
3);
9970 dumpUnexpectedNotifications(description,
3);
9973 description = aDescription +
"setting the value property to ''";
9974 waitNotifications = promiseReceiveNotifications();
9975 aElement.value =
"";
9976 await waitNotifications;
9977 ensureToRemovePrecedingPositionChangeNotification();
9978 checkTextChangeNotification(notifications[
0], description, { offset:
0, removedLength: getNativeText(
"ab\ncd\nef\ngh\n").length, addedLength:
0 });
9979 checkSelectionChangeNotification(notifications[
1], description, { offset:
0, text:
"" });
9980 checkPositionChangeNotification(notifications[
2], description);
9981 ensureToRemovePostPositionChangeNotification(description,
3);
9982 dumpUnexpectedNotifications(description,
3);
9985 async function testWithHTMLEditor(aDescription, aElement, aDefaultParagraphSeparator)
9987 let doc = aElement.ownerDocument;
9988 let win = doc.defaultView;
9989 let sel = doc.getSelection();
9990 let inDesignMode = doc.designMode ==
"on";
9991 let offsetAtStart =
0;
9992 let offsetAtContainer =
0;
9993 let isDefaultParagraphSeparatorBlock = aDefaultParagraphSeparator !=
"br";
9994 doc.execCommand(
"defaultParagraphSeparator", false, aDefaultParagraphSeparator);
9996 //
"[]",
"<p>[]</p>" or
"<div>[]</div>"
9997 switch (aDefaultParagraphSeparator) {
9999 aElement.innerHTML =
"";
10003 aElement.innerHTML =
"<" + aDefaultParagraphSeparator +
"></" + aDefaultParagraphSeparator +
">";
10004 sel.collapse(aElement.firstChild,
0);
10005 offsetAtContainer = offsetAtStart + kLFLen;
10008 ok(false, aDescription +
"aDefaultParagraphSeparator is illegal value");
10009 await flushNotifications();
10013 if (inDesignMode) {
10018 await flushNotifications();
10021 let description = aDescription +
"typing 'a'";
10022 let waitNotifications = promiseReceiveNotifications();
10023 synthesizeKey(
"a", {}, win, callback);
10024 await waitNotifications;
10025 ensureToRemovePrecedingPositionChangeNotification();
10026 checkTextChangeNotification(notifications[
0], description, { offset:
0 + offsetAtContainer, removedLength:
0, addedLength:
1 });
10027 checkSelectionChangeNotification(notifications[
1], description, { offset:
1 + offsetAtContainer, text:
"" });
10028 checkPositionChangeNotification(notifications[
2], description);
10029 dumpUnexpectedNotifications(description,
3);
10032 description = aDescription +
"typing 'b'";
10033 waitNotifications = promiseReceiveNotifications();
10034 synthesizeKey(
"b", {}, win, callback);
10035 await waitNotifications;
10036 ensureToRemovePrecedingPositionChangeNotification();
10037 checkTextChangeNotification(notifications[
0], description, { offset:
1 + offsetAtContainer, removedLength:
0, addedLength:
1 });
10038 checkSelectionChangeNotification(notifications[
1], description, { offset:
2 + offsetAtContainer, text:
"" });
10039 checkPositionChangeNotification(notifications[
2], description);
10040 dumpUnexpectedNotifications(description,
3);
10043 description = aDescription +
"typing 'c'";
10044 waitNotifications = promiseReceiveNotifications();
10045 synthesizeKey(
"c", {}, win, callback);
10046 await waitNotifications;
10047 ensureToRemovePrecedingPositionChangeNotification();
10048 checkTextChangeNotification(notifications[
0], description, { offset:
2 + offsetAtContainer, removedLength:
0, addedLength:
1 });
10049 checkSelectionChangeNotification(notifications[
1], description, { offset:
3 + offsetAtContainer, text:
"" });
10050 checkPositionChangeNotification(notifications[
2], description);
10051 dumpUnexpectedNotifications(description,
3);
10054 description = aDescription +
"selecting 'c' with pressing Shift+ArrowLeft";
10055 waitNotifications = promiseReceiveNotifications();
10056 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
10057 await waitNotifications;
10058 ensureToRemovePrecedingPositionChangeNotification();
10059 checkSelectionChangeNotification(notifications[
0], description, { offset:
2 + offsetAtContainer, text:
"c", reversed: true });
10060 dumpUnexpectedNotifications(description,
1);
10063 description = aDescription +
"selecting 'bc' with pressing Shift+ArrowLeft";
10064 waitNotifications = promiseReceiveNotifications();
10065 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
10066 await waitNotifications;
10067 ensureToRemovePrecedingPositionChangeNotification();
10068 checkSelectionChangeNotification(notifications[
0], description, { offset:
1 + offsetAtContainer, text:
"bc", reversed: true });
10069 dumpUnexpectedNotifications(description,
1);
10072 description = aDescription +
"selecting 'bc' with pressing Shift+ArrowLeft";
10073 waitNotifications = promiseReceiveNotifications();
10074 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
10075 await waitNotifications;
10076 ensureToRemovePrecedingPositionChangeNotification();
10077 checkSelectionChangeNotification(notifications[
0], description, { offset:
0 + offsetAtContainer, text:
"abc", reversed: true });
10078 dumpUnexpectedNotifications(description,
1);
10081 description = aDescription +
"collapsing selection to the left-most with pressing ArrowLeft";
10082 waitNotifications = promiseReceiveNotifications();
10083 synthesizeKey(
"KEY_ArrowLeft", {}, win, callback);
10084 await waitNotifications;
10085 ensureToRemovePrecedingPositionChangeNotification();
10086 checkSelectionChangeNotification(notifications[
0], description, { offset:
0 + offsetAtContainer, text:
"" });
10087 dumpUnexpectedNotifications(description,
1);
10090 description = aDescription +
"selecting 'a' with pressing Shift+ArrowRight";
10091 waitNotifications = promiseReceiveNotifications();
10092 synthesizeKey(
"KEY_ArrowRight", {shiftKey: true}, win, callback);
10093 await waitNotifications;
10094 ensureToRemovePrecedingPositionChangeNotification();
10095 checkSelectionChangeNotification(notifications[
0], description, { offset:
0 + offsetAtContainer, text:
"a" });
10096 dumpUnexpectedNotifications(description,
1);
10099 description = aDescription +
"selecting 'ab' with pressing Shift+ArrowRight";
10100 waitNotifications = promiseReceiveNotifications();
10101 synthesizeKey(
"KEY_ArrowRight", {shiftKey: true}, win, callback);
10102 await waitNotifications;
10103 ensureToRemovePrecedingPositionChangeNotification();
10104 checkSelectionChangeNotification(notifications[
0], description, { offset:
0 + offsetAtContainer, text:
"ab" });
10105 dumpUnexpectedNotifications(description,
1);
10108 description = aDescription +
"deleting 'ab' with pressing Delete";
10109 waitNotifications = promiseReceiveNotifications();
10110 synthesizeKey(
"KEY_Delete", {}, win, callback);
10111 await waitNotifications;
10112 ensureToRemovePrecedingPositionChangeNotification();
10113 checkTextChangeNotification(notifications[
0], description, { offset:
0 + offsetAtContainer, removedLength:
2, addedLength:
0 });
10114 checkSelectionChangeNotification(notifications[
1], description, { offset:
0 + offsetAtContainer, text:
"" });
10115 checkPositionChangeNotification(notifications[
2], description);
10116 dumpUnexpectedNotifications(description,
3);
10119 description = aDescription +
"deleting following 'c' with pressing Delete";
10120 waitNotifications = promiseReceiveNotifications();
10121 synthesizeKey(
"KEY_Delete", {}, win, callback);
10122 await waitNotifications;
10123 ensureToRemovePrecedingPositionChangeNotification();
10124 checkTextChangeNotification(notifications[
0], description, { offset:
0 + offsetAtContainer, removedLength:
1, addedLength: kLFLen });
10125 checkPositionChangeNotification(notifications[
1], description);
10126 dumpUnexpectedNotifications(description,
2);
10129 synthesizeKey(
"a", {}, win, callback);
10130 synthesizeKey(
"b", {}, win, callback);
10131 synthesizeKey(
"c", {}, win, callback);
10132 await flushNotifications();
10135 description = aDescription +
"deleting 'c' with pressing Backspace";
10136 waitNotifications = promiseReceiveNotifications();
10137 synthesizeKey(
"KEY_Backspace", {}, win, callback);
10138 await waitNotifications;
10139 ensureToRemovePrecedingPositionChangeNotification();
10140 checkTextChangeNotification(notifications[
0], description, { offset:
2 + offsetAtContainer, removedLength:
1, addedLength:
0 });
10141 checkSelectionChangeNotification(notifications[
1], description, { offset:
2 + offsetAtContainer, text:
"" });
10142 checkPositionChangeNotification(notifications[
2], description);
10143 dumpUnexpectedNotifications(description,
3);
10146 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
10147 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
10148 await flushNotifications();
10151 description = aDescription +
"deleting 'ab' with pressing Backspace";
10152 waitNotifications = promiseReceiveNotifications();
10153 synthesizeKey(
"KEY_Backspace", {}, win, callback);
10154 await waitNotifications;
10155 ensureToRemovePrecedingPositionChangeNotification();
10156 checkTextChangeNotification(notifications[
0], description, { offset:
0 + offsetAtContainer, removedLength:
2, addedLength:
0 });
10157 checkSelectionChangeNotification(notifications[
1], description, { offset:
0 + offsetAtContainer, text:
"" });
10158 checkPositionChangeNotification(notifications[
2], description);
10159 dumpUnexpectedNotifications(description,
3);
10162 synthesizeKey(
"a", {}, win, callback);
10163 synthesizeKey(
"b", {}, win, callback);
10164 synthesizeKey(
"c", {}, win, callback);
10165 synthesizeKey(
"d", {}, win, callback);
10166 await flushNotifications();
10169 synthesizeKey(
"KEY_ArrowLeft", {}, win, callback);
10170 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
10171 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
10172 await flushNotifications();
10175 description = aDescription +
"deleting 'bc' with pressing Backspace";
10176 waitNotifications = promiseReceiveNotifications();
10177 synthesizeKey(
"KEY_Backspace", {}, win, callback);
10178 await waitNotifications;
10179 ensureToRemovePrecedingPositionChangeNotification();
10180 checkTextChangeNotification(notifications[
0], description, { offset:
1 + offsetAtContainer, removedLength:
2, addedLength:
0 });
10181 checkSelectionChangeNotification(notifications[
1], description, { offset:
1 + offsetAtContainer, text:
"" });
10182 checkPositionChangeNotification(notifications[
2], description);
10183 dumpUnexpectedNotifications(description,
3);
10186 synthesizeKey(
"b", {}, win, callback);
10187 synthesizeKey(
"c", {}, win, callback);
10188 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
10189 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
10190 await flushNotifications();
10193 description = aDescription +
"replacing 'bc' with 'B' with pressing Shift+B";
10194 waitNotifications = promiseReceiveNotifications();
10195 synthesizeKey(
"B", {shiftKey: true}, win, callback);
10196 await waitNotifications;
10197 ensureToRemovePrecedingPositionChangeNotification();
10198 checkTextChangeNotification(notifications[
0], description, { offset:
1 + offsetAtContainer, removedLength:
2, addedLength:
1 });
10199 checkSelectionChangeNotification(notifications[
1], description, { offset:
2 + offsetAtContainer, text:
"" });
10200 checkPositionChangeNotification(notifications[
2], description);
10201 dumpUnexpectedNotifications(description,
3);
10203 //
"aB<br>[]d" or
"<block>aB</block><block>[]d</block>"
10204 description = aDescription +
"inserting a line break after 'B' with pressing Enter";
10205 waitNotifications = promiseReceiveNotifications();
10206 synthesizeKey(
"KEY_Enter", {}, win, callback);
10207 await waitNotifications;
10208 ensureToRemovePrecedingPositionChangeNotification();
10209 if (isDefaultParagraphSeparatorBlock) {
10210 // Splitting current block causes removing
"d</block>" and inserting
"</block><block>d</block>".
10211 checkTextChangeNotification(notifications[
0], description, {
10212 offset: offsetAtContainer +
"aB".length,
10213 removedLength: getNativeText(
"d\n").length,
10214 addedLength: getNativeText(
"\nd\n").length,
10217 // Inserting
<br> causes removing
"d" and inserting
"<br>d"
10218 checkTextChangeNotification(notifications[
0], description, {
10219 offset: offsetAtContainer +
"aB".length,
10220 removedLength:
"d".length,
10221 addedLength: getNativeText(
"\nd").length,
10224 checkSelectionChangeNotification(notifications[
1], description, { offset: getNativeText(
"aB\n").length + offsetAtContainer, text:
"" });
10225 checkPositionChangeNotification(notifications[
2], description);
10226 dumpUnexpectedNotifications(description,
3);
10229 description = aDescription +
"removing a line break after 'B' with pressing Backspace";
10230 waitNotifications = promiseReceiveNotifications();
10231 synthesizeKey(
"KEY_Backspace", {}, win, callback);
10232 await waitNotifications;
10233 ensureToRemovePrecedingPositionChangeNotification();
10234 if (isDefaultParagraphSeparatorBlock) {
10235 // Joining two blocks causes removing
"aB</block><block>d</block>" and inserting
"aBd</block>"
10236 checkTextChangeNotification(notifications[
0], description, {
10237 offset: offsetAtContainer,
10238 removedLength: getNativeText(
"aB\nd\n").length,
10239 addedLength: getNativeText(
"aBd\n").length,
10241 checkSelectionChangeNotification(notifications[
1], description, { offset:
2 + offsetAtContainer, text:
"" });
10242 checkPositionChangeNotification(notifications[
2], description);
10243 dumpUnexpectedNotifications(description,
3);
10245 checkTextChangeNotification(notifications[
0], description, {
10246 offset: offsetAtContainer +
"aB".length,
10247 removedLength: kLFLen,
10250 is(notifications.length,
3, description +
" should cause 3 notifications");
10251 is(notifications[
1] && notifications[
1].type,
"notify-selection-change", description +
" should cause selection change notification");
10252 is(notifications[
2] && notifications[
2].type,
"notify-position-change", description +
" should cause position change notification");
10256 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
10257 await flushNotifications();
10259 //
"a<br>[]d" or
"<block>a</block><block>[]d</block>"
10260 description = aDescription +
"replacing 'B' with a line break with pressing Enter";
10261 waitNotifications = promiseReceiveNotifications();
10262 synthesizeKey(
"KEY_Enter", {}, win, callback);
10263 await waitNotifications;
10264 ensureToRemovePrecedingPositionChangeNotification();
10265 if (isDefaultParagraphSeparatorBlock) {
10266 // Splitting current block causes removing
"Bd</block>" and inserting
"</block><block>d</block>".
10267 checkTextChangeNotification(notifications[
0], description, {
10268 offset: offsetAtContainer +
"a".length,
10269 removedLength: getNativeText(
"Bd\n").length,
10270 addedLength: getNativeText(
"\nd\n").length,
10273 checkTextChangeNotification(notifications[
0], description, {
10274 offset: offsetAtContainer +
"a".length,
10275 removedLength:
"B".length,
10276 addedLength: kLFLen,
10279 checkSelectionChangeNotification(notifications[
1], description, { offset: getNativeText(
"a\n").length + offsetAtContainer, text:
"" });
10280 checkPositionChangeNotification(notifications[
2], description);
10281 dumpUnexpectedNotifications(description,
3);
10283 //
"a[<br>]d" or
"<block>a[</block><block>]d</block>"
10284 description = aDescription +
"selecting '\\n' with pressing Shift+ArrowLeft";
10285 waitNotifications = promiseReceiveNotifications();
10286 synthesizeKey(
"KEY_ArrowLeft", {shiftKey: true}, win, callback);
10287 await waitNotifications;
10288 ensureToRemovePrecedingPositionChangeNotification();
10289 checkSelectionChangeNotification(notifications[
0], description, { offset:
1 + offsetAtContainer, text: kLF, reversed: true });
10290 dumpUnexpectedNotifications(description,
1);
10293 description = aDescription +
"removing selected '\\n' with pressing Delete";
10294 waitNotifications = promiseReceiveNotifications();
10295 synthesizeKey(
"KEY_Delete", {}, win, callback);
10296 await waitNotifications;
10297 ensureToRemovePrecedingPositionChangeNotification();
10298 if (isDefaultParagraphSeparatorBlock) {
10299 // Joining the blocks causes removing
"a</block><block>d</block>" and inserting
"<block>ad</block>".
10300 checkTextChangeNotification(notifications[
0], description, {
10301 offset: offsetAtContainer,
10302 removedLength: getNativeText(
"a\nd\n").length,
10303 addedLength: getNativeText(
"ad\n").length,
10306 checkTextChangeNotification(notifications[
0], description, {
10307 offset: offsetAtContainer +
"a".length,
10308 removedLength: kLFLen,
10312 checkSelectionChangeNotification(notifications[
1], description, { offset:
1 + offsetAtContainer, text:
"" });
10313 checkPositionChangeNotification(notifications[
2], description);
10314 dumpUnexpectedNotifications(description,
3);
10316 // aElement.innerHTML =
"<div>1<div>2<div>3</div>4</div>5</div>"
10317 description = aDescription +
"inserting HTML which has nested block elements";
10318 waitNotifications = promiseReceiveNotifications();
10319 aElement.innerHTML =
"<div>1<div>2<div>3</div>4</div>5</div>";
10320 await waitNotifications;
10321 ensureToRemovePrecedingPositionChangeNotification();
10322 // There is
<br> after the end of the line. Therefore, removed length includes a line breaker length.
10323 if (isDefaultParagraphSeparatorBlock) {
10324 checkTextChangeNotification(notifications[
0], description, { offset:
0 + offsetAtContainer - kLFLen, removedLength: getNativeText(
"\nad\n").length, addedLength: getNativeText(
"\n1\n2\n345").length });
10326 checkTextChangeNotification(notifications[
0], description, { offset:
0 + offsetAtContainer, removedLength:
2 + kLFLen, addedLength: getNativeText(
"\n1\n2\n345").length });
10328 checkSelectionChangeNotification(notifications[
1], description, { offset:
0, text:
"" });
10329 checkPositionChangeNotification(notifications[
2], description);
10330 dumpUnexpectedNotifications(description,
3);
10332 //
"<div>1[<div>2<div>3</div>4</div>]5</div>" and removing selection
10333 sel.setBaseAndExtent(aElement.firstChild.firstChild,
1, aElement.firstChild.childNodes.item(
2),
0);
10334 await flushNotifications();
10335 description = aDescription +
"deleting child nodes with pressing Delete key";
10336 waitNotifications = promiseReceiveNotifications();
10337 synthesizeKey(
"KEY_Delete", {}, win, callback);
10338 await waitNotifications;
10339 ensureToRemovePrecedingPositionChangeNotification();
10340 is(aElement.innerHTML,
"<div>15</div>", description +
" should remove '<div>2<div>3</div>4</div>'");
10341 checkTextChangeNotification(notifications[
0], description, { offset: getNativeText(
"\n1").length + offsetAtStart, removedLength: getNativeText(
"\n2\n34").length, addedLength:
0 });
10342 checkSelectionChangeNotification(notifications[
1], description, { offset: getNativeText(
"\n1").length + offsetAtStart, text:
"" });
10343 checkPositionChangeNotification(notifications[
2], description);
10344 dumpUnexpectedNotifications(description,
3);
10346 //
"<div>1[<div>2<div>3</div>]4</div>5</div>" and removing selection
10347 aElement.innerHTML =
"<div>1<div>2<div>3</div>4</div>5</div>";
10348 sel.setBaseAndExtent(aElement.firstChild.firstChild,
1, aElement.firstChild.childNodes.item(
1).childNodes.item(
2),
0);
10349 await flushNotifications();
10350 description = aDescription +
"deleting child nodes (partially #1) with pressing Delete key";
10351 waitNotifications = promiseReceiveNotifications();
10352 synthesizeKey(
"KEY_Delete", {}, win, callback);
10353 await waitNotifications;
10354 ensureToRemovePrecedingPositionChangeNotification();
10355 is(aElement.innerHTML,
"<div>145</div>", description +
" should remove '<div>2<div>3</div></div>'");
10356 // It causes removing '
<div>2<div>3</div>4</div>' and inserting '
4'.
10357 checkTextChangeNotification(notifications[
0], description, { offset: getNativeText(
"\n1").length + offsetAtStart, removedLength: getNativeText(
"\n2\n34").length, addedLength:
1 });
10358 checkSelectionChangeNotification(notifications[
1], description, { offset: getNativeText(
"\n1").length + offsetAtStart, text:
"" });
10359 checkPositionChangeNotification(notifications[
2], description);
10360 dumpUnexpectedNotifications(description,
3);
10362 //
"<div>1[<div>2<div>]3</div>4</div>5</div>" and removing selection
10363 aElement.innerHTML =
"<div>1<div>2<div>3</div>4</div>5</div>";
10364 sel.setBaseAndExtent(aElement.firstChild.firstChild,
1, aElement.firstChild.childNodes.item(
1).childNodes.item(
1).firstChild,
0);
10365 await flushNotifications();
10366 description = aDescription +
"deleting child nodes (partially #2) with pressing Delete key";
10367 waitNotifications = promiseReceiveNotifications();
10368 synthesizeKey(
"KEY_Delete", {}, win, callback);
10369 await waitNotifications;
10370 ensureToRemovePrecedingPositionChangeNotification();
10371 is(aElement.innerHTML,
"<div>13<div>4</div>5</div>", description +
" should remove '<div>2</div>'");
10372 // It causes removing '
1<div>2<div>3</div></div>' and inserting '
13<div>'.
10373 checkTextChangeNotification(notifications[
0], description, { offset: kLFLen + offsetAtStart, removedLength: getNativeText(
"1\n2\n3").length, addedLength: getNativeText(
"13\n").length });
10374 checkSelectionChangeNotification(notifications[
1], description, { offset: getNativeText(
"\n1").length + offsetAtStart, text:
"" });
10375 checkPositionChangeNotification(notifications[
2], description);
10376 dumpUnexpectedNotifications(description,
3);
10378 //
"<div>1<div>2<div>3[</div>4</div>]5</div>" and removing selection
10379 aElement.innerHTML =
"<div>1<div>2<div>3</div>4</div>5</div>";
10380 sel.setBaseAndExtent(aElement.firstChild.childNodes.item(
1).childNodes.item(
1).firstChild,
1, aElement.firstChild.childNodes.item(
2),
0);
10381 await flushNotifications();
10382 description = aDescription +
"deleting child nodes (partially #3) with pressing Delete key";
10383 waitNotifications = promiseReceiveNotifications();
10384 synthesizeKey(
"KEY_Delete", {}, win, callback);
10385 await waitNotifications;
10386 ensureToRemovePrecedingPositionChangeNotification();
10387 is(aElement.innerHTML,
"<div>1<div>2<div>35</div></div></div>", description +
" should remove '4'");
10388 // It causes removing '
45' and inserting '
5'.
10389 checkTextChangeNotification(notifications[
0], description, { offset: getNativeText(
"\n1\n2\n3").length + offsetAtStart, removedLength:
2, addedLength:
1 });
10390 checkSelectionChangeNotification(notifications[
1], description, { offset: getNativeText(
"\n1\n2\n3").length + offsetAtStart, text:
"" });
10391 checkPositionChangeNotification(notifications[
2], description);
10392 dumpUnexpectedNotifications(description,
3);
10394 // aElement.innerHTML =
"<div>1<div>2<div>3</div>4</div>5<div>6<div>7</div>8</div>9</div>"
10395 description = aDescription +
"inserting HTML which has a pair of nested block elements";
10396 waitNotifications = promiseReceiveNotifications();
10397 aElement.innerHTML =
"<div>1<div>2<div>3</div>4</div>5<div>6<div>7</div>8</div>9</div>";
10398 await waitNotifications;
10399 ensureToRemovePrecedingPositionChangeNotification();
10400 checkTextChangeNotification(notifications[
0], description, { offset:
0 + offsetAtStart, removedLength: getNativeText(
"\n1\n2\n35").length, addedLength: getNativeText(
"\n1\n2\n345\n6\n789").length });
10401 checkSelectionChangeNotification(notifications[
1], description, { offset:
0 + offsetAtStart, text:
"" });
10402 checkPositionChangeNotification(notifications[
2], description);
10403 dumpUnexpectedNotifications(description,
3);
10405 //
"<div>1<div>2<div>3[</div>4</div>5<div>6<div>]7</div>8</div>9</div>" and removing selection
10406 sel.setBaseAndExtent(aElement.firstChild.childNodes.item(
1).childNodes.item(
1).firstChild,
1, aElement.firstChild.childNodes.item(
3).childNodes.item(
1).firstChild,
0);
10407 await flushNotifications();
10408 description = aDescription +
"deleting child nodes (between same level descendants) with pressing Delete key";
10409 waitNotifications = promiseReceiveNotifications();
10410 synthesizeKey(
"KEY_Delete", {}, win, callback);
10411 await waitNotifications;
10412 ensureToRemovePrecedingPositionChangeNotification();
10413 is(aElement.innerHTML,
"<div>1<div>2<div>37</div></div><div>8</div>9</div>", description +
" should remove '456<div>7'");
10414 // It causes removing '
<div>3</div>4</div>5<div>6<div>7</div>' and inserting '
<div>37</div><div>'.
10415 checkTextChangeNotification(notifications[
0], description, { offset: getNativeText(
"\n1\n2").length + offsetAtStart, removedLength: getNativeText(
"\n345\n6\n7").length, addedLength: getNativeText(
"\n37\n").length });
10416 checkSelectionChangeNotification(notifications[
1], description, { offset: getNativeText(
"\n1\n2\n3").length + offsetAtStart, text:
"" });
10417 checkPositionChangeNotification(notifications[
2], description);
10418 dumpUnexpectedNotifications(description,
3);
10420 //
"<div>1<div>2[<div>3</div>4</div>5<div>6<div>]7</div>8</div>9</div>" and removing selection
10421 aElement.innerHTML =
"<div>1<div>2<div>3</div>4</div>5<div>6<div>7</div>8</div>9</div>";
10422 sel.setBaseAndExtent(aElement.firstChild.childNodes.item(
1).firstChild,
1, aElement.firstChild.childNodes.item(
3).childNodes.item(
1).firstChild,
0);
10423 await flushNotifications();
10424 description = aDescription +
"deleting child nodes (between different level descendants #1) with pressing Delete key";
10425 waitNotifications = promiseReceiveNotifications();
10426 synthesizeKey(
"KEY_Delete", {}, win, callback);
10427 await waitNotifications;
10428 ensureToRemovePrecedingPositionChangeNotification();
10429 is(aElement.innerHTML,
"<div>1<div>27</div><div>8</div>9</div>", description +
" should remove '<div>2<div>3</div>4</div>5<div>6<div>7</div>'");
10430 // It causes removing '
<div>2<div>3</div>4</div>5<div>6<div>7</div>' and inserting '
<div>27</div>'.
10431 checkTextChangeNotification(notifications[
0], description, { offset: getNativeText(
"\n1").length + offsetAtStart, removedLength: getNativeText(
"\n2\n345\n6\n7").length, addedLength: getNativeText(
"\n27\n").length });
10432 checkSelectionChangeNotification(notifications[
1], description, { offset: getNativeText(
"\n1\n2").length + offsetAtStart, text:
"" });
10433 checkPositionChangeNotification(notifications[
2], description);
10434 dumpUnexpectedNotifications(description,
3);
10436 //
"<div>1<div>2[<div>3</div>4</div>5<div>6<div>7</div>8</div>]9</div>" and removing selection
10437 aElement.innerHTML =
"<div>1<div>2<div>3</div>4</div>5<div>6<div>7</div>8</div>9</div>";
10438 sel.setBaseAndExtent(aElement.firstChild.childNodes.item(
1).firstChild,
1, aElement.firstChild.childNodes.item(
4),
0);
10439 await flushNotifications();
10440 description = aDescription +
"deleting child nodes (between different level descendants #2) with pressing Delete key";
10441 waitNotifications = promiseReceiveNotifications();
10442 synthesizeKey(
"KEY_Delete", {}, win, callback);
10443 await waitNotifications;
10444 ensureToRemovePrecedingPositionChangeNotification();
10445 is(aElement.innerHTML,
"<div>1<div>29</div></div>", description +
" should remove '<div>3</div>4</div>5<div>6<div>7</div>8</div>'");
10446 // It causes removing '
<div>3</div>4</div>5</div>6<div>7</div>8</div>9' and inserting '
9</div>'.
10447 checkTextChangeNotification(notifications[
0], description, { offset: getNativeText(
"\n1\n2").length + offsetAtStart, removedLength: getNativeText(
"\n345\n6\n789").length, addedLength:
1 });
10448 checkSelectionChangeNotification(notifications[
1], description, { offset: getNativeText(
"\n1\n2").length + offsetAtStart, text:
"" });
10449 checkPositionChangeNotification(notifications[
2], description);
10450 dumpUnexpectedNotifications(description,
3);
10452 //
"<div>1<div>2<div>3[</div>4</div>5<div>]6<div>7</div>8</div>9</div>" and removing selection
10453 aElement.innerHTML =
"<div>1<div>2<div>3</div>4</div>5<div>6<div>7</div>8</div>9</div>";
10454 sel.setBaseAndExtent(aElement.firstChild.childNodes.item(
1).childNodes.item(
1).firstChild,
1, aElement.firstChild.childNodes.item(
3).firstChild,
0);
10455 await flushNotifications();
10456 description = aDescription +
"deleting child nodes (between different level descendants #3) with pressing Delete key";
10457 waitNotifications = promiseReceiveNotifications();
10458 synthesizeKey(
"KEY_Delete", {}, win, callback);
10459 await waitNotifications;
10460 ensureToRemovePrecedingPositionChangeNotification();
10461 is(aElement.innerHTML,
"<div>1<div>2<div>36<div>7</div>8</div></div>9</div>", description +
" should remove '<div>36<div>7</div>8</div>'");
10462 // It causes removing '
<div>3</div>4</div>5<div>6<div>7</div>8</div>' and inserting '
<div>36<div>7</div>8</div>'.
10463 checkTextChangeNotification(notifications[
0], description, { offset: getNativeText(
"\n1\n2").length + offsetAtStart, removedLength: getNativeText(
"\n345\n6\n78").length, addedLength: getNativeText(
"\n36\n78").length });
10464 checkSelectionChangeNotification(notifications[
1], description, { offset: getNativeText(
"\n1\n2\n3").length + offsetAtStart, text:
"" });
10465 checkPositionChangeNotification(notifications[
2], description);
10466 dumpUnexpectedNotifications(description,
3);
10468 //
"<div>1<div>2<div>3[</div>4</div>5<div>6<div>7</div>8</div>]9</div>" and removing selection
10469 aElement.innerHTML =
"<div>1<div>2<div>3</div>4</div>5<div>6<div>7</div>8</div>9</div>";
10470 sel.setBaseAndExtent(aElement.firstChild.childNodes.item(
1).childNodes.item(
1).firstChild,
1, aElement.firstChild.childNodes.item(
4),
0);
10471 await flushNotifications();
10472 description = aDescription +
"deleting child nodes (between different level descendants #4) with pressing Delete key";
10473 waitNotifications = promiseReceiveNotifications();
10474 synthesizeKey(
"KEY_Delete", {}, win, callback);
10475 await waitNotifications;
10476 ensureToRemovePrecedingPositionChangeNotification();
10477 is(aElement.innerHTML,
"<div>1<div>2<div>39</div></div></div>", description +
" should remove '</div>4</div>5<div>6<div>7</div>8</div>'");
10478 // It causes removing '
</div>4</div>5<div>6<div>7</div>8</div>' and inserting '
<div>36<div>7</div>8</div>'.
10479 checkTextChangeNotification(notifications[
0], description, { offset: getNativeText(
"\n1\n2\n3").length + offsetAtStart, removedLength: getNativeText(
"45\n6\n789").length, addedLength: getNativeText(
"9").length });
10480 checkSelectionChangeNotification(notifications[
1], description, { offset: getNativeText(
"\n1\n2\n3").length + offsetAtStart, text:
"" });
10481 checkPositionChangeNotification(notifications[
2], description);
10482 dumpUnexpectedNotifications(description,
3);
10484 //
"<p>abc</p><p><br></p><p>{<br>}</p>" and removing second paragraph with DOM API
10485 aElement.innerHTML =
"<p>abc</p><p><br></p><p><br></p>";
10486 sel.collapse(aElement.firstChild.nextSibling.nextSibling,
0);
10487 await flushNotifications();
10488 description = aDescription +
"deleting previous paragraph with DOM API";
10489 waitNotifications = promiseReceiveNotifications();
10490 synthesizeKey(
"KEY_Unidentified", { code:
"" }, win, callback); // For setting the callback to recode notifications
10491 aElement.firstChild.nextSibling.remove();
10492 await waitNotifications;
10493 ensureToRemovePrecedingPositionChangeNotification();
10494 is(aElement.innerHTML,
"<p>abc</p><p><br></p>", description +
" the second paragraph should've been removed");
10495 checkTextChangeNotification(notifications[
0], description, { offset: getNativeText(
"\nabc").length + offsetAtStart, removedLength: getNativeText(
"\n\n").length, addedLength:
0 });
10496 checkSelectionChangeNotification(notifications[
1], description, { offset: getNativeText(
"\nabc\n").length + offsetAtStart, text:
"" });
10497 checkPositionChangeNotification(notifications[
2], description);
10498 dumpUnexpectedNotifications(description,
3);
10500 //
"<p>abc</p><p>{<br>}</p><p><br></p>" and removing last paragraph with DOM API
10501 aElement.innerHTML =
"<p>abc</p><p><br></p><p><br></p>";
10502 sel.collapse(aElement.firstChild.nextSibling,
0);
10503 await flushNotifications();
10504 description = aDescription +
"deleting next paragraph with DOM API";
10505 waitNotifications = promiseReceiveNotifications();
10506 synthesizeKey(
"KEY_Unidentified", { code:
"" }, win, callback); // For setting the callback to recode notifications
10507 aElement.firstChild.nextSibling.nextSibling.remove();
10508 await waitNotifications;
10509 ensureToRemovePrecedingPositionChangeNotification();
10510 is(aElement.innerHTML,
"<p>abc</p><p><br></p>", description +
" the last paragraph should've been removed");
10511 checkTextChangeNotification(notifications[
0], description, { offset: getNativeText(
"\nabc\n\n").length + offsetAtStart, removedLength: getNativeText(
"\n\n").length, addedLength:
0 });
10512 checkPositionChangeNotification(notifications[
1], description);
10513 dumpUnexpectedNotifications(description,
2);
10516 await testWithPlaintextEditor(
"runIMEContentObserverTest with input element: ", input, false);
10517 await testWithPlaintextEditor(
"runIMEContentObserverTest with textarea element: ", textarea, true);
10518 await testWithHTMLEditor(
"runIMEContentObserverTest with contenteditable (defaultParagraphSeparator is br): ", contenteditable,
"br");
10519 await testWithHTMLEditor(
"runIMEContentObserverTest with contenteditable (defaultParagraphSeparator is p): ", contenteditable,
"p");
10520 await testWithHTMLEditor(
"runIMEContentObserverTest with contenteditable (defaultParagraphSeparator is div): ", contenteditable,
"div");
10521 // XXX Due to the difference of HTML editor behavior between designMode and contenteditable,
10522 // testWithHTMLEditor() gets some unexpected behavior. However, IMEContentObserver is
10523 // not depend on editor's detail. So, we should investigate this issue later. It's not
10524 // so important for now.
10525 // await testWithHTMLEditor(
"runIMEContentObserverTest in designMode (defaultParagraphSeparator is br): ", iframe2.contentDocument.body,
"br");
10526 // await testWithHTMLEditor(
"runIMEContentObserverTest in designMode (defaultParagraphSeparator is p): ", iframe2.contentDocument.body,
"p");
10527 // await testWithHTMLEditor(
"runIMEContentObserverTest in designMode (defaultParagraphSeparator is div): ", iframe2.contentDocument.body,
"div");
10530 async function runPasswordMaskDelayTest() {
10531 await SpecialPowers.pushPrefEnv({
10532 set: [[
"editor.password.mask_delay",
600],
10533 [
"editor.password.testing.mask_delay", true],
10537 let iframe5 = document.getElementById(
"iframe5");
10538 let iframe6 = document.getElementById(
"iframe6");
10539 let inputWindow = iframe5.contentWindow;
10540 let passwordWindow = iframe6.contentWindow;
10542 let inputElement = iframe5.contentDocument.getElementById(
"input");
10543 let passwordElement = iframe6.contentDocument.getElementById(
"password");
10545 const kMask = passwordElement.editor.passwordMask;
10547 function promiseAllPasswordMasked() {
10548 return new Promise(resolve =
> {
10549 passwordElement.addEventListener(
"MozLastInputMasked", resolve, {once: true});
10553 function checkSnapshots(aResult, aReference, aMatch, aDescription) {
10554 let [correct, data1, data2] = compareSnapshots(aResult, aReference, true);
10555 is(correct, aMatch, `${aDescription}\nREFTEST IMAGE
1 (TEST): ${data1}\nREFTEST IMAGE
2 (REFERENCE): ${data2}`);
10558 // First character input
10559 passwordElement.value =
"";
10560 passwordElement.focus();
10561 let waitForMaskingLastInput = promiseAllPasswordMasked();
10562 synthesizeKey(
"a");
10563 let unmaskedResult = await snapshotWindow(passwordWindow, true);
10564 await waitForMaskingLastInput;
10565 let maskedResult = await snapshotWindow(passwordWindow, true);
10567 inputElement.value =
"a";
10568 inputElement.focus();
10569 inputElement.setSelectionRange(
1,
1);
10570 let unmaskedReference = await snapshotWindow(inputWindow, true);
10571 inputElement.value = kMask;
10572 inputElement.setSelectionRange(
1,
1);
10573 let maskedReference = await snapshotWindow(inputWindow, true);
10574 checkSnapshots(unmaskedResult, unmaskedReference, true,
10575 "runPasswordMaskDelayTest(): first inputted character should be unmasked for a while");
10576 checkSnapshots(maskedResult, maskedReference, true,
10577 "runPasswordMaskDelayTest(): first inputted character should be masked after a while");
10579 // Second character input
10580 passwordElement.value =
"a";
10581 passwordElement.focus();
10582 passwordElement.setSelectionRange(
1,
1);
10583 waitForMaskingLastInput = promiseAllPasswordMasked();
10584 synthesizeKey(
"b");
10585 unmaskedResult = await snapshotWindow(passwordWindow, true);
10586 await waitForMaskingLastInput;
10587 maskedResult = await snapshotWindow(passwordWindow, true);
10589 inputElement.value = `${kMask}b`;
10590 inputElement.focus();
10591 inputElement.setSelectionRange(
2,
2);
10592 unmaskedReference = await snapshotWindow(inputWindow, true);
10593 inputElement.value = `${kMask}${kMask}`;
10594 inputElement.setSelectionRange(
2,
2);
10595 maskedReference = await snapshotWindow(inputWindow, true);
10596 checkSnapshots(unmaskedResult, unmaskedReference, true,
10597 "runPasswordMaskDelayTest(): second inputted character should be unmasked for a while");
10598 checkSnapshots(maskedResult, maskedReference, true,
10599 "runPasswordMaskDelayTest(): second inputted character should be masked after a while");
10601 // Typing new character should mask the previous unmasked characters
10602 passwordElement.value =
"ab";
10603 passwordElement.focus();
10604 passwordElement.setSelectionRange(
2,
2);
10605 waitForMaskingLastInput = promiseAllPasswordMasked();
10606 synthesizeKey(
"c");
10607 synthesizeKey(
"d");
10608 unmaskedResult = await snapshotWindow(passwordWindow, true);
10609 await waitForMaskingLastInput;
10610 maskedResult = await snapshotWindow(passwordWindow, true);
10612 inputElement.value = `${kMask}${kMask}${kMask}d`;
10613 inputElement.focus();
10614 inputElement.setSelectionRange(
4,
4);
10615 unmaskedReference = await snapshotWindow(inputWindow, true);
10616 inputElement.value = `${kMask}${kMask}${kMask}${kMask}`;
10617 inputElement.setSelectionRange(
4,
4);
10618 maskedReference = await snapshotWindow(inputWindow, true);
10619 checkSnapshots(unmaskedResult, unmaskedReference, true,
10620 "runPasswordMaskDelayTest(): forth character input should mask the third character");
10621 checkSnapshots(maskedResult, maskedReference, true,
10622 "runPasswordMaskDelayTest(): forth inputted character should be masked after a while");
10624 // Typing middle of password should unmask the last input character
10625 passwordElement.value =
"abcd";
10626 passwordElement.focus();
10627 passwordElement.setSelectionRange(
2,
2);
10628 waitForMaskingLastInput = promiseAllPasswordMasked();
10629 synthesizeKey(
"e");
10630 unmaskedResult = await snapshotWindow(passwordWindow, true);
10631 await waitForMaskingLastInput;
10632 maskedResult = await snapshotWindow(passwordWindow, true);
10634 inputElement.value = `${kMask}${kMask}e${kMask}${kMask}`;
10635 inputElement.focus();
10636 inputElement.setSelectionRange(
3,
3);
10637 unmaskedReference = await snapshotWindow(inputWindow, true);
10638 inputElement.value = `${kMask}${kMask}${kMask}${kMask}${kMask}`;
10639 inputElement.setSelectionRange(
3,
3);
10640 maskedReference = await snapshotWindow(inputWindow, true);
10641 checkSnapshots(unmaskedResult, unmaskedReference, true,
10642 "runPasswordMaskDelayTest(): inserted character should be unmasked for a while");
10643 checkSnapshots(maskedResult, maskedReference, true,
10644 "runPasswordMaskDelayTest(): inserted character should be masked after a while");
10646 // Composition string should be unmasked for a while, and shouldn't be committed at masking
10647 passwordElement.value =
"ab";
10648 passwordElement.focus();
10649 passwordElement.setSelectionRange(
1,
1);
10650 waitForMaskingLastInput = promiseAllPasswordMasked();
10651 synthesizeCompositionChange(
10654 clauses: [{ length:
1, attr: COMPOSITION_ATTR_RAW_CLAUSE }],
10656 caret: { start:
1, length:
0 },
10658 unmaskedResult = await snapshotWindow(passwordWindow, true);
10659 await waitForMaskingLastInput;
10660 maskedResult = await snapshotWindow(passwordWindow, true);
10661 is(getEditor(passwordElement).composing, true,
10662 "runPasswordMaskDelayTest(): composition shouldn't be commited at masking the composing string #1");
10663 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"KEY_Enter" } });
10665 inputElement.value = `${kMask}${kMask}`;
10666 inputElement.focus();
10667 inputElement.setSelectionRange(
1,
1);
10668 synthesizeCompositionChange(
10671 clauses: [{ length:
1, attr: COMPOSITION_ATTR_RAW_CLAUSE }],
10673 caret: { start:
1, length:
0 },
10675 unmaskedReference = await snapshotWindow(inputWindow, true);
10676 synthesizeCompositionChange(
10679 clauses: [{ length:
1, attr: COMPOSITION_ATTR_RAW_CLAUSE }],
10681 caret: { start:
1, length:
0 },
10683 maskedReference = await snapshotWindow(inputWindow, true);
10684 checkSnapshots(unmaskedResult, unmaskedReference, true,
10685 "runPasswordMaskDelayTest(): composing character should be unmasked for a while");
10686 checkSnapshots(maskedResult, maskedReference, true,
10687 "runPasswordMaskDelayTest(): composing character should be masked after a while");
10688 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"KEY_Enter" } });
10690 // Updating composition string should unmask the composition string for a while
10691 passwordElement.value =
"ab";
10692 passwordElement.focus();
10693 passwordElement.setSelectionRange(
1,
1);
10694 waitForMaskingLastInput = promiseAllPasswordMasked();
10695 synthesizeCompositionChange(
10698 clauses: [{ length:
1, attr: COMPOSITION_ATTR_RAW_CLAUSE }],
10700 caret: { start:
1, length:
0 },
10702 await waitForMaskingLastInput;
10703 waitForMaskingLastInput = promiseAllPasswordMasked();
10704 synthesizeCompositionChange(
10707 clauses: [{ length:
1, attr: COMPOSITION_ATTR_RAW_CLAUSE }],
10709 caret: { start:
1, length:
0 },
10711 unmaskedResult = await snapshotWindow(passwordWindow, true);
10712 await waitForMaskingLastInput;
10713 maskedResult = await snapshotWindow(passwordWindow, true);
10714 is(getEditor(passwordElement).composing, true,
10715 "runPasswordMaskDelayTest(): composition shouldn't be commited at masking the composing string #2");
10716 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"KEY_Enter" } });
10718 inputElement.value = `${kMask}${kMask}`;
10719 inputElement.focus();
10720 inputElement.setSelectionRange(
1,
1);
10721 synthesizeCompositionChange(
10724 clauses: [{ length:
1, attr: COMPOSITION_ATTR_RAW_CLAUSE }],
10726 caret: { start:
1, length:
0 },
10728 unmaskedReference = await snapshotWindow(inputWindow, true);
10729 synthesizeCompositionChange(
10732 clauses: [{ length:
1, attr: COMPOSITION_ATTR_RAW_CLAUSE }],
10734 caret: { start:
1, length:
0 },
10736 maskedReference = await snapshotWindow(inputWindow, true);
10737 checkSnapshots(unmaskedResult, unmaskedReference, true,
10738 "runPasswordMaskDelayTest(): updated composing character should be unmasked for a while");
10739 checkSnapshots(maskedResult, maskedReference, true,
10740 "runPasswordMaskDelayTest(): updated composing character should be masked after a while");
10741 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"KEY_Enter" } });
10743 // Composing multi-characters should be unmasked for a while.
10744 passwordElement.value =
"ab";
10745 passwordElement.focus();
10746 passwordElement.setSelectionRange(
1,
1);
10747 waitForMaskingLastInput = promiseAllPasswordMasked();
10748 synthesizeCompositionChange(
10751 clauses: [{ length:
1, attr: COMPOSITION_ATTR_RAW_CLAUSE }],
10753 caret: { start:
1, length:
0 },
10755 await waitForMaskingLastInput;
10756 waitForMaskingLastInput = promiseAllPasswordMasked();
10757 synthesizeCompositionChange(
10760 clauses: [{ length:
2, attr: COMPOSITION_ATTR_RAW_CLAUSE }],
10762 caret: { start:
2, length:
0 },
10764 unmaskedResult = await snapshotWindow(passwordWindow, true);
10765 await waitForMaskingLastInput;
10766 maskedResult = await snapshotWindow(passwordWindow, true);
10767 is(getEditor(passwordElement).composing, true,
10768 "runPasswordMaskDelayTest(): composition shouldn't be commited at masking the composing string #3");
10769 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"KEY_Enter" } });
10771 inputElement.value = `${kMask}${kMask}`;
10772 inputElement.focus();
10773 inputElement.setSelectionRange(
1,
1);
10774 synthesizeCompositionChange(
10777 clauses: [{ length:
2, attr: COMPOSITION_ATTR_RAW_CLAUSE }],
10779 caret: { start:
2, length:
0 },
10781 unmaskedReference = await snapshotWindow(inputWindow, true);
10782 synthesizeCompositionChange(
10784 { string: `${kMask}${kMask}`,
10785 clauses: [{ length:
2, attr: COMPOSITION_ATTR_RAW_CLAUSE }],
10787 caret: { start:
2, length:
0 },
10789 maskedReference = await snapshotWindow(inputWindow, true);
10790 checkSnapshots(unmaskedResult, unmaskedReference, true,
10791 "runPasswordMaskDelayTest(): all of composing string should be unmasked for a while");
10792 checkSnapshots(maskedResult, maskedReference, true,
10793 "runPasswordMaskDelayTest(): all of composing string should be masked after a while");
10794 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"KEY_Enter" } });
10796 // Committing composition should make the commit string unmasked.
10797 passwordElement.value =
"ab";
10798 passwordElement.focus();
10799 passwordElement.setSelectionRange(
1,
1);
10800 waitForMaskingLastInput = promiseAllPasswordMasked();
10801 synthesizeCompositionChange(
10804 clauses: [{ length:
2, attr: COMPOSITION_ATTR_RAW_CLAUSE }],
10806 caret: { start:
2, length:
0 },
10808 await waitForMaskingLastInput;
10809 waitForMaskingLastInput = promiseAllPasswordMasked();
10810 synthesizeComposition({ type:
"compositioncommitasis", key: { key:
"KEY_Enter" } });
10811 unmaskedResult = await snapshotWindow(passwordWindow, true);
10812 await waitForMaskingLastInput;
10813 maskedResult = await snapshotWindow(passwordWindow, true);
10815 inputElement.value = `${kMask}cd${kMask}`;
10816 inputElement.focus();
10817 inputElement.setSelectionRange(
3,
3);
10818 unmaskedReference = await snapshotWindow(inputWindow, true);
10819 inputElement.value = `${kMask}${kMask}${kMask}${kMask}`;
10820 inputElement.setSelectionRange(
3,
3);
10821 maskedReference = await snapshotWindow(inputWindow, true);
10822 checkSnapshots(unmaskedResult, unmaskedReference, true,
10823 "runPasswordMaskDelayTest(): committed string should be unmasked for a while");
10824 checkSnapshots(maskedResult, maskedReference, true,
10825 "runPasswordMaskDelayTest(): committed string should be masked after a while");
10828 async function runInputModeTest()
10832 function handler(aEvent)
10834 result.push(aEvent);
10837 textarea.inputMode =
"text";
10838 textarea.value =
"";
10841 textarea.addEventListener(
"compositionupdate", handler, true);
10842 textarea.addEventListener(
"compositionend", handler, true);
10844 synthesizeCompositionChange({
10845 composition: {string:
"a ", clauses: [{length:
2, attr: COMPOSITION_ATTR_RAW_CLAUSE}]},
10848 is(result[
0].type,
"compositionupdate",
"Set initial composition for inputmode test");
10851 textarea.inputMode =
"tel";
10852 is(result.length,
0,
"No compositonend event even if inputmode is updated");
10855 synthesizeComposition({ type:
"compositioncommitasis" });
10856 textarea.inputMode =
"";
10857 textarea.value =
"";
10858 textarea.removeEventListener(
"compositionupdate", handler, true);
10859 textarea.removeEventListener(
"compositionend", handler, true);
10863 async function runTest()
10865 window.addEventListener(
"unload", window.arguments[
0].SimpleTest.finish, {once: true, capture: true});
10867 contenteditable = document.getElementById(
"iframe4").contentDocument.getElementById(
"contenteditable");
10868 windowOfContenteditable = document.getElementById(
"iframe4").contentWindow;
10869 textareaInFrame = iframe.contentDocument.getElementById(
"textarea");
10871 contenteditableBySpan = document.getElementById(
"iframe7").contentDocument.getElementById(
"contenteditable");
10872 windowOfContenteditableBySpan = document.getElementById(
"iframe7").contentWindow;
10874 await runIMEContentObserverTest();
10875 await runEditorReframeTests();
10876 await runAsyncForceCommitTest();
10877 await runRemoveContentTest();
10878 await runPanelTest();
10879 await runPasswordMaskDelayTest();
10880 await runBug1584901Test();
10881 await runInputModeTest();
10882 await runCompositionTest();
10883 await runCompositionCommitTest();
10884 await runSetSelectionEventTest();
10887 runCompositionCommitAsIsTest();
10888 runCompositionEventTest();
10889 runCompositionTestWhoseTextNodeModified();
10890 runQueryTextRectInContentEditableTest();
10891 runCharAtPointTest(textarea,
"textarea in the document");
10892 runCharAtPointAtOutsideTest();
10893 runQueryTextContentEventTest();
10894 runQuerySelectionEventTest();
10895 runQueryIMESelectionTest();
10896 runQueryContentEventRelativeToInsertionPoint();
10897 runQueryPasswordTest();
10898 runCSSTransformTest();
10899 runBug722639Test();
10900 runBug1375825Test();
10901 runBug1530649Test();
10902 runBug1571375Test();
10903 runBug1675313Test();
10904 runCommitCompositionWithSpaceKey();
10905 runCompositionWithSelectionChange();
10906 runForceCommitTest();
10907 runNestedSettingValue();
10908 runBug811755Test();
10909 runIsComposingTest();
10910 runRedundantChangeTest();
10911 runNotRedundantChangeTest();
10912 runNativeLineBreakerTest();
10913 runControlCharTest();
10915 runMaxLengthTest();
10920 window.arguments[
0].SimpleTest.waitForFocus(runTest, window);