Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 <?xml version="1.0"?>
2 <?xml-stylesheet href="chrome://global/skin" type="text/css"?>
3 <?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
4 type="text/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"
8 onunload="onunload();">
10 <script type="application/javascript"
11 src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
12 <script type="application/javascript"
13 src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js" />
14 <script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js"></script>
16 <panel id="panel" hidden="true"
17 orient="vertical"
18 onpopupshown="onPanelShown(event);"
19 onpopuphidden="onPanelHidden(event);">
20 <vbox id="vbox">
21 <textbox id="textbox" onfocus="onFocusPanelTextbox(event);"
22 multiline="true" cols="20" rows="4"/>
23 </vbox>
24 </panel>
26 <body xmlns="http://www.w3.org/1999/xhtml">
27 <p id="display">
28 <div id="div" style="margin: 0; padding: 0; font-size: 24px;">Here is a text frame.</div>
29 <textarea style="margin: 0;" id="textarea" cols="20" rows="4"></textarea><br/>
30 <iframe id="iframe" width="300" height="150"
31 src="data:text/html,<textarea id='textarea' cols='20' rows='4'></textarea>"></iframe><br/>
32 <iframe id="iframe2" width="300" height="150"
33 src="data:text/html,<body onload='document.designMode=%22on%22'>body content</body>"></iframe><br/>
34 <iframe id="iframe3" width="300" height="150"
35 src="data:text/html,<body onload='document.designMode=%22on%22'>body content</body>"></iframe><br/>
36 <input id="input" type="text"/><br/>
37 </p>
38 <div id="content" style="display: none">
40 </div>
41 <pre id="test">
42 </pre>
43 </body>
45 <script class="testbody" type="application/javascript">
46 <![CDATA[
48 window.opener.wrappedJSObject.SimpleTest.waitForFocus(runTest, window);
50 function ok(aCondition, aMessage)
51 {
52 window.opener.wrappedJSObject.SimpleTest.ok(aCondition, aMessage);
53 }
55 function is(aLeft, aRight, aMessage)
56 {
57 window.opener.wrappedJSObject.SimpleTest.is(aLeft, aRight, aMessage);
58 }
60 function isnot(aLeft, aRight, aMessage)
61 {
62 window.opener.wrappedJSObject.SimpleTest.isnot(aLeft, aRight, aMessage);
63 }
65 function finish()
66 {
67 window.close();
68 }
70 function onunload()
71 {
72 window.opener.wrappedJSObject.SimpleTest.finish();
73 }
75 var div = document.getElementById("div");
76 var textarea = document.getElementById("textarea");
77 var panel = document.getElementById("panel");
78 var textbox = document.getElementById("textbox");
79 var iframe = document.getElementById("iframe");
80 var iframe2 = document.getElementById("iframe2");
81 var iframe3 = document.getElementById("iframe3");
82 var input = document.getElementById("input");
83 var textareaInFrame;
85 const nsIDOMNSEditableElement = Components.interfaces.nsIDOMNSEditableElement;
86 const nsIEditorIMESupport = Components.interfaces.nsIEditorIMESupport;
87 const nsIInterfaceRequestor = Components.interfaces.nsIInterfaceRequestor;
88 const nsIWebNavigation = Components.interfaces.nsIWebNavigation;
89 const nsIDocShell = Components.interfaces.nsIDocShell;
91 function hitEventLoop(aFunc, aTimes)
92 {
93 if (--aTimes) {
94 setTimeout(hitEventLoop, 0, aFunc, aTimes);
95 } else {
96 setTimeout(aFunc, 20);
97 }
98 }
100 function getEditorIMESupport(aNode)
101 {
102 return aNode.QueryInterface(nsIDOMNSEditableElement).
103 editor.
104 QueryInterface(nsIEditorIMESupport);
105 }
107 function getHTMLEditorIMESupport(aWindow)
108 {
109 return aWindow.QueryInterface(nsIInterfaceRequestor).
110 getInterface(nsIWebNavigation).
111 QueryInterface(nsIDocShell).
112 editor;
113 }
115 const kIsWin = (navigator.platform.indexOf("Win") == 0);
116 const kIsMac = (navigator.platform.indexOf("Mac") == 0);
118 const kLFLen = kIsWin ? 2 : 1;
120 function checkQueryContentResult(aResult, aMessage)
121 {
122 ok(aResult, aMessage + ": the result is null");
123 if (!aResult) {
124 return false;
125 }
126 ok(aResult.succeeded, aMessage + ": the query content failed");
127 return aResult.succeeded;
128 }
130 function checkContent(aExpectedText, aMessage, aID)
131 {
132 var textContent = synthesizeQueryTextContent(0, 100);
133 if (!checkQueryContentResult(textContent, aMessage +
134 ": synthesizeQueryTextContent " + aID)) {
135 return false;
136 }
137 is(textContent.text, aExpectedText,
138 aMessage + ": composition string is wrong" + aID);
139 return textContent.text == aExpectedText;
140 }
142 function checkSelection(aExpectedOffset, aExpectedText, aMessage, aID)
143 {
144 var selectedText = synthesizeQuerySelectedText();
145 if (!checkQueryContentResult(selectedText, aMessage +
146 ": synthesizeQuerySelectedText " + aID)) {
147 return false;
148 }
149 is(selectedText.offset, aExpectedOffset,
150 aMessage + ": selection offset is wrong" + aID);
151 is(selectedText.text, aExpectedText,
152 aMessage + ": selected text is wrong" + aID);
153 return selectedText.offset == aExpectedOffset &&
154 selectedText.text == aExpectedText;
155 }
157 function checkRect(aRect, aExpectedRect, aMessage)
158 {
159 is(aRect.left, aExpectedRect.left, aMessage + ": left is wrong");
160 is(aRect.top, aExpectedRect.top, aMessage + " top is wrong");
161 is(aRect.width, aExpectedRect.width, aMessage + ": width is wrong");
162 is(aRect.height, aExpectedRect.height, aMessage + ": height is wrong");
163 return aRect.left == aExpectedRect.left &&
164 aRect.top == aExpectedRect.top &&
165 aRect.width == aExpectedRect.width &&
166 aRect.height == aExpectedRect.height;
167 }
169 function checkRectContainsRect(aRect, aContainer, aMessage)
170 {
171 var container = { left: Math.ceil(aContainer.left),
172 top: Math.ceil(aContainer.top),
173 width: Math.floor(aContainer.width),
174 height: Math.floor(aContainer.height) };
176 var ret = container.left <= aRect.left &&
177 container.top <= aRect.top &&
178 container.left + container.width >= aRect.left + aRect.width &&
179 container.top + container.height >= aRect.top + aRect.height;
180 ret = ret && aMessage;
181 ok(ret, aMessage + " container={ left=" + container.left + ", top=" +
182 container.top + ", width=" + container.width + ", height=" +
183 container.height + " } rect={ left=" + aRect.left + ", top=" + aRect.top +
184 ", width=" + aRect.width + ", height=" + aRect.height + " }");
185 return ret;
186 }
188 function runUndoRedoTest()
189 {
190 textarea.value = "";
191 textarea.focus();
193 // start composition
194 synthesizeComposition({ type: "compositionstart" });
196 // input raw characters
197 synthesizeComposition({ type: "compositionupdate", data: "\u306D" });
198 synthesizeText(
199 { "composition":
200 { "string": "\u306D",
201 "clauses":
202 [
203 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
204 ]
205 },
206 "caret": { "start": 1, "length": 0 }
207 });
209 synthesizeComposition({ type: "compositionupdate", data: "\u306D\u3053" });
210 synthesizeText(
211 { "composition":
212 { "string": "\u306D\u3053",
213 "clauses":
214 [
215 { "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT }
216 ]
217 },
218 "caret": { "start": 2, "length": 0 }
219 });
221 // convert
222 synthesizeComposition({ type: "compositionupdate", data: "\u732B" });
223 synthesizeText(
224 { "composition":
225 { "string": "\u732B",
226 "clauses":
227 [
228 { "length": 1,
229 "attr": COMPOSITION_ATTR_SELECTEDCONVERTEDTEXT }
230 ]
231 },
232 "caret": { "start": 1, "length": 0 }
233 });
235 // commit
236 synthesizeText(
237 { "composition":
238 { "string": "\u732B",
239 "clauses":
240 [
241 { "length": 0, "attr": 0 }
242 ]
243 },
244 "caret": { "start": 1, "length": 0 }
245 });
247 // end composition
248 synthesizeComposition({ type: "compositionend", data: "\u732B" });
250 // start composition
251 synthesizeComposition({ type: "compositionstart" });
253 // input raw characters
254 synthesizeComposition({ type: "compositionupdate", data: "\u307E" });
255 synthesizeText(
256 { "composition":
257 { "string": "\u307E",
258 "clauses":
259 [
260 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
261 ]
262 },
263 "caret": { "start": 1, "length": 0 }
264 });
266 // cancel the composition
267 synthesizeComposition({ type: "compositionupdate", data: "" });
268 synthesizeText(
269 { "composition":
270 { "string": "",
271 "clauses":
272 [
273 { "length": 0, "attr": 0 }
274 ]
275 },
276 "caret": { "start": 0, "length": 0 }
277 });
279 // end composition
280 synthesizeComposition({ type: "compositionend", data: "" });
282 // start composition
283 synthesizeComposition({ type: "compositionstart" });
285 // input raw characters
286 synthesizeComposition({ type: "compositionupdate", data: "\u3080" });
287 synthesizeText(
288 { "composition":
289 { "string": "\u3080",
290 "clauses":
291 [
292 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
293 ]
294 },
295 "caret": { "start": 1, "length": 0 }
296 });
298 synthesizeComposition({ type: "compositionupdate", data: "\u3080\u3059" });
299 synthesizeText(
300 { "composition":
301 { "string": "\u3080\u3059",
302 "clauses":
303 [
304 { "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT }
305 ]
306 },
307 "caret": { "start": 2, "length": 0 }
308 });
310 synthesizeComposition({ type: "compositionupdate",
311 data: "\u3080\u3059\u3081" });
312 synthesizeText(
313 { "composition":
314 { "string": "\u3080\u3059\u3081",
315 "clauses":
316 [
317 { "length": 3, "attr": COMPOSITION_ATTR_RAWINPUT }
318 ]
319 },
320 "caret": { "start": 3, "length": 0 }
321 });
323 // convert
324 synthesizeComposition({ type: "compositionupdate", data: "\u5A18" });
325 synthesizeText(
326 { "composition":
327 { "string": "\u5A18",
328 "clauses":
329 [
330 { "length": 1,
331 "attr": COMPOSITION_ATTR_SELECTEDCONVERTEDTEXT }
332 ]
333 },
334 "caret": { "start": 1, "length": 0 }
335 });
337 // commit
338 synthesizeText(
339 { "composition":
340 { "string": "\u5A18",
341 "clauses":
342 [
343 { "length": 0, "attr": 0 }
344 ]
345 },
346 "caret": { "start": 1, "length": 0 }
347 });
349 // end composition
350 synthesizeComposition({ type: "compositionend", data: "\u5A18" });
352 synthesizeKey(" ", {});
353 synthesizeKey("m", {});
354 synthesizeKey("e", {});
355 synthesizeKey("a", {});
356 synthesizeKey("n", {});
357 synthesizeKey("t", {});
358 synthesizeKey("VK_BACK_SPACE", {});
359 synthesizeKey("s", {});
360 synthesizeKey(" ", {});
361 synthesizeKey("\"", {});
362 synthesizeKey("c", {});
363 synthesizeKey("a", {});
364 synthesizeKey("t", {});
365 synthesizeKey("-", {});
366 synthesizeKey("g", {});
367 synthesizeKey("i", {});
368 synthesizeKey("r", {});
369 synthesizeKey("l", {});
370 synthesizeKey("\"", {});
371 synthesizeKey(".", {});
372 synthesizeKey(" ", {});
373 synthesizeKey("VK_SHIFT", { type: "keydown" });
374 synthesizeKey("S", { shiftKey: true });
375 synthesizeKey("VK_SHIFT", { type: "keyup" });
376 synthesizeKey("h", {});
377 synthesizeKey("e", {});
378 synthesizeKey(" ", {});
379 synthesizeKey("i", {});
380 synthesizeKey("s", {});
381 synthesizeKey(" ", {});
382 synthesizeKey("a", {});
383 synthesizeKey(" ", {});
385 // start composition
386 synthesizeComposition({ type: "compositionstart" });
388 // input raw characters
389 synthesizeComposition({ type: "compositionupdate", data: "\u3088" });
390 synthesizeText(
391 { "composition":
392 { "string": "\u3088",
393 "clauses":
394 [
395 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
396 ]
397 },
398 "caret": { "start": 1, "length": 0 }
399 });
401 synthesizeComposition({ type: "compositionupdate", data: "\u3088\u3046" });
402 synthesizeText(
403 { "composition":
404 { "string": "\u3088\u3046",
405 "clauses":
406 [
407 { "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT }
408 ]
409 },
410 "caret": { "start": 2, "length": 0 }
411 });
413 synthesizeComposition({ type: "compositionupdate",
414 data: "\u3088\u3046\u304b" });
415 synthesizeText(
416 { "composition":
417 { "string": "\u3088\u3046\u304b",
418 "clauses":
419 [
420 { "length": 3, "attr": COMPOSITION_ATTR_RAWINPUT }
421 ]
422 },
423 "caret": { "start": 3, "length": 0 }
424 });
426 synthesizeComposition({ type: "compositionupdate",
427 data: "\u3088\u3046\u304b\u3044" });
428 synthesizeText(
429 { "composition":
430 { "string": "\u3088\u3046\u304b\u3044",
431 "clauses":
432 [
433 { "length": 4, "attr": COMPOSITION_ATTR_RAWINPUT }
434 ]
435 },
436 "caret": { "start": 4, "length": 0 }
437 });
439 // convert
440 synthesizeComposition({ type: "compositionupdate", data: "\u5996\u602a" });
441 synthesizeText(
442 { "composition":
443 { "string": "\u5996\u602a",
444 "clauses":
445 [
446 { "length": 2, "attr": COMPOSITION_ATTR_SELECTEDCONVERTEDTEXT }
447 ]
448 },
449 "caret": { "start": 2, "length": 0 }
450 });
452 // commit
453 synthesizeText(
454 { "composition":
455 { "string": "\u5996\u602a",
456 "clauses":
457 [
458 { "length": 0, "attr": 0 }
459 ]
460 },
461 "caret": { "start": 2, "length": 0 }
462 });
464 // end composition
465 synthesizeComposition({ type: "compositionend", data: "\u5996\u602a" });
467 synthesizeKey("VK_BACK_SPACE", {});
468 synthesizeKey("VK_BACK_SPACE", {});
469 synthesizeKey("VK_BACK_SPACE", {});
470 synthesizeKey("VK_BACK_SPACE", {});
471 synthesizeKey("VK_BACK_SPACE", {});
472 synthesizeKey("VK_BACK_SPACE", {});
473 synthesizeKey("VK_BACK_SPACE", {});
474 synthesizeKey("VK_BACK_SPACE", {});
475 synthesizeKey("VK_BACK_SPACE", {});
476 synthesizeKey("VK_BACK_SPACE", {});
477 synthesizeKey("VK_BACK_SPACE", {});
478 synthesizeKey("VK_BACK_SPACE", {});
480 var i = 0;
481 if (!checkContent("\u732B\u5A18 means \"cat-girl\".",
482 "runUndoRedoTest", "#" + ++i) ||
483 !checkSelection(20, "", "runUndoRedoTest", "#" + i)) {
484 return;
485 }
487 synthesizeKey("Z", {accelKey: true});
489 if (!checkContent("\u732B\u5A18 means \"cat-girl\". She is a \u5996\u602A",
490 "runUndoRedoTest", "#" + ++i) ||
491 !checkSelection(32, "", "runUndoRedoTest", "#" + i)) {
492 return;
493 }
495 synthesizeKey("Z", {accelKey: true});
497 if (!checkContent("\u732B\u5A18 means \"cat-girl\". She is a ",
498 "runUndoRedoTest", "#" + ++i) ||
499 !checkSelection(30, "", "runUndoRedoTest", "#" + i)) {
500 return;
501 }
503 synthesizeKey("Z", {accelKey: true});
505 if (!checkContent("\u732B\u5A18 mean",
506 "runUndoRedoTest", "#" + ++i) ||
507 !checkSelection(7, "", "runUndoRedoTest", "#" + i)) {
508 return;
509 }
511 synthesizeKey("Z", {accelKey: true});
513 if (!checkContent("\u732B\u5A18 meant",
514 "runUndoRedoTest", "#" + ++i) ||
515 !checkSelection(8, "", "runUndoRedoTest", "#" + i)) {
516 return;
517 }
519 synthesizeKey("Z", {accelKey: true});
521 if (!checkContent("\u732B\u5A18",
522 "runUndoRedoTest", "#" + ++i) ||
523 !checkSelection(2, "", "runUndoRedoTest", "#" + i)) {
524 return;
525 }
527 synthesizeKey("Z", {accelKey: true});
529 if (!checkContent("\u732B",
530 "runUndoRedoTest", "#" + ++i) ||
531 !checkSelection(1, "", "runUndoRedoTest", "#" + i)) {
532 return;
533 }
535 synthesizeKey("Z", {accelKey: true});
537 // XXX this is unexpected behavior, see bug 258291
538 if (!checkContent("\u732B",
539 "runUndoRedoTest", "#" + ++i) ||
540 !checkSelection(1, "", "runUndoRedoTest", "#" + i)) {
541 return;
542 }
544 synthesizeKey("Z", {accelKey: true});
546 if (!checkContent("",
547 "runUndoRedoTest", "#" + ++i) ||
548 !checkSelection(0, "", "runUndoRedoTest", "#" + i)) {
549 return;
550 }
552 synthesizeKey("Z", {accelKey: true});
554 if (!checkContent("",
555 "runUndoRedoTest", "#" + ++i) ||
556 !checkSelection(0, "", "runUndoRedoTest", "#" + i)) {
557 return;
558 }
560 synthesizeKey("Z", {accelKey: true, shiftKey: true});
562 if (!checkContent("\u732B",
563 "runUndoRedoTest", "#" + ++i) ||
564 !checkSelection(1, "", "runUndoRedoTest", "#" + i)) {
565 return;
566 }
568 synthesizeKey("Z", {accelKey: true, shiftKey: true});
570 // XXX this is unexpected behavior, see bug 258291
571 if (!checkContent("\u732B",
572 "runUndoRedoTest", "#" + ++i) ||
573 !checkSelection(1, "", "runUndoRedoTest", "#" + i)) {
574 return;
575 }
577 synthesizeKey("Z", {accelKey: true, shiftKey: true});
579 if (!checkContent("\u732B\u5A18",
580 "runUndoRedoTest", "#" + ++i) ||
581 !checkSelection(2, "", "runUndoRedoTest", "#" + i)) {
582 return;
583 }
585 synthesizeKey("Z", {accelKey: true, shiftKey: true});
587 if (!checkContent("\u732B\u5A18 meant",
588 "runUndoRedoTest", "#" + ++i) ||
589 !checkSelection(8, "", "runUndoRedoTest", "#" + i)) {
590 return;
591 }
593 synthesizeKey("Z", {accelKey: true, shiftKey: true});
595 if (!checkContent("\u732B\u5A18 mean",
596 "runUndoRedoTest", "#" + ++i) ||
597 !checkSelection(7, "", "runUndoRedoTest", "#" + i)) {
598 return;
599 }
601 synthesizeKey("Z", {accelKey: true, shiftKey: true});
603 if (!checkContent("\u732B\u5A18 means \"cat-girl\". She is a ",
604 "runUndoRedoTest", "#" + ++i) ||
605 !checkSelection(30, "", "runUndoRedoTest", "#" + i)) {
606 return;
607 }
609 synthesizeKey("Z", {accelKey: true, shiftKey: true});
611 if (!checkContent("\u732B\u5A18 means \"cat-girl\". She is a \u5996\u602A",
612 "runUndoRedoTest", "#" + ++i) ||
613 !checkSelection(32, "", "runUndoRedoTest", "#" + i)) {
614 return;
615 }
617 synthesizeKey("Z", {accelKey: true, shiftKey: true});
619 if (!checkContent("\u732B\u5A18 means \"cat-girl\".",
620 "runUndoRedoTest", "#" + ++i) ||
621 !checkSelection(20, "", "runUndoRedoTest", "#" + i)) {
622 return;
623 }
625 synthesizeKey("Z", {accelKey: true, shiftKey: true});
627 if (!checkContent("\u732B\u5A18 means \"cat-girl\".",
628 "runUndoRedoTest", "#" + ++i) ||
629 !checkSelection(20, "", "runUndoRedoTest", "#" + i)) {
630 return;
631 }
632 }
634 function runCompositionTest()
635 {
636 textarea.value = "";
637 textarea.focus();
638 var caretRects = [];
640 var caretRect = synthesizeQueryCaretRect(0);
641 if (!checkQueryContentResult(caretRect,
642 "runCompositionTest: synthesizeQueryCaretRect #0")) {
643 return false;
644 }
645 caretRects[0] = caretRect;
647 // start composition
648 synthesizeComposition({ type: "compositionstart" });
650 // input first character
651 synthesizeComposition({ type: "compositionupdate", data: "\u3089" });
652 synthesizeText(
653 { "composition":
654 { "string": "\u3089",
655 "clauses":
656 [
657 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
658 ]
659 },
660 "caret": { "start": 1, "length": 0 }
661 });
663 if (!checkContent("\u3089", "runCompositionTest", "#1-1") ||
664 !checkSelection(1, "", "runCompositionTest", "#1-1")) {
665 return;
666 }
668 caretRect = synthesizeQueryCaretRect(1);
669 if (!checkQueryContentResult(caretRect,
670 "runCompositionTest: synthesizeQueryCaretRect #1-1")) {
671 return false;
672 }
673 caretRects[1] = caretRect;
675 // input second character
676 synthesizeComposition({ type: "compositionupdate", data: "\u3089\u30FC" });
677 synthesizeText(
678 { "composition":
679 { "string": "\u3089\u30FC",
680 "clauses":
681 [
682 { "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT }
683 ]
684 },
685 "caret": { "start": 2, "length": 0 }
686 });
688 if (!checkContent("\u3089\u30FC", "runCompositionTest", "#1-2") ||
689 !checkSelection(2, "", "runCompositionTest", "#1-2")) {
690 return;
691 }
693 caretRect = synthesizeQueryCaretRect(2);
694 if (!checkQueryContentResult(caretRect,
695 "runCompositionTest: synthesizeQueryCaretRect #1-2")) {
696 return false;
697 }
698 caretRects[2] = caretRect;
700 isnot(caretRects[2].left, caretRects[1].left,
701 "runCompositionTest: caret isn't moved (#1-2)");
702 is(caretRects[2].top, caretRects[1].top,
703 "runCompositionTest: caret is moved to another line (#1-2)");
704 is(caretRects[2].width, caretRects[1].width,
705 "runCompositionTest: caret width is wrong (#1-2)");
706 is(caretRects[2].height, caretRects[1].height,
707 "runCompositionTest: caret width is wrong (#1-2)");
709 // input third character
710 synthesizeComposition({ type: "compositionupdate",
711 data: "\u3089\u30FC\u3081" });
712 synthesizeText(
713 { "composition":
714 { "string": "\u3089\u30FC\u3081",
715 "clauses":
716 [
717 { "length": 3, "attr": COMPOSITION_ATTR_RAWINPUT }
718 ]
719 },
720 "caret": { "start": 3, "length": 0 }
721 });
723 if (!checkContent("\u3089\u30FC\u3081", "runCompositionTest", "#1-3") ||
724 !checkSelection(3, "", "runCompositionTest", "#1-3")) {
725 return;
726 }
728 caretRect = synthesizeQueryCaretRect(3);
729 if (!checkQueryContentResult(caretRect,
730 "runCompositionTest: synthesizeQueryCaretRect #1-3")) {
731 return false;
732 }
733 caretRects[3] = caretRect;
735 isnot(caretRects[3].left, caretRects[2].left,
736 "runCompositionTest: caret isn't moved (#1-3)");
737 is(caretRects[3].top, caretRects[2].top,
738 "runCompositionTest: caret is moved to another line (#1-3)");
739 is(caretRects[3].width, caretRects[2].width,
740 "runCompositionTest: caret width is wrong (#1-3)");
741 is(caretRects[3].height, caretRects[2].height,
742 "runCompositionTest: caret height is wrong (#1-3)");
744 // moves the caret left
745 synthesizeText(
746 { "composition":
747 { "string": "\u3089\u30FC\u3081",
748 "clauses":
749 [
750 { "length": 3, "attr": COMPOSITION_ATTR_RAWINPUT }
751 ]
752 },
753 "caret": { "start": 2, "length": 0 }
754 });
756 if (!checkContent("\u3089\u30FC\u3081", "runCompositionTest", "#1-3-1") ||
757 !checkSelection(2, "", "runCompositionTest", "#1-3-1")) {
758 return;
759 }
762 caretRect = synthesizeQueryCaretRect(2);
763 if (!checkQueryContentResult(caretRect,
764 "runCompositionTest: synthesizeQueryCaretRect #1-3-1")) {
765 return false;
766 }
768 is(caretRect.left, caretRects[2].left,
769 "runCompositionTest: caret rects are different (#1-3-1, left)");
770 is(caretRect.top, caretRects[2].top,
771 "runCompositionTest: caret rects are different (#1-3-1, top)");
772 // by bug 335359, the caret width depends on the right side's character.
773 is(caretRect.width, caretRects[2].width + 1,
774 "runCompositionTest: caret rects are different (#1-3-1, width)");
775 is(caretRect.height, caretRects[2].height,
776 "runCompositionTest: caret rects are different (#1-3-1, height)");
778 // moves the caret left
779 synthesizeText(
780 { "composition":
781 { "string": "\u3089\u30FC\u3081",
782 "clauses":
783 [
784 { "length": 3, "attr": COMPOSITION_ATTR_RAWINPUT }
785 ]
786 },
787 "caret": { "start": 1, "length": 0 }
788 });
790 if (!checkContent("\u3089\u30FC\u3081", "runCompositionTest", "#1-3-2") ||
791 !checkSelection(1, "", "runCompositionTest", "#1-3-2")) {
792 return;
793 }
796 caretRect = synthesizeQueryCaretRect(1);
797 if (!checkQueryContentResult(caretRect,
798 "runCompositionTest: synthesizeQueryCaretRect #1-3-2")) {
799 return false;
800 }
802 is(caretRect.left, caretRects[1].left,
803 "runCompositionTest: caret rects are different (#1-3-2, left)");
804 is(caretRect.top, caretRects[1].top,
805 "runCompositionTest: caret rects are different (#1-3-2, top)");
806 // by bug 335359, the caret width depends on the right side's character.
807 is(caretRect.width, caretRects[1].width + 1,
808 "runCompositionTest: caret rects are different (#1-3-2, width)");
809 is(caretRect.height, caretRects[1].height,
810 "runCompositionTest: caret rects are different (#1-3-2, height)");
812 synthesizeComposition({ type: "compositionupdate",
813 data: "\u3089\u30FC\u3081\u3093" });
814 synthesizeText(
815 { "composition":
816 { "string": "\u3089\u30FC\u3081\u3093",
817 "clauses":
818 [
819 { "length": 4, "attr": COMPOSITION_ATTR_RAWINPUT }
820 ]
821 },
822 "caret": { "start": 4, "length": 0 }
823 });
825 if (!checkContent("\u3089\u30FC\u3081\u3093", "runCompositionTest", "#1-4") ||
826 !checkSelection(4, "", "runCompositionTest", "#1-4")) {
827 return;
828 }
831 // backspace
832 synthesizeComposition({ type: "compositionupdate",
833 data: "\u3089\u30FC\u3081" });
834 synthesizeText(
835 { "composition":
836 { "string": "\u3089\u30FC\u3081",
837 "clauses":
838 [
839 { "length": 3, "attr": COMPOSITION_ATTR_RAWINPUT }
840 ]
841 },
842 "caret": { "start": 3, "length": 0 }
843 });
845 if (!checkContent("\u3089\u30FC\u3081", "runCompositionTest", "#1-5") ||
846 !checkSelection(3, "", "runCompositionTest", "#1-5")) {
847 return;
848 }
850 // re-input
851 synthesizeComposition({ type: "compositionupdate",
852 data: "\u3089\u30FC\u3081\u3093" });
853 synthesizeText(
854 { "composition":
855 { "string": "\u3089\u30FC\u3081\u3093",
856 "clauses":
857 [
858 { "length": 4, "attr": COMPOSITION_ATTR_RAWINPUT }
859 ]
860 },
861 "caret": { "start": 4, "length": 0 }
862 });
864 if (!checkContent("\u3089\u30FC\u3081\u3093", "runCompositionTest", "#1-6") ||
865 !checkSelection(4, "", "runCompositionTest", "#1-6")) {
866 return;
867 }
869 synthesizeComposition({ type: "compositionupdate",
870 data: "\u3089\u30FC\u3081\u3093\u3055" });
871 synthesizeText(
872 { "composition":
873 { "string": "\u3089\u30FC\u3081\u3093\u3055",
874 "clauses":
875 [
876 { "length": 5, "attr": COMPOSITION_ATTR_RAWINPUT }
877 ]
878 },
879 "caret": { "start": 5, "length": 0 }
880 });
882 if (!checkContent("\u3089\u30FC\u3081\u3093\u3055", "runCompositionTest", "#1-7") ||
883 !checkSelection(5, "", "runCompositionTest", "#1-7")) {
884 return;
885 }
887 synthesizeComposition({ type: "compositionupdate",
888 data: "\u3089\u30FC\u3081\u3093\u3055\u3044" });
889 synthesizeText(
890 { "composition":
891 { "string": "\u3089\u30FC\u3081\u3093\u3055\u3044",
892 "clauses":
893 [
894 { "length": 6, "attr": COMPOSITION_ATTR_RAWINPUT }
895 ]
896 },
897 "caret": { "start": 6, "length": 0 }
898 });
900 if (!checkContent("\u3089\u30FC\u3081\u3093\u3055\u3044", "runCompositionTest", "#1-8") ||
901 !checkSelection(6, "", "runCompositionTest", "#1-8")) {
902 return;
903 }
905 synthesizeComposition({ type: "compositionupdate",
906 data: "\u3089\u30FC\u3081\u3093\u3055\u3044\u3053" });
907 synthesizeText(
908 { "composition":
909 { "string": "\u3089\u30FC\u3081\u3093\u3055\u3044\u3053",
910 "clauses":
911 [
912 { "length": 7, "attr": COMPOSITION_ATTR_RAWINPUT }
913 ]
914 },
915 "caret": { "start": 7, "length": 0 }
916 });
918 if (!checkContent("\u3089\u30FC\u3081\u3093\u3055\u3044\u3053", "runCompositionTest", "#1-8") ||
919 !checkSelection(7, "", "runCompositionTest", "#1-8")) {
920 return;
921 }
923 synthesizeComposition({ type: "compositionupdate",
924 data: "\u3089\u30FC\u3081\u3093\u3055\u3044\u3053\u3046" });
925 synthesizeText(
926 { "composition":
927 { "string": "\u3089\u30FC\u3081\u3093\u3055\u3044\u3053\u3046",
928 "clauses":
929 [
930 { "length": 8, "attr": COMPOSITION_ATTR_RAWINPUT }
931 ]
932 },
933 "caret": { "start": 8, "length": 0 }
934 });
936 if (!checkContent("\u3089\u30FC\u3081\u3093\u3055\u3044\u3053\u3046",
937 "runCompositionTest", "#1-9") ||
938 !checkSelection(8, "", "runCompositionTest", "#1-9")) {
939 return;
940 }
942 // convert
943 synthesizeComposition({ type: "compositionupdate",
944 data: "\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8" });
945 synthesizeText(
946 { "composition":
947 { "string": "\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8",
948 "clauses":
949 [
950 { "length": 4,
951 "attr": COMPOSITION_ATTR_SELECTEDCONVERTEDTEXT },
952 { "length": 2,
953 "attr": COMPOSITION_ATTR_CONVERTEDTEXT }
954 ]
955 },
956 "caret": { "start": 4, "length": 0 }
957 });
959 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8",
960 "runCompositionTest", "#1-10") ||
961 !checkSelection(4, "", "runCompositionTest", "#1-10")) {
962 return;
963 }
965 // change the selected clause
966 synthesizeText(
967 { "composition":
968 { "string": "\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8",
969 "clauses":
970 [
971 { "length": 4,
972 "attr": COMPOSITION_ATTR_CONVERTEDTEXT },
973 { "length": 2,
974 "attr": COMPOSITION_ATTR_SELECTEDCONVERTEDTEXT }
975 ]
976 },
977 "caret": { "start": 6, "length": 0 }
978 });
980 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8",
981 "runCompositionTest", "#1-11") ||
982 !checkSelection(6, "", "runCompositionTest", "#1-11")) {
983 return;
984 }
986 // reset clauses
987 synthesizeComposition({ type: "compositionupdate",
988 data: "\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046" });
989 synthesizeText(
990 { "composition":
991 { "string": "\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046",
992 "clauses":
993 [
994 { "length": 5,
995 "attr": COMPOSITION_ATTR_SELECTEDCONVERTEDTEXT },
996 { "length": 3,
997 "attr": COMPOSITION_ATTR_CONVERTEDTEXT }
998 ]
999 },
1000 "caret": { "start": 5, "length": 0 }
1001 });
1003 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046",
1004 "runCompositionTest", "#1-12") ||
1005 !checkSelection(5, "", "runCompositionTest", "#1-12")) {
1006 return;
1007 }
1010 var textRect1 = synthesizeQueryTextRect(0, 1);
1011 var textRect2 = synthesizeQueryTextRect(1, 1);
1012 if (!checkQueryContentResult(textRect1,
1013 "runCompositionTest: synthesizeQueryTextRect #1-12-1") ||
1014 !checkQueryContentResult(textRect2,
1015 "runCompositionTest: synthesizeQueryTextRect #1-12-2")) {
1016 return false;
1017 }
1019 // commit the composition string
1020 synthesizeText(
1021 { "composition":
1022 { "string": "\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046",
1023 "clauses":
1024 [
1025 { "length": 0, "attr": 0 }
1026 ]
1027 },
1028 "caret": { "start": 8, "length": 0 }
1029 });
1031 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046",
1032 "runCompositionTest", "#1-13") ||
1033 !checkSelection(8, "", "runCompositionTest", "#1-13")) {
1034 return;
1035 }
1037 synthesizeComposition({ type: "compositionend",
1038 data: "\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046" });
1040 var textRect3 = synthesizeQueryTextRect(0, 1);
1041 var textRect4 = synthesizeQueryTextRect(1, 1);
1043 if (!checkQueryContentResult(textRect3,
1044 "runCompositionTest: synthesizeQueryTextRect #1-13-1") ||
1045 !checkQueryContentResult(textRect4,
1046 "runCompositionTest: synthesizeQueryTextRect #1-13-2")) {
1047 return false;
1048 }
1050 checkRect(textRect3, textRect1, "runCompositionTest: textRect #1-13-1");
1051 checkRect(textRect4, textRect2, "runCompositionTest: textRect #1-13-2");
1053 // restart composition
1054 synthesizeComposition({ type: "compositionstart" });
1056 // input characters
1057 synthesizeComposition({ type: "compositionupdate", data: "\u3057" });
1058 synthesizeText(
1059 { "composition":
1060 { "string": "\u3057",
1061 "clauses":
1062 [
1063 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
1064 ]
1065 },
1066 "caret": { "start": 1, "length": 0 }
1067 });
1069 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046\u3057",
1070 "runCompositionTest", "#2-1") ||
1071 !checkSelection(8 + 1, "", "runCompositionTest", "#2-1")) {
1072 return;
1073 }
1075 synthesizeComposition({ type: "compositionupdate", data: "\u3058" });
1076 synthesizeText(
1077 { "composition":
1078 { "string": "\u3058",
1079 "clauses":
1080 [
1081 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
1082 ]
1083 },
1084 "caret": { "start": 1, "length": 0 }
1085 });
1087 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046\u3058",
1088 "runCompositionTest", "#2-2") ||
1089 !checkSelection(8 + 1, "", "runCompositionTest", "#2-2")) {
1090 return;
1091 }
1093 synthesizeComposition({ type: "compositionupdate", data: "\u3058\u3087" });
1094 synthesizeText(
1095 { "composition":
1096 { "string": "\u3058\u3087",
1097 "clauses":
1098 [
1099 { "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT }
1100 ]
1101 },
1102 "caret": { "start": 2, "length": 0 }
1103 });
1105 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046\u3058\u3087",
1106 "runCompositionTest", "#2-3") ||
1107 !checkSelection(8 + 2, "", "runCompositionTest", "#2-3")) {
1108 return;
1109 }
1111 synthesizeComposition({ type: "compositionupdate",
1112 data: "\u3058\u3087\u3046" });
1113 synthesizeText(
1114 { "composition":
1115 { "string": "\u3058\u3087\u3046",
1116 "clauses":
1117 [
1118 { "length": 3, "attr": COMPOSITION_ATTR_RAWINPUT }
1119 ]
1120 },
1121 "caret": { "start": 3, "length": 0 }
1122 });
1124 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046\u3058\u3087\u3046",
1125 "runCompositionTest", "#2-4") ||
1126 !checkSelection(8 + 3, "", "runCompositionTest", "#2-4")) {
1127 return;
1128 }
1130 // commit the composition string
1131 synthesizeText(
1132 { "composition":
1133 { "string": "\u3058\u3087\u3046",
1134 "clauses":
1135 [
1136 { "length": 0, "attr": 0 }
1137 ]
1138 },
1139 "caret": { "start": 3, "length": 0 }
1140 });
1142 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046\u3058\u3087\u3046",
1143 "runCompositionTest", "#2-4") ||
1144 !checkSelection(8 + 3, "", "runCompositionTest", "#2-4")) {
1145 return;
1146 }
1148 synthesizeComposition({ type: "compositionend", data: "\u3058\u3087\u3046" });
1150 // set selection
1151 var selectionSetTest = synthesizeSelectionSet(4, 7, false);
1152 ok(selectionSetTest, "runCompositionTest: selectionSetTest failed");
1154 if (!checkSelection(4, "\u3055\u884C\u3053\u3046\u3058\u3087\u3046", "runCompositionTest", "#3-1")) {
1155 return;
1156 }
1158 // start composition with selection
1159 synthesizeComposition({ type: "compositionstart" });
1161 synthesizeComposition({ type: "compositionupdate", data: "\u304A" });
1162 synthesizeText(
1163 { "composition":
1164 { "string": "\u304A",
1165 "clauses":
1166 [
1167 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
1168 ]
1169 },
1170 "caret": { "start": 1, "length": 0 }
1171 });
1173 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u304A",
1174 "runCompositionTest", "#3-2") ||
1175 !checkSelection(4 + 1, "", "runCompositionTest", "#3-2")) {
1176 return;
1177 }
1179 // remove the composition string
1180 synthesizeComposition({ type: "compositionupdate", data: "" });
1181 synthesizeText(
1182 { "composition":
1183 { "string": "",
1184 "clauses":
1185 [
1186 { "length": 0, "attr": 0 }
1187 ]
1188 },
1189 "caret": { "start": 0, "length": 0 }
1190 });
1192 if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
1193 "runCompositionTest", "#3-3") ||
1194 !checkSelection(4, "", "runCompositionTest", "#3-3")) {
1195 return;
1196 }
1198 // re-input the composition string
1199 synthesizeComposition({ type: "compositionupdate", data: "\u3046" });
1200 synthesizeText(
1201 { "composition":
1202 { "string": "\u3046",
1203 "clauses":
1204 [
1205 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
1206 ]
1207 },
1208 "caret": { "start": 1, "length": 0 }
1209 });
1211 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u3046",
1212 "runCompositionTest", "#3-4") ||
1213 !checkSelection(4 + 1, "", "runCompositionTest", "#3-4")) {
1214 return;
1215 }
1217 // cancel the composition
1218 synthesizeComposition({ type: "compositionupdate", data: "" });
1219 synthesizeText(
1220 { "composition":
1221 { "string": "",
1222 "clauses":
1223 [
1224 { "length": 0, "attr": 0 }
1225 ]
1226 },
1227 "caret": { "start": 0, "length": 0 }
1228 });
1230 synthesizeComposition({ type: "compositionend", data: "" });
1232 if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
1233 "runCompositionTest", "#3-5") ||
1234 !checkSelection(4, "", "runCompositionTest", "#3-5")) {
1235 return;
1236 }
1238 // bug 271815, some Chinese IMEs for Linux make empty composition string
1239 // and compty clause information when it lists up Chinese characters on
1240 // its candidate window.
1241 synthesizeComposition({ type: "compositionstart" });
1243 synthesizeText(
1244 { "composition":
1245 { "string": "",
1246 "clauses":
1247 [
1248 { "length": 0, "attr": 0 }
1249 ]
1250 },
1251 "caret": { "start": 0, "length": 0 }
1252 });
1254 if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
1255 "runCompositionTest", "#4-1") ||
1256 !checkSelection(4, "", "runCompositionTest", "#4-1")) {
1257 return;
1258 }
1260 synthesizeText(
1261 { "composition":
1262 { "string": "",
1263 "clauses":
1264 [
1265 { "length": 0, "attr": 0 }
1266 ]
1267 },
1268 "caret": { "start": 0, "length": 0 }
1269 });
1271 if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
1272 "runCompositionTest", "#4-2") ||
1273 !checkSelection(4, "", "runCompositionTest", "#4-2")) {
1274 return;
1275 }
1277 synthesizeComposition({ type: "compositionupdate", data: "\u6700" });
1278 synthesizeText(
1279 { "composition":
1280 { "string": "\u6700",
1281 "clauses":
1282 [
1283 { "length": 0, "attr": 0 }
1284 ]
1285 },
1286 "caret": { "start": 1, "length": 0 }
1287 });
1289 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700",
1290 "runCompositionTest", "#4-3") ||
1291 !checkSelection(5, "", "runCompositionTest", "#4-3")) {
1292 return;
1293 }
1295 synthesizeComposition({ type: "compositionend", data: "\u6700" });
1297 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700",
1298 "runCompositionTest", "#4-4") ||
1299 !checkSelection(5, "", "runCompositionTest", "#4-4")) {
1300 return;
1301 }
1303 // testing the canceling case
1304 synthesizeComposition({ type: "compositionstart" });
1306 synthesizeText(
1307 { "composition":
1308 { "string": "",
1309 "clauses":
1310 [
1311 { "length": 0, "attr": 0 }
1312 ]
1313 },
1314 "caret": { "start": 0, "length": 0 }
1315 });
1317 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700",
1318 "runCompositionTest", "#4-5") ||
1319 !checkSelection(5, "", "runCompositionTest", "#4-5")) {
1320 return;
1321 }
1323 synthesizeText(
1324 { "composition":
1325 { "string": "",
1326 "clauses":
1327 [
1328 { "length": 0, "attr": 0 }
1329 ]
1330 },
1331 "caret": { "start": 0, "length": 0 }
1332 });
1334 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700",
1335 "runCompositionTest", "#4-6") ||
1336 !checkSelection(5, "", "runCompositionTest", "#4-6")) {
1337 return;
1338 }
1340 synthesizeComposition({ type: "compositionend", data: "\u6700" });
1342 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700",
1343 "runCompositionTest", "#4-7") ||
1344 !checkSelection(5, "", "runCompositionTest", "#4-7")) {
1345 return;
1346 }
1348 // testing whether the empty composition string deletes selected string.
1349 synthesizeKey("VK_LEFT", { shiftKey: true });
1351 synthesizeComposition({ type: "compositionstart" });
1353 synthesizeText(
1354 { "composition":
1355 { "string": "",
1356 "clauses":
1357 [
1358 { "length": 0, "attr": 0 }
1359 ]
1360 },
1361 "caret": { "start": 0, "length": 0 }
1362 });
1364 if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
1365 "runCompositionTest", "#4-8") ||
1366 !checkSelection(4, "", "runCompositionTest", "#4-8")) {
1367 return;
1368 }
1370 synthesizeComposition({ type: "compositionupdate", data: "\u9AD8" });
1371 synthesizeText(
1372 { "composition":
1373 { "string": "\u9AD8",
1374 "clauses":
1375 [
1376 { "length": 0, "attr": 0 }
1377 ]
1378 },
1379 "caret": { "start": 1, "length": 0 }
1380 });
1382 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u9AD8",
1383 "runCompositionTest", "#4-9") ||
1384 !checkSelection(5, "", "runCompositionTest", "#4-9")) {
1385 return;
1386 }
1388 synthesizeComposition({ type: "compositionend", data: "\u9AD8" });
1390 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u9AD8",
1391 "runCompositionTest", "#4-10") ||
1392 !checkSelection(5, "", "runCompositionTest", "#4-10")) {
1393 return;
1394 }
1396 synthesizeKey("VK_BACK_SPACE", {});
1397 if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
1398 "runCompositionTest", "#4-11") ||
1399 !checkSelection(4, "", "runCompositionTest", "#4-11")) {
1400 return;
1401 }
1403 // bug 23558, ancient Japanese IMEs on Window may send empty text event
1404 // twice at canceling composition.
1405 synthesizeComposition({ type: "compositionstart" });
1407 synthesizeComposition({ type: "compositionupdate", data: "\u6700" });
1408 synthesizeText(
1409 { "composition":
1410 { "string": "\u6700",
1411 "clauses":
1412 [
1413 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
1414 ]
1415 },
1416 "caret": { "start": 1, "length": 0 }
1417 });
1419 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700",
1420 "runCompositionTest", "#5-1") ||
1421 !checkSelection(4 + 1, "", "runCompositionTest", "#5-1")) {
1422 return;
1423 }
1425 synthesizeComposition({ type: "compositionupdate", data: "" });
1426 synthesizeText(
1427 { "composition":
1428 { "string": "",
1429 "clauses":
1430 [
1431 { "length": 0, "attr": 0 }
1432 ]
1433 },
1434 "caret": { "start": 0, "length": 0 }
1435 });
1437 if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
1438 "runCompositionTest", "#5-2") ||
1439 !checkSelection(4, "", "runCompositionTest", "#5-2")) {
1440 return;
1441 }
1443 synthesizeText(
1444 { "composition":
1445 { "string": "",
1446 "clauses":
1447 [
1448 { "length": 0, "attr": 0 }
1449 ]
1450 },
1451 "caret": { "start": 0, "length": 0 }
1452 });
1454 if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
1455 "runCompositionTest", "#5-3") ||
1456 !checkSelection(4, "", "runCompositionTest", "#5-3")) {
1457 return;
1458 }
1460 synthesizeComposition({ type: "compositionend", data: "\u9AD8" });
1462 if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
1463 "runCompositionTest", "#5-4") ||
1464 !checkSelection(4, "", "runCompositionTest", "#5-4")) {
1465 return;
1466 }
1468 // Undo tests for the testcases for bug 23558 and bug 271815
1469 synthesizeKey("Z", { accelKey: true });
1471 // XXX this is unexpected behavior, see bug 258291
1472 if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
1473 "runCompositionTest", "#6-1") ||
1474 !checkSelection(4, "", "runCompositionTest", "#6-1")) {
1475 return;
1476 }
1478 synthesizeKey("Z", { accelKey: true });
1480 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u9AD8",
1481 "runCompositionTest", "#6-2") ||
1482 !checkSelection(5, "", "runCompositionTest", "#6-2")) {
1483 return;
1484 }
1486 synthesizeKey("Z", { accelKey: true });
1488 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700",
1489 "runCompositionTest", "#6-3") ||
1490 !checkSelection(4, "\u6700", "runCompositionTest", "#6-3")) {
1491 return;
1492 }
1494 synthesizeKey("Z", { accelKey: true });
1496 // XXX this is unexpected behavior, see bug 258291
1497 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700",
1498 "runCompositionTest", "#6-4") ||
1499 !checkSelection(5, "", "runCompositionTest", "#6-4")) {
1500 return;
1501 }
1503 synthesizeKey("Z", { accelKey: true });
1505 if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
1506 "runCompositionTest", "#6-5") ||
1507 !checkSelection(4, "", "runCompositionTest", "#6-5")) {
1508 return;
1509 }
1510 }
1512 function runCompositionEventTest()
1513 {
1514 const kDescription = "runCompositionEventTest: ";
1515 const kEvents = ["compositionstart", "compositionupdate", "compositionend",
1516 "input"];
1518 input.value = "";
1519 input.focus();
1521 var windowEventCounts = [], windowEventData = [], windowEventLocale = [];
1522 var inputEventCounts = [], inputEventData = [], inputEventLocale = [];
1523 var preventDefault = false;
1524 var stopPropagation = false;
1526 function initResults()
1527 {
1528 for (var i = 0; i < kEvents.length; i++) {
1529 windowEventCounts[kEvents[i]] = 0;
1530 windowEventData[kEvents[i]] = "";
1531 windowEventLocale[kEvents[i]] = "";
1532 inputEventCounts[kEvents[i]] = 0;
1533 inputEventData[kEvents[i]] = "";
1534 inputEventLocale[kEvents[i]] = "";
1535 }
1536 }
1538 function compositionEventHandlerForWindow(aEvent)
1539 {
1540 windowEventCounts[aEvent.type]++;
1541 windowEventData[aEvent.type] = aEvent.data;
1542 windowEventLocale[aEvent.type] = aEvent.locale;
1543 if (preventDefault) {
1544 aEvent.preventDefault();
1545 }
1546 if (stopPropagation) {
1547 aEvent.stopPropagation();
1548 }
1549 }
1551 function formEventHandlerForWindow(aEvent)
1552 {
1553 ok(aEvent.isTrusted, "input events must be trusted events");
1554 windowEventCounts[aEvent.type]++;
1555 windowEventData[aEvent.type] = input.value;
1556 }
1558 function compositionEventHandlerForInput(aEvent)
1559 {
1560 inputEventCounts[aEvent.type]++;
1561 inputEventData[aEvent.type] = aEvent.data;
1562 inputEventLocale[aEvent.type] = aEvent.locale;
1563 if (preventDefault) {
1564 aEvent.preventDefault();
1565 }
1566 if (stopPropagation) {
1567 aEvent.stopPropagation();
1568 }
1569 }
1571 function formEventHandlerForInput(aEvent)
1572 {
1573 inputEventCounts[aEvent.type]++;
1574 inputEventData[aEvent.type] = input.value;
1575 }
1577 window.addEventListener("compositionstart", compositionEventHandlerForWindow,
1578 true, true);
1579 window.addEventListener("compositionend", compositionEventHandlerForWindow,
1580 true, true);
1581 window.addEventListener("compositionupdate", compositionEventHandlerForWindow,
1582 true, true);
1583 window.addEventListener("input", formEventHandlerForWindow,
1584 true, true);
1586 input.addEventListener("compositionstart", compositionEventHandlerForInput,
1587 true, true);
1588 input.addEventListener("compositionend", compositionEventHandlerForInput,
1589 true, true);
1590 input.addEventListener("compositionupdate", compositionEventHandlerForInput,
1591 true, true);
1592 input.addEventListener("input", formEventHandlerForInput,
1593 true, true);
1595 // test for normal case
1596 initResults();
1598 synthesizeComposition({ type: "compositionstart" });
1599 synthesizeComposition({ type: "compositionupdate", data: "\u3089" });
1600 synthesizeText(
1601 { "composition":
1602 { "string": "\u3089",
1603 "clauses":
1604 [
1605 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
1606 ]
1607 },
1608 "caret": { "start": 1, "length": 0 }
1609 });
1611 is(windowEventCounts["compositionstart"], 1,
1612 kDescription + "compositionstart hasn't been handled by window #1");
1613 is(windowEventData["compositionstart"], "",
1614 kDescription + "data of compositionstart isn't empty (window) #1");
1615 is(windowEventLocale["compositionstart"], "",
1616 kDescription + "locale of compositionstart isn't empty (window) #1");
1617 is(inputEventCounts["compositionstart"], 1,
1618 kDescription + "compositionstart hasn't been handled by input #1");
1619 is(inputEventData["compositionstart"], "",
1620 kDescription + "data of compositionstart isn't empty (input) #1");
1621 is(inputEventLocale["compositionstart"], "",
1622 kDescription + "locale of compositionstart isn't empty (input) #1");
1624 is(windowEventCounts["compositionupdate"], 1,
1625 kDescription + "compositionupdate hasn't been handled by window #1");
1626 is(windowEventData["compositionupdate"], "\u3089",
1627 kDescription + "data of compositionupdate doesn't match (window) #1");
1628 is(windowEventLocale["compositionupdate"], "",
1629 kDescription + "locale of compositionupdate isn't empty (window) #1");
1630 is(inputEventCounts["compositionupdate"], 1,
1631 kDescription + "compositionupdate hasn't been handled by input #1");
1632 is(inputEventData["compositionupdate"], "\u3089",
1633 kDescription + "data of compositionupdate doesn't match (input) #1");
1634 is(inputEventLocale["compositionupdate"], "",
1635 kDescription + "locale of compositionupdate isn't empty (input) #1");
1637 is(windowEventCounts["compositionend"], 0,
1638 kDescription + "compositionend has been handled by window #1");
1639 is(inputEventCounts["compositionend"], 0,
1640 kDescription + "compositionend has been handled by input #1");
1642 is(windowEventCounts["input"], 1,
1643 kDescription + "input hasn't been handled by window #1");
1644 is(windowEventData["input"], "\u3089",
1645 kDescription + "value of input element wasn't modified (window) #1");
1646 is(inputEventCounts["input"], 1,
1647 kDescription + "input hasn't been handled by input #1");
1648 is(inputEventData["input"], "\u3089",
1649 kDescription + "value of input element wasn't modified (input) #1");
1651 synthesizeComposition({ type: "compositionupdate", data: "\u3089\u30FC" });
1652 synthesizeText(
1653 { "composition":
1654 { "string": "\u3089\u30FC",
1655 "clauses":
1656 [
1657 { "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT }
1658 ]
1659 },
1660 "caret": { "start": 2, "length": 0 }
1661 });
1663 is(windowEventCounts["compositionstart"], 1,
1664 kDescription + "compositionstart has been handled more than once by window #2");
1665 is(inputEventCounts["compositionstart"], 1,
1666 kDescription + "compositionstart has been handled more than once by input #2");
1668 is(windowEventCounts["compositionupdate"], 2,
1669 kDescription + "compositionupdate hasn't been handled by window #2");
1670 is(windowEventData["compositionupdate"], "\u3089\u30FC",
1671 kDescription + "data of compositionupdate doesn't match (window) #2");
1672 is(windowEventLocale["compositionupdate"], "",
1673 kDescription + "locale of compositionupdate isn't empty (window) #2");
1674 is(inputEventCounts["compositionupdate"], 2,
1675 kDescription + "compositionupdate hasn't been handled by input #2");
1676 is(inputEventData["compositionupdate"], "\u3089\u30FC",
1677 kDescription + "data of compositionupdate doesn't match (input) #2");
1678 is(inputEventLocale["compositionupdate"], "",
1679 kDescription + "locale of compositionupdate isn't empty (input) #2");
1681 is(windowEventCounts["compositionend"], 0,
1682 kDescription + "compositionend has been handled during composition by window #2");
1683 is(inputEventCounts["compositionend"], 0,
1684 kDescription + "compositionend has been handled during composition by input #2");
1686 is(windowEventCounts["input"], 2,
1687 kDescription + "input hasn't been handled by window #2");
1688 is(windowEventData["input"], "\u3089\u30FC",
1689 kDescription + "value of input element wasn't modified (window) #2");
1690 is(inputEventCounts["input"], 2,
1691 kDescription + "input hasn't been handled by input #2");
1692 is(inputEventData["input"], "\u3089\u30FC",
1693 kDescription + "value of input element wasn't modified (input) #2");
1695 // text event shouldn't cause composition update, e.g., at committing.
1696 synthesizeText(
1697 { "composition":
1698 { "string": "\u3089\u30FC",
1699 "clauses":
1700 [
1701 { "length": 0, "attr": 0 }
1702 ]
1703 },
1704 "caret": { "start": 2, "length": 0 }
1705 });
1707 synthesizeComposition({ type: "compositionend", data: "\u3089\u30FC" });
1709 is(windowEventCounts["compositionstart"], 1,
1710 kDescription + "compositionstart has been handled more than once by window #3");
1711 is(inputEventCounts["compositionstart"], 1,
1712 kDescription + "compositionstart has been handled more than once by input #3");
1714 is(windowEventCounts["compositionupdate"], 2,
1715 kDescription + "compositionupdate has been fired unexpectedly on window #3");
1716 is(inputEventCounts["compositionupdate"], 2,
1717 kDescription + "compositionupdate has been fired unexpectedly on input #3");
1719 is(windowEventCounts["compositionend"], 1,
1720 kDescription + "compositionend hasn't been handled by window #3");
1721 is(windowEventData["compositionend"], "\u3089\u30FC",
1722 kDescription + "data of compositionend doesn't match (window) #3");
1723 is(windowEventLocale["compositionend"], "",
1724 kDescription + "locale of compositionend isn't empty (window) #3");
1725 is(inputEventCounts["compositionend"], 1,
1726 kDescription + "compositionend hasn't been handled by input #3");
1727 is(inputEventData["compositionend"], "\u3089\u30FC",
1728 kDescription + "data of compositionend doesn't match (input) #3");
1729 is(inputEventLocale["compositionend"], "",
1730 kDescription + "locale of compositionend isn't empty (input) #3");
1732 is(windowEventCounts["input"], 3,
1733 kDescription + "input hasn't been handled by window #3");
1734 is(windowEventData["input"], "\u3089\u30FC",
1735 kDescription + "value of input element wasn't modified (window) #3");
1736 is(inputEventCounts["input"], 3,
1737 kDescription + "input hasn't been handled by input #3");
1738 is(inputEventData["input"], "\u3089\u30FC",
1739 kDescription + "value of input element wasn't modified (input) #3");
1741 // select the second character, then, data of composition start should be
1742 // the selected character.
1743 initResults();
1744 synthesizeKey("VK_LEFT", { shiftKey: true });
1746 synthesizeComposition({ type: "compositionstart" });
1748 synthesizeComposition({ type: "compositionupdate", data: "\u3089" });
1749 synthesizeText(
1750 { "composition":
1751 { "string": "\u3089",
1752 "clauses":
1753 [
1754 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
1755 ]
1756 },
1757 "caret": { "start": 1, "length": 0 }
1758 });
1760 synthesizeText(
1761 { "composition":
1762 { "string": "\u3089",
1763 "clauses":
1764 [
1765 { "length": 0, "attr": 0 }
1766 ]
1767 },
1768 "caret": { "start": 1, "length": 0 }
1769 });
1771 synthesizeComposition({ type: "compositionend", data: "\u3089" });
1773 is(windowEventCounts["compositionstart"], 1,
1774 kDescription + "compositionstart hasn't been handled by window #4");
1775 is(windowEventData["compositionstart"], "\u30FC",
1776 kDescription + "data of compositionstart is empty (window) #4");
1777 is(windowEventLocale["compositionstart"], "",
1778 kDescription + "locale of compositionstart isn't empty (window) #4");
1779 is(inputEventCounts["compositionstart"], 1,
1780 kDescription + "compositionstart hasn't been handled by input #4");
1781 is(inputEventData["compositionstart"], "\u30FC",
1782 kDescription + "data of compositionstart is empty (input) #4");
1783 is(inputEventLocale["compositionstart"], "",
1784 kDescription + "locale of compositionstart isn't empty (input) #4");
1786 is(windowEventCounts["compositionupdate"], 1,
1787 kDescription + "compositionupdate hasn't been handled by window #4");
1788 is(windowEventData["compositionupdate"], "\u3089",
1789 kDescription + "data of compositionupdate doesn't match (window) #4");
1790 is(windowEventLocale["compositionupdate"], "",
1791 kDescription + "locale of compositionupdate isn't empty (window) #4");
1792 is(inputEventCounts["compositionupdate"], 1,
1793 kDescription + "compositionupdate hasn't been handled by input #4");
1794 is(inputEventData["compositionupdate"], "\u3089",
1795 kDescription + "data of compositionupdate doesn't match (input) #4");
1796 is(inputEventLocale["compositionupdate"], "",
1797 kDescription + "locale of compositionupdate isn't empty (input) #4");
1799 is(windowEventCounts["compositionend"], 1,
1800 kDescription + "compositionend hasn't been handled by window #4");
1801 is(windowEventData["compositionend"], "\u3089",
1802 kDescription + "data of compositionend doesn't match (window) #4");
1803 is(windowEventLocale["compositionend"], "",
1804 kDescription + "locale of compositionend isn't empty (window) #4");
1805 is(inputEventCounts["compositionend"], 1,
1806 kDescription + "compositionend hasn't been handled by input #4");
1807 is(inputEventData["compositionend"], "\u3089",
1808 kDescription + "data of compositionend doesn't match (input) #4");
1809 is(inputEventLocale["compositionend"], "",
1810 kDescription + "locale of compositionend isn't empty (input) #4");
1812 is(windowEventCounts["input"], 2,
1813 kDescription + "input hasn't been handled by window #4");
1814 is(windowEventData["input"], "\u3089\u3089",
1815 kDescription + "value of input element wasn't modified (window) #4");
1816 is(inputEventCounts["input"], 2,
1817 kDescription + "input hasn't been handled by input #4");
1818 is(inputEventData["input"], "\u3089\u3089",
1819 kDescription + "value of input element wasn't modified (input) #4");
1821 // preventDefault() should effect nothing.
1822 preventDefault = true;
1824 initResults();
1825 synthesizeKey("A", { accelKey: true }); // Select All
1827 synthesizeComposition({ type: "compositionstart" });
1829 synthesizeComposition({ type: "compositionupdate", data: "\u306D" });
1830 synthesizeText(
1831 { "composition":
1832 { "string": "\u306D",
1833 "clauses":
1834 [
1835 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
1836 ]
1837 },
1838 "caret": { "start": 1, "length": 0 }
1839 });
1841 synthesizeText(
1842 { "composition":
1843 { "string": "\u306D",
1844 "clauses":
1845 [
1846 { "length": 0, "attr": 0 }
1847 ]
1848 },
1849 "caret": { "start": 1, "length": 0 }
1850 });
1852 synthesizeComposition({ type: "compositionend", data: "\u306D" });
1854 is(windowEventCounts["compositionstart"], 1,
1855 kDescription + "compositionstart hasn't been handled by window #5");
1856 is(windowEventData["compositionstart"], "\u3089\u3089",
1857 kDescription + "data of compositionstart is empty (window) #5");
1858 is(windowEventLocale["compositionstart"], "",
1859 kDescription + "locale of compositionstart isn't empty (window) #5");
1860 is(inputEventCounts["compositionstart"], 1,
1861 kDescription + "compositionstart hasn't been handled by input #5");
1862 is(inputEventData["compositionstart"], "\u3089\u3089",
1863 kDescription + "data of compositionstart is empty (input) #5");
1864 is(inputEventLocale["compositionstart"], "",
1865 kDescription + "locale of compositionstart isn't empty (input) #5");
1867 is(windowEventCounts["compositionupdate"], 1,
1868 kDescription + "compositionupdate hasn't been handled by window #5");
1869 is(windowEventData["compositionupdate"], "\u306D",
1870 kDescription + "data of compositionupdate doesn't match (window) #5");
1871 is(windowEventLocale["compositionupdate"], "",
1872 kDescription + "locale of compositionupdate isn't empty (window) #5");
1873 is(inputEventCounts["compositionupdate"], 1,
1874 kDescription + "compositionupdate hasn't been handled by input #5");
1875 is(inputEventData["compositionupdate"], "\u306D",
1876 kDescription + "data of compositionupdate doesn't match (input) #5");
1877 is(inputEventLocale["compositionupdate"], "",
1878 kDescription + "locale of compositionupdate isn't empty (input) #5");
1880 is(windowEventCounts["compositionend"], 1,
1881 kDescription + "compositionend hasn't been handled by window #5");
1882 is(windowEventData["compositionend"], "\u306D",
1883 kDescription + "data of compositionend doesn't match (window) #5");
1884 is(windowEventLocale["compositionend"], "",
1885 kDescription + "locale of compositionend isn't empty (window) #5");
1886 is(inputEventCounts["compositionend"], 1,
1887 kDescription + "compositionend hasn't been handled by input #5");
1888 is(inputEventData["compositionend"], "\u306D",
1889 kDescription + "data of compositionend doesn't match (input) #5");
1890 is(inputEventLocale["compositionend"], "",
1891 kDescription + "locale of compositionend isn't empty (input) #5");
1893 is(windowEventCounts["input"], 2,
1894 kDescription + "input hasn't been handled by window #5");
1895 is(windowEventData["input"], "\u306D",
1896 kDescription + "value of input element wasn't modified (window) #5");
1897 is(inputEventCounts["input"], 2,
1898 kDescription + "input hasn't been handled by input #5");
1899 is(inputEventData["input"], "\u306D",
1900 kDescription + "value of input element wasn't modified (input) #5");
1902 prevnetDefault = false;
1904 // stopPropagation() should effect nothing (except event count)
1905 stopPropagation = true;
1907 initResults();
1908 synthesizeKey("A", { accelKey: true }); // Select All
1910 synthesizeComposition({ type: "compositionstart" });
1912 synthesizeComposition({ type: "compositionupdate", data: "\u306E" });
1913 synthesizeText(
1914 { "composition":
1915 { "string": "\u306E",
1916 "clauses":
1917 [
1918 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
1919 ]
1920 },
1921 "caret": { "start": 1, "length": 0 }
1922 });
1924 synthesizeText(
1925 { "composition":
1926 { "string": "\u306E",
1927 "clauses":
1928 [
1929 { "length": 0, "attr": 0 }
1930 ]
1931 },
1932 "caret": { "start": 1, "length": 0 }
1933 });
1935 synthesizeComposition({ type: "compositionend", data: "\u306E" });
1937 is(windowEventCounts["compositionstart"], 1,
1938 kDescription + "compositionstart hasn't been handled by window #6");
1939 is(windowEventData["compositionstart"], "\u306D",
1940 kDescription + "data of compositionstart is empty #6");
1941 is(windowEventLocale["compositionstart"], "",
1942 kDescription + "locale of compositionstart isn't empty #6");
1943 is(inputEventCounts["compositionstart"], 0,
1944 kDescription + "compositionstart has been handled by input #6");
1946 is(windowEventCounts["compositionupdate"], 1,
1947 kDescription + "compositionupdate hasn't been handled by window #6");
1948 is(windowEventData["compositionupdate"], "\u306E",
1949 kDescription + "data of compositionupdate doesn't match #6");
1950 is(windowEventLocale["compositionupdate"], "",
1951 kDescription + "locale of compositionupdate isn't empty #6");
1952 is(inputEventCounts["compositionupdate"], 0,
1953 kDescription + "compositionupdate has been handled by input #6");
1955 is(windowEventCounts["compositionend"], 1,
1956 kDescription + "compositionend hasn't been handled by window #6");
1957 is(windowEventData["compositionend"], "\u306E",
1958 kDescription + "data of compositionend doesn't match #6");
1959 is(windowEventLocale["compositionend"], "",
1960 kDescription + "locale of compositionend isn't empty #6");
1961 is(inputEventCounts["compositionend"], 0,
1962 kDescription + "compositionend has been handled by input #6");
1964 is(windowEventCounts["input"], 2,
1965 kDescription + "input hasn't been handled by window #6");
1966 is(windowEventData["input"], "\u306E",
1967 kDescription + "value of input element wasn't modified (window) #6");
1968 is(inputEventCounts["input"], 2,
1969 kDescription + "input hasn't been handled by input #6");
1970 is(inputEventData["input"], "\u306E",
1971 kDescription + "value of input element wasn't modified (input) #6");
1973 stopPropagation = false;
1975 // create event and dispatch it.
1976 initResults();
1978 input.value = "value of input";
1979 synthesizeKey("A", { accelKey: true }); // Select All
1981 var compositionstart = document.createEvent("CompositionEvent");
1982 compositionstart.initCompositionEvent("compositionstart",
1983 true, true, document.defaultView,
1984 "start data", "start locale");
1985 is(compositionstart.type, "compositionstart",
1986 kDescription + "type doesn't match #7");
1987 is(compositionstart.data, "start data",
1988 kDescription + "data doesn't match #7");
1989 is(compositionstart.locale, "start locale",
1990 kDescription + "locale doesn't match #7");
1991 is(compositionstart.detail, 0,
1992 kDescription + "detail isn't 0 #7");
1994 input.dispatchEvent(compositionstart);
1996 is(windowEventCounts["compositionstart"], 1,
1997 kDescription + "compositionstart hasn't been handled by window #7");
1998 is(windowEventData["compositionstart"], "start data",
1999 kDescription + "data of compositionstart was changed (window) #7");
2000 is(windowEventLocale["compositionstart"], "start locale",
2001 kDescription + "locale of compositionstart was changed (window) #7");
2002 is(inputEventCounts["compositionstart"], 1,
2003 kDescription + "compositionstart hasn't been handled by input #7");
2004 is(inputEventData["compositionstart"], "start data",
2005 kDescription + "data of compositionstart was changed (input) #7");
2006 is(inputEventLocale["compositionstart"], "start locale",
2007 kDescription + "locale of compositionstart was changed (input) #7");
2009 is(input.value, "value of input",
2010 kDescription + "input value was changed #7");
2012 var compositionupdate1 = document.createEvent("compositionevent");
2013 compositionupdate1.initCompositionEvent("compositionupdate",
2014 true, false, document.defaultView,
2015 "composing string", "composing locale");
2016 is(compositionupdate1.type, "compositionupdate",
2017 kDescription + "type doesn't match #8");
2018 is(compositionupdate1.data, "composing string",
2019 kDescription + "data doesn't match #8");
2020 is(compositionupdate1.locale, "composing locale",
2021 kDescription + "locale doesn't match #8");
2022 is(compositionupdate1.detail, 0,
2023 kDescription + "detail isn't 0 #8");
2025 input.dispatchEvent(compositionupdate1);
2027 is(windowEventCounts["compositionupdate"], 1,
2028 kDescription + "compositionupdate hasn't been handled by window #8");
2029 is(windowEventData["compositionupdate"], "composing string",
2030 kDescription + "data of compositionupdate was changed (window) #8");
2031 is(windowEventLocale["compositionupdate"], "composing locale",
2032 kDescription + "locale of compositionupdate was changed (window) #8");
2033 is(inputEventCounts["compositionupdate"], 1,
2034 kDescription + "compositionupdate hasn't been handled by input #8");
2035 is(inputEventData["compositionupdate"], "composing string",
2036 kDescription + "data of compositionupdate was changed (input) #8");
2037 is(inputEventLocale["compositionupdate"], "composing locale",
2038 kDescription + "locale of compositionupdate was changed (input) #8");
2040 is(input.value, "value of input",
2041 kDescription + "input value was changed #8");
2043 var compositionupdate2 = document.createEvent("compositionEvent");
2044 compositionupdate2.initCompositionEvent("compositionupdate",
2045 true, false, document.defaultView,
2046 "commit string", "commit locale");
2047 is(compositionupdate2.type, "compositionupdate",
2048 kDescription + "type doesn't match #9");
2049 is(compositionupdate2.data, "commit string",
2050 kDescription + "data doesn't match #9");
2051 is(compositionupdate2.locale, "commit locale",
2052 kDescription + "locale doesn't match #9");
2053 is(compositionupdate2.detail, 0,
2054 kDescription + "detail isn't 0 #9");
2056 input.dispatchEvent(compositionupdate2);
2058 is(windowEventCounts["compositionupdate"], 2,
2059 kDescription + "compositionupdate hasn't been handled by window #9");
2060 is(windowEventData["compositionupdate"], "commit string",
2061 kDescription + "data of compositionupdate was changed (window) #9");
2062 is(windowEventLocale["compositionupdate"], "commit locale",
2063 kDescription + "locale of compositionupdate was changed (window) #9");
2064 is(inputEventCounts["compositionupdate"], 2,
2065 kDescription + "compositionupdate hasn't been handled by input #9");
2066 is(inputEventData["compositionupdate"], "commit string",
2067 kDescription + "data of compositionupdate was changed (input) #9");
2068 is(inputEventLocale["compositionupdate"], "commit locale",
2069 kDescription + "locale of compositionupdate was changed (input) #9");
2071 is(input.value, "value of input",
2072 kDescription + "input value was changed #9");
2074 var compositionend = document.createEvent("Compositionevent");
2075 compositionend.initCompositionEvent("compositionend",
2076 true, false, document.defaultView,
2077 "end data", "end locale");
2078 is(compositionend.type, "compositionend",
2079 kDescription + "type doesn't match #10");
2080 is(compositionend.data, "end data",
2081 kDescription + "data doesn't match #10");
2082 is(compositionend.locale, "end locale",
2083 kDescription + "locale doesn't match #10");
2084 is(compositionend.detail, 0,
2085 kDescription + "detail isn't 0 #10");
2087 input.dispatchEvent(compositionend);
2089 is(windowEventCounts["compositionend"], 1,
2090 kDescription + "compositionend hasn't been handled by window #10");
2091 is(windowEventData["compositionend"], "end data",
2092 kDescription + "data of compositionend was changed (window) #10");
2093 is(windowEventLocale["compositionend"], "end locale",
2094 kDescription + "locale of compositionend was changed (window) #10");
2095 is(inputEventCounts["compositionend"], 1,
2096 kDescription + "compositionend hasn't been handled by input #10");
2097 is(inputEventData["compositionend"], "end data",
2098 kDescription + "data of compositionend was changed (input) #10");
2099 is(inputEventLocale["compositionend"], "end locale",
2100 kDescription + "locale of compositionend was changed (input) #10");
2102 is(input.value, "value of input",
2103 kDescription + "input value was changed #10");
2105 window.removeEventListener("compositionstart",
2106 compositionEventHandlerForWindow, true);
2107 window.removeEventListener("compositionend",
2108 compositionEventHandlerForWindow, true);
2109 window.removeEventListener("compositionupdate",
2110 compositionEventHandlerForWindow, true);
2111 window.removeEventListener("input",
2112 formEventHandlerForWindow, true);
2114 input.removeEventListener("compositionstart",
2115 compositionEventHandlerForInput, true);
2116 input.removeEventListener("compositionend",
2117 compositionEventHandlerForInput, true);
2118 input.removeEventListener("compositionupdate",
2119 compositionEventHandlerForInput, true);
2120 input.removeEventListener("input",
2121 formEventHandlerForInput, true);
2122 }
2124 function runCharAtPointTest(aFocusedEditor, aTargetName)
2125 {
2126 aFocusedEditor.value = "This is a test of the\nContent Events";
2127 // 012345678901234567890 12345678901234
2128 // 0 1 2 3
2130 aFocusedEditor.focus();
2132 const kNone = -1;
2133 const kTestingOffset = [ 0, 10, 20, 21 + kLFLen, 34 + kLFLen];
2134 const kLeftSideOffset = [ kNone, 9, 19, kNone, 33 + kLFLen];
2135 const kRightSideOffset = [ 1, 11, kNone, 22 + kLFLen, kNone];
2137 var editorRect = synthesizeQueryEditorRect();
2138 if (!checkQueryContentResult(editorRect,
2139 "runCharAtPointTest (" + aTargetName + "): editorRect")) {
2140 return;
2141 }
2143 for (var i = 0; i < kTestingOffset.length; i++) {
2144 var textRect = synthesizeQueryTextRect(kTestingOffset[i], 1);
2145 if (!checkQueryContentResult(textRect,
2146 "runCharAtPointTest (" + aTargetName + "): textRect: i=" + i)) {
2147 continue;
2148 }
2150 checkRectContainsRect(textRect, editorRect,
2151 "runCharAtPointTest (" + aTargetName +
2152 "): the text rect isn't in the editor");
2154 // Test #1, getting same character rect by the point near the top-left.
2155 var charAtPt1 = synthesizeCharAtPoint(textRect.left + 1,
2156 textRect.top + 1);
2157 if (checkQueryContentResult(charAtPt1,
2158 "runCharAtPointTest (" + aTargetName + "): charAtPt1: i=" + i)) {
2159 ok(!charAtPt1.notFound,
2160 "runCharAtPointTest (" + aTargetName + "): charAtPt1 isn't found: i=" + i);
2161 if (!charAtPt1.notFound) {
2162 is(charAtPt1.offset, kTestingOffset[i],
2163 "runCharAtPointTest (" + aTargetName + "): charAtPt1 offset is wrong: i=" + i);
2164 checkRect(charAtPt1, textRect, "runCharAtPointTest (" + aTargetName +
2165 "): charAtPt1 left is wrong: i=" + i);
2166 }
2167 }
2169 // Test #2, getting same character rect by the point near the bottom-right.
2170 var charAtPt2 = synthesizeCharAtPoint(textRect.left + textRect.width - 2,
2171 textRect.top + textRect.height - 2);
2172 if (checkQueryContentResult(charAtPt2,
2173 "runCharAtPointTest (" + aTargetName + "): charAtPt2: i=" + i)) {
2174 ok(!charAtPt2.notFound,
2175 "runCharAtPointTest (" + aTargetName + "): charAtPt2 isn't found: i=" + i);
2176 if (!charAtPt2.notFound) {
2177 is(charAtPt2.offset, kTestingOffset[i],
2178 "runCharAtPointTest (" + aTargetName + "): charAtPt2 offset is wrong: i=" + i);
2179 checkRect(charAtPt2, textRect, "runCharAtPointTest (" + aTargetName +
2180 "): charAtPt1 left is wrong: i=" + i);
2181 }
2182 }
2184 // Test #3, getting left character offset.
2185 var charAtPt3 = synthesizeCharAtPoint(textRect.left - 2,
2186 textRect.top + 1);
2187 if (checkQueryContentResult(charAtPt3,
2188 "runCharAtPointTest (" + aTargetName + "): charAtPt3: i=" + i)) {
2189 is(charAtPt3.notFound, kLeftSideOffset[i] == kNone,
2190 kLeftSideOffset[i] == kNone ?
2191 "runCharAtPointTest (" + aTargetName + "): charAtPt3 is found: i=" + i :
2192 "runCharAtPointTest (" + aTargetName + "): charAtPt3 isn't found: i=" + i);
2193 if (!charAtPt3.notFound) {
2194 is(charAtPt3.offset, kLeftSideOffset[i],
2195 "runCharAtPointTest (" + aTargetName + "): charAtPt3 offset is wrong: i=" + i);
2196 }
2197 }
2199 // Test #4, getting right character offset.
2200 var charAtPt4 = synthesizeCharAtPoint(textRect.left + textRect.width + 1,
2201 textRect.top + textRect.height - 2);
2202 if (checkQueryContentResult(charAtPt4,
2203 "runCharAtPointTest (" + aTargetName + "): charAtPt4: i=" + i)) {
2204 is(charAtPt4.notFound, kRightSideOffset[i] == kNone,
2205 kRightSideOffset[i] == kNone ?
2206 "runCharAtPointTest (" + aTargetName + "): charAtPt4 is found: i=" + i :
2207 "runCharAtPointTest (" + aTargetName + "): charAtPt4 isn't found: i=" + i);
2208 if (!charAtPt4.notFound) {
2209 is(charAtPt4.offset, kRightSideOffset[i],
2210 "runCharAtPointTest (" + aTargetName + "): charAtPt4 offset is wrong: i=" + i);
2211 }
2212 }
2213 }
2214 }
2216 function runCharAtPointAtOutsideTest()
2217 {
2218 textarea.focus();
2219 textarea.value = "some text";
2220 var editorRect = synthesizeQueryEditorRect();
2221 if (!checkQueryContentResult(editorRect,
2222 "runCharAtPointAtOutsideTest: editorRect")) {
2223 return;
2224 }
2225 // Check on a text node which is at the outside of editor.
2226 var charAtPt = synthesizeCharAtPoint(editorRect.left + 20,
2227 editorRect.top - 10);
2228 if (checkQueryContentResult(charAtPt,
2229 "runCharAtPointAtOutsideTest: charAtPt")) {
2230 ok(charAtPt.notFound,
2231 "runCharAtPointAtOutsideTest: charAtPt is found on outside of editor");
2232 }
2233 }
2235 function runBug722639Test()
2236 {
2237 textarea.focus();
2238 textarea.value = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
2239 textarea.value += textarea.value;
2240 textarea.value += textarea.value; // 80 characters
2242 var firstLine = synthesizeQueryTextRect(0, 1);
2243 if (!checkQueryContentResult(firstLine,
2244 "runBug722639Test: firstLine")) {
2245 return;
2246 }
2247 var secondLine = synthesizeQueryTextRect(kLFLen, 1);
2248 if (!checkQueryContentResult(secondLine,
2249 "runBug722639Test: secondLine")) {
2250 return;
2251 }
2252 var lineHeight = secondLine.top - firstLine.top;
2253 ok(lineHeight > 0,
2254 "runBug722639Test: lineHeight must be positive");
2255 is(secondLine.left, firstLine.left,
2256 "runBug722639Test: the left value must be always same value");
2257 var previousTop = secondLine.top;
2258 for (var i = 2; i < textarea.value.length; i++) {
2259 var currentLine = synthesizeQueryTextRect(kLFLen * i, 1);
2260 if (!checkQueryContentResult(currentLine,
2261 "runBug722639Test: " + i + "th currentLine")) {
2262 return;
2263 }
2264 // NOTE: the top position may be 1px larger or smaller than other lines
2265 // due to sub pixel positioning.
2266 if (Math.abs(currentLine.top - (previousTop + lineHeight)) <= 1) {
2267 ok(true, "runBug722639Test: " + i + "th line's top is expected");
2268 } else {
2269 is(currentLine.top, previousTop + lineHeight,
2270 "runBug722639Test: " + i + "th line's top is unexpected");
2271 }
2272 is(currentLine.left, firstLine.left,
2273 "runBug722639Test: " + i + "th line's left is unexpected");
2274 previousTop = currentLine.top;
2275 }
2276 }
2278 function runForceCommitTest()
2279 {
2280 var events;
2281 function eventHandler(aEvent)
2282 {
2283 events.push(aEvent);
2284 }
2285 window.addEventListener("compositionstart", eventHandler, true);
2286 window.addEventListener("compositionupdate", eventHandler, true);
2287 window.addEventListener("compositionend", eventHandler, true);
2288 window.addEventListener("input", eventHandler, true);
2289 window.addEventListener("text", eventHandler, true);
2291 // Make the composition in textarea commit by click in the textarea
2292 textarea.focus();
2293 textarea.value = "";
2295 events = [];
2296 synthesizeComposition({ type: "compositionstart" });
2298 synthesizeComposition({ type: "compositionupdate", data: "\u306E" });
2299 synthesizeText(
2300 { "composition":
2301 { "string": "\u306E",
2302 "clauses":
2303 [
2304 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
2305 ]
2306 },
2307 "caret": { "start": 1, "length": 0 }
2308 });
2310 is(events.length, 4,
2311 "runForceCommitTest: wrong event count #1");
2312 is(events[0].type, "compositionstart",
2313 "runForceCommitTest: the 1st event must be compositionstart #1");
2314 is(events[1].type, "compositionupdate",
2315 "runForceCommitTest: the 2nd event must be compositionupdate #1");
2316 is(events[2].type, "text",
2317 "runForceCommitTest: the 3rd event must be text #1");
2318 is(events[3].type, "input",
2319 "runForceCommitTest: the 4th event must be input #1");
2321 events = [];
2322 synthesizeMouseAtCenter(textarea, {});
2324 is(events.length, 3,
2325 "runForceCommitTest: wrong event count #2");
2326 is(events[0].type, "text",
2327 "runForceCommitTest: the 1st event must be text #2");
2328 is(events[1].type, "compositionend",
2329 "runForceCommitTest: the 2nd event must be compositionend #2");
2330 is(events[2].type, "input",
2331 "runForceCommitTest: the 3rd event must be input #2");
2332 is(events[1].data, "\u306E",
2333 "runForceCommitTest: compositionend has wrong data #2");
2334 is(events[0].target, textarea,
2335 "runForceCommitTest: The 1st event was fired on wrong event target #2");
2336 is(events[1].target, textarea,
2337 "runForceCommitTest: The 2nd event was fired on wrong event target #2");
2338 is(events[2].target, textarea,
2339 "runForceCommitTest: The 3rd event was fired on wrong event target #2");
2340 ok(!getEditorIMESupport(textarea).isComposing,
2341 "runForceCommitTest: the textarea still has composition #2");
2342 is(textarea.value, "\u306E",
2343 "runForceCommitTest: the textarea doesn't have the committed text #2");
2345 // Make the composition in textarea commit by click in another editor (input)
2346 textarea.focus();
2347 textarea.value = "";
2348 input.value = "";
2350 synthesizeComposition({ type: "compositionstart" });
2352 synthesizeComposition({ type: "compositionupdate", data: "\u306E" });
2353 synthesizeText(
2354 { "composition":
2355 { "string": "\u306E",
2356 "clauses":
2357 [
2358 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
2359 ]
2360 },
2361 "caret": { "start": 1, "length": 0 }
2362 });
2364 events = [];
2365 synthesizeMouseAtCenter(input, {});
2367 is(events.length, 3,
2368 "runForceCommitTest: wrong event count #3");
2369 is(events[0].type, "text",
2370 "runForceCommitTest: the 1st event must be text #3");
2371 is(events[1].type, "compositionend",
2372 "runForceCommitTest: the 2nd event must be compositionend #3");
2373 is(events[2].type, "input",
2374 "runForceCommitTest: the 3rd event must be input #3");
2375 is(events[1].data, "\u306E",
2376 "runForceCommitTest: compositionend has wrong data #3");
2377 is(events[0].target, textarea,
2378 "runForceCommitTest: The 1st event was fired on wrong event target #3");
2379 is(events[1].target, textarea,
2380 "runForceCommitTest: The 2nd event was fired on wrong event target #3");
2381 is(events[2].target, textarea,
2382 "runForceCommitTest: The 3rd event was fired on wrong event target #3");
2383 ok(!getEditorIMESupport(textarea).isComposing,
2384 "runForceCommitTest: the textarea still has composition #3");
2385 ok(!getEditorIMESupport(input).isComposing,
2386 "runForceCommitTest: the input has composition #3");
2387 is(textarea.value, "\u306E",
2388 "runForceCommitTest: the textarea doesn't have the committed text #3");
2389 is(input.value, "",
2390 "runForceCommitTest: the input has the committed text? #3");
2392 // Make the composition in textarea commit by blur()
2393 textarea.focus();
2394 textarea.value = "";
2396 synthesizeComposition({ type: "compositionstart" });
2398 synthesizeComposition({ type: "compositionupdate", data: "\u306E" });
2399 synthesizeText(
2400 { "composition":
2401 { "string": "\u306E",
2402 "clauses":
2403 [
2404 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
2405 ]
2406 },
2407 "caret": { "start": 1, "length": 0 }
2408 });
2410 events = [];
2411 textarea.blur();
2413 is(events.length, 3,
2414 "runForceCommitTest: wrong event count #4");
2415 is(events[0].type, "text",
2416 "runForceCommitTest: the 1st event must be text #4");
2417 is(events[1].type, "compositionend",
2418 "runForceCommitTest: the 2nd event must be compositionend #4");
2419 is(events[2].type, "input",
2420 "runForceCommitTest: the 3rd event must be input #4");
2421 is(events[1].data, "\u306E",
2422 "runForceCommitTest: compositionend has wrong data #4");
2423 is(events[0].target, textarea,
2424 "runForceCommitTest: The 1st event was fired on wrong event target #4");
2425 is(events[1].target, textarea,
2426 "runForceCommitTest: The 2nd event was fired on wrong event target #4");
2427 is(events[2].target, textarea,
2428 "runForceCommitTest: The 3rd event was fired on wrong event target #4");
2429 ok(!getEditorIMESupport(textarea).isComposing,
2430 "runForceCommitTest: the textarea still has composition #4");
2431 is(textarea.value, "\u306E",
2432 "runForceCommitTest: the textarea doesn't have the committed text #4");
2434 // Make the composition in textarea commit by input.focus()
2435 textarea.focus();
2436 textarea.value = "";
2437 input.value = "";
2439 synthesizeComposition({ type: "compositionstart" });
2441 synthesizeComposition({ type: "compositionupdate", data: "\u306E" });
2442 synthesizeText(
2443 { "composition":
2444 { "string": "\u306E",
2445 "clauses":
2446 [
2447 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
2448 ]
2449 },
2450 "caret": { "start": 1, "length": 0 }
2451 });
2453 events = [];
2454 input.focus();
2456 is(events.length, 3,
2457 "runForceCommitTest: wrong event count #5");
2458 is(events[0].type, "text",
2459 "runForceCommitTest: the 1st event must be text #5");
2460 is(events[1].type, "compositionend",
2461 "runForceCommitTest: the 2nd event must be compositionend #5");
2462 is(events[2].type, "input",
2463 "runForceCommitTest: the 3rd event must be input #5");
2464 is(events[1].data, "\u306E",
2465 "runForceCommitTest: compositionend has wrong data #5");
2466 is(events[0].target, textarea,
2467 "runForceCommitTest: The 1st event was fired on wrong event target #5");
2468 is(events[1].target, textarea,
2469 "runForceCommitTest: The 2nd event was fired on wrong event target #5");
2470 is(events[2].target, textarea,
2471 "runForceCommitTest: The 3rd event was fired on wrong event target #5");
2472 ok(!getEditorIMESupport(textarea).isComposing,
2473 "runForceCommitTest: the textarea still has composition #5");
2474 ok(!getEditorIMESupport(input).isComposing,
2475 "runForceCommitTest: the input has composition #5");
2476 is(textarea.value, "\u306E",
2477 "runForceCommitTest: the textarea doesn't have the committed text #5");
2478 is(input.value, "",
2479 "runForceCommitTest: the input has the committed text? #5");
2481 // Make the composition in textarea commit by click in another document's editor
2482 textarea.focus();
2483 textarea.value = "";
2484 textareaInFrame.value = "";
2486 synthesizeComposition({ type: "compositionstart" });
2488 synthesizeComposition({ type: "compositionupdate", data: "\u306E" });
2489 synthesizeText(
2490 { "composition":
2491 { "string": "\u306E",
2492 "clauses":
2493 [
2494 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
2495 ]
2496 },
2497 "caret": { "start": 1, "length": 0 }
2498 });
2500 events = [];
2501 synthesizeMouseAtCenter(textareaInFrame, {}, iframe.contentWindow);
2503 is(events.length, 3,
2504 "runForceCommitTest: wrong event count #6");
2505 is(events[0].type, "text",
2506 "runForceCommitTest: the 1st event must be text #6");
2507 is(events[1].type, "compositionend",
2508 "runForceCommitTest: the 2nd event must be compositionend #6");
2509 is(events[2].type, "input",
2510 "runForceCommitTest: the 3rd event must be input #6");
2511 is(events[1].data, "\u306E",
2512 "runForceCommitTest: compositionend has wrong data #6");
2513 is(events[0].target, textarea,
2514 "runForceCommitTest: The 1st event was fired on wrong event target #6");
2515 is(events[1].target, textarea,
2516 "runForceCommitTest: The 2nd event was fired on wrong event target #6");
2517 is(events[2].target, textarea,
2518 "runForceCommitTest: The 3rd event was fired on wrong event target #6");
2519 ok(!getEditorIMESupport(textarea).isComposing,
2520 "runForceCommitTest: the textarea still has composition #6");
2521 ok(!getEditorIMESupport(textareaInFrame).isComposing,
2522 "runForceCommitTest: the textarea in frame has composition #6");
2523 is(textarea.value, "\u306E",
2524 "runForceCommitTest: the textarea doesn't have the committed text #6");
2525 is(textareaInFrame.value, "",
2526 "runForceCommitTest: the textarea in frame has the committed text? #6");
2528 // Make the composition in textarea commit by another document's editor's focus()
2529 textarea.focus();
2530 textarea.value = "";
2531 textareaInFrame.value = "";
2533 synthesizeComposition({ type: "compositionstart" });
2535 synthesizeComposition({ type: "compositionupdate", data: "\u306E" });
2536 synthesizeText(
2537 { "composition":
2538 { "string": "\u306E",
2539 "clauses":
2540 [
2541 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
2542 ]
2543 },
2544 "caret": { "start": 1, "length": 0 }
2545 });
2547 events = [];
2548 textareaInFrame.focus();
2550 is(events.length, 3,
2551 "runForceCommitTest: wrong event count #7");
2552 is(events[0].type, "text",
2553 "runForceCommitTest: the 1st event must be text #7");
2554 is(events[1].type, "compositionend",
2555 "runForceCommitTest: the 2nd event must be compositionend #7");
2556 is(events[2].type, "input",
2557 "runForceCommitTest: the 3rd event must be input #7");
2558 is(events[1].data, "\u306E",
2559 "runForceCommitTest: compositionend has wrong data #7");
2560 is(events[0].target, textarea,
2561 "runForceCommitTest: The 1st event was fired on wrong event target #7");
2562 is(events[1].target, textarea,
2563 "runForceCommitTest: The 2nd event was fired on wrong event target #7");
2564 is(events[2].target, textarea,
2565 "runForceCommitTest: The 3rd event was fired on wrong event target #7");
2566 ok(!getEditorIMESupport(textarea).isComposing,
2567 "runForceCommitTest: the textarea still has composition #7");
2568 ok(!getEditorIMESupport(textareaInFrame).isComposing,
2569 "runForceCommitTest: the textarea in frame has composition #7");
2570 is(textarea.value, "\u306E",
2571 "runForceCommitTest: the textarea doesn't have the committed text #7");
2572 is(textareaInFrame.value, "",
2573 "runForceCommitTest: the textarea in frame has the committed text? #7");
2575 // Make the composition in a textarea commit by click in another editable document
2576 textarea.focus();
2577 textarea.value = "";
2578 iframe2.contentDocument.body.innerHTML = "Text in the Body";
2579 var iframe2BodyInnerHTML = iframe2.contentDocument.body.innerHTML;
2581 synthesizeComposition({ type: "compositionstart" });
2583 synthesizeComposition({ type: "compositionupdate", data: "\u306E" });
2584 synthesizeText(
2585 { "composition":
2586 { "string": "\u306E",
2587 "clauses":
2588 [
2589 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
2590 ]
2591 },
2592 "caret": { "start": 1, "length": 0 }
2593 });
2595 events = [];
2596 synthesizeMouseAtCenter(iframe2.contentDocument.body, {}, iframe2.contentWindow);
2598 is(events.length, 3,
2599 "runForceCommitTest: wrong event count #8");
2600 is(events[0].type, "text",
2601 "runForceCommitTest: the 1st event must be text #8");
2602 is(events[1].type, "compositionend",
2603 "runForceCommitTest: the 2nd event must be compositionend #8");
2604 is(events[2].type, "input",
2605 "runForceCommitTest: the 3rd event must be input #8");
2606 is(events[1].data, "\u306E",
2607 "runForceCommitTest: compositionend has wrong data #8");
2608 is(events[0].target, textarea,
2609 "runForceCommitTest: The 1st event was fired on wrong event target #8");
2610 is(events[1].target, textarea,
2611 "runForceCommitTest: The 2nd event was fired on wrong event target #8");
2612 is(events[2].target, textarea,
2613 "runForceCommitTest: The 3rd event was fired on wrong event target #8");
2614 ok(!getEditorIMESupport(textarea).isComposing,
2615 "runForceCommitTest: the textarea still has composition #8");
2616 ok(!getHTMLEditorIMESupport(iframe2.contentWindow).isComposing,
2617 "runForceCommitTest: the editable document has composition #8");
2618 is(textarea.value, "\u306E",
2619 "runForceCommitTest: the textarea doesn't have the committed text #8");
2620 is(iframe2.contentDocument.body.innerHTML, iframe2BodyInnerHTML,
2621 "runForceCommitTest: the editable document has the committed text? #8");
2623 // Make the composition in an editable document commit by click in it
2624 iframe2.contentWindow.focus();
2625 iframe2.contentDocument.body.innerHTML = "Text in the Body";
2626 iframe2BodyInnerHTML = iframe2.contentDocument.body.innerHTML;
2628 synthesizeComposition({ type: "compositionstart" }, iframe2.contentWindow);
2630 synthesizeComposition({ type: "compositionupdate", data: "\u306E" }, iframe2.contentWindow);
2631 synthesizeText(
2632 { "composition":
2633 { "string": "\u306E",
2634 "clauses":
2635 [
2636 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
2637 ]
2638 },
2639 "caret": { "start": 1, "length": 0 }
2640 }, iframe2.contentWindow);
2642 events = [];
2643 synthesizeMouseAtCenter(iframe2.contentDocument.body, {}, iframe2.contentWindow);
2645 is(events.length, 3,
2646 "runForceCommitTest: wrong event count #9");
2647 is(events[0].type, "text",
2648 "runForceCommitTest: the 1st event must be text #9");
2649 is(events[1].type, "compositionend",
2650 "runForceCommitTest: the 2nd event must be compositionend #9");
2651 is(events[2].type, "input",
2652 "runForceCommitTest: the 3rd event must be input #9");
2653 is(events[1].data, "\u306E",
2654 "runForceCommitTest: compositionend has wrong data #9");
2655 is(events[0].target, iframe2.contentDocument.body,
2656 "runForceCommitTest: The 1st event was fired on wrong event target #9");
2657 is(events[1].target, iframe2.contentDocument.body,
2658 "runForceCommitTest: The 2nd event was fired on wrong event target #9");
2659 is(events[2].target, iframe2.contentDocument.body,
2660 "runForceCommitTest: The 3rd event was fired on wrong event target #9");
2661 ok(!getHTMLEditorIMESupport(iframe2.contentWindow).isComposing,
2662 "runForceCommitTest: the editable document still has composition #9");
2663 ok(iframe2.contentDocument.body.innerHTML != iframe2BodyInnerHTML &&
2664 iframe2.contentDocument.body.innerHTML.indexOf("\u306E") >= 0,
2665 "runForceCommitTest: the editable document doesn't have the committed text #9");
2667 // Make the composition in an editable document commit by click in another document's editor
2668 textarea.value = "";
2669 iframe2.contentWindow.focus();
2670 iframe2.contentDocument.body.innerHTML = "Text in the Body";
2671 iframe2BodyInnerHTML = iframe2.contentDocument.body.innerHTML;
2673 synthesizeComposition({ type: "compositionstart" }, iframe2.contentWindow);
2675 synthesizeComposition({ type: "compositionupdate", data: "\u306E" }, iframe2.contentWindow);
2676 synthesizeText(
2677 { "composition":
2678 { "string": "\u306E",
2679 "clauses":
2680 [
2681 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
2682 ]
2683 },
2684 "caret": { "start": 1, "length": 0 }
2685 }, iframe2.contentWindow);
2687 events = [];
2688 synthesizeMouseAtCenter(textarea, {});
2690 is(events.length, 3,
2691 "runForceCommitTest: wrong event count #10");
2692 is(events[0].type, "text",
2693 "runForceCommitTest: the 1st event must be text #10");
2694 is(events[1].type, "compositionend",
2695 "runForceCommitTest: the 2nd event must be compositionend #10");
2696 is(events[2].type, "input",
2697 "runForceCommitTest: the 3rd event must be input #10");
2698 is(events[1].data, "\u306E",
2699 "runForceCommitTest: compositionend has wrong data #10");
2700 is(events[0].target, iframe2.contentDocument.body,
2701 "runForceCommitTest: The 1st event was fired on wrong event target #10");
2702 is(events[1].target, iframe2.contentDocument.body,
2703 "runForceCommitTest: The 2nd event was fired on wrong event target #10");
2704 is(events[2].target, iframe2.contentDocument.body,
2705 "runForceCommitTest: The 3rd event was fired on wrong event target #10");
2706 ok(!getHTMLEditorIMESupport(iframe2.contentWindow).isComposing,
2707 "runForceCommitTest: the editable document still has composition #10");
2708 ok(!getEditorIMESupport(textarea).isComposing,
2709 "runForceCommitTest: the textarea has composition #10");
2710 ok(iframe2.contentDocument.body.innerHTML != iframe2BodyInnerHTML &&
2711 iframe2.contentDocument.body.innerHTML.indexOf("\u306E") >= 0,
2712 "runForceCommitTest: the editable document doesn't have the committed text #10");
2713 is(textarea.value, "",
2714 "runForceCommitTest: the textarea has the committed text? #10");
2716 // Make the composition in an editable document commit by click in the another editable document
2717 iframe2.contentWindow.focus();
2718 iframe2.contentDocument.body.innerHTML = "Text in the Body";
2719 iframe2BodyInnerHTML = iframe2.contentDocument.body.innerHTML;
2720 iframe3.contentDocument.body.innerHTML = "Text in the Body";
2721 iframe3BodyInnerHTML = iframe2.contentDocument.body.innerHTML;
2723 synthesizeComposition({ type: "compositionstart" }, iframe2.contentWindow);
2725 synthesizeComposition({ type: "compositionupdate", data: "\u306E" }, iframe2.contentWindow);
2726 synthesizeText(
2727 { "composition":
2728 { "string": "\u306E",
2729 "clauses":
2730 [
2731 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
2732 ]
2733 },
2734 "caret": { "start": 1, "length": 0 }
2735 }, iframe2.contentWindow);
2737 events = [];
2738 synthesizeMouseAtCenter(iframe3.contentDocument.body, {}, iframe3.contentWindow);
2740 is(events.length, 3,
2741 "runForceCommitTest: wrong event count #11");
2742 is(events[0].type, "text",
2743 "runForceCommitTest: the 1st event must be text #11");
2744 is(events[1].type, "compositionend",
2745 "runForceCommitTest: the 2nd event must be compositionend #11");
2746 is(events[2].type, "input",
2747 "runForceCommitTest: the 3rd event must be input #11");
2748 is(events[1].data, "\u306E",
2749 "runForceCommitTest: compositionend has wrong data #11");
2750 is(events[0].target, iframe2.contentDocument.body,
2751 "runForceCommitTest: The 1st event was fired on wrong event target #11");
2752 is(events[1].target, iframe2.contentDocument.body,
2753 "runForceCommitTest: The 2nd event was fired on wrong event target #11");
2754 is(events[2].target, iframe2.contentDocument.body,
2755 "runForceCommitTest: The 3rd event was fired on wrong event target #11");
2756 ok(!getHTMLEditorIMESupport(iframe2.contentWindow).isComposing,
2757 "runForceCommitTest: the editable document still has composition #11");
2758 ok(!getHTMLEditorIMESupport(iframe3.contentWindow).isComposing,
2759 "runForceCommitTest: the other editable document has composition #11");
2760 ok(iframe2.contentDocument.body.innerHTML != iframe2BodyInnerHTML &&
2761 iframe2.contentDocument.body.innerHTML.indexOf("\u306E") >= 0,
2762 "runForceCommitTest: the editable document doesn't have the committed text #11");
2763 is(iframe3.contentDocument.body.innerHTML, iframe3BodyInnerHTML,
2764 "runForceCommitTest: the other editable document has the committed text? #11");
2766 window.removeEventListener("compositionstart", eventHandler, true);
2767 window.removeEventListener("compositionupdate", eventHandler, true);
2768 window.removeEventListener("compositionend", eventHandler, true);
2769 window.removeEventListener("input", eventHandler, true);
2770 window.removeEventListener("text", eventHandler, true);
2771 }
2773 function runBug811755Test()
2774 {
2775 iframe2.contentDocument.body.innerHTML = "<div>content<br/></div>";
2776 iframe2.contentWindow.focus();
2777 // Query everything
2778 var textContent = synthesizeQueryTextContent(0, 10);
2779 if (!checkQueryContentResult(textContent, "runBug811755Test: synthesizeQueryTextContent #1")) {
2780 return false;
2781 }
2782 // Query everything but specify exact end offset, which should be immediately after the <br> node
2783 // If PreContentIterator is used, the next node after <br> is the node after </div>.
2784 // If ContentIterator is used, the next node is the <div> node itself. In this case, the end
2785 // node ends up being before the start node, and an empty string is returned.
2786 var queryContent = synthesizeQueryTextContent(0, textContent.text.length);
2787 if (!checkQueryContentResult(queryContent, "runBug811755Test: synthesizeQueryTextContent #2")) {
2788 return false;
2789 }
2790 is(queryContent.text, textContent.text, "runBug811755Test: two queried texts don't match");
2791 return queryContent.text == textContent.text;
2792 }
2794 function runIsComposingTest()
2795 {
2796 var expectedIsComposing = false;
2797 var descriptionBase = "runIsComposingTest: ";
2798 var description = "";
2800 function eventHandler(aEvent)
2801 {
2802 if (aEvent.type == "keydown" || aEvent.type == "keyup") {
2803 is(aEvent.isComposing, expectedIsComposing,
2804 "runIsComposingTest: " + description + " (type=" + aEvent.type + ", key=" + aEvent.key + ")");
2805 } else {
2806 is(aEvent.isComposing, expectedIsComposing,
2807 "runIsComposingTest: " + description + " (type=" + aEvent.type + ")");
2808 }
2809 }
2811 textarea.addEventListener("keydown", eventHandler, true);
2812 textarea.addEventListener("keypress", eventHandler, true);
2813 textarea.addEventListener("keyup", eventHandler, true);
2814 textarea.addEventListener("input", eventHandler, true);
2816 textarea.focus();
2817 textarea.value = "";
2819 // XXX These cases shouldn't occur in actual native key events because we
2820 // don't dispatch key events while composition (bug 354358).
2821 expectedIsComposing = false;
2822 description = "events before dispatching compositionstart";
2823 synthesizeKey("VK_LEFT", {});
2825 synthesizeKey("a", { type: "keydown" });
2826 synthesizeComposition({ type: "compositionstart" });
2827 expectedIsComposing = true;
2828 description = "events after dispatching compositionstart";
2829 synthesizeComposition({ type: "compositionupdate", data: "\u3042" });
2830 synthesizeText(
2831 { "composition":
2832 { "string": "\u3042",
2833 "clauses":
2834 [
2835 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
2836 ]
2837 },
2838 "caret": { "start": 1, "length": 0 }
2839 });
2840 synthesizeKey("a", { type: "keyup" });
2842 // Although, firing keypress event during composition is a bug.
2843 synthesizeKey("VK_INSERT", {});
2845 description = "events for committing composition string";
2846 synthesizeKey("VK_RETURN", { type: "keydown" });
2847 synthesizeText(
2848 { "composition":
2849 { "string": "\u3042",
2850 "clauses":
2851 [
2852 { "length": 0, "attr": 0 }
2853 ]
2854 },
2855 "caret": { "start": 1, "length": 0 }
2856 });
2858 // input event will be fired by synthesizing compositionend event.
2859 // Then, its isComposing should be false.
2860 expectedIsComposing = false;
2861 description = "events after dispatching compositionend";
2862 synthesizeComposition({ type: "compositionend" });
2863 synthesizeKey("VK_RETURN", { type: "keyup" });
2865 textarea.removeEventListener("keydown", eventHandler, true);
2866 textarea.removeEventListener("keypress", eventHandler, true);
2867 textarea.removeEventListener("keyup", eventHandler, true);
2868 textarea.removeEventListener("input", eventHandler, true);
2870 textarea.value = "";
2871 }
2873 function runRemoveContentTest(aCallback)
2874 {
2875 var events = [];
2876 function eventHandler(aEvent)
2877 {
2878 events.push(aEvent);
2879 }
2880 textarea.addEventListener("compositionstart", eventHandler, true);
2881 textarea.addEventListener("compositionupdate", eventHandler, true);
2882 textarea.addEventListener("compositionend", eventHandler, true);
2883 textarea.addEventListener("input", eventHandler, true);
2884 textarea.addEventListener("text", eventHandler, true);
2886 textarea.focus();
2887 textarea.value = "";
2889 synthesizeComposition({ type: "compositionstart" });
2891 synthesizeComposition({ type: "compositionupdate", data: "\u306E" });
2892 synthesizeText(
2893 { "composition":
2894 { "string": "\u306E",
2895 "clauses":
2896 [
2897 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
2898 ]
2899 },
2900 "caret": { "start": 1, "length": 0 }
2901 });
2903 var nextSibling = textarea.nextSibling;
2904 var parent = textarea.parentElement;
2906 events = [];
2907 parent.removeChild(textarea);
2909 hitEventLoop(function () {
2910 // XXX Currently, "input" event isn't fired on removed content.
2911 is(events.length, 3,
2912 "runRemoveContentTest: wrong event count #1");
2913 is(events[0].type, "compositionupdate",
2914 "runRemoveContentTest: the 1st event must be compositionupdate #1");
2915 is(events[1].type, "text",
2916 "runRemoveContentTest: the 2nd event must be text #1");
2917 is(events[2].type, "compositionend",
2918 "runRemoveContentTest: the 3rd event must be compositionend #1");
2919 is(events[0].data, "",
2920 "runRemoveContentTest: compositionupdate has wrong data #1");
2921 is(events[2].data, "",
2922 "runRemoveContentTest: compositionend has wrong data #1");
2923 is(events[0].target, textarea,
2924 "runRemoveContentTest: The 1st event was fired on wrong event target #1");
2925 is(events[1].target, textarea,
2926 "runRemoveContentTest: The 2nd event was fired on wrong event target #1");
2927 is(events[2].target, textarea,
2928 "runRemoveContentTest: The 3rd event was fired on wrong event target #1");
2929 ok(!getEditorIMESupport(textarea).isComposing,
2930 "runRemoveContentTest: the textarea still has composition #1");
2931 todo_is(textarea.value, "",
2932 "runRemoveContentTest: the textarea has the committed text? #1");
2934 parent.insertBefore(textarea, nextSibling);
2936 textarea.focus();
2937 textarea.value = "";
2939 synthesizeComposition({ type: "compositionstart" });
2941 events = [];
2942 parent.removeChild(textarea);
2944 hitEventLoop(function () {
2945 // XXX Currently, "input" event isn't fired on removed content.
2946 is(events.length, 1,
2947 "runRemoveContentTest: wrong event count #2");
2948 is(events[0].type, "compositionend",
2949 "runRemoveContentTest: the 1st event must be compositionend #2");
2950 is(events[0].data, "",
2951 "runRemoveContentTest: compositionupdate has wrong data #2");
2952 is(events[0].target, textarea,
2953 "runRemoveContentTest: The 1st event was fired on wrong event target #2");
2954 ok(!getEditorIMESupport(textarea).isComposing,
2955 "runRemoveContentTest: the textarea still has composition #2");
2956 is(textarea.value, "",
2957 "runRemoveContentTest: the textarea has the committed text? #2");
2959 parent.insertBefore(textarea, nextSibling);
2961 textarea.removeEventListener("compositionstart", eventHandler, true);
2962 textarea.removeEventListener("compositionupdate", eventHandler, true);
2963 textarea.removeEventListener("compositionend", eventHandler, true);
2964 textarea.removeEventListener("input", eventHandler, true);
2965 textarea.removeEventListener("text", eventHandler, true);
2967 SimpleTest.executeSoon(aCallback);
2968 }, 50);
2969 }, 50);
2970 }
2972 function runTestOnAnotherContext(aPanelOrFrame, aFocusedEditor, aTestName)
2973 {
2974 aFocusedEditor.value = "";
2976 var editorRect = synthesizeQueryEditorRect();
2977 if (!checkQueryContentResult(editorRect, aTestName + ": editorRect")) {
2978 return;
2979 }
2981 var r = aPanelOrFrame.getBoundingClientRect();
2982 var parentRect = { "left": r.left, "top": r.top, "width": r.right - r.left,
2983 "height": r.bottom - r.top };
2984 checkRectContainsRect(editorRect, parentRect, aTestName +
2985 ": the editor rect coordinates are wrong");
2987 // start composition
2988 synthesizeComposition({ type: "compositionstart" });
2990 // input characters
2991 synthesizeComposition({ type: "compositionupdate",
2992 data: "\u3078\u3093\u3057\u3093" });
2993 synthesizeText(
2994 { "composition":
2995 { "string": "\u3078\u3093\u3057\u3093",
2996 "clauses":
2997 [
2998 { "length": 4, "attr": COMPOSITION_ATTR_RAWINPUT }
2999 ]
3000 },
3001 "caret": { "start": 4, "length": 0 }
3002 });
3004 if (!checkContent("\u3078\u3093\u3057\u3093", aTestName, "#1-1") ||
3005 !checkSelection(4, "", aTestName, "#1-1")) {
3006 return;
3007 }
3009 // convert them #1
3010 synthesizeComposition({ type: "compositionupdate", data: "\u8FD4\u4FE1" });
3011 synthesizeText(
3012 { "composition":
3013 { "string": "\u8FD4\u4FE1",
3014 "clauses":
3015 [
3016 { "length": 2,
3017 "attr": COMPOSITION_ATTR_SELECTEDCONVERTEDTEXT }
3018 ]
3019 },
3020 "caret": { "start": 2, "length": 0 }
3021 });
3023 if (!checkContent("\u8FD4\u4FE1", aTestName, "#1-2") ||
3024 !checkSelection(2, "", aTestName, "#1-2")) {
3025 return;
3026 }
3028 // convert them #2
3029 synthesizeComposition({ type: "compositionupdate", data: "\u5909\u8EAB" });
3030 synthesizeText(
3031 { "composition":
3032 { "string": "\u5909\u8EAB",
3033 "clauses":
3034 [
3035 { "length": 2,
3036 "attr": COMPOSITION_ATTR_SELECTEDCONVERTEDTEXT }
3037 ]
3038 },
3039 "caret": { "start": 2, "length": 0 }
3040 });
3042 if (!checkContent("\u5909\u8EAB", aTestName, "#1-3") ||
3043 !checkSelection(2, "", aTestName, "#1-3")) {
3044 return;
3045 }
3047 // commit them
3048 synthesizeText(
3049 { "composition":
3050 { "string": "\u5909\u8EAB",
3051 "clauses":
3052 [
3053 { "length": 0, "attr": 0 }
3054 ]
3055 },
3056 "caret": { "start": 2, "length": 0 }
3057 });
3059 if (!checkContent("\u5909\u8EAB", aTestName, "#1-4") ||
3060 !checkSelection(2, "", aTestName, "#1-4")) {
3061 return;
3062 }
3064 synthesizeComposition({ type: "compositionend", data: "\u5909\u8EAB" });
3066 is(aFocusedEditor.value, "\u5909\u8EAB",
3067 aTestName + ": composition isn't in the focused editor");
3068 if (aFocusedEditor.value != "\u5909\u8EAB") {
3069 return;
3070 }
3072 var textRect = synthesizeQueryTextRect(0, 1);
3073 var caretRect = synthesizeQueryCaretRect(2);
3074 if (!checkQueryContentResult(textRect,
3075 aTestName + ": synthesizeQueryTextRect") ||
3076 !checkQueryContentResult(caretRect,
3077 aTestName + ": synthesizeQueryCaretRect")) {
3078 return;
3079 }
3080 checkRectContainsRect(textRect, editorRect, aTestName + ":testRect");
3081 checkRectContainsRect(caretRect, editorRect, aTestName + ":caretRect");
3082 }
3084 function runFrameTest()
3085 {
3086 textareaInFrame.focus();
3087 runTestOnAnotherContext(iframe, textareaInFrame, "runFrameTest");
3088 runCharAtPointTest(textareaInFrame, "textarea in the iframe");
3089 }
3091 var gPanelShown = false;
3092 var gPanelFocused = false;
3093 function onPanelShown(aEvent)
3094 {
3095 gPanelShown = true;
3096 textbox.focus();
3097 setTimeout(doPanelTest, 0);
3098 }
3100 function onFocusPanelTextbox(aEvent)
3101 {
3102 gPanelFocused = true;
3103 setTimeout(doPanelTest, 0);
3104 }
3106 var gIsPanelHiding = false;
3107 var gIsRunPanelTestInternal = false;
3108 function doPanelTest()
3109 {
3110 if (!gPanelFocused || !gPanelShown) {
3111 return;
3112 }
3113 if (gIsRunPanelTestInternal) {
3114 return;
3115 }
3116 gIsRunPanelTestInternal = true;
3117 runTestOnAnotherContext(panel, textbox, "runPanelTest");
3118 runCharAtPointTest(textbox, "textbox in the panel");
3119 gIsPanelHiding = true;
3120 panel.hidePopup();
3121 }
3123 function onPanelHidden(aEvent)
3124 {
3125 panel.hidden = true;
3126 ok(gIsPanelHiding, "runPanelTest: the panel is hidden unexpectedly");
3127 finish();
3128 }
3130 function runPanelTest()
3131 {
3132 panel.hidden = false;
3133 panel.openPopupAtScreen(window.screenX + window.outerWidth, 0, false);
3134 }
3136 function runMaxLengthTest()
3137 {
3138 input.maxLength = 1;
3139 input.value = "";
3140 input.focus();
3142 var kDesc ="runMaxLengthTest";
3144 // start composition
3145 synthesizeComposition({ type: "compositionstart" });
3147 // input first character
3148 synthesizeComposition({ type: "compositionupdate", data: "\u3089" });
3149 synthesizeText(
3150 { "composition":
3151 { "string": "\u3089",
3152 "clauses":
3153 [
3154 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
3155 ]
3156 },
3157 "caret": { "start": 1, "length": 0 }
3158 });
3160 if (!checkContent("\u3089", kDesc, "#1-1") ||
3161 !checkSelection(1, "", kDesc, "#1-1")) {
3162 return;
3163 }
3165 // input second character
3166 synthesizeComposition({ type: "compositionupdate", data: "\u3089\u30FC" });
3167 synthesizeText(
3168 { "composition":
3169 { "string": "\u3089\u30FC",
3170 "clauses":
3171 [
3172 { "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT }
3173 ]
3174 },
3175 "caret": { "start": 2, "length": 0 }
3176 });
3178 if (!checkContent("\u3089\u30FC", kDesc, "#1-2") ||
3179 !checkSelection(2, "", kDesc, "#1-2")) {
3180 return;
3181 }
3183 // input third character
3184 synthesizeComposition({ type: "compositionupdate",
3185 data: "\u3089\u30FC\u3081" });
3186 synthesizeText(
3187 { "composition":
3188 { "string": "\u3089\u30FC\u3081",
3189 "clauses":
3190 [
3191 { "length": 3, "attr": COMPOSITION_ATTR_RAWINPUT }
3192 ]
3193 },
3194 "caret": { "start": 3, "length": 0 }
3195 });
3197 if (!checkContent("\u3089\u30FC\u3081", kDesc, "#1-3") ||
3198 !checkSelection(3, "", kDesc, "#1-3")) {
3199 return;
3200 }
3202 // input fourth character
3203 synthesizeComposition({ type: "compositionupdate",
3204 data: "\u3089\u30FC\u3081\u3093" });
3205 synthesizeText(
3206 { "composition":
3207 { "string": "\u3089\u30FC\u3081\u3093",
3208 "clauses":
3209 [
3210 { "length": 4, "attr": COMPOSITION_ATTR_RAWINPUT }
3211 ]
3212 },
3213 "caret": { "start": 4, "length": 0 }
3214 });
3216 if (!checkContent("\u3089\u30FC\u3081\u3093", kDesc, "#1-4") ||
3217 !checkSelection(4, "", kDesc, "#1-4")) {
3218 return;
3219 }
3222 // backspace
3223 synthesizeComposition({ type: "compositionupdate",
3224 data: "\u3089\u30FC\u3081" });
3225 synthesizeText(
3226 { "composition":
3227 { "string": "\u3089\u30FC\u3081",
3228 "clauses":
3229 [
3230 { "length": 3, "attr": COMPOSITION_ATTR_RAWINPUT }
3231 ]
3232 },
3233 "caret": { "start": 3, "length": 0 }
3234 });
3236 if (!checkContent("\u3089\u30FC\u3081", kDesc, "#1-5") ||
3237 !checkSelection(3, "", kDesc, "#1-5")) {
3238 return;
3239 }
3241 // re-input
3242 synthesizeComposition({ type: "compositionupdate",
3243 data: "\u3089\u30FC\u3081\u3093" });
3244 synthesizeText(
3245 { "composition":
3246 { "string": "\u3089\u30FC\u3081\u3093",
3247 "clauses":
3248 [
3249 { "length": 4, "attr": COMPOSITION_ATTR_RAWINPUT }
3250 ]
3251 },
3252 "caret": { "start": 4, "length": 0 }
3253 });
3255 if (!checkContent("\u3089\u30FC\u3081\u3093", kDesc, "#1-6") ||
3256 !checkSelection(4, "", kDesc, "#1-6")) {
3257 return;
3258 }
3260 synthesizeComposition({ type: "compositionupdate",
3261 data: "\u3089\u30FC\u3081\u3093\u3055" });
3262 synthesizeText(
3263 { "composition":
3264 { "string": "\u3089\u30FC\u3081\u3093\u3055",
3265 "clauses":
3266 [
3267 { "length": 5, "attr": COMPOSITION_ATTR_RAWINPUT }
3268 ]
3269 },
3270 "caret": { "start": 5, "length": 0 }
3271 });
3273 if (!checkContent("\u3089\u30FC\u3081\u3093\u3055", kDesc, "#1-7") ||
3274 !checkSelection(5, "", kDesc, "#1-7")) {
3275 return;
3276 }
3278 synthesizeComposition({ type: "compositionupdate",
3279 data: "\u3089\u30FC\u3081\u3093\u3055\u3044" });
3280 synthesizeText(
3281 { "composition":
3282 { "string": "\u3089\u30FC\u3081\u3093\u3055\u3044",
3283 "clauses":
3284 [
3285 { "length": 6, "attr": COMPOSITION_ATTR_RAWINPUT }
3286 ]
3287 },
3288 "caret": { "start": 6, "length": 0 }
3289 });
3291 if (!checkContent("\u3089\u30FC\u3081\u3093\u3055\u3044", kDesc, "#1-8") ||
3292 !checkSelection(6, "", kDesc, "#1-8")) {
3293 return;
3294 }
3296 synthesizeComposition({ type: "compositionupdate",
3297 data: "\u3089\u30FC\u3081\u3093\u3055\u3044\u3053" });
3298 synthesizeText(
3299 { "composition":
3300 { "string": "\u3089\u30FC\u3081\u3093\u3055\u3044\u3053",
3301 "clauses":
3302 [
3303 { "length": 7, "attr": COMPOSITION_ATTR_RAWINPUT }
3304 ]
3305 },
3306 "caret": { "start": 7, "length": 0 }
3307 });
3309 if (!checkContent("\u3089\u30FC\u3081\u3093\u3055\u3044\u3053",
3310 kDesc, "#1-8") ||
3311 !checkSelection(7, "", kDesc, "#1-8")) {
3312 return;
3313 }
3315 synthesizeComposition({ type: "compositionupdate",
3316 data: "\u3089\u30FC\u3081\u3093\u3055\u3044\u3053\u3046" });
3317 synthesizeText(
3318 { "composition":
3319 { "string": "\u3089\u30FC\u3081\u3093\u3055\u3044\u3053\u3046",
3320 "clauses":
3321 [
3322 { "length": 8, "attr": COMPOSITION_ATTR_RAWINPUT }
3323 ]
3324 },
3325 "caret": { "start": 8, "length": 0 }
3326 });
3328 if (!checkContent("\u3089\u30FC\u3081\u3093\u3055\u3044\u3053\u3046",
3329 kDesc, "#1-9") ||
3330 !checkSelection(8, "", kDesc, "#1-9")) {
3331 return;
3332 }
3334 // convert
3335 synthesizeComposition({ type: "compositionupdate",
3336 data: "\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8" });
3337 synthesizeText(
3338 { "composition":
3339 { "string": "\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8",
3340 "clauses":
3341 [
3342 { "length": 4,
3343 "attr": COMPOSITION_ATTR_SELECTEDCONVERTEDTEXT },
3344 { "length": 2,
3345 "attr": COMPOSITION_ATTR_CONVERTEDTEXT }
3346 ]
3347 },
3348 "caret": { "start": 4, "length": 0 }
3349 });
3351 if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8", kDesc, "#1-10") ||
3352 !checkSelection(4, "", kDesc, "#1-10")) {
3353 return;
3354 }
3356 // commit the composition string
3357 synthesizeText(
3358 { "composition":
3359 { "string": "\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8",
3360 "clauses":
3361 [
3362 { "length": 0, "attr": 0 }
3363 ]
3364 },
3365 "caret": { "start": 6, "length": 0 }
3366 });
3368 if (!checkContent("\u30E9", kDesc, "#1-11") ||
3369 !checkSelection(1, "", kDesc, "#1-11")) {
3370 return;
3371 }
3373 synthesizeComposition({ type: "compositionend",
3374 data: "\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8" });
3376 // restart composition
3377 synthesizeComposition({ type: "compositionstart" });
3379 // input characters
3380 synthesizeComposition({ type: "compositionupdate", data: "\u3057" });
3381 synthesizeText(
3382 { "composition":
3383 { "string": "\u3057",
3384 "clauses":
3385 [
3386 { "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
3387 ]
3388 },
3389 "caret": { "start": 1, "length": 0 }
3390 });
3392 if (!checkContent("\u30E9\u3057", kDesc, "#2-1") ||
3393 !checkSelection(1 + 1, "", kDesc, "#2-1")) {
3394 return;
3395 }
3397 // commit the composition string
3398 synthesizeComposition({ type: "compositionupdate", data: "\u3058" });
3399 synthesizeText(
3400 { "composition":
3401 { "string": "\u3058",
3402 "clauses":
3403 [
3404 { "length": 0, "attr": 0 }
3405 ]
3406 },
3407 "caret": { "start": 1, "length": 0 }
3408 });
3410 if (!checkContent("\u30E9", kDesc, "#2-2") ||
3411 !checkSelection(1 + 0, "", kDesc, "#2-2")) {
3412 return;
3413 }
3415 synthesizeComposition({ type: "compositionend", data: "\u3058" });
3417 // Undo
3418 synthesizeKey("Z", {accelKey: true});
3420 // XXX this is unexpected behavior, see bug 258291
3421 if (!checkContent("\u30E9", kDesc, "#3-1") ||
3422 !checkSelection(1 + 0, "", kDesc, "#3-1")) {
3423 return;
3424 }
3426 // Undo
3427 synthesizeKey("Z", {accelKey: true});
3428 if (!checkContent("", kDesc, "#3-2") ||
3429 !checkSelection(0, "", kDesc, "#3-2")) {
3430 return;
3431 }
3433 // Redo
3434 synthesizeKey("Z", {accelKey: true, shiftKey: true});
3435 if (!checkContent("\u30E9", kDesc, "#3-3") ||
3436 !checkSelection(1, "", kDesc, "#3-3")) {
3437 return;
3438 }
3440 // Redo
3441 synthesizeKey("Z", {accelKey: true, shiftKey: true});
3442 if (!checkContent("\u30E9", kDesc, "#3-4") ||
3443 !checkSelection(1 + 0, "", kDesc, "#3-4")) {
3444 return;
3445 }
3446 }
3448 function runTest()
3449 {
3450 textareaInFrame = iframe.contentDocument.getElementById("textarea");
3452 runUndoRedoTest();
3453 runCompositionTest();
3454 runCompositionEventTest();
3455 runCharAtPointTest(textarea, "textarea in the document");
3456 runCharAtPointAtOutsideTest();
3457 runBug722639Test();
3458 runForceCommitTest();
3459 runBug811755Test();
3460 runIsComposingTest();
3461 runRemoveContentTest(function () {
3462 runFrameTest();
3463 runPanelTest();
3464 runMaxLengthTest();
3465 });
3466 }
3468 ]]>
3469 </script>
3471 </window>