gecko-dev/widget/tests/window_composition_text_querycontent.xul

5778 lines
245 KiB
XML

<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<window title="Testing composition, text and query content events"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onunload="onunload();">
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js" />
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js"></script>
<panel id="panel" hidden="true"
orient="vertical"
onpopupshown="onPanelShown(event);"
onpopuphidden="onPanelHidden(event);">
<vbox id="vbox">
<textbox id="textbox" onfocus="onFocusPanelTextbox(event);"
multiline="true" cols="20" rows="4" style="font-size: 36px;"/>
</vbox>
</panel>
<body xmlns="http://www.w3.org/1999/xhtml">
<p id="display">
<div id="div" style="margin: 0; padding: 0; font-size: 36px;">Here is a text frame.</div>
<textarea style="margin: 0;" id="textarea" cols="20" rows="4"></textarea><br/>
<iframe id="iframe" width="300" height="150"
src="data:text/html,&lt;textarea id='textarea' cols='20' rows='4'&gt;&lt;/textarea&gt;"></iframe><br/>
<iframe id="iframe2" width="300" height="150"
src="data:text/html,&lt;body onload='document.designMode=%22on%22'&gt;body content&lt;/body&gt;"></iframe><br/>
<iframe id="iframe3" width="300" height="150"
src="data:text/html,&lt;body onload='document.designMode=%22on%22'&gt;body content&lt;/body&gt;"></iframe><br/>
<iframe id="iframe4" width="300" height="150"
src="data:text/html,&lt;div contenteditable id='contenteditable'&gt;&lt;/div&gt;"></iframe><br/>
<input id="input" type="text"/><br/>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<script class="testbody" type="application/javascript">
<![CDATA[
window.opener.wrappedJSObject.SimpleTest.waitForFocus(runTest, window);
function ok(aCondition, aMessage)
{
window.opener.wrappedJSObject.SimpleTest.ok(aCondition, aMessage);
}
function is(aLeft, aRight, aMessage)
{
window.opener.wrappedJSObject.SimpleTest.is(aLeft, aRight, aMessage);
}
function isnot(aLeft, aRight, aMessage)
{
window.opener.wrappedJSObject.SimpleTest.isnot(aLeft, aRight, aMessage);
}
function finish()
{
window.close();
}
function onunload()
{
window.opener.wrappedJSObject.SimpleTest.finish();
}
var div = document.getElementById("div");
var textarea = document.getElementById("textarea");
var panel = document.getElementById("panel");
var textbox = document.getElementById("textbox");
var iframe = document.getElementById("iframe");
var iframe2 = document.getElementById("iframe2");
var iframe3 = document.getElementById("iframe3");
var contenteditable;
var windowOfContenteditable;
var input = document.getElementById("input");
var textareaInFrame;
const nsITextInputProcessorCallback = Components.interfaces.nsITextInputProcessorCallback;
const nsIDOMNSEditableElement = Components.interfaces.nsIDOMNSEditableElement;
const nsIEditorIMESupport = Components.interfaces.nsIEditorIMESupport;
const nsIInterfaceRequestor = Components.interfaces.nsIInterfaceRequestor;
const nsIWebNavigation = Components.interfaces.nsIWebNavigation;
const nsIDocShell = Components.interfaces.nsIDocShell;
function hitEventLoop(aFunc, aTimes)
{
if (--aTimes) {
setTimeout(hitEventLoop, 0, aFunc, aTimes);
} else {
setTimeout(aFunc, 20);
}
}
function getEditorIMESupport(aNode)
{
return aNode.QueryInterface(nsIDOMNSEditableElement).
editor.
QueryInterface(nsIEditorIMESupport);
}
function getHTMLEditorIMESupport(aWindow)
{
return aWindow.QueryInterface(nsIInterfaceRequestor).
getInterface(nsIWebNavigation).
QueryInterface(nsIDocShell).
editor;
}
const kIsWin = (navigator.platform.indexOf("Win") == 0);
const kIsMac = (navigator.platform.indexOf("Mac") == 0);
const kLFLen = kIsWin ? 2 : 1;
const kLF = kIsWin ? "\r\n" : "\n";
function checkQueryContentResult(aResult, aMessage)
{
ok(aResult, aMessage + ": the result is null");
if (!aResult) {
return false;
}
ok(aResult.succeeded, aMessage + ": the query content failed");
return aResult.succeeded;
}
function checkContent(aExpectedText, aMessage, aID)
{
if (!aID) {
aID = "";
}
var textContent = synthesizeQueryTextContent(0, 100);
if (!checkQueryContentResult(textContent, aMessage +
": synthesizeQueryTextContent " + aID)) {
return false;
}
is(textContent.text, aExpectedText,
aMessage + ": composition string is wrong " + aID);
return textContent.text == aExpectedText;
}
function checkSelection(aExpectedOffset, aExpectedText, aMessage, aID)
{
if (!aID) {
aID = "";
}
var selectedText = synthesizeQuerySelectedText();
if (!checkQueryContentResult(selectedText, aMessage +
": synthesizeQuerySelectedText " + aID)) {
return false;
}
is(selectedText.offset, aExpectedOffset,
aMessage + ": selection offset is wrong " + aID);
is(selectedText.text, aExpectedText,
aMessage + ": selected text is wrong " + aID);
return selectedText.offset == aExpectedOffset &&
selectedText.text == aExpectedText;
}
function checkRect(aRect, aExpectedRect, aMessage)
{
is(aRect.left, aExpectedRect.left, aMessage + ": left is wrong");
is(aRect.top, aExpectedRect.top, aMessage + " top is wrong");
is(aRect.width, aExpectedRect.width, aMessage + ": width is wrong");
is(aRect.height, aExpectedRect.height, aMessage + ": height is wrong");
return aRect.left == aExpectedRect.left &&
aRect.top == aExpectedRect.top &&
aRect.width == aExpectedRect.width &&
aRect.height == aExpectedRect.height;
}
function checkRectContainsRect(aRect, aContainer, aMessage)
{
var container = { left: Math.ceil(aContainer.left),
top: Math.ceil(aContainer.top),
width: Math.floor(aContainer.width),
height: Math.floor(aContainer.height) };
var ret = container.left <= aRect.left &&
container.top <= aRect.top &&
container.left + container.width >= aRect.left + aRect.width &&
container.top + container.height >= aRect.top + aRect.height;
ret = ret && aMessage;
ok(ret, aMessage + " container={ left=" + container.left + ", top=" +
container.top + ", width=" + container.width + ", height=" +
container.height + " } rect={ left=" + aRect.left + ", top=" + aRect.top +
", width=" + aRect.width + ", height=" + aRect.height + " }");
return ret;
}
function runUndoRedoTest()
{
textarea.value = "";
textarea.focus();
// input raw characters
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306D",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306D\u3053",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
// convert
synthesizeCompositionChange(
{ "composition":
{ "string": "\u732B",
"clauses":
[
{ "length": 1,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
// commit
synthesizeComposition({ type: "compositioncommitasis" });
// input raw characters
synthesizeCompositionChange(
{ "composition":
{ "string": "\u307E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
// cancel the composition
synthesizeComposition({ type: "compositioncommit", data: "" });
// input raw characters
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3080",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3080\u3059",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3080\u3059\u3081",
"clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 3, "length": 0 }
});
// convert
synthesizeCompositionChange(
{ "composition":
{ "string": "\u5A18",
"clauses":
[
{ "length": 1,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
// commit
synthesizeComposition({ type: "compositioncommitasis" });
synthesizeKey(" ", {});
synthesizeKey("m", {});
synthesizeKey("e", {});
synthesizeKey("a", {});
synthesizeKey("n", {});
synthesizeKey("t", {});
synthesizeKey("VK_BACK_SPACE", {});
synthesizeKey("s", {});
synthesizeKey(" ", {});
synthesizeKey("\"", {});
synthesizeKey("c", {});
synthesizeKey("a", {});
synthesizeKey("t", {});
synthesizeKey("-", {});
synthesizeKey("g", {});
synthesizeKey("i", {});
synthesizeKey("r", {});
synthesizeKey("l", {});
synthesizeKey("\"", {});
synthesizeKey(".", {});
synthesizeKey(" ", {});
synthesizeKey("VK_SHIFT", { type: "keydown" });
synthesizeKey("S", { shiftKey: true });
synthesizeKey("VK_SHIFT", { type: "keyup" });
synthesizeKey("h", {});
synthesizeKey("e", {});
synthesizeKey(" ", {});
synthesizeKey("i", {});
synthesizeKey("s", {});
synthesizeKey(" ", {});
synthesizeKey("a", {});
synthesizeKey(" ", {});
// input raw characters
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3088",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3088\u3046",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3088\u3046\u304b",
"clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 3, "length": 0 }
});
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3088\u3046\u304b\u3044",
"clauses":
[
{ "length": 4, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 4, "length": 0 }
});
// convert
synthesizeCompositionChange(
{ "composition":
{ "string": "\u5996\u602a",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
// commit
synthesizeComposition({ type: "compositioncommitasis" });
synthesizeKey("VK_BACK_SPACE", {});
synthesizeKey("VK_BACK_SPACE", {});
synthesizeKey("VK_BACK_SPACE", {});
synthesizeKey("VK_BACK_SPACE", {});
synthesizeKey("VK_BACK_SPACE", {});
synthesizeKey("VK_BACK_SPACE", {});
synthesizeKey("VK_BACK_SPACE", {});
synthesizeKey("VK_BACK_SPACE", {});
synthesizeKey("VK_BACK_SPACE", {});
synthesizeKey("VK_BACK_SPACE", {});
synthesizeKey("VK_BACK_SPACE", {});
synthesizeKey("VK_BACK_SPACE", {});
var i = 0;
if (!checkContent("\u732B\u5A18 means \"cat-girl\".",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(20, "", "runUndoRedoTest", "#" + i)) {
return;
}
synthesizeKey("Z", {accelKey: true});
if (!checkContent("\u732B\u5A18 means \"cat-girl\". She is a \u5996\u602A",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(32, "", "runUndoRedoTest", "#" + i)) {
return;
}
synthesizeKey("Z", {accelKey: true});
if (!checkContent("\u732B\u5A18 means \"cat-girl\". She is a ",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(30, "", "runUndoRedoTest", "#" + i)) {
return;
}
synthesizeKey("Z", {accelKey: true});
if (!checkContent("\u732B\u5A18 mean",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(7, "", "runUndoRedoTest", "#" + i)) {
return;
}
synthesizeKey("Z", {accelKey: true});
if (!checkContent("\u732B\u5A18 meant",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(8, "", "runUndoRedoTest", "#" + i)) {
return;
}
synthesizeKey("Z", {accelKey: true});
if (!checkContent("\u732B\u5A18",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(2, "", "runUndoRedoTest", "#" + i)) {
return;
}
synthesizeKey("Z", {accelKey: true});
if (!checkContent("\u732B",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(1, "", "runUndoRedoTest", "#" + i)) {
return;
}
synthesizeKey("Z", {accelKey: true});
// XXX this is unexpected behavior, see bug 258291
if (!checkContent("\u732B",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(1, "", "runUndoRedoTest", "#" + i)) {
return;
}
synthesizeKey("Z", {accelKey: true});
if (!checkContent("",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(0, "", "runUndoRedoTest", "#" + i)) {
return;
}
synthesizeKey("Z", {accelKey: true});
if (!checkContent("",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(0, "", "runUndoRedoTest", "#" + i)) {
return;
}
synthesizeKey("Z", {accelKey: true, shiftKey: true});
if (!checkContent("\u732B",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(1, "", "runUndoRedoTest", "#" + i)) {
return;
}
synthesizeKey("Z", {accelKey: true, shiftKey: true});
// XXX this is unexpected behavior, see bug 258291
if (!checkContent("\u732B",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(1, "", "runUndoRedoTest", "#" + i)) {
return;
}
synthesizeKey("Z", {accelKey: true, shiftKey: true});
if (!checkContent("\u732B\u5A18",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(2, "", "runUndoRedoTest", "#" + i)) {
return;
}
synthesizeKey("Z", {accelKey: true, shiftKey: true});
if (!checkContent("\u732B\u5A18 meant",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(8, "", "runUndoRedoTest", "#" + i)) {
return;
}
synthesizeKey("Z", {accelKey: true, shiftKey: true});
if (!checkContent("\u732B\u5A18 mean",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(7, "", "runUndoRedoTest", "#" + i)) {
return;
}
synthesizeKey("Z", {accelKey: true, shiftKey: true});
if (!checkContent("\u732B\u5A18 means \"cat-girl\". She is a ",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(30, "", "runUndoRedoTest", "#" + i)) {
return;
}
synthesizeKey("Z", {accelKey: true, shiftKey: true});
if (!checkContent("\u732B\u5A18 means \"cat-girl\". She is a \u5996\u602A",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(32, "", "runUndoRedoTest", "#" + i)) {
return;
}
synthesizeKey("Z", {accelKey: true, shiftKey: true});
if (!checkContent("\u732B\u5A18 means \"cat-girl\".",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(20, "", "runUndoRedoTest", "#" + i)) {
return;
}
synthesizeKey("Z", {accelKey: true, shiftKey: true});
if (!checkContent("\u732B\u5A18 means \"cat-girl\".",
"runUndoRedoTest", "#" + ++i) ||
!checkSelection(20, "", "runUndoRedoTest", "#" + i)) {
return;
}
}
function runCompositionCommitAsIsTest()
{
textarea.focus();
var result = {};
function clearResult()
{
result = { compositionupdate: false, compositionend: false, text: false, input: false }
}
function handler(aEvent)
{
result[aEvent.type] = true;
}
textarea.addEventListener("compositionupdate", handler, true);
textarea.addEventListener("compositionend", handler, true);
textarea.addEventListener("input", handler, true);
textarea.addEventListener("text", handler, true);
// compositioncommitasis with composing string.
textarea.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3042",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
is(textarea.value, "\u3042", "runCompositionCommitAsIsTest: textarea doesn't have composition string #1");
clearResult();
synthesizeComposition({ type: "compositioncommitasis" });
is(result.compositionupdate, false, "runCompositionCommitAsIsTest: compositionupdate shouldn't be fired after dispatching compositioncommitasis #1");
is(result.compositionend, true, "runCompositionCommitAsIsTest: compositionend should be fired after dispatching compositioncommitasis #1");
is(result.text, true, "runCompositionCommitAsIsTest: text should be fired after dispatching compositioncommitasis because it's dispatched when there is composing string #1");
is(result.input, true, "runCompositionCommitAsIsTest: input should be fired after dispatching compositioncommitasis #1");
is(textarea.value, "\u3042", "runCompositionCommitAsIsTest: textarea doesn't have committed string #1");
// compositioncommitasis with committed string.
textarea.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3042",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
is(textarea.value, "\u3042", "runCompositionCommitAsIsTest: textarea doesn't have composition string #2");
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3042",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 1, "length": 0 }
});
is(textarea.value, "\u3042", "runCompositionCommitAsIsTest: textarea doesn't have committed string #2");
clearResult();
synthesizeComposition({ type: "compositioncommitasis" });
is(result.compositionupdate, false, "runCompositionCommitAsIsTest: compositionupdate shouldn't be fired after dispatching compositioncommitasis #2");
is(result.compositionend, true, "runCompositionCommitAsIsTest: compositionend should be fired after dispatching compositioncommitasis #2");
is(result.text, false, "runCompositionCommitAsIsTest: text shouldn't be fired after dispatching compositioncommitasis because it's dispatched when there is already committed string #2");
is(result.input, true, "runCompositionCommitAsIsTest: input should be fired after dispatching compositioncommitasis #2");
is(textarea.value, "\u3042", "runCompositionCommitAsIsTest: textarea doesn't have committed string #2");
// compositioncommitasis with committed string.
textarea.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3042",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
is(textarea.value, "\u3042", "runCompositionCommitAsIsTest: textarea doesn't have composition string #3");
synthesizeCompositionChange(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 0, "length": 0 }
});
is(textarea.value, "", "runCompositionCommitAsIsTest: textarea has non-empty composition string #3");
clearResult();
synthesizeComposition({ type: "compositioncommitasis" });
is(result.compositionupdate, false, "runCompositionCommitAsIsTest: compositionupdate shouldn't be fired after dispatching compositioncommitasis #3");
is(result.compositionend, true, "runCompositionCommitAsIsTest: compositionend should be fired after dispatching compositioncommitasis #3");
is(result.text, false, "runCompositionCommitAsIsTest: text shouldn't be fired after dispatching compositioncommitasis because it's dispatched when there is empty composition string #3");
is(result.input, true, "runCompositionCommitAsIsTest: input should be fired after dispatching compositioncommitasis #3");
is(textarea.value, "", "runCompositionCommitAsIsTest: textarea doesn't have committed string #3");
textarea.removeEventListener("compositionupdate", handler, true);
textarea.removeEventListener("compositionend", handler, true);
textarea.removeEventListener("input", handler, true);
textarea.removeEventListener("text", handler, true);
}
function runCompositionCommitTest()
{
textarea.focus();
var result = {};
function clearResult()
{
result = { compositionupdate: false, compositionend: false, text: false, input: false }
}
function handler(aEvent)
{
result[aEvent.type] = true;
}
textarea.addEventListener("compositionupdate", handler, true);
textarea.addEventListener("compositionend", handler, true);
textarea.addEventListener("input", handler, true);
textarea.addEventListener("text", handler, true);
// compositioncommit with different composing string.
textarea.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3042",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
is(textarea.value, "\u3042", "runCompositionCommitTest: textarea doesn't have composition string #1");
clearResult();
synthesizeComposition({ type: "compositioncommit", data: "\u3043" });
is(result.compositionupdate, true, "runCompositionCommitTest: compositionupdate should be fired after dispatching compositioncommit #1");
is(result.compositionend, true, "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #1");
is(result.text, true, "runCompositionCommitTest: text should be fired after dispatching compositioncommit because it's dispatched when there is compoing string #1");
is(result.input, true, "runCompositionCommitTest: input should be fired after dispatching compositioncommit #1");
is(textarea.value, "\u3043", "runCompositionCommitTest: textarea doesn't have committed string #1");
// compositioncommit with different committed string when there is already committed string
textarea.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3042",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
is(textarea.value, "\u3042", "runCompositionCommitTest: textarea doesn't have composition string #2");
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3042",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 1, "length": 0 }
});
is(textarea.value, "\u3042", "runCompositionCommitTest: textarea doesn't have committed string #2");
clearResult();
synthesizeComposition({ type: "compositioncommit", data: "\u3043" });
is(result.compositionupdate, true, "runCompositionCommitTest: compositionupdate should be fired after dispatching compositioncommit #2");
is(result.compositionend, true, "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #2");
is(result.text, true, "runCompositionCommitTest: text should be fired after dispatching compositioncommit #2");
is(result.input, true, "runCompositionCommitTest: input should be fired after dispatching compositioncommit #2");
is(textarea.value, "\u3043", "runCompositionCommitTest: textarea doesn't have committed string #2");
// compositioncommit with empty composition string.
textarea.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3042",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
is(textarea.value, "\u3042", "runCompositionCommitTest: textarea doesn't have composition string #3");
synthesizeCompositionChange(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 0, "length": 0 }
});
is(textarea.value, "", "runCompositionCommitTest: textarea has non-empty composition string #3");
clearResult();
synthesizeComposition({ type: "compositioncommit", data: "\u3043" });
is(result.compositionupdate, true, "runCompositionCommitTest: compositionupdate should be fired after dispatching compositioncommit #3");
is(result.compositionend, true, "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #3");
is(result.text, true, "runCompositionCommitTest: text should be fired after dispatching compositioncommit #3");
is(result.input, true, "runCompositionCommitTest: input should be fired after dispatching compositioncommit #3");
is(textarea.value, "\u3043", "runCompositionCommitTest: textarea doesn't have committed string #3");
// compositioncommit with non-empty composition string.
textarea.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3042",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
is(textarea.value, "\u3042", "runCompositionCommitTest: textarea doesn't have composition string #4");
clearResult();
synthesizeComposition({ type: "compositioncommit", data: "" });
is(result.compositionupdate, true, "runCompositionCommitTest: compositionupdate should be fired after dispatching compositioncommit #4");
is(result.compositionend, true, "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #4");
is(result.text, true, "runCompositionCommitTest: text should be fired after dispatching compositioncommit #4");
is(result.input, true, "runCompositionCommitTest: input should be fired after dispatching compositioncommit #4");
is(textarea.value, "", "runCompositionCommitTest: textarea should be empty #4");
// compositioncommit immediately without compositionstart
textarea.value = "";
clearResult();
synthesizeComposition({ type: "compositioncommit", data: "\u3042" });
is(result.compositionupdate, true, "runCompositionCommitTest: compositionupdate should be fired after dispatching compositioncommit #5");
is(result.compositionend, true, "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #5");
is(result.text, true, "runCompositionCommitTest: text should be fired after dispatching compositioncommit #5");
is(result.input, true, "runCompositionCommitTest: input should be fired after dispatching compositioncommit #5");
is(textarea.value, "\u3042", "runCompositionCommitTest: textarea should be empty #5");
// compositioncommit with same composition string.
textarea.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3042",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
is(textarea.value, "\u3042", "runCompositionCommitTest: textarea doesn't have composition string #5");
clearResult();
synthesizeComposition({ type: "compositioncommit", data: "\u3042" });
is(result.compositionupdate, false, "runCompositionCommitTest: compositionupdate shouldn't be fired after dispatching compositioncommit #5");
is(result.compositionend, true, "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #5");
is(result.text, true, "runCompositionCommitTest: text should be fired after dispatching compositioncommit because there was composition string #5");
is(result.input, true, "runCompositionCommitTest: input should be fired after dispatching compositioncommit #5");
is(textarea.value, "\u3042", "runCompositionCommitTest: textarea should have committed string #5");
// compositioncommit with same composition string when there is committed string
textarea.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3042",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
is(textarea.value, "\u3042", "runCompositionCommitTest: textarea doesn't have composition string #6");
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3042",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 1, "length": 0 }
});
is(textarea.value, "\u3042", "runCompositionCommitTest: textarea doesn't have composition string #6");
clearResult();
synthesizeComposition({ type: "compositioncommit", data: "\u3042" });
is(result.compositionupdate, false, "runCompositionCommitTest: compositionupdate shouldn't be fired after dispatching compositioncommit #6");
is(result.compositionend, true, "runCompositionCommitTest: compositionend should be fired after dispatching compositioncommit #6");
is(result.text, false, "runCompositionCommitTest: text shouldn't be fired after dispatching compositioncommit because there was already committed string #6");
is(result.input, true, "runCompositionCommitTest: input should be fired after dispatching compositioncommit #6");
is(textarea.value, "\u3042", "runCompositionCommitTest: textarea should have committed string #6");
textarea.removeEventListener("compositionupdate", handler, true);
textarea.removeEventListener("compositionend", handler, true);
textarea.removeEventListener("input", handler, true);
textarea.removeEventListener("text", handler, true);
}
function runCompositionTest()
{
textarea.value = "";
textarea.focus();
var caretRects = [];
var caretRect = synthesizeQueryCaretRect(0);
if (!checkQueryContentResult(caretRect,
"runCompositionTest: synthesizeQueryCaretRect #0")) {
return false;
}
caretRects[0] = caretRect;
// input first character
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
if (!checkContent("\u3089", "runCompositionTest", "#1-1") ||
!checkSelection(1, "", "runCompositionTest", "#1-1")) {
return;
}
caretRect = synthesizeQueryCaretRect(1);
if (!checkQueryContentResult(caretRect,
"runCompositionTest: synthesizeQueryCaretRect #1-1")) {
return false;
}
caretRects[1] = caretRect;
// input second character
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
if (!checkContent("\u3089\u30FC", "runCompositionTest", "#1-2") ||
!checkSelection(2, "", "runCompositionTest", "#1-2")) {
return;
}
caretRect = synthesizeQueryCaretRect(2);
if (!checkQueryContentResult(caretRect,
"runCompositionTest: synthesizeQueryCaretRect #1-2")) {
return false;
}
caretRects[2] = caretRect;
isnot(caretRects[2].left, caretRects[1].left,
"runCompositionTest: caret isn't moved (#1-2)");
is(caretRects[2].top, caretRects[1].top,
"runCompositionTest: caret is moved to another line (#1-2)");
is(caretRects[2].width, caretRects[1].width,
"runCompositionTest: caret width is wrong (#1-2)");
is(caretRects[2].height, caretRects[1].height,
"runCompositionTest: caret width is wrong (#1-2)");
// input third character
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC\u3081",
"clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 3, "length": 0 }
});
if (!checkContent("\u3089\u30FC\u3081", "runCompositionTest", "#1-3") ||
!checkSelection(3, "", "runCompositionTest", "#1-3")) {
return;
}
caretRect = synthesizeQueryCaretRect(3);
if (!checkQueryContentResult(caretRect,
"runCompositionTest: synthesizeQueryCaretRect #1-3")) {
return false;
}
caretRects[3] = caretRect;
isnot(caretRects[3].left, caretRects[2].left,
"runCompositionTest: caret isn't moved (#1-3)");
is(caretRects[3].top, caretRects[2].top,
"runCompositionTest: caret is moved to another line (#1-3)");
is(caretRects[3].width, caretRects[2].width,
"runCompositionTest: caret width is wrong (#1-3)");
is(caretRects[3].height, caretRects[2].height,
"runCompositionTest: caret height is wrong (#1-3)");
// moves the caret left
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC\u3081",
"clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
if (!checkContent("\u3089\u30FC\u3081", "runCompositionTest", "#1-3-1") ||
!checkSelection(2, "", "runCompositionTest", "#1-3-1")) {
return;
}
caretRect = synthesizeQueryCaretRect(2);
if (!checkQueryContentResult(caretRect,
"runCompositionTest: synthesizeQueryCaretRect #1-3-1")) {
return false;
}
is(caretRect.left, caretRects[2].left,
"runCompositionTest: caret rects are different (#1-3-1, left)");
is(caretRect.top, caretRects[2].top,
"runCompositionTest: caret rects are different (#1-3-1, top)");
// by bug 335359, the caret width depends on the right side's character.
is(caretRect.width, caretRects[2].width + 1,
"runCompositionTest: caret rects are different (#1-3-1, width)");
is(caretRect.height, caretRects[2].height,
"runCompositionTest: caret rects are different (#1-3-1, height)");
// moves the caret left
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC\u3081",
"clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
if (!checkContent("\u3089\u30FC\u3081", "runCompositionTest", "#1-3-2") ||
!checkSelection(1, "", "runCompositionTest", "#1-3-2")) {
return;
}
caretRect = synthesizeQueryCaretRect(1);
if (!checkQueryContentResult(caretRect,
"runCompositionTest: synthesizeQueryCaretRect #1-3-2")) {
return false;
}
is(caretRect.left, caretRects[1].left,
"runCompositionTest: caret rects are different (#1-3-2, left)");
is(caretRect.top, caretRects[1].top,
"runCompositionTest: caret rects are different (#1-3-2, top)");
// by bug 335359, the caret width depends on the right side's character.
is(caretRect.width, caretRects[1].width + 1,
"runCompositionTest: caret rects are different (#1-3-2, width)");
is(caretRect.height, caretRects[1].height,
"runCompositionTest: caret rects are different (#1-3-2, height)");
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC\u3081\u3093",
"clauses":
[
{ "length": 4, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 4, "length": 0 }
});
if (!checkContent("\u3089\u30FC\u3081\u3093", "runCompositionTest", "#1-4") ||
!checkSelection(4, "", "runCompositionTest", "#1-4")) {
return;
}
// backspace
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC\u3081",
"clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 3, "length": 0 }
});
if (!checkContent("\u3089\u30FC\u3081", "runCompositionTest", "#1-5") ||
!checkSelection(3, "", "runCompositionTest", "#1-5")) {
return;
}
// re-input
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC\u3081\u3093",
"clauses":
[
{ "length": 4, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 4, "length": 0 }
});
if (!checkContent("\u3089\u30FC\u3081\u3093", "runCompositionTest", "#1-6") ||
!checkSelection(4, "", "runCompositionTest", "#1-6")) {
return;
}
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC\u3081\u3093\u3055",
"clauses":
[
{ "length": 5, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 5, "length": 0 }
});
if (!checkContent("\u3089\u30FC\u3081\u3093\u3055", "runCompositionTest", "#1-7") ||
!checkSelection(5, "", "runCompositionTest", "#1-7")) {
return;
}
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC\u3081\u3093\u3055\u3044",
"clauses":
[
{ "length": 6, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 6, "length": 0 }
});
if (!checkContent("\u3089\u30FC\u3081\u3093\u3055\u3044", "runCompositionTest", "#1-8") ||
!checkSelection(6, "", "runCompositionTest", "#1-8")) {
return;
}
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC\u3081\u3093\u3055\u3044\u3053",
"clauses":
[
{ "length": 7, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 7, "length": 0 }
});
if (!checkContent("\u3089\u30FC\u3081\u3093\u3055\u3044\u3053", "runCompositionTest", "#1-8") ||
!checkSelection(7, "", "runCompositionTest", "#1-8")) {
return;
}
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC\u3081\u3093\u3055\u3044\u3053\u3046",
"clauses":
[
{ "length": 8, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 8, "length": 0 }
});
if (!checkContent("\u3089\u30FC\u3081\u3093\u3055\u3044\u3053\u3046",
"runCompositionTest", "#1-9") ||
!checkSelection(8, "", "runCompositionTest", "#1-9")) {
return;
}
// convert
synthesizeCompositionChange(
{ "composition":
{ "string": "\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8",
"clauses":
[
{ "length": 4,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
{ "length": 2,
"attr": COMPOSITION_ATTR_CONVERTED_CLAUSE }
]
},
"caret": { "start": 4, "length": 0 }
});
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8",
"runCompositionTest", "#1-10") ||
!checkSelection(4, "", "runCompositionTest", "#1-10")) {
return;
}
// change the selected clause
synthesizeCompositionChange(
{ "composition":
{ "string": "\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8",
"clauses":
[
{ "length": 4,
"attr": COMPOSITION_ATTR_CONVERTED_CLAUSE },
{ "length": 2,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
]
},
"caret": { "start": 6, "length": 0 }
});
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8",
"runCompositionTest", "#1-11") ||
!checkSelection(6, "", "runCompositionTest", "#1-11")) {
return;
}
// reset clauses
synthesizeCompositionChange(
{ "composition":
{ "string": "\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046",
"clauses":
[
{ "length": 5,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
{ "length": 3,
"attr": COMPOSITION_ATTR_CONVERTED_CLAUSE }
]
},
"caret": { "start": 5, "length": 0 }
});
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046",
"runCompositionTest", "#1-12") ||
!checkSelection(5, "", "runCompositionTest", "#1-12")) {
return;
}
var textRect1 = synthesizeQueryTextRect(0, 1);
var textRect2 = synthesizeQueryTextRect(1, 1);
if (!checkQueryContentResult(textRect1,
"runCompositionTest: synthesizeQueryTextRect #1-12-1") ||
!checkQueryContentResult(textRect2,
"runCompositionTest: synthesizeQueryTextRect #1-12-2")) {
return false;
}
// commit the composition string
synthesizeComposition({ type: "compositioncommitasis" });
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046",
"runCompositionTest", "#1-13") ||
!checkSelection(8, "", "runCompositionTest", "#1-13")) {
return;
}
var textRect3 = synthesizeQueryTextRect(0, 1);
var textRect4 = synthesizeQueryTextRect(1, 1);
if (!checkQueryContentResult(textRect3,
"runCompositionTest: synthesizeQueryTextRect #1-13-1") ||
!checkQueryContentResult(textRect4,
"runCompositionTest: synthesizeQueryTextRect #1-13-2")) {
return false;
}
checkRect(textRect3, textRect1, "runCompositionTest: textRect #1-13-1");
checkRect(textRect4, textRect2, "runCompositionTest: textRect #1-13-2");
// restart composition and input characters
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3057",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046\u3057",
"runCompositionTest", "#2-1") ||
!checkSelection(8 + 1, "", "runCompositionTest", "#2-1")) {
return;
}
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3058",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046\u3058",
"runCompositionTest", "#2-2") ||
!checkSelection(8 + 1, "", "runCompositionTest", "#2-2")) {
return;
}
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3058\u3087",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046\u3058\u3087",
"runCompositionTest", "#2-3") ||
!checkSelection(8 + 2, "", "runCompositionTest", "#2-3")) {
return;
}
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3058\u3087\u3046",
"clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 3, "length": 0 }
});
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046\u3058\u3087\u3046",
"runCompositionTest", "#2-4") ||
!checkSelection(8 + 3, "", "runCompositionTest", "#2-4")) {
return;
}
// commit the composition string
synthesizeComposition({ type: "compositioncommitasis" });
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u3055\u884C\u3053\u3046\u3058\u3087\u3046",
"runCompositionTest", "#2-4") ||
!checkSelection(8 + 3, "", "runCompositionTest", "#2-4")) {
return;
}
// set selection
var selectionSetTest = synthesizeSelectionSet(4, 7, false);
ok(selectionSetTest, "runCompositionTest: selectionSetTest failed");
if (!checkSelection(4, "\u3055\u884C\u3053\u3046\u3058\u3087\u3046", "runCompositionTest", "#3-1")) {
return;
}
// start composition with selection
synthesizeCompositionChange(
{ "composition":
{ "string": "\u304A",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u304A",
"runCompositionTest", "#3-2") ||
!checkSelection(4 + 1, "", "runCompositionTest", "#3-2")) {
return;
}
// remove the composition string
synthesizeCompositionChange(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 0, "length": 0 }
});
if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
"runCompositionTest", "#3-3") ||
!checkSelection(4, "", "runCompositionTest", "#3-3")) {
return;
}
// re-input the composition string
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3046",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u3046",
"runCompositionTest", "#3-4") ||
!checkSelection(4 + 1, "", "runCompositionTest", "#3-4")) {
return;
}
// cancel the composition
synthesizeComposition({ type: "compositioncommit", data: "" });
if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
"runCompositionTest", "#3-5") ||
!checkSelection(4, "", "runCompositionTest", "#3-5")) {
return;
}
// bug 271815, some Chinese IMEs for Linux make empty composition string
// and compty clause information when it lists up Chinese characters on
// its candidate window.
synthesizeCompositionChange(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 0, "length": 0 }
});
if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
"runCompositionTest", "#4-1") ||
!checkSelection(4, "", "runCompositionTest", "#4-1")) {
return;
}
synthesizeCompositionChange(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 0, "length": 0 }
});
if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
"runCompositionTest", "#4-2") ||
!checkSelection(4, "", "runCompositionTest", "#4-2")) {
return;
}
synthesizeComposition({ type: "compositioncommit", data: "\u6700" });
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700",
"runCompositionTest", "#4-3") ||
!checkSelection(5, "", "runCompositionTest", "#4-3")) {
return;
}
// testing the canceling case
synthesizeCompositionChange(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 0, "length": 0 }
});
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700",
"runCompositionTest", "#4-5") ||
!checkSelection(5, "", "runCompositionTest", "#4-5")) {
return;
}
synthesizeComposition({ type: "compositioncommitasis" });
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700",
"runCompositionTest", "#4-6") ||
!checkSelection(5, "", "runCompositionTest", "#4-6")) {
return;
}
// testing whether the empty composition string deletes selected string.
synthesizeKey("VK_LEFT", { shiftKey: true });
synthesizeCompositionChange(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 0, "length": 0 }
});
if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
"runCompositionTest", "#4-8") ||
!checkSelection(4, "", "runCompositionTest", "#4-8")) {
return;
}
synthesizeComposition({ type: "compositioncommit", data: "\u9AD8" });
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u9AD8",
"runCompositionTest", "#4-9") ||
!checkSelection(5, "", "runCompositionTest", "#4-9")) {
return;
}
synthesizeKey("VK_BACK_SPACE", {});
if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
"runCompositionTest", "#4-11") ||
!checkSelection(4, "", "runCompositionTest", "#4-11")) {
return;
}
// bug 23558, ancient Japanese IMEs on Window may send empty text event
// twice at canceling composition.
synthesizeCompositionChange(
{ "composition":
{ "string": "\u6700",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700",
"runCompositionTest", "#5-1") ||
!checkSelection(4 + 1, "", "runCompositionTest", "#5-1")) {
return;
}
synthesizeCompositionChange(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 0, "length": 0 }
});
if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
"runCompositionTest", "#5-2") ||
!checkSelection(4, "", "runCompositionTest", "#5-2")) {
return;
}
synthesizeComposition({ type: "compositioncommitasis" });
if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
"runCompositionTest", "#5-3") ||
!checkSelection(4, "", "runCompositionTest", "#5-3")) {
return;
}
// Undo tests for the testcases for bug 23558 and bug 271815
synthesizeKey("Z", { accelKey: true });
// XXX this is unexpected behavior, see bug 258291
if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
"runCompositionTest", "#6-1") ||
!checkSelection(4, "", "runCompositionTest", "#6-1")) {
return;
}
synthesizeKey("Z", { accelKey: true });
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u9AD8",
"runCompositionTest", "#6-2") ||
!checkSelection(5, "", "runCompositionTest", "#6-2")) {
return;
}
synthesizeKey("Z", { accelKey: true });
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700",
"runCompositionTest", "#6-3") ||
!checkSelection(4, "\u6700", "runCompositionTest", "#6-3")) {
return;
}
synthesizeKey("Z", { accelKey: true });
// XXX this is unexpected behavior, see bug 258291
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700",
"runCompositionTest", "#6-4") ||
!checkSelection(5, "", "runCompositionTest", "#6-4")) {
return;
}
synthesizeKey("Z", { accelKey: true });
if (!checkContent("\u30E9\u30FC\u30E1\u30F3",
"runCompositionTest", "#6-5") ||
!checkSelection(4, "", "runCompositionTest", "#6-5")) {
return;
}
}
function runCompositionEventTest()
{
const kDescription = "runCompositionEventTest: ";
const kEvents = ["compositionstart", "compositionupdate", "compositionend",
"input"];
input.value = "";
input.focus();
var windowEventCounts = [], windowEventData = [], windowEventLocale = [];
var inputEventCounts = [], inputEventData = [], inputEventLocale = [];
var preventDefault = false;
var stopPropagation = false;
function initResults()
{
for (var i = 0; i < kEvents.length; i++) {
windowEventCounts[kEvents[i]] = 0;
windowEventData[kEvents[i]] = "";
windowEventLocale[kEvents[i]] = "";
inputEventCounts[kEvents[i]] = 0;
inputEventData[kEvents[i]] = "";
inputEventLocale[kEvents[i]] = "";
}
}
function compositionEventHandlerForWindow(aEvent)
{
windowEventCounts[aEvent.type]++;
windowEventData[aEvent.type] = aEvent.data;
windowEventLocale[aEvent.type] = aEvent.locale;
if (preventDefault) {
aEvent.preventDefault();
}
if (stopPropagation) {
aEvent.stopPropagation();
}
}
function formEventHandlerForWindow(aEvent)
{
ok(aEvent.isTrusted, "input events must be trusted events");
windowEventCounts[aEvent.type]++;
windowEventData[aEvent.type] = input.value;
}
function compositionEventHandlerForInput(aEvent)
{
inputEventCounts[aEvent.type]++;
inputEventData[aEvent.type] = aEvent.data;
inputEventLocale[aEvent.type] = aEvent.locale;
if (preventDefault) {
aEvent.preventDefault();
}
if (stopPropagation) {
aEvent.stopPropagation();
}
}
function formEventHandlerForInput(aEvent)
{
inputEventCounts[aEvent.type]++;
inputEventData[aEvent.type] = input.value;
}
window.addEventListener("compositionstart", compositionEventHandlerForWindow,
true, true);
window.addEventListener("compositionend", compositionEventHandlerForWindow,
true, true);
window.addEventListener("compositionupdate", compositionEventHandlerForWindow,
true, true);
window.addEventListener("input", formEventHandlerForWindow,
true, true);
input.addEventListener("compositionstart", compositionEventHandlerForInput,
true, true);
input.addEventListener("compositionend", compositionEventHandlerForInput,
true, true);
input.addEventListener("compositionupdate", compositionEventHandlerForInput,
true, true);
input.addEventListener("input", formEventHandlerForInput,
true, true);
// test for normal case
initResults();
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
is(windowEventCounts["compositionstart"], 1,
kDescription + "compositionstart hasn't been handled by window #1");
is(windowEventData["compositionstart"], "",
kDescription + "data of compositionstart isn't empty (window) #1");
is(windowEventLocale["compositionstart"], "",
kDescription + "locale of compositionstart isn't empty (window) #1");
is(inputEventCounts["compositionstart"], 1,
kDescription + "compositionstart hasn't been handled by input #1");
is(inputEventData["compositionstart"], "",
kDescription + "data of compositionstart isn't empty (input) #1");
is(inputEventLocale["compositionstart"], "",
kDescription + "locale of compositionstart isn't empty (input) #1");
is(windowEventCounts["compositionupdate"], 1,
kDescription + "compositionupdate hasn't been handled by window #1");
is(windowEventData["compositionupdate"], "\u3089",
kDescription + "data of compositionupdate doesn't match (window) #1");
is(windowEventLocale["compositionupdate"], "",
kDescription + "locale of compositionupdate isn't empty (window) #1");
is(inputEventCounts["compositionupdate"], 1,
kDescription + "compositionupdate hasn't been handled by input #1");
is(inputEventData["compositionupdate"], "\u3089",
kDescription + "data of compositionupdate doesn't match (input) #1");
is(inputEventLocale["compositionupdate"], "",
kDescription + "locale of compositionupdate isn't empty (input) #1");
is(windowEventCounts["compositionend"], 0,
kDescription + "compositionend has been handled by window #1");
is(inputEventCounts["compositionend"], 0,
kDescription + "compositionend has been handled by input #1");
is(windowEventCounts["input"], 1,
kDescription + "input hasn't been handled by window #1");
is(windowEventData["input"], "\u3089",
kDescription + "value of input element wasn't modified (window) #1");
is(inputEventCounts["input"], 1,
kDescription + "input hasn't been handled by input #1");
is(inputEventData["input"], "\u3089",
kDescription + "value of input element wasn't modified (input) #1");
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
is(windowEventCounts["compositionstart"], 1,
kDescription + "compositionstart has been handled more than once by window #2");
is(inputEventCounts["compositionstart"], 1,
kDescription + "compositionstart has been handled more than once by input #2");
is(windowEventCounts["compositionupdate"], 2,
kDescription + "compositionupdate hasn't been handled by window #2");
is(windowEventData["compositionupdate"], "\u3089\u30FC",
kDescription + "data of compositionupdate doesn't match (window) #2");
is(windowEventLocale["compositionupdate"], "",
kDescription + "locale of compositionupdate isn't empty (window) #2");
is(inputEventCounts["compositionupdate"], 2,
kDescription + "compositionupdate hasn't been handled by input #2");
is(inputEventData["compositionupdate"], "\u3089\u30FC",
kDescription + "data of compositionupdate doesn't match (input) #2");
is(inputEventLocale["compositionupdate"], "",
kDescription + "locale of compositionupdate isn't empty (input) #2");
is(windowEventCounts["compositionend"], 0,
kDescription + "compositionend has been handled during composition by window #2");
is(inputEventCounts["compositionend"], 0,
kDescription + "compositionend has been handled during composition by input #2");
is(windowEventCounts["input"], 2,
kDescription + "input hasn't been handled by window #2");
is(windowEventData["input"], "\u3089\u30FC",
kDescription + "value of input element wasn't modified (window) #2");
is(inputEventCounts["input"], 2,
kDescription + "input hasn't been handled by input #2");
is(inputEventData["input"], "\u3089\u30FC",
kDescription + "value of input element wasn't modified (input) #2");
// text event shouldn't cause composition update, e.g., at committing.
synthesizeComposition({ type: "compositioncommitasis" });
is(windowEventCounts["compositionstart"], 1,
kDescription + "compositionstart has been handled more than once by window #3");
is(inputEventCounts["compositionstart"], 1,
kDescription + "compositionstart has been handled more than once by input #3");
is(windowEventCounts["compositionupdate"], 2,
kDescription + "compositionupdate has been fired unexpectedly on window #3");
is(inputEventCounts["compositionupdate"], 2,
kDescription + "compositionupdate has been fired unexpectedly on input #3");
is(windowEventCounts["compositionend"], 1,
kDescription + "compositionend hasn't been handled by window #3");
is(windowEventData["compositionend"], "\u3089\u30FC",
kDescription + "data of compositionend doesn't match (window) #3");
is(windowEventLocale["compositionend"], "",
kDescription + "locale of compositionend isn't empty (window) #3");
is(inputEventCounts["compositionend"], 1,
kDescription + "compositionend hasn't been handled by input #3");
is(inputEventData["compositionend"], "\u3089\u30FC",
kDescription + "data of compositionend doesn't match (input) #3");
is(inputEventLocale["compositionend"], "",
kDescription + "locale of compositionend isn't empty (input) #3");
is(windowEventCounts["input"], 3,
kDescription + "input hasn't been handled by window #3");
is(windowEventData["input"], "\u3089\u30FC",
kDescription + "value of input element wasn't modified (window) #3");
is(inputEventCounts["input"], 3,
kDescription + "input hasn't been handled by input #3");
is(inputEventData["input"], "\u3089\u30FC",
kDescription + "value of input element wasn't modified (input) #3");
// select the second character, then, data of composition start should be
// the selected character.
initResults();
synthesizeKey("VK_LEFT", { shiftKey: true });
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
synthesizeComposition({ type: "compositioncommitasis" });
is(windowEventCounts["compositionstart"], 1,
kDescription + "compositionstart hasn't been handled by window #4");
is(windowEventData["compositionstart"], "\u30FC",
kDescription + "data of compositionstart is empty (window) #4");
is(windowEventLocale["compositionstart"], "",
kDescription + "locale of compositionstart isn't empty (window) #4");
is(inputEventCounts["compositionstart"], 1,
kDescription + "compositionstart hasn't been handled by input #4");
is(inputEventData["compositionstart"], "\u30FC",
kDescription + "data of compositionstart is empty (input) #4");
is(inputEventLocale["compositionstart"], "",
kDescription + "locale of compositionstart isn't empty (input) #4");
is(windowEventCounts["compositionupdate"], 1,
kDescription + "compositionupdate hasn't been handled by window #4");
is(windowEventData["compositionupdate"], "\u3089",
kDescription + "data of compositionupdate doesn't match (window) #4");
is(windowEventLocale["compositionupdate"], "",
kDescription + "locale of compositionupdate isn't empty (window) #4");
is(inputEventCounts["compositionupdate"], 1,
kDescription + "compositionupdate hasn't been handled by input #4");
is(inputEventData["compositionupdate"], "\u3089",
kDescription + "data of compositionupdate doesn't match (input) #4");
is(inputEventLocale["compositionupdate"], "",
kDescription + "locale of compositionupdate isn't empty (input) #4");
is(windowEventCounts["compositionend"], 1,
kDescription + "compositionend hasn't been handled by window #4");
is(windowEventData["compositionend"], "\u3089",
kDescription + "data of compositionend doesn't match (window) #4");
is(windowEventLocale["compositionend"], "",
kDescription + "locale of compositionend isn't empty (window) #4");
is(inputEventCounts["compositionend"], 1,
kDescription + "compositionend hasn't been handled by input #4");
is(inputEventData["compositionend"], "\u3089",
kDescription + "data of compositionend doesn't match (input) #4");
is(inputEventLocale["compositionend"], "",
kDescription + "locale of compositionend isn't empty (input) #4");
is(windowEventCounts["input"], 2,
kDescription + "input hasn't been handled by window #4");
is(windowEventData["input"], "\u3089\u3089",
kDescription + "value of input element wasn't modified (window) #4");
is(inputEventCounts["input"], 2,
kDescription + "input hasn't been handled by input #4");
is(inputEventData["input"], "\u3089\u3089",
kDescription + "value of input element wasn't modified (input) #4");
// preventDefault() should effect nothing.
preventDefault = true;
initResults();
synthesizeKey("A", { accelKey: true }); // Select All
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306D",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
synthesizeComposition({ type: "compositioncommitasis" });
is(windowEventCounts["compositionstart"], 1,
kDescription + "compositionstart hasn't been handled by window #5");
is(windowEventData["compositionstart"], "\u3089\u3089",
kDescription + "data of compositionstart is empty (window) #5");
is(windowEventLocale["compositionstart"], "",
kDescription + "locale of compositionstart isn't empty (window) #5");
is(inputEventCounts["compositionstart"], 1,
kDescription + "compositionstart hasn't been handled by input #5");
is(inputEventData["compositionstart"], "\u3089\u3089",
kDescription + "data of compositionstart is empty (input) #5");
is(inputEventLocale["compositionstart"], "",
kDescription + "locale of compositionstart isn't empty (input) #5");
is(windowEventCounts["compositionupdate"], 1,
kDescription + "compositionupdate hasn't been handled by window #5");
is(windowEventData["compositionupdate"], "\u306D",
kDescription + "data of compositionupdate doesn't match (window) #5");
is(windowEventLocale["compositionupdate"], "",
kDescription + "locale of compositionupdate isn't empty (window) #5");
is(inputEventCounts["compositionupdate"], 1,
kDescription + "compositionupdate hasn't been handled by input #5");
is(inputEventData["compositionupdate"], "\u306D",
kDescription + "data of compositionupdate doesn't match (input) #5");
is(inputEventLocale["compositionupdate"], "",
kDescription + "locale of compositionupdate isn't empty (input) #5");
is(windowEventCounts["compositionend"], 1,
kDescription + "compositionend hasn't been handled by window #5");
is(windowEventData["compositionend"], "\u306D",
kDescription + "data of compositionend doesn't match (window) #5");
is(windowEventLocale["compositionend"], "",
kDescription + "locale of compositionend isn't empty (window) #5");
is(inputEventCounts["compositionend"], 1,
kDescription + "compositionend hasn't been handled by input #5");
is(inputEventData["compositionend"], "\u306D",
kDescription + "data of compositionend doesn't match (input) #5");
is(inputEventLocale["compositionend"], "",
kDescription + "locale of compositionend isn't empty (input) #5");
is(windowEventCounts["input"], 2,
kDescription + "input hasn't been handled by window #5");
is(windowEventData["input"], "\u306D",
kDescription + "value of input element wasn't modified (window) #5");
is(inputEventCounts["input"], 2,
kDescription + "input hasn't been handled by input #5");
is(inputEventData["input"], "\u306D",
kDescription + "value of input element wasn't modified (input) #5");
prevnetDefault = false;
// stopPropagation() should effect nothing (except event count)
stopPropagation = true;
initResults();
synthesizeKey("A", { accelKey: true }); // Select All
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
synthesizeComposition({ type: "compositioncommitasis" });
is(windowEventCounts["compositionstart"], 1,
kDescription + "compositionstart hasn't been handled by window #6");
is(windowEventData["compositionstart"], "\u306D",
kDescription + "data of compositionstart is empty #6");
is(windowEventLocale["compositionstart"], "",
kDescription + "locale of compositionstart isn't empty #6");
is(inputEventCounts["compositionstart"], 0,
kDescription + "compositionstart has been handled by input #6");
is(windowEventCounts["compositionupdate"], 1,
kDescription + "compositionupdate hasn't been handled by window #6");
is(windowEventData["compositionupdate"], "\u306E",
kDescription + "data of compositionupdate doesn't match #6");
is(windowEventLocale["compositionupdate"], "",
kDescription + "locale of compositionupdate isn't empty #6");
is(inputEventCounts["compositionupdate"], 0,
kDescription + "compositionupdate has been handled by input #6");
is(windowEventCounts["compositionend"], 1,
kDescription + "compositionend hasn't been handled by window #6");
is(windowEventData["compositionend"], "\u306E",
kDescription + "data of compositionend doesn't match #6");
is(windowEventLocale["compositionend"], "",
kDescription + "locale of compositionend isn't empty #6");
is(inputEventCounts["compositionend"], 0,
kDescription + "compositionend has been handled by input #6");
is(windowEventCounts["input"], 2,
kDescription + "input hasn't been handled by window #6");
is(windowEventData["input"], "\u306E",
kDescription + "value of input element wasn't modified (window) #6");
is(inputEventCounts["input"], 2,
kDescription + "input hasn't been handled by input #6");
is(inputEventData["input"], "\u306E",
kDescription + "value of input element wasn't modified (input) #6");
stopPropagation = false;
// create event and dispatch it.
initResults();
input.value = "value of input";
synthesizeKey("A", { accelKey: true }); // Select All
var compositionstart = document.createEvent("CompositionEvent");
compositionstart.initCompositionEvent("compositionstart",
true, true, document.defaultView,
"start data", "start locale");
is(compositionstart.type, "compositionstart",
kDescription + "type doesn't match #7");
is(compositionstart.data, "start data",
kDescription + "data doesn't match #7");
is(compositionstart.locale, "start locale",
kDescription + "locale doesn't match #7");
is(compositionstart.detail, 0,
kDescription + "detail isn't 0 #7");
input.dispatchEvent(compositionstart);
is(windowEventCounts["compositionstart"], 1,
kDescription + "compositionstart hasn't been handled by window #7");
is(windowEventData["compositionstart"], "start data",
kDescription + "data of compositionstart was changed (window) #7");
is(windowEventLocale["compositionstart"], "start locale",
kDescription + "locale of compositionstart was changed (window) #7");
is(inputEventCounts["compositionstart"], 1,
kDescription + "compositionstart hasn't been handled by input #7");
is(inputEventData["compositionstart"], "start data",
kDescription + "data of compositionstart was changed (input) #7");
is(inputEventLocale["compositionstart"], "start locale",
kDescription + "locale of compositionstart was changed (input) #7");
is(input.value, "value of input",
kDescription + "input value was changed #7");
var compositionupdate1 = document.createEvent("compositionevent");
compositionupdate1.initCompositionEvent("compositionupdate",
true, false, document.defaultView,
"composing string", "composing locale");
is(compositionupdate1.type, "compositionupdate",
kDescription + "type doesn't match #8");
is(compositionupdate1.data, "composing string",
kDescription + "data doesn't match #8");
is(compositionupdate1.locale, "composing locale",
kDescription + "locale doesn't match #8");
is(compositionupdate1.detail, 0,
kDescription + "detail isn't 0 #8");
input.dispatchEvent(compositionupdate1);
is(windowEventCounts["compositionupdate"], 1,
kDescription + "compositionupdate hasn't been handled by window #8");
is(windowEventData["compositionupdate"], "composing string",
kDescription + "data of compositionupdate was changed (window) #8");
is(windowEventLocale["compositionupdate"], "composing locale",
kDescription + "locale of compositionupdate was changed (window) #8");
is(inputEventCounts["compositionupdate"], 1,
kDescription + "compositionupdate hasn't been handled by input #8");
is(inputEventData["compositionupdate"], "composing string",
kDescription + "data of compositionupdate was changed (input) #8");
is(inputEventLocale["compositionupdate"], "composing locale",
kDescription + "locale of compositionupdate was changed (input) #8");
is(input.value, "value of input",
kDescription + "input value was changed #8");
var compositionupdate2 = document.createEvent("compositionEvent");
compositionupdate2.initCompositionEvent("compositionupdate",
true, false, document.defaultView,
"commit string", "commit locale");
is(compositionupdate2.type, "compositionupdate",
kDescription + "type doesn't match #9");
is(compositionupdate2.data, "commit string",
kDescription + "data doesn't match #9");
is(compositionupdate2.locale, "commit locale",
kDescription + "locale doesn't match #9");
is(compositionupdate2.detail, 0,
kDescription + "detail isn't 0 #9");
input.dispatchEvent(compositionupdate2);
is(windowEventCounts["compositionupdate"], 2,
kDescription + "compositionupdate hasn't been handled by window #9");
is(windowEventData["compositionupdate"], "commit string",
kDescription + "data of compositionupdate was changed (window) #9");
is(windowEventLocale["compositionupdate"], "commit locale",
kDescription + "locale of compositionupdate was changed (window) #9");
is(inputEventCounts["compositionupdate"], 2,
kDescription + "compositionupdate hasn't been handled by input #9");
is(inputEventData["compositionupdate"], "commit string",
kDescription + "data of compositionupdate was changed (input) #9");
is(inputEventLocale["compositionupdate"], "commit locale",
kDescription + "locale of compositionupdate was changed (input) #9");
is(input.value, "value of input",
kDescription + "input value was changed #9");
var compositionend = document.createEvent("Compositionevent");
compositionend.initCompositionEvent("compositionend",
true, false, document.defaultView,
"end data", "end locale");
is(compositionend.type, "compositionend",
kDescription + "type doesn't match #10");
is(compositionend.data, "end data",
kDescription + "data doesn't match #10");
is(compositionend.locale, "end locale",
kDescription + "locale doesn't match #10");
is(compositionend.detail, 0,
kDescription + "detail isn't 0 #10");
input.dispatchEvent(compositionend);
is(windowEventCounts["compositionend"], 1,
kDescription + "compositionend hasn't been handled by window #10");
is(windowEventData["compositionend"], "end data",
kDescription + "data of compositionend was changed (window) #10");
is(windowEventLocale["compositionend"], "end locale",
kDescription + "locale of compositionend was changed (window) #10");
is(inputEventCounts["compositionend"], 1,
kDescription + "compositionend hasn't been handled by input #10");
is(inputEventData["compositionend"], "end data",
kDescription + "data of compositionend was changed (input) #10");
is(inputEventLocale["compositionend"], "end locale",
kDescription + "locale of compositionend was changed (input) #10");
is(input.value, "value of input",
kDescription + "input value was changed #10");
window.removeEventListener("compositionstart",
compositionEventHandlerForWindow, true);
window.removeEventListener("compositionend",
compositionEventHandlerForWindow, true);
window.removeEventListener("compositionupdate",
compositionEventHandlerForWindow, true);
window.removeEventListener("input",
formEventHandlerForWindow, true);
input.removeEventListener("compositionstart",
compositionEventHandlerForInput, true);
input.removeEventListener("compositionend",
compositionEventHandlerForInput, true);
input.removeEventListener("compositionupdate",
compositionEventHandlerForInput, true);
input.removeEventListener("input",
formEventHandlerForInput, true);
}
function runCharAtPointTest(aFocusedEditor, aTargetName)
{
aFocusedEditor.value = "This is a test of the\nContent Events";
// 012345678901234567890 12345678901234
// 0 1 2 3
aFocusedEditor.focus();
const kNone = -1;
const kTestingOffset = [ 0, 10, 20, 21 + kLFLen, 34 + kLFLen];
const kLeftSideOffset = [ kNone, 9, 19, kNone, 33 + kLFLen];
const kRightSideOffset = [ 1, 11, kNone, 22 + kLFLen, kNone];
const kLeftTentativeCaretOffset = [ 0, 10, 20, 21 + kLFLen, 34 + kLFLen];
const kRightTentativeCaretOffset = [ 1, 11, 21, 22 + kLFLen, 35 + kLFLen];
var editorRect = synthesizeQueryEditorRect();
if (!checkQueryContentResult(editorRect,
"runCharAtPointTest (" + aTargetName + "): editorRect")) {
return;
}
for (var i = 0; i < kTestingOffset.length; i++) {
var textRect = synthesizeQueryTextRect(kTestingOffset[i], 1);
if (!checkQueryContentResult(textRect,
"runCharAtPointTest (" + aTargetName + "): textRect: i=" + i)) {
continue;
}
checkRectContainsRect(textRect, editorRect,
"runCharAtPointTest (" + aTargetName +
"): the text rect isn't in the editor");
// Test #1, getting same character rect by the point near the top-left.
var charAtPt1 = synthesizeCharAtPoint(textRect.left + 1,
textRect.top + 1);
if (checkQueryContentResult(charAtPt1,
"runCharAtPointTest (" + aTargetName + "): charAtPt1: i=" + i)) {
ok(!charAtPt1.notFound,
"runCharAtPointTest (" + aTargetName + "): charAtPt1 isn't found: i=" + i);
if (!charAtPt1.notFound) {
is(charAtPt1.offset, kTestingOffset[i],
"runCharAtPointTest (" + aTargetName + "): charAtPt1 offset is wrong: i=" + i);
checkRect(charAtPt1, textRect, "runCharAtPointTest (" + aTargetName +
"): charAtPt1 left is wrong: i=" + i);
}
ok(!charAtPt1.tentativeCaretOffsetNotFound,
"runCharAtPointTest (" + aTargetName + "): tentative caret offset for charAtPt1 isn't found: i=" + i);
if (!charAtPt1.tentativeCaretOffsetNotFound) {
is(charAtPt1.tentativeCaretOffset, kLeftTentativeCaretOffset[i],
"runCharAtPointTest (" + aTargetName + "): tentative caret offset for charAtPt1 is wrong: i=" + i);
}
}
// Test #2, getting same character rect by the point near the bottom-right.
var charAtPt2 = synthesizeCharAtPoint(textRect.left + textRect.width - 2,
textRect.top + textRect.height - 2);
if (checkQueryContentResult(charAtPt2,
"runCharAtPointTest (" + aTargetName + "): charAtPt2: i=" + i)) {
ok(!charAtPt2.notFound,
"runCharAtPointTest (" + aTargetName + "): charAtPt2 isn't found: i=" + i);
if (!charAtPt2.notFound) {
is(charAtPt2.offset, kTestingOffset[i],
"runCharAtPointTest (" + aTargetName + "): charAtPt2 offset is wrong: i=" + i);
checkRect(charAtPt2, textRect, "runCharAtPointTest (" + aTargetName +
"): charAtPt1 left is wrong: i=" + i);
}
ok(!charAtPt2.tentativeCaretOffsetNotFound,
"runCharAtPointTest (" + aTargetName + "): tentative caret offset for charAtPt2 isn't found: i=" + i);
if (!charAtPt2.tentativeCaretOffsetNotFound) {
is(charAtPt2.tentativeCaretOffset, kRightTentativeCaretOffset[i],
"runCharAtPointTest (" + aTargetName + "): tentative caret offset for charAtPt2 is wrong: i=" + i);
}
}
// Test #3, getting left character offset.
var charAtPt3 = synthesizeCharAtPoint(textRect.left - 2,
textRect.top + 1);
if (checkQueryContentResult(charAtPt3,
"runCharAtPointTest (" + aTargetName + "): charAtPt3: i=" + i)) {
is(charAtPt3.notFound, kLeftSideOffset[i] == kNone,
kLeftSideOffset[i] == kNone ?
"runCharAtPointTest (" + aTargetName + "): charAtPt3 is found: i=" + i :
"runCharAtPointTest (" + aTargetName + "): charAtPt3 isn't found: i=" + i);
if (!charAtPt3.notFound) {
is(charAtPt3.offset, kLeftSideOffset[i],
"runCharAtPointTest (" + aTargetName + "): charAtPt3 offset is wrong: i=" + i);
}
if (kLeftSideOffset[i] == kNone) {
// There may be no enough padding-left (depends on platform)
todo(false,
"runCharAtPointTest (" + aTargetName + "): tentative caret offset for charAtPt3 isn't tested: i=" + i);
} else {
ok(!charAtPt3.tentativeCaretOffsetNotFound,
"runCharAtPointTest (" + aTargetName + "): tentative caret offset for charAtPt3 isn't found: i=" + i);
if (!charAtPt3.tentativeCaretOffsetNotFound) {
is(charAtPt3.tentativeCaretOffset, kLeftTentativeCaretOffset[i],
"runCharAtPointTest (" + aTargetName + "): tentative caret offset for charAtPt3 is wrong: i=" + i);
}
}
}
// Test #4, getting right character offset.
var charAtPt4 = synthesizeCharAtPoint(textRect.left + textRect.width + 1,
textRect.top + textRect.height - 2);
if (checkQueryContentResult(charAtPt4,
"runCharAtPointTest (" + aTargetName + "): charAtPt4: i=" + i)) {
is(charAtPt4.notFound, kRightSideOffset[i] == kNone,
kRightSideOffset[i] == kNone ?
"runCharAtPointTest (" + aTargetName + "): charAtPt4 is found: i=" + i :
"runCharAtPointTest (" + aTargetName + "): charAtPt4 isn't found: i=" + i);
if (!charAtPt4.notFound) {
is(charAtPt4.offset, kRightSideOffset[i],
"runCharAtPointTest (" + aTargetName + "): charAtPt4 offset is wrong: i=" + i);
}
ok(!charAtPt4.tentativeCaretOffsetNotFound,
"runCharAtPointTest (" + aTargetName + "): tentative caret offset for charAtPt4 isn't found: i=" + i);
if (!charAtPt4.tentativeCaretOffsetNotFound) {
is(charAtPt4.tentativeCaretOffset, kRightTentativeCaretOffset[i],
"runCharAtPointTest (" + aTargetName + "): tentative caret offset for charAtPt4 is wrong: i=" + i);
}
}
}
}
function runCharAtPointAtOutsideTest()
{
textarea.focus();
textarea.value = "some text";
var editorRect = synthesizeQueryEditorRect();
if (!checkQueryContentResult(editorRect,
"runCharAtPointAtOutsideTest: editorRect")) {
return;
}
// Check on a text node which is at the outside of editor.
var charAtPt = synthesizeCharAtPoint(editorRect.left + 20,
editorRect.top - 10);
if (checkQueryContentResult(charAtPt,
"runCharAtPointAtOutsideTest: charAtPt")) {
ok(charAtPt.notFound,
"runCharAtPointAtOutsideTest: charAtPt is found on outside of editor");
ok(charAtPt.tentativeCaretOffsetNotFound,
"runCharAtPointAtOutsideTest: tentative caret offset for charAtPt is found on outside of editor");
}
}
function runSetSelectionEventTest()
{
contenteditable.focus();
var selection = windowOfContenteditable.getSelection();
// #1
contenteditable.innerHTML = "abc<br>def";
synthesizeSelectionSet(0, 100);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node of the editor");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of children");
checkSelection(0, "abc" + kLF + "def", "runSetSelectionEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(2, 2 + kLFLen);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #1 (2, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
is(selection.anchorOffset, 2,
"runSetSelectionEventTest #1 (2, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 2");
is(selection.focusNode, contenteditable.lastChild,
"runSetSelectionEventTest #1 (2, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #1 (2, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(2, "c" + kLF + "d", "runSetSelectionEventTest #1 (2, 2+kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(1, 2);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #1 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #1 (1, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #1 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the first text node");
is(selection.focusOffset, contenteditable.firstChild.wholeText.length,
"runSetSelectionEventTest #1 (1, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node");
checkSelection(1, "bc", "runSetSelectionEventTest #1 (1, 2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(3, kLFLen);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
is(selection.anchorOffset, contenteditable.firstChild.wholeText.length,
"runSetSelectionEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the first text node");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, 2,
"runSetSelectionEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the index of the last text node");
checkSelection(3, kLF, "runSetSelectionEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(6+kLFLen, 0);
is(selection.anchorNode, contenteditable.lastChild,
"runSetSelectionEventTest #1 (6+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
is(selection.anchorOffset, contenteditable.lastChild.wholeText.length,
"runSetSelectionEventTest #1 (6+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
is(selection.focusNode, contenteditable.lastChild,
"runSetSelectionEventTest #1 (6+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
is(selection.anchorOffset, contenteditable.lastChild.wholeText.length,
"runSetSelectionEventTest #1 (6+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(6 + kLFLen, "", "runSetSelectionEventTest #1 (6+kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(100, 0);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #1 (100, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node of the editor");
is(selection.anchorOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #1 (100, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of children");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #1 (100, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node of the editor");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #1 (100, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of children");
checkSelection(6 + kLFLen, "", "runSetSelectionEventTest #1 (100, 0), \"" + contenteditable.innerHTML + "\"");
// #2
contenteditable.innerHTML = "<p>a<b>b</b>c</p><p>def</p>";
synthesizeSelectionSet(kLFLen, 4+kLFLen);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first <p> node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the first <p> node");
is(selection.focusNode, contenteditable.lastChild.firstChild,
"runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the second <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(kLFLen, "abc" + kLF + "d", "runSetSelectionEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen, 2);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first <p> node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the first <p> node");
is(selection.focusNode, contenteditable.firstChild.childNodes.item(1).firstChild,
"runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <b> node");
is(selection.focusOffset, contenteditable.firstChild.childNodes.item(1).firstChild.wholeText.length,
"runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node in the <b> node");
checkSelection(kLFLen, "ab", "runSetSelectionEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(1+kLFLen, 2);
is(selection.anchorNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node in the first <p> node");
is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
"runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node in the first <p> node");
checkSelection(1+kLFLen, "bc", "runSetSelectionEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(2+kLFLen, 2+kLFLen);
is(selection.anchorNode, contenteditable.firstChild.childNodes.item(1).firstChild,
"runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <b> node");
is(selection.anchorOffset, contenteditable.firstChild.childNodes.item(1).firstChild.wholeText.length,
"runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the text node in the <b> node");
is(selection.focusNode, contenteditable.lastChild.firstChild,
"runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the last <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(2+kLFLen, "c" + kLF + "d", "runSetSelectionEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(3+kLFLen*2, 1);
is(selection.anchorNode, contenteditable.lastChild,
"runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the second <p> node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the second <p> node");
is(selection.focusNode, contenteditable.lastChild.firstChild,
"runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the second <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(3+kLFLen*2, "d", "runSetSelectionEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, 0);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #2 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #2 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #2 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #2 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(0, "", "runSetSelectionEventTest #2 (0, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, kLFLen);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #2 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #2 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the first <p> node");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #2 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the first <p> node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #2 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(0, kLF, "runSetSelectionEventTest #2 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(2+kLFLen, 1+kLFLen);
is(selection.anchorNode, contenteditable.firstChild.childNodes.item(1).firstChild,
"runSetSelectionEventTest #2 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node of the <b> node");
is(selection.anchorOffset, contenteditable.firstChild.childNodes.item(1).firstChild.wholeText.length,
"runSetSelectionEventTest #2 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node of the first <b> node");
is(selection.focusNode, contenteditable.lastChild,
"runSetSelectionEventTest #2 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the second <p> node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #2 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(2+kLFLen, "c" + kLF, "runSetSelectionEventTest #2 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(3+kLFLen, kLFLen);
is(selection.anchorNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #2 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node of the first <p> node");
is(selection.anchorOffset, contenteditable.firstChild.lastChild.wholeText.length,
"runSetSelectionEventTest #2 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node of the first <p> node");
is(selection.focusNode, contenteditable.lastChild,
"runSetSelectionEventTest #2 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the second <p> node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #2 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(3+kLFLen, kLF, "runSetSelectionEventTest #2 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(3+kLFLen, 1+kLFLen);
is(selection.anchorNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #2 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node of the first <p> node");
is(selection.anchorOffset, contenteditable.firstChild.lastChild.wholeText.length,
"runSetSelectionEventTest #2 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node of the first <p> node");
is(selection.focusNode, contenteditable.lastChild.firstChild,
"runSetSelectionEventTest #2 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node of the second <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #2 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(3+kLFLen, kLF + "d", "runSetSelectionEventTest #2 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
// #3
contenteditable.innerHTML = "<div>abc<p>def</p></div>";
synthesizeSelectionSet(1+kLFLen, 2);
is(selection.anchorNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the first text node");
is(selection.focusOffset, contenteditable.firstChild.firstChild.wholeText.length,
"runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the first text node");
checkSelection(1+kLFLen, "bc", "runSetSelectionEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(1+kLFLen, 3+kLFLen);
is(selection.anchorNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
"runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(1+kLFLen, "bc" + kLF + "d", "runSetSelectionEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(3+kLFLen, 0);
is(selection.anchorNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
is(selection.anchorOffset, contenteditable.firstChild.firstChild.wholeText.length,
"runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the first text node");
is(selection.focusNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the first text node");
is(selection.focusOffset, contenteditable.firstChild.firstChild.wholeText.length,
"runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the first text node");
checkSelection(3+kLFLen, "", "runSetSelectionEventTest #3 (3+kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, 6+kLFLen*2);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
"runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
is(selection.focusOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
"runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(0, kLF + "abc" + kLF + "def", "runSetSelectionEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, 100);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(0, kLF + "abc" + kLF + "def", "runSetSelectionEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(4+kLFLen*2, 2);
is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
"runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
"runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
is(selection.focusOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
"runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(4+kLFLen*2, "ef", "runSetSelectionEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(4+kLFLen*2, 100);
is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
"runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(4+kLFLen*2, "ef", "runSetSelectionEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(6+kLFLen*2, 0);
is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
"runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
is(selection.anchorOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
"runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
"runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
is(selection.focusOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
"runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(6+kLFLen*2, "", "runSetSelectionEventTest #3 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(6+kLFLen*2, 1);
is(selection.anchorNode, contenteditable.firstChild.lastChild.firstChild,
"runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
is(selection.anchorOffset, contenteditable.firstChild.lastChild.firstChild.wholeText.length,
"runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(6+kLFLen*2, "", "runSetSelectionEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, kLFLen);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #3 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #3 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the first text node");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #3 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the <div> node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #3 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(0, kLF, "runSetSelectionEventTest #3 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, 1+kLFLen);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #3 (0, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #3 (0, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the <div> node");
is(selection.focusNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #3 (0, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the first text node of the <div> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #3 (0, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(0, kLF + "a", "runSetSelectionEventTest #3 (0, 1+kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(2+kLFLen, 1+kLFLen);
is(selection.anchorNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #3 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node of the <div> node");
is(selection.anchorOffset, 2,
"runSetSelectionEventTest #3 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 2");
is(selection.focusNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #3 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #3 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(2+kLFLen, "c" + kLF, "runSetSelectionEventTest #3 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(3+kLFLen, kLFLen);
is(selection.anchorNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #3 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node of the <div> node");
is(selection.anchorOffset, contenteditable.firstChild.firstChild.wholeText.length,
"runSetSelectionEventTest #3 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the text node of the <div> node");
is(selection.focusNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #3 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #3 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(3+kLFLen, kLF, "runSetSelectionEventTest #3 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(3+kLFLen, 1+kLFLen);
is(selection.anchorNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #3 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node of the <div> node");
is(selection.anchorOffset, contenteditable.firstChild.firstChild.wholeText.length,
"runSetSelectionEventTest #3 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the text node of the <div> node");
is(selection.focusNode, contenteditable.firstChild.lastChild.firstChild,
"runSetSelectionEventTest #3 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node of the <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #3 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(3+kLFLen, kLF + "d", "runSetSelectionEventTest #3 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\"");
// #4
contenteditable.innerHTML = "<div><p>abc</p>def</div>";
synthesizeSelectionSet(1+kLFLen*2, 2);
is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
"runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild.firstChild.firstChild,
"runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
is(selection.focusOffset, contenteditable.firstChild.firstChild.firstChild.wholeText.length,
"runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node in the <p> node");
checkSelection(1+kLFLen*2, "bc", "runSetSelectionEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(1+kLFLen*2, 3);
is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
"runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(1+kLFLen*2, "bcd", "runSetSelectionEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(3+kLFLen*2, 0);
is(selection.anchorNode, contenteditable.firstChild.firstChild.firstChild,
"runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node in the <p> node");
is(selection.anchorOffset, contenteditable.firstChild.firstChild.firstChild.wholeText.length,
"runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the text node in the <p> node");
is(selection.focusNode, contenteditable.firstChild.firstChild.firstChild,
"runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
is(selection.focusOffset, contenteditable.firstChild.firstChild.firstChild.wholeText.length,
"runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the text node in the <p> node");
checkSelection(3+kLFLen*2, "", "runSetSelectionEventTest #4 (3+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, 6+kLFLen*2);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
"runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(0, kLF + kLF + "abcdef", "runSetSelectionEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, 100);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(0, kLF + kLF + "abcdef", "runSetSelectionEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(4+kLFLen*2, 2);
is(selection.anchorNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
"runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(4+kLFLen*2, "ef", "runSetSelectionEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(4+kLFLen*2, 100);
is(selection.anchorNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(4+kLFLen*2, "ef", "runSetSelectionEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(6+kLFLen*2, 0);
is(selection.anchorNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
is(selection.anchorOffset, contenteditable.firstChild.lastChild.wholeText.length,
"runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
is(selection.focusNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
is(selection.focusOffset, contenteditable.firstChild.lastChild.wholeText.length,
"runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(6+kLFLen*2, "", "runSetSelectionEventTest #4 (6+kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(6+kLFLen*2, 1);
is(selection.anchorNode, contenteditable.firstChild.lastChild,
"runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the last text node");
is(selection.anchorOffset, contenteditable.firstChild.lastChild.wholeText.length,
"runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the length of the last text node");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(6+kLFLen*2, "", "runSetSelectionEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, kLFLen);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #4 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #4 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the <div> node");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #4 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the <div> node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #4 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(0, kLF, "runSetSelectionEventTest #4 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, kLFLen*2);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #4 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #4 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the <div> node");
is(selection.focusNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #4 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #4 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(0, kLF + kLF, "runSetSelectionEventTest #4 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, 1+kLFLen*2);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #4 (0, 1+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #4 (0, 1+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the <div> node");
is(selection.focusNode, contenteditable.firstChild.firstChild.firstChild,
"runSetSelectionEventTest #4 (0, 1+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #4 (0, 1+kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(0, kLF + kLF + "a", "runSetSelectionEventTest #4 (0, 1+kLFLen*2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen, 0);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #4 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <div> node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #4 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #4 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <div> node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #4 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(kLFLen, "", "runSetSelectionEventTest #4 (kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen, kLFLen);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #4 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <div> node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #4 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the <p> node");
is(selection.focusNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #4 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #4 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(kLFLen, kLF, "runSetSelectionEventTest #4 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen, 1+kLFLen);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #4 (kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <div> node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #4 (kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the <p> node");
is(selection.focusNode, contenteditable.firstChild.firstChild.firstChild,
"runSetSelectionEventTest #4 (kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node in the <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #4 (kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(kLFLen, kLF +"a", "runSetSelectionEventTest #4 (kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\"");
// #5
contenteditable.innerHTML = "<br>";
synthesizeSelectionSet(0, 0);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #5 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #5 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #5 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #5 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(0, "", "runSetSelectionEventTest #5 (0, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, kLFLen);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(0, kLF, "runSetSelectionEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen, 0);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #5 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #5 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the root's children");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #5 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #5 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(kLFLen, "", "runSetSelectionEventTest #5 (kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen, 1);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the root's children");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(kLFLen, "", "runSetSelectionEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\"");
// #6
contenteditable.innerHTML = "<p><br></p>";
synthesizeSelectionSet(kLFLen, kLFLen);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
checkSelection(kLFLen, kLF, "runSetSelectionEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen*2, 0);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the <p>'s children");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
checkSelection(kLFLen*2, "", "runSetSelectionEventTest #6 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen*2, 1);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the root's children");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(kLFLen*2, "", "runSetSelectionEventTest #6 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, kLFLen);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(0, kLF, "runSetSelectionEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, kLFLen*2);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #6 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #6 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #6 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #6 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
checkSelection(0, kLF + kLF, "runSetSelectionEventTest #6 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen, 0);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(kLFLen, "", "runSetSelectionEventTest #6 (kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
// #7
contenteditable.innerHTML = "<br><br>";
synthesizeSelectionSet(0, kLFLen);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(0, kLF, "runSetSelectionEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, kLFLen * 2);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #7 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #7 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #7 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #7 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(0, kLF + kLF, "runSetSelectionEventTest #7 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen, 0);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #7 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #7 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #7 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #7 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(kLFLen, "", "runSetSelectionEventTest #7 (kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen, kLFLen);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #7 (kLFLen, kLFLen) selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(kLFLen, kLF, "runSetSelectionEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen * 2, 0);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #7 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #7 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the root's children");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #7 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #7 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(kLFLen * 2, "", "runSetSelectionEventTest #7 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
// #8
contenteditable.innerHTML = "<p><br><br></p>";
synthesizeSelectionSet(kLFLen, kLFLen);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(kLFLen, kLF, "runSetSelectionEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen, kLFLen * 2);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
checkSelection(kLFLen, kLF + kLF, "runSetSelectionEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen*2, 0);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 1");
checkSelection(kLFLen*2, "", "runSetSelectionEventTest #8 (kLFLen*2, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen*2, kLFLen);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 1");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen*2, kLFLen) selection focus node should be the <p> node");
is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
checkSelection(kLFLen*2, kLF, "runSetSelectionEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen*3, 0);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the <p> node");
is(selection.anchorOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the count of the <p>'s children");
is(selection.focusNode, contenteditable.firstChild,
"runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, contenteditable.firstChild.childNodes.length,
"runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the <p>'s children");
checkSelection(kLFLen*3, "", "runSetSelectionEventTest #8 (kLFLen*3, 0), \"" + contenteditable.innerHTML + "\"");
// #9 (ContentEventHandler cannot distinguish if <p> can have children, so, the result is same as case #5, "<br>")
contenteditable.innerHTML = "<p></p>";
synthesizeSelectionSet(kLFLen, 0);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #9 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #9 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the <p> node + 1");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #9 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the <p> node");
is(selection.focusOffset, 1,
"runSetSelectionEventTest #9 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the index of the <p> node + 1");
checkSelection(kLFLen, "", "runSetSelectionEventTest #9 (kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(kLFLen, 1);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #9 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 1,
"runSetSelectionEventTest #9 (kLFLen, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be the index of the <p> node + 1");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #9 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #9 (kLFLen, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(kLFLen, "", "runSetSelectionEventTest #9 (kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
// #10
contenteditable.innerHTML = "";
synthesizeSelectionSet(0, 0);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #10 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #10 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #10 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #10 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(0, "", "runSetSelectionEventTest #10 (0, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, 1);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #10 (0, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #10 (0, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #10 (0, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #10 (0, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(0, "", "runSetSelectionEventTest #10 (0, 1), \"" + contenteditable.innerHTML + "\"");
// #11
contenteditable.innerHTML = "<span></span><i><u></u></i>";
synthesizeSelectionSet(0, 0);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #11 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #11 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #11 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #11 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(0, "", "runSetSelectionEventTest #11 (0, 0), \"" + contenteditable.innerHTML + "\"");
synthesizeSelectionSet(0, 1);
is(selection.anchorNode, contenteditable,
"runSetSelectionEventTest #11 (0, 1), \"" + contenteditable.innerHTML + "\": selection anchor node should be the root node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #11 (0, 1), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable,
"runSetSelectionEventTest #11 (0, 1), \"" + contenteditable.innerHTML + "\": selection focus node should be the root node");
is(selection.focusOffset, contenteditable.childNodes.length,
"runSetSelectionEventTest #11 (0, 1), \"" + contenteditable.innerHTML + "\": selection focus offset should be the count of the root's children");
checkSelection(0, "", "runSetSelectionEventTest #11 (0, 1), \"" + contenteditable.innerHTML + "\"");
// #12
contenteditable.innerHTML = "<span>abc</span><i><u></u></i>";
synthesizeSelectionSet(0, 0);
is(selection.anchorNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #12 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #12 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.firstChild.firstChild,
"runSetSelectionEventTest #12 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #12 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(0, "", "runSetSelectionEventTest #12 (0, 0), \"" + contenteditable.innerHTML + "\"");
// #13
contenteditable.innerHTML = "<span></span><i>abc<u></u></i>";
synthesizeSelectionSet(0, 0);
is(selection.anchorNode, contenteditable.childNodes.item(1).firstChild,
"runSetSelectionEventTest #13 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #13 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.childNodes.item(1).firstChild,
"runSetSelectionEventTest #13 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #13 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(0, "", "runSetSelectionEventTest #13 (0, 0), \"" + contenteditable.innerHTML + "\"");
// #14
contenteditable.innerHTML = "<span></span><i><u>abc</u></i>";
synthesizeSelectionSet(0, 0);
is(selection.anchorNode, contenteditable.childNodes.item(1).firstChild.firstChild,
"runSetSelectionEventTest #14 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #14 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.childNodes.item(1).firstChild.firstChild,
"runSetSelectionEventTest #14 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #14 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(0, "", "runSetSelectionEventTest #14 (0, 0), \"" + contenteditable.innerHTML + "\"");
// #15
contenteditable.innerHTML = "<span></span><i><u></u>abc</i>";
synthesizeSelectionSet(0, 0);
is(selection.anchorNode, contenteditable.childNodes.item(1).lastChild,
"runSetSelectionEventTest #15 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the text node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #15 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.childNodes.item(1).lastChild,
"runSetSelectionEventTest #15 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the text node");
is(selection.focusOffset, 0,
"runSetSelectionEventTest #15 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be 0");
checkSelection(0, "", "runSetSelectionEventTest #15 (0, 0), \"" + contenteditable.innerHTML + "\"");
// #16
contenteditable.innerHTML = "a<blink>b</blink>c";
synthesizeSelectionSet(0, 3);
is(selection.anchorNode, contenteditable.firstChild,
"runSetSelectionEventTest #15 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor node should be the first text node");
is(selection.anchorOffset, 0,
"runSetSelectionEventTest #15 (0, 0), \"" + contenteditable.innerHTML + "\": selection anchor offset should be 0");
is(selection.focusNode, contenteditable.lastChild,
"runSetSelectionEventTest #15 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus node should be the last text node");
is(selection.focusOffset, contenteditable.lastChild.wholeText.length,
"runSetSelectionEventTest #15 (0, 0), \"" + contenteditable.innerHTML + "\": selection focus offset should be the length of the last text node");
checkSelection(0, "abc", "runSetSelectionEventTest #16 (0, 3), \"" + contenteditable.innerHTML + "\"");
}
function runQueryTextContentEventTest()
{
contenteditable.focus();
var result;
// #1
contenteditable.innerHTML = "abc<br>def";
result = synthesizeQueryTextContent(0, 6 + kLFLen);
is(result.text, "abc" + kLF + "def", "runQueryTextContentEventTest #1 (0, 6+kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, 100);
is(result.text, "abc" + kLF + "def", "runQueryTextContentEventTest #1 (0, 100), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(2, 2 + kLFLen);
is(result.text, "c" + kLF + "d", "runQueryTextContentEventTest #1 (2, 2+kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(1, 2);
is(result.text, "bc", "runQueryTextContentEventTest #1 (1, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(3, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #1 (3, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(6 + kLFLen, 1);
is(result.text, "", "runQueryTextContentEventTest #1 (6 + kLFLen, 0), \"" + contenteditable.innerHTML + "\"");
// #2
contenteditable.innerHTML = "<p>a<b>b</b>c</p><p>def</p>";
result = synthesizeQueryTextContent(kLFLen, 4+kLFLen);
is(result.text, "abc" + kLF + "d", "runQueryTextContentEventTest #2 (kLFLen, 4+kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen, 2);
is(result.text, "ab", "runQueryTextContentEventTest #2 (kLFLen, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(1+kLFLen, 2);
is(result.text, "bc", "runQueryTextContentEventTest #2 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(2+kLFLen, 2+kLFLen);
is(result.text, "c" + kLF + "d", "runQueryTextContentEventTest #2 (2+kLFLen, 2+kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(3+kLFLen*2, 1);
is(result.text, "d", "runQueryTextContentEventTest #2 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #2 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(2+kLFLen, 1+kLFLen);
is(result.text, "c" + kLF, "runQueryTextContentEventTest #2 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(3+kLFLen, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #2 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(3+kLFLen, 1+kLFLen);
is(result.text, kLF + "d", "runQueryTextContentEventTest #2 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\"");
// #3
contenteditable.innerHTML = "<div>abc<p>def</p></div>";
result = synthesizeQueryTextContent(1+kLFLen, 2);
is(result.text, "bc", "runQueryTextContentEventTest #3 (1+kLFLen, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(1+kLFLen, 3+kLFLen);
is(result.text, "bc" + kLF + "d", "runQueryTextContentEventTest #3 (1+kLFLen, 3+kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(3+kLFLen*2, 1);
is(result.text, "d", "runQueryTextContentEventTest #3 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, 6+kLFLen*2);
is(result.text, kLF + "abc" + kLF + "def", "runQueryTextContentEventTest #3 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, 100);
is(result.text, kLF + "abc" + kLF + "def", "runQueryTextContentEventTest #3 (0, 100), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(4+kLFLen*2, 2);
is(result.text, "ef", "runQueryTextContentEventTest #3 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(4+kLFLen*2, 100);
is(result.text, "ef", "runQueryTextContentEventTest #3 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(6+kLFLen*2, 1);
is(result.text, "", "runQueryTextContentEventTest #3 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #3 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, 1+kLFLen);
is(result.text, kLF + "a", "runQueryTextContentEventTest #3 (0, 1+kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(2+kLFLen, 1+kLFLen);
is(result.text, "c" + kLF, "runQueryTextContentEventTest #3 (2+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(3+kLFLen, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #3 (3+kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(3+kLFLen, 1+kLFLen);
is(result.text, kLF + "d", "runQueryTextContentEventTest #3 (3+kLFLen, 1+kLFLen), \"" + contenteditable.innerHTML + "\"");
// #4
contenteditable.innerHTML = "<div><p>abc</p>def</div>";
result = synthesizeQueryTextContent(1+kLFLen*2, 2);
is(result.text, "bc", "runQueryTextContentEventTest #4 (1+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(1+kLFLen*2, 3);
is(result.text, "bcd", "runQueryTextContentEventTest #4 (1+kLFLen*2, 3), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(3+kLFLen*2, 1);
is(result.text, "d", "runQueryTextContentEventTest #4 (3+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, 6+kLFLen*2);
is(result.text, kLF + kLF + "abcdef", "runQueryTextContentEventTest #4 (0, 6+kLFLen*2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, 100);
is(result.text, kLF + kLF + "abcdef", "runQueryTextContentEventTest #4 (0, 100), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(4+kLFLen*2, 2);
is(result.text, "ef", "runQueryTextContentEventTest #4 (4+kLFLen*2, 2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(4+kLFLen*2, 100);
is(result.text, "ef", "runQueryTextContentEventTest #4 (4+kLFLen*2, 100), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(6+kLFLen*2, 1);
is(result.text, "", "runQueryTextContentEventTest #4 (6+kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #4 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, kLFLen*2);
is(result.text, kLF + kLF, "runQueryTextContentEventTest #4 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, 1+kLFLen*2);
is(result.text, kLF + kLF + "a", "runQueryTextContentEventTest #4 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #4 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen, 1+kLFLen);
is(result.text, kLF + "a", "runQueryTextContentEventTest #4 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
// #5
contenteditable.innerHTML = "<br>";
result = synthesizeQueryTextContent(0, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #5 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen, 1);
is(result.text, "", "runQueryTextContentEventTest #5 (kLFLen, 1), \"" + contenteditable.innerHTML + "\"");
// #6
contenteditable.innerHTML = "<p><br></p>";
result = synthesizeQueryTextContent(kLFLen, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #6 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen*2, 1);
is(result.text, "", "runQueryTextContentEventTest #5 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #6 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, kLFLen*2);
is(result.text, kLF + kLF, "runQueryTextContentEventTest #6 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
// #7
contenteditable.innerHTML = "<br><br>";
result = synthesizeQueryTextContent(0, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #7 (0, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(0, kLFLen * 2);
is(result.text, kLF + kLF, "runQueryTextContentEventTest #7 (0, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #7 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen * 2, 1);
is(result.text, "", "runQueryTextContentEventTest #7 (kLFLen*2, 1), \"" + contenteditable.innerHTML + "\"");
// #8
contenteditable.innerHTML = "<p><br><br></p>";
result = synthesizeQueryTextContent(kLFLen, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #8 (kLFLen, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen, kLFLen * 2);
is(result.text, kLF + kLF, "runQueryTextContentEventTest #8 (kLFLen, kLFLen*2), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen*2, kLFLen);
is(result.text, kLF, "runQueryTextContentEventTest #8 (kLFLen*2, kLFLen), \"" + contenteditable.innerHTML + "\"");
result = synthesizeQueryTextContent(kLFLen*3, 1);
is(result.text, "", "runQueryTextContentEventTest #8 (kLFLen*3, 1), \"" + contenteditable.innerHTML + "\"");
// #16
contenteditable.innerHTML = "a<blink>b</blink>c";
result = synthesizeQueryTextContent(0, 3);
is(result.text, "abc", "runQueryTextContentEventTest #16 (0, 3), \"" + contenteditable.innerHTML + "\"");
}
function runCSSTransformTest()
{
textarea.focus();
textarea.value = "some text";
textarea.selectionStart = textarea.selectionEnd = textarea.value.length;
var editorRect = synthesizeQueryEditorRect();
if (!checkQueryContentResult(editorRect,
"runCSSTransformTest: editorRect")) {
return;
}
var firstCharRect = synthesizeQueryTextRect(0, 1);
if (!checkQueryContentResult(firstCharRect,
"runCSSTransformTest: firstCharRect")) {
return;
}
var lastCharRect = synthesizeQueryTextRect(textarea.value.length - 1, textarea.value.length);
if (!checkQueryContentResult(lastCharRect,
"runCSSTransformTest: lastCharRect")) {
return;
}
var caretRect = synthesizeQueryCaretRect(textarea.selectionStart);
if (!checkQueryContentResult(caretRect,
"runCSSTransformTest: caretRect")) {
return;
}
var caretRectBeforeFirstChar = synthesizeQueryCaretRect(0);
if (!checkQueryContentResult(caretRectBeforeFirstChar,
"runCSSTransformTest: caretRectBeforeFirstChar")) {
return;
}
try {
textarea.style.transform = "translate(10px, 15px)";
function movedRect(aRect, aX, aY)
{
return { left: aRect.left + aX, top: aRect.top + aY, width: aRect.width, height: aRect.height }
}
var editorRectTranslated = synthesizeQueryEditorRect();
if (!checkQueryContentResult(editorRectTranslated,
"runCSSTransformTest: editorRectTranslated") ||
!checkRect(editorRectTranslated, movedRect(editorRect, 10, 15),
"runCSSTransformTest: editorRectTranslated")) {
return;
}
var firstCharRectTranslated = synthesizeQueryTextRect(0, 1);
if (!checkQueryContentResult(firstCharRectTranslated,
"runCSSTransformTest: firstCharRectTranslated") ||
!checkRect(firstCharRectTranslated, movedRect(firstCharRect, 10, 15),
"runCSSTransformTest: firstCharRectTranslated")) {
return;
}
var lastCharRectTranslated = synthesizeQueryTextRect(textarea.value.length - 1, textarea.value.length);
if (!checkQueryContentResult(lastCharRectTranslated,
"runCSSTransformTest: lastCharRectTranslated") ||
!checkRect(lastCharRectTranslated, movedRect(lastCharRect, 10, 15),
"runCSSTransformTest: lastCharRectTranslated")) {
return;
}
var caretRectTranslated = synthesizeQueryCaretRect(textarea.selectionStart);
if (!checkQueryContentResult(caretRectTranslated,
"runCSSTransformTest: caretRectTranslated") ||
!checkRect(caretRectTranslated, movedRect(caretRect, 10, 15),
"runCSSTransformTest: caretRectTranslated")) {
return;
}
var caretRectBeforeFirstCharTranslated = synthesizeQueryCaretRect(0);
if (!checkQueryContentResult(caretRectBeforeFirstCharTranslated,
"runCSSTransformTest: caretRectBeforeFirstCharTranslated") ||
!checkRect(caretRectBeforeFirstCharTranslated, movedRect(caretRectBeforeFirstChar, 10, 15),
"runCSSTransformTest: caretRectBeforeFirstCharTranslated")) {
return;
}
// XXX It's too difficult to check the result with scale and rotate...
} finally {
textarea.style.transform = "";
}
}
function runBug722639Test()
{
textarea.focus();
textarea.value = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
textarea.value += textarea.value;
textarea.value += textarea.value; // 80 characters
var firstLine = synthesizeQueryTextRect(0, 1);
if (!checkQueryContentResult(firstLine,
"runBug722639Test: firstLine")) {
return;
}
var secondLine = synthesizeQueryTextRect(kLFLen, 1);
if (!checkQueryContentResult(secondLine,
"runBug722639Test: secondLine")) {
return;
}
var lineHeight = secondLine.top - firstLine.top;
ok(lineHeight > 0,
"runBug722639Test: lineHeight must be positive");
is(secondLine.left, firstLine.left,
"runBug722639Test: the left value must be always same value");
var previousTop = secondLine.top;
for (var i = 2; i < textarea.value.length; i++) {
var currentLine = synthesizeQueryTextRect(kLFLen * i, 1);
if (!checkQueryContentResult(currentLine,
"runBug722639Test: " + i + "th currentLine")) {
return;
}
// NOTE: the top position may be 1px larger or smaller than other lines
// due to sub pixel positioning.
if (Math.abs(currentLine.top - (previousTop + lineHeight)) <= 1) {
ok(true, "runBug722639Test: " + i + "th line's top is expected");
} else {
is(currentLine.top, previousTop + lineHeight,
"runBug722639Test: " + i + "th line's top is unexpected");
}
is(currentLine.left, firstLine.left,
"runBug722639Test: " + i + "th line's left is unexpected");
previousTop = currentLine.top;
}
}
function runForceCommitTest()
{
var events;
function eventHandler(aEvent)
{
events.push(aEvent);
}
window.addEventListener("compositionstart", eventHandler, true);
window.addEventListener("compositionupdate", eventHandler, true);
window.addEventListener("compositionend", eventHandler, true);
window.addEventListener("input", eventHandler, true);
window.addEventListener("text", eventHandler, true);
// Make the composition in textarea commit by click in the textarea
textarea.focus();
textarea.value = "";
events = [];
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
is(events.length, 4,
"runForceCommitTest: wrong event count #1");
is(events[0].type, "compositionstart",
"runForceCommitTest: the 1st event must be compositionstart #1");
is(events[1].type, "compositionupdate",
"runForceCommitTest: the 2nd event must be compositionupdate #1");
is(events[2].type, "text",
"runForceCommitTest: the 3rd event must be text #1");
is(events[3].type, "input",
"runForceCommitTest: the 4th event must be input #1");
events = [];
synthesizeMouseAtCenter(textarea, {});
is(events.length, 3,
"runForceCommitTest: wrong event count #2");
is(events[0].type, "text",
"runForceCommitTest: the 1st event must be text #2");
is(events[1].type, "compositionend",
"runForceCommitTest: the 2nd event must be compositionend #2");
is(events[2].type, "input",
"runForceCommitTest: the 3rd event must be input #2");
is(events[1].data, "\u306E",
"runForceCommitTest: compositionend has wrong data #2");
is(events[0].target, textarea,
"runForceCommitTest: The 1st event was fired on wrong event target #2");
is(events[1].target, textarea,
"runForceCommitTest: The 2nd event was fired on wrong event target #2");
is(events[2].target, textarea,
"runForceCommitTest: The 3rd event was fired on wrong event target #2");
ok(!getEditorIMESupport(textarea).isComposing,
"runForceCommitTest: the textarea still has composition #2");
is(textarea.value, "\u306E",
"runForceCommitTest: the textarea doesn't have the committed text #2");
// Make the composition in textarea commit by click in another editor (input)
textarea.focus();
textarea.value = "";
input.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
events = [];
synthesizeMouseAtCenter(input, {});
is(events.length, 3,
"runForceCommitTest: wrong event count #3");
is(events[0].type, "text",
"runForceCommitTest: the 1st event must be text #3");
is(events[1].type, "compositionend",
"runForceCommitTest: the 2nd event must be compositionend #3");
is(events[2].type, "input",
"runForceCommitTest: the 3rd event must be input #3");
is(events[1].data, "\u306E",
"runForceCommitTest: compositionend has wrong data #3");
is(events[0].target, textarea,
"runForceCommitTest: The 1st event was fired on wrong event target #3");
is(events[1].target, textarea,
"runForceCommitTest: The 2nd event was fired on wrong event target #3");
is(events[2].target, textarea,
"runForceCommitTest: The 3rd event was fired on wrong event target #3");
ok(!getEditorIMESupport(textarea).isComposing,
"runForceCommitTest: the textarea still has composition #3");
ok(!getEditorIMESupport(input).isComposing,
"runForceCommitTest: the input has composition #3");
is(textarea.value, "\u306E",
"runForceCommitTest: the textarea doesn't have the committed text #3");
is(input.value, "",
"runForceCommitTest: the input has the committed text? #3");
// Make the composition in textarea commit by blur()
textarea.focus();
textarea.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
events = [];
textarea.blur();
is(events.length, 3,
"runForceCommitTest: wrong event count #4");
is(events[0].type, "text",
"runForceCommitTest: the 1st event must be text #4");
is(events[1].type, "compositionend",
"runForceCommitTest: the 2nd event must be compositionend #4");
is(events[2].type, "input",
"runForceCommitTest: the 3rd event must be input #4");
is(events[1].data, "\u306E",
"runForceCommitTest: compositionend has wrong data #4");
is(events[0].target, textarea,
"runForceCommitTest: The 1st event was fired on wrong event target #4");
is(events[1].target, textarea,
"runForceCommitTest: The 2nd event was fired on wrong event target #4");
is(events[2].target, textarea,
"runForceCommitTest: The 3rd event was fired on wrong event target #4");
ok(!getEditorIMESupport(textarea).isComposing,
"runForceCommitTest: the textarea still has composition #4");
is(textarea.value, "\u306E",
"runForceCommitTest: the textarea doesn't have the committed text #4");
// Make the composition in textarea commit by input.focus()
textarea.focus();
textarea.value = "";
input.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
events = [];
input.focus();
is(events.length, 3,
"runForceCommitTest: wrong event count #5");
is(events[0].type, "text",
"runForceCommitTest: the 1st event must be text #5");
is(events[1].type, "compositionend",
"runForceCommitTest: the 2nd event must be compositionend #5");
is(events[2].type, "input",
"runForceCommitTest: the 3rd event must be input #5");
is(events[1].data, "\u306E",
"runForceCommitTest: compositionend has wrong data #5");
is(events[0].target, textarea,
"runForceCommitTest: The 1st event was fired on wrong event target #5");
is(events[1].target, textarea,
"runForceCommitTest: The 2nd event was fired on wrong event target #5");
is(events[2].target, textarea,
"runForceCommitTest: The 3rd event was fired on wrong event target #5");
ok(!getEditorIMESupport(textarea).isComposing,
"runForceCommitTest: the textarea still has composition #5");
ok(!getEditorIMESupport(input).isComposing,
"runForceCommitTest: the input has composition #5");
is(textarea.value, "\u306E",
"runForceCommitTest: the textarea doesn't have the committed text #5");
is(input.value, "",
"runForceCommitTest: the input has the committed text? #5");
// Make the composition in textarea commit by click in another document's editor
textarea.focus();
textarea.value = "";
textareaInFrame.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
events = [];
synthesizeMouseAtCenter(textareaInFrame, {}, iframe.contentWindow);
is(events.length, 3,
"runForceCommitTest: wrong event count #6");
is(events[0].type, "text",
"runForceCommitTest: the 1st event must be text #6");
is(events[1].type, "compositionend",
"runForceCommitTest: the 2nd event must be compositionend #6");
is(events[2].type, "input",
"runForceCommitTest: the 3rd event must be input #6");
is(events[1].data, "\u306E",
"runForceCommitTest: compositionend has wrong data #6");
is(events[0].target, textarea,
"runForceCommitTest: The 1st event was fired on wrong event target #6");
is(events[1].target, textarea,
"runForceCommitTest: The 2nd event was fired on wrong event target #6");
is(events[2].target, textarea,
"runForceCommitTest: The 3rd event was fired on wrong event target #6");
ok(!getEditorIMESupport(textarea).isComposing,
"runForceCommitTest: the textarea still has composition #6");
ok(!getEditorIMESupport(textareaInFrame).isComposing,
"runForceCommitTest: the textarea in frame has composition #6");
is(textarea.value, "\u306E",
"runForceCommitTest: the textarea doesn't have the committed text #6");
is(textareaInFrame.value, "",
"runForceCommitTest: the textarea in frame has the committed text? #6");
// Make the composition in textarea commit by another document's editor's focus()
textarea.focus();
textarea.value = "";
textareaInFrame.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
events = [];
textareaInFrame.focus();
is(events.length, 3,
"runForceCommitTest: wrong event count #7");
is(events[0].type, "text",
"runForceCommitTest: the 1st event must be text #7");
is(events[1].type, "compositionend",
"runForceCommitTest: the 2nd event must be compositionend #7");
is(events[2].type, "input",
"runForceCommitTest: the 3rd event must be input #7");
is(events[1].data, "\u306E",
"runForceCommitTest: compositionend has wrong data #7");
is(events[0].target, textarea,
"runForceCommitTest: The 1st event was fired on wrong event target #7");
is(events[1].target, textarea,
"runForceCommitTest: The 2nd event was fired on wrong event target #7");
is(events[2].target, textarea,
"runForceCommitTest: The 3rd event was fired on wrong event target #7");
ok(!getEditorIMESupport(textarea).isComposing,
"runForceCommitTest: the textarea still has composition #7");
ok(!getEditorIMESupport(textareaInFrame).isComposing,
"runForceCommitTest: the textarea in frame has composition #7");
is(textarea.value, "\u306E",
"runForceCommitTest: the textarea doesn't have the committed text #7");
is(textareaInFrame.value, "",
"runForceCommitTest: the textarea in frame has the committed text? #7");
// Make the composition in a textarea commit by click in another editable document
textarea.focus();
textarea.value = "";
iframe2.contentDocument.body.innerHTML = "Text in the Body";
var iframe2BodyInnerHTML = iframe2.contentDocument.body.innerHTML;
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
events = [];
synthesizeMouseAtCenter(iframe2.contentDocument.body, {}, iframe2.contentWindow);
is(events.length, 3,
"runForceCommitTest: wrong event count #8");
is(events[0].type, "text",
"runForceCommitTest: the 1st event must be text #8");
is(events[1].type, "compositionend",
"runForceCommitTest: the 2nd event must be compositionend #8");
is(events[2].type, "input",
"runForceCommitTest: the 3rd event must be input #8");
is(events[1].data, "\u306E",
"runForceCommitTest: compositionend has wrong data #8");
is(events[0].target, textarea,
"runForceCommitTest: The 1st event was fired on wrong event target #8");
is(events[1].target, textarea,
"runForceCommitTest: The 2nd event was fired on wrong event target #8");
is(events[2].target, textarea,
"runForceCommitTest: The 3rd event was fired on wrong event target #8");
ok(!getEditorIMESupport(textarea).isComposing,
"runForceCommitTest: the textarea still has composition #8");
ok(!getHTMLEditorIMESupport(iframe2.contentWindow).isComposing,
"runForceCommitTest: the editable document has composition #8");
is(textarea.value, "\u306E",
"runForceCommitTest: the textarea doesn't have the committed text #8");
is(iframe2.contentDocument.body.innerHTML, iframe2BodyInnerHTML,
"runForceCommitTest: the editable document has the committed text? #8");
// Make the composition in an editable document commit by click in it
iframe2.contentWindow.focus();
iframe2.contentDocument.body.innerHTML = "Text in the Body";
iframe2BodyInnerHTML = iframe2.contentDocument.body.innerHTML;
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
}, iframe2.contentWindow);
events = [];
synthesizeMouseAtCenter(iframe2.contentDocument.body, {}, iframe2.contentWindow);
is(events.length, 3,
"runForceCommitTest: wrong event count #9");
is(events[0].type, "text",
"runForceCommitTest: the 1st event must be text #9");
is(events[1].type, "compositionend",
"runForceCommitTest: the 2nd event must be compositionend #9");
is(events[2].type, "input",
"runForceCommitTest: the 3rd event must be input #9");
is(events[1].data, "\u306E",
"runForceCommitTest: compositionend has wrong data #9");
is(events[0].target, iframe2.contentDocument.body,
"runForceCommitTest: The 1st event was fired on wrong event target #9");
is(events[1].target, iframe2.contentDocument.body,
"runForceCommitTest: The 2nd event was fired on wrong event target #9");
is(events[2].target, iframe2.contentDocument.body,
"runForceCommitTest: The 3rd event was fired on wrong event target #9");
ok(!getHTMLEditorIMESupport(iframe2.contentWindow).isComposing,
"runForceCommitTest: the editable document still has composition #9");
ok(iframe2.contentDocument.body.innerHTML != iframe2BodyInnerHTML &&
iframe2.contentDocument.body.innerHTML.indexOf("\u306E") >= 0,
"runForceCommitTest: the editable document doesn't have the committed text #9");
// Make the composition in an editable document commit by click in another document's editor
textarea.value = "";
iframe2.contentWindow.focus();
iframe2.contentDocument.body.innerHTML = "Text in the Body";
iframe2BodyInnerHTML = iframe2.contentDocument.body.innerHTML;
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
}, iframe2.contentWindow);
events = [];
synthesizeMouseAtCenter(textarea, {});
is(events.length, 3,
"runForceCommitTest: wrong event count #10");
is(events[0].type, "text",
"runForceCommitTest: the 1st event must be text #10");
is(events[1].type, "compositionend",
"runForceCommitTest: the 2nd event must be compositionend #10");
is(events[2].type, "input",
"runForceCommitTest: the 3rd event must be input #10");
is(events[1].data, "\u306E",
"runForceCommitTest: compositionend has wrong data #10");
is(events[0].target, iframe2.contentDocument.body,
"runForceCommitTest: The 1st event was fired on wrong event target #10");
is(events[1].target, iframe2.contentDocument.body,
"runForceCommitTest: The 2nd event was fired on wrong event target #10");
is(events[2].target, iframe2.contentDocument.body,
"runForceCommitTest: The 3rd event was fired on wrong event target #10");
ok(!getHTMLEditorIMESupport(iframe2.contentWindow).isComposing,
"runForceCommitTest: the editable document still has composition #10");
ok(!getEditorIMESupport(textarea).isComposing,
"runForceCommitTest: the textarea has composition #10");
ok(iframe2.contentDocument.body.innerHTML != iframe2BodyInnerHTML &&
iframe2.contentDocument.body.innerHTML.indexOf("\u306E") >= 0,
"runForceCommitTest: the editable document doesn't have the committed text #10");
is(textarea.value, "",
"runForceCommitTest: the textarea has the committed text? #10");
// Make the composition in an editable document commit by click in the another editable document
iframe2.contentWindow.focus();
iframe2.contentDocument.body.innerHTML = "Text in the Body";
iframe2BodyInnerHTML = iframe2.contentDocument.body.innerHTML;
iframe3.contentDocument.body.innerHTML = "Text in the Body";
iframe3BodyInnerHTML = iframe2.contentDocument.body.innerHTML;
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
}, iframe2.contentWindow);
events = [];
synthesizeMouseAtCenter(iframe3.contentDocument.body, {}, iframe3.contentWindow);
is(events.length, 3,
"runForceCommitTest: wrong event count #11");
is(events[0].type, "text",
"runForceCommitTest: the 1st event must be text #11");
is(events[1].type, "compositionend",
"runForceCommitTest: the 2nd event must be compositionend #11");
is(events[2].type, "input",
"runForceCommitTest: the 3rd event must be input #11");
is(events[1].data, "\u306E",
"runForceCommitTest: compositionend has wrong data #11");
is(events[0].target, iframe2.contentDocument.body,
"runForceCommitTest: The 1st event was fired on wrong event target #11");
is(events[1].target, iframe2.contentDocument.body,
"runForceCommitTest: The 2nd event was fired on wrong event target #11");
is(events[2].target, iframe2.contentDocument.body,
"runForceCommitTest: The 3rd event was fired on wrong event target #11");
ok(!getHTMLEditorIMESupport(iframe2.contentWindow).isComposing,
"runForceCommitTest: the editable document still has composition #11");
ok(!getHTMLEditorIMESupport(iframe3.contentWindow).isComposing,
"runForceCommitTest: the other editable document has composition #11");
ok(iframe2.contentDocument.body.innerHTML != iframe2BodyInnerHTML &&
iframe2.contentDocument.body.innerHTML.indexOf("\u306E") >= 0,
"runForceCommitTest: the editable document doesn't have the committed text #11");
is(iframe3.contentDocument.body.innerHTML, iframe3BodyInnerHTML,
"runForceCommitTest: the other editable document has the committed text? #11");
input.focus();
input.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
events = [];
input.value = "set value";
is(events.length, 3,
"runForceCommitTest: wrong event count #12");
is(events[0].type, "text",
"runForceCommitTest: the 1st event must be text #12");
is(events[1].type, "compositionend",
"runForceCommitTest: the 2nd event must be compositionend #12");
is(events[2].type, "input",
"runForceCommitTest: the 3rd event must be input #12");
is(events[1].data, "\u306E",
"runForceCommitTest: compositionend has wrong data #12");
is(events[0].target, input,
"runForceCommitTest: The 1st event was fired on wrong event target #12");
is(events[1].target, input,
"runForceCommitTest: The 2nd event was fired on wrong event target #12");
is(events[2].target, input,
"runForceCommitTest: The 3rd event was fired on wrong event target #12");
ok(!getEditorIMESupport(input).isComposing,
"runForceCommitTest: the input still has composition #12");
is(input.value, "set value",
"runForceCommitTest: the input doesn't have the set text #12");
textarea.focus();
textarea.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
events = [];
textarea.value = "set value";
is(events.length, 3,
"runForceCommitTest: wrong event count #13");
is(events[0].type, "text",
"runForceCommitTest: the 1st event must be text #13");
is(events[1].type, "compositionend",
"runForceCommitTest: the 2nd event must be compositionend #13");
is(events[2].type, "input",
"runForceCommitTest: the 3rd event must be input #13");
is(events[1].data, "\u306E",
"runForceCommitTest: compositionend has wrong data #13");
is(events[0].target, textarea,
"runForceCommitTest: The 1st event was fired on wrong event target #13");
is(events[1].target, textarea,
"runForceCommitTest: The 2nd event was fired on wrong event target #13");
is(events[2].target, textarea,
"runForceCommitTest: The 3rd event was fired on wrong event target #13");
ok(!getEditorIMESupport(textarea).isComposing,
"runForceCommitTest: the textarea still has composition #13");
is(textarea.value, "set value",
"runForceCommitTest: the textarea doesn't have the set text #13");
input.focus();
input.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
events = [];
input.value += " appended value";
is(events.length, 3,
"runForceCommitTest: wrong event count #14");
is(events[0].type, "text",
"runForceCommitTest: the 1st event must be text #14");
is(events[1].type, "compositionend",
"runForceCommitTest: the 2nd event must be compositionend #14");
is(events[2].type, "input",
"runForceCommitTest: the 3rd event must be input #14");
is(events[1].data, "\u306E",
"runForceCommitTest: compositionend has wrong data #14");
is(events[0].target, input,
"runForceCommitTest: The 1st event was fired on wrong event target #14");
is(events[1].target, input,
"runForceCommitTest: The 2nd event was fired on wrong event target #14");
is(events[2].target, input,
"runForceCommitTest: The 3rd event was fired on wrong event target #14");
ok(!getEditorIMESupport(input).isComposing,
"runForceCommitTest: the input still has composition #14");
is(input.value, "\u306E appended value",
"runForceCommitTest: the input should have both composed text and appended text #14");
input.focus();
input.value = "abcd";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
events = [];
input.value = "abcd\u306E";
is(events.length, 0,
"runForceCommitTest: setting same value to input with composition shouldn't cause any events #15");
is(input.value, "abcd\u306E",
"runForceCommitTest: the input has unexpected value #15");
input.blur(); // commit composition
textarea.focus();
textarea.value = "abcd";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
events = [];
textarea.value = "abcd\u306E";
is(events.length, 0,
"runForceCommitTest: setting same value to textarea with composition shouldn't cause any events #16");
is(textarea.value, "abcd\u306E",
"runForceCommitTest: the input has unexpected value #16");
textarea.blur(); // commit composition
window.removeEventListener("compositionstart", eventHandler, true);
window.removeEventListener("compositionupdate", eventHandler, true);
window.removeEventListener("compositionend", eventHandler, true);
window.removeEventListener("input", eventHandler, true);
window.removeEventListener("text", eventHandler, true);
}
function runNestedSettingValue()
{
var isTesting = false;
var events = [];
function eventHandler(aEvent)
{
events.push(aEvent);
if (isTesting) {
aEvent.target.value += aEvent.type + ", ";
}
}
window.addEventListener("compositionstart", eventHandler, true);
window.addEventListener("compositionupdate", eventHandler, true);
window.addEventListener("compositionend", eventHandler, true);
window.addEventListener("input", eventHandler, true);
window.addEventListener("text", eventHandler, true);
textarea.focus();
textarea.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
events = [];
isTesting = true;
textarea.value = "first setting value, ";
isTesting = false;
is(events.length, 3,
"runNestedSettingValue: wrong event count #1");
is(events[0].type, "text",
"runNestedSettingValue: the 1st event must be text #1");
is(events[1].type, "compositionend",
"runNestedSettingValue: the 2nd event must be compositionend #1");
is(events[2].type, "input",
"runNestedSettingValue: the 3rd event must be input #1");
is(events[1].data, "\u306E",
"runNestedSettingValue: compositionend has wrong data #1");
is(events[0].target, textarea,
"runNestedSettingValue: The 1st event was fired on wrong event target #1");
is(events[1].target, textarea,
"runNestedSettingValue: The 2nd event was fired on wrong event target #1");
is(events[2].target, textarea,
"runNestedSettingValue: The 3rd event was fired on wrong event target #1");
ok(!getEditorIMESupport(textarea).isComposing,
"runNestedSettingValue: the textarea still has composition #1");
is(textarea.value, "first setting value, text, compositionend, input, ",
"runNestedSettingValue: the textarea should have all string set to value attribute");
input.focus();
input.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
events = [];
isTesting = true;
input.value = "first setting value, ";
isTesting = false;
is(events.length, 3,
"runNestedSettingValue: wrong event count #2");
is(events[0].type, "text",
"runNestedSettingValue: the 1st event must be text #2");
is(events[1].type, "compositionend",
"runNestedSettingValue: the 2nd event must be compositionend #2");
is(events[2].type, "input",
"runNestedSettingValue: the 3rd event must be input #2");
is(events[1].data, "\u306E",
"runNestedSettingValue: compositionend has wrong data #2");
is(events[0].target, input,
"runNestedSettingValue: The 1st event was fired on wrong event target #2");
is(events[1].target, input,
"runNestedSettingValue: The 2nd event was fired on wrong event target #2");
is(events[2].target, input,
"runNestedSettingValue: The 3rd event was fired on wrong event target #2");
ok(!getEditorIMESupport(input).isComposing,
"runNestedSettingValue: the input still has composition #2");
is(textarea.value, "first setting value, text, compositionend, input, ",
"runNestedSettingValue: the input should have all string set to value attribute #2");
textarea.focus();
textarea.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
events = [];
isTesting = true;
textarea.setRangeText("first setting value, ");
isTesting = false;
is(events.length, 3,
"runNestedSettingValue: wrong event count #3");
is(events[0].type, "text",
"runNestedSettingValue: the 1st event must be text #3");
is(events[1].type, "compositionend",
"runNestedSettingValue: the 2nd event must be compositionend #3");
is(events[2].type, "input",
"runNestedSettingValue: the 3rd event must be input #3");
is(events[1].data, "\u306E",
"runNestedSettingValue: compositionend has wrong data #3");
is(events[0].target, textarea,
"runNestedSettingValue: The 1st event was fired on wrong event target #3");
is(events[1].target, textarea,
"runNestedSettingValue: The 2nd event was fired on wrong event target #3");
is(events[2].target, textarea,
"runNestedSettingValue: The 3rd event was fired on wrong event target #3");
ok(!getEditorIMESupport(textarea).isComposing,
"runNestedSettingValue: the textarea still has composition #3");
is(textarea.value, "\u306Efirst setting value, text, compositionend, input, ",
"runNestedSettingValue: the textarea should have appended by setRangeText() and all string set to value attribute #3");
input.focus();
input.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
events = [];
isTesting = true;
input.setRangeText("first setting value, ");
isTesting = false;
is(events.length, 3,
"runNestedSettingValue: wrong event count #4");
is(events[0].type, "text",
"runNestedSettingValue: the 1st event must be text #4");
is(events[1].type, "compositionend",
"runNestedSettingValue: the 2nd event must be compositionend #4");
is(events[2].type, "input",
"runNestedSettingValue: the 3rd event must be input #4");
is(events[1].data, "\u306E",
"runNestedSettingValue: compositionend has wrong data #4");
is(events[0].target, input,
"runNestedSettingValue: The 1st event was fired on wrong event target #4");
is(events[1].target, input,
"runNestedSettingValue: The 2nd event was fired on wrong event target #4");
is(events[2].target, input,
"runNestedSettingValue: The 3rd event was fired on wrong event target #4");
ok(!getEditorIMESupport(input).isComposing,
"runNestedSettingValue: the input still has composition #4");
is(textarea.value, "\u306Efirst setting value, text, compositionend, input, ",
"runNestedSettingValue: the input should have all string appended by setRangeText() and set to value attribute #4");
window.removeEventListener("compositionstart", eventHandler, true);
window.removeEventListener("compositionupdate", eventHandler, true);
window.removeEventListener("compositionend", eventHandler, true);
window.removeEventListener("input", eventHandler, true);
window.removeEventListener("text", eventHandler, true);
}
function runAsyncForceCommitTest(aNextTest)
{
var events;
function eventHandler(aEvent)
{
events.push(aEvent);
};
// If IME commits composition for a request, TextComposition commits
// composition automatically because most web apps must expect that active
// composition should be committed synchronously. Therefore, in this case,
// a click during composition should cause committing composition
// synchronously and delayed commit shouldn't cause composition events.
var commitRequested = false;
function callback(aTIP, aNotification)
{
ok(true, aNotification.type);
if (aNotification.type != "request-to-commit") {
return true;
}
commitRequested = true;
setTimeout(function () {
events = [];
aTIP.commitComposition();
is(events.length, 0,
"runAsyncForceCommitTest: composition events shouldn't been fired by asynchronous call of nsITextInputProcessor.commitComposition()");
window.removeEventListener("compositionstart", eventHandler, true);
window.removeEventListener("compositionupdate", eventHandler, true);
window.removeEventListener("compositionend", eventHandler, true);
window.removeEventListener("input", eventHandler, true);
window.removeEventListener("text", eventHandler, true);
SimpleTest.executeSoon(aNextTest);
}, 1);
return true;
};
window.addEventListener("compositionstart", eventHandler, true);
window.addEventListener("compositionupdate", eventHandler, true);
window.addEventListener("compositionend", eventHandler, true);
window.addEventListener("input", eventHandler, true);
window.addEventListener("text", eventHandler, true);
// Make the composition in textarea commit by click in the textarea
textarea.focus();
textarea.value = "";
events = [];
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
}, window, callback);
is(events.length, 4,
"runAsyncForceCommitTest: wrong event count #1");
is(events[0].type, "compositionstart",
"runAsyncForceCommitTest: the 1st event must be compositionstart #1");
is(events[1].type, "compositionupdate",
"runAsyncForceCommitTest: the 2nd event must be compositionupdate #1");
is(events[2].type, "text",
"runAsyncForceCommitTest: the 3rd event must be text #1");
is(events[3].type, "input",
"runAsyncForceCommitTest: the 4th event must be input #1");
events = [];
commitRequested = false;
synthesizeMouseAtCenter(textarea, {});
ok(commitRequested,
"runAsyncForceCommitTest: \"request-to-commit\" should've been notified");
is(events.length, 3,
"runAsyncForceCommitTest: wrong event count #2");
is(events[0].type, "text",
"runAsyncForceCommitTest: the 1st event must be text #2");
is(events[1].type, "compositionend",
"runAsyncForceCommitTest: the 2nd event must be compositionend #2");
is(events[2].type, "input",
"runAsyncForceCommitTest: the 3rd event must be input #2");
is(events[1].data, "\u306E",
"runAsyncForceCommitTest: compositionend has wrong data #2");
is(events[0].target, textarea,
"runAsyncForceCommitTest: The 1st event was fired on wrong event target #2");
is(events[1].target, textarea,
"runAsyncForceCommitTest: The 2nd event was fired on wrong event target #2");
is(events[2].target, textarea,
"runAsyncForceCommitTest: The 3rd event was fired on wrong event target #2");
ok(!getEditorIMESupport(textarea).isComposing,
"runAsyncForceCommitTest: the textarea still has composition #2");
is(textarea.value, "\u306E",
"runAsyncForceCommitTest: the textarea doesn't have the committed text #2");
}
function runBug811755Test()
{
iframe2.contentDocument.body.innerHTML = "<div>content<br/></div>";
iframe2.contentWindow.focus();
// Query everything
var textContent = synthesizeQueryTextContent(0, 10);
if (!checkQueryContentResult(textContent, "runBug811755Test: synthesizeQueryTextContent #1")) {
return false;
}
// Query everything but specify exact end offset, which should be immediately after the <br> node
// If PreContentIterator is used, the next node after <br> is the node after </div>.
// If ContentIterator is used, the next node is the <div> node itself. In this case, the end
// node ends up being before the start node, and an empty string is returned.
var queryContent = synthesizeQueryTextContent(0, textContent.text.length);
if (!checkQueryContentResult(queryContent, "runBug811755Test: synthesizeQueryTextContent #2")) {
return false;
}
is(queryContent.text, textContent.text, "runBug811755Test: two queried texts don't match");
return queryContent.text == textContent.text;
}
function runIsComposingTest()
{
var expectedIsComposing = false;
var descriptionBase = "runIsComposingTest: ";
var description = "";
function eventHandler(aEvent)
{
if (aEvent.type == "keydown" || aEvent.type == "keyup") {
is(aEvent.isComposing, expectedIsComposing,
"runIsComposingTest: " + description + " (type=" + aEvent.type + ", key=" + aEvent.key + ")");
} else {
is(aEvent.isComposing, expectedIsComposing,
"runIsComposingTest: " + description + " (type=" + aEvent.type + ")");
}
}
function onComposition(aEvent)
{
if (aEvent.type == "compositionstart") {
expectedIsComposing = true;
} else if (aEvent.type == "compositionend") {
expectedIsComposing = false;
}
}
textarea.addEventListener("keydown", eventHandler, true);
textarea.addEventListener("keypress", eventHandler, true);
textarea.addEventListener("keyup", eventHandler, true);
textarea.addEventListener("input", eventHandler, true);
textarea.addEventListener("compositionstart", onComposition, true);
textarea.addEventListener("compositionend", onComposition, true);
textarea.focus();
textarea.value = "";
// XXX These cases shouldn't occur in actual native key events because we
// don't dispatch key events while composition (bug 354358).
SpecialPowers.setBoolPref("dom.keyboardevent.dispatch_during_composition", true);
description = "events before dispatching compositionstart";
synthesizeKey("VK_LEFT", {});
description = "events after dispatching compositionchange";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3042",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 },
"key": { key: "a", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A },
});
// Although, firing keypress event during composition is a bug.
synthesizeKey("VK_INSERT", {});
description = "events for committing composition string";
synthesizeComposition({ type: "compositioncommitasis",
key: { key: "KEY_Enter", code: "Enter", type: "keydown" } });
// input event will be fired by synthesizing compositionend event.
// Then, its isComposing should be false.
description = "events after dispatching compositioncommitasis";
synthesizeKey("VK_RETURN", { type: "keyup" });
SpecialPowers.clearUserPref("dom.keyboardevent.dispatch_during_composition");
textarea.removeEventListener("keydown", eventHandler, true);
textarea.removeEventListener("keypress", eventHandler, true);
textarea.removeEventListener("keyup", eventHandler, true);
textarea.removeEventListener("input", eventHandler, true);
textarea.removeEventListener("compositionstart", onComposition, true);
textarea.removeEventListener("compositionend", onComposition, true);
textarea.value = "";
}
function runRedundantChangeTest()
{
textarea.focus();
var result = {};
function clearResult()
{
result = { compositionupdate: false, compositionend: false, text: false, input: false, inputaftercompositionend: false };
}
function handler(aEvent)
{
if (aEvent.type == "input" && result.compositionend) {
result.inputaftercompositionend = true;
return;
}
result[aEvent.type] = true;
}
textarea.addEventListener("compositionupdate", handler, true);
textarea.addEventListener("compositionend", handler, true);
textarea.addEventListener("input", handler, true);
textarea.addEventListener("text", handler, true);
textarea.value = "";
// synthesize change event
clearResult();
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3042",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
is(result.compositionupdate, true, "runRedundantChangeTest: compositionupdate should be fired after synthesizing composition change #1");
is(result.compositionend, false, "runRedundantChangeTest: compositionend shouldn't be fired after synthesizing composition change #1");
is(result.text, true, "runRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string #1");
is(result.input, true, "runRedundantChangeTest: input should be fired after synthesizing composition change #1");
is(textarea.value, "\u3042", "runRedundantChangeTest: textarea has uncommitted string #1");
// synthesize another change event
clearResult();
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3042\u3044",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
is(result.compositionupdate, true, "runRedundantChangeTest: compositionupdate should be fired after synthesizing composition change #2");
is(result.compositionend, false, "runRedundantChangeTest: compositionend shouldn't be fired after synthesizing composition change #2");
is(result.text, true, "runRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string #2");
is(result.input, true, "runRedundantChangeTest: input should be fired after synthesizing composition change #2");
is(textarea.value, "\u3042\u3044", "runRedundantChangeTest: textarea has uncommitted string #2");
// synthesize same change event again
clearResult();
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3042\u3044",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
is(result.compositionupdate, false, "runRedundantChangeTest: compositionupdate shouldn't be fired after synthesizing composition change again");
is(result.compositionend, false, "runRedundantChangeTest: compositionend shouldn't be fired after synthesizing composition change again");
is(result.text, false, "runRedundantChangeTest: text shouldn't be fired after synthesizing composition change again because it's dispatched when there is composing string");
is(result.input, false, "runRedundantChangeTest: input shouldn't be fired after synthesizing composition change again");
is(textarea.value, "\u3042\u3044", "runRedundantChangeTest: textarea has uncommitted string #3");
// synthesize commit-as-is
clearResult();
synthesizeComposition({ type: "compositioncommitasis" });
is(result.compositionupdate, false, "runRedundantChangeTest: compositionupdate shouldn't be fired after synthesizing composition commit-as-is");
is(result.compositionend, true, "runRedundantChangeTest: compositionend should be fired after synthesizing composition commit-as-is");
is(result.text, true, "runRedundantChangeTest: text shouldn't be fired after synthesizing composition commit-as-is for removing the ranges");
is(result.input, false, "runRedundantChangeTest: input shouldn't be fired before compositionend at synthesizing commit-as-is");
is(result.inputaftercompositionend, true, "runRedundantChangeTest: input should be fired after synthesizing composition commit-as-is after compositionend");
is(textarea.value, "\u3042\u3044", "runRedundantChangeTest: textarea has the commit string");
textarea.removeEventListener("compositionupdate", handler, true);
textarea.removeEventListener("compositionend", handler, true);
textarea.removeEventListener("input", handler, true);
textarea.removeEventListener("text", handler, true);
}
function runNotRedundantChangeTest()
{
textarea.focus();
var result = {};
function clearResult()
{
result = { compositionupdate: false, compositionend: false, text: false, input: false, inputaftercompositionend: false };
}
function handler(aEvent)
{
if (aEvent.type == "input" && result.compositionend) {
result.inputaftercompositionend = true;
return;
}
result[aEvent.type] = true;
}
textarea.addEventListener("compositionupdate", handler, true);
textarea.addEventListener("compositionend", handler, true);
textarea.addEventListener("input", handler, true);
textarea.addEventListener("text", handler, true);
textarea.value = "abcde";
// synthesize change event with non-null ranges
clearResult();
synthesizeCompositionChange(
{ "composition":
{ "string": "ABCDE",
"clauses":
[
{ "length": 5, "attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
]
},
"caret": { "start": 5, "length": 0 }
});
is(result.compositionupdate, true, "runNotRedundantChangeTest: compositionupdate should be fired after synthesizing composition change with non-null ranges");
is(result.compositionend, false, "runNotRedundantChangeTest: compositionend shouldn't be fired after synthesizing composition change with non-null ranges");
is(result.text, true, "runNotRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string with non-null ranges");
is(result.input, true, "runNotRedundantChangeTest: input should be fired after synthesizing composition change with non-null ranges");
is(textarea.value, "abcdeABCDE", "runNotRedundantChangeTest: textarea has uncommitted string #1");
// synthesize change event with null ranges
clearResult();
synthesizeCompositionChange(
{ "composition":
{ "string": "ABCDE",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
});
is(result.compositionupdate, false, "runNotRedundantChangeTest: compositionupdate shouldn't be fired after synthesizing composition change with null ranges after non-null ranges");
is(result.compositionend, false, "runNotRedundantChangeTest: compositionend shouldn't be fired after synthesizing composition change with null ranges after non-null ranges");
is(result.text, true, "runNotRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string with null ranges after non-null ranges");
is(result.input, true, "runNotRedundantChangeTest: input should be fired after synthesizing composition change with null ranges after non-null ranges");
is(textarea.value, "abcdeABCDE", "runNotRedundantChangeTest: textarea has uncommitted string #2");
// synthesize change event with non-null ranges
clearResult();
synthesizeCompositionChange(
{ "composition":
{ "string": "ABCDE",
"clauses":
[
{ "length": 5, "attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
]
},
"caret": { "start": 5, "length": 0 }
});
is(result.compositionupdate, false, "runNotRedundantChangeTest: compositionupdate shouldn't be fired after synthesizing composition change with non-null ranges after null ranges");
is(result.compositionend, false, "runNotRedundantChangeTest: compositionend shouldn't be fired after synthesizing composition change with non-null ranges after null ranges");
is(result.text, true, "runNotRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string with non-null ranges after null ranges");
is(result.input, true, "runNotRedundantChangeTest: input should be fired after synthesizing composition change with non-null ranges after null ranges");
is(textarea.value, "abcdeABCDE", "runNotRedundantChangeTest: textarea has uncommitted string #3");
// synthesize change event with empty data and null ranges
clearResult();
synthesizeCompositionChange(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
});
is(result.compositionupdate, true, "runNotRedundantChangeTest: compositionupdate should be fired after synthesizing composition change with empty data and null ranges after non-null ranges");
is(result.compositionend, false, "runNotRedundantChangeTest: compositionend shouldn't be fired after synthesizing composition change with empty data and null ranges after non-null ranges");
is(result.text, true, "runNotRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string with empty data and null ranges after non-null ranges");
is(result.input, true, "runNotRedundantChangeTest: input should be fired after synthesizing composition change with empty data and null ranges after non-null ranges");
is(textarea.value, "abcde", "runNotRedundantChangeTest: textarea doesn't have uncommitted string #1");
// synthesize change event with non-null ranges
clearResult();
synthesizeCompositionChange(
{ "composition":
{ "string": "ABCDE",
"clauses":
[
{ "length": 5, "attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
]
},
"caret": { "start": 5, "length": 0 }
});
is(result.compositionupdate, true, "runNotRedundantChangeTest: compositionupdate should be fired after synthesizing composition change with non-null ranges after empty data and null ranges");
is(result.compositionend, false, "runNotRedundantChangeTest: compositionend shouldn't be fired after synthesizing composition change with non-null ranges after empty data and null ranges");
is(result.text, true, "runNotRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string with non-null ranges after empty data and null ranges");
is(result.input, true, "runNotRedundantChangeTest: input should be fired after synthesizing composition change with non-null ranges after empty data and null ranges");
is(textarea.value, "abcdeABCDE", "runNotRedundantChangeTest: textarea has uncommitted string #4");
clearResult();
synthesizeComposition({ type: "compositioncommit", data: "" });
is(result.compositionupdate, true, "runNotRedundantChangeTest: compositionupdate should be fired after synthesizing composition commit with empty data after non-empty data");
is(result.compositionend, true, "runNotRedundantChangeTest: compositionend should be fired after synthesizing composition commit with empty data after non-empty data");
is(result.text, true, "runNotRedundantChangeTest: text should be fired after synthesizing composition change because it's dispatched when there is composing string with empty data after non-empty data");
is(result.input, false, "runNotRedundantChangeTest: input shouldn't be fired before compositionend after synthesizing composition change with empty data after non-empty data");
is(result.inputaftercompositionend, true, "runNotRedundantChangeTest: input should be fired after compositionend after synthesizing composition change with empty data after non-empty data");
is(textarea.value, "abcde", "runNotRedundantChangeTest: textarea doesn't have uncommitted string #2");
textarea.removeEventListener("compositionupdate", handler, true);
textarea.removeEventListener("compositionend", handler, true);
textarea.removeEventListener("input", handler, true);
textarea.removeEventListener("text", handler, true);
}
function runControlCharTest()
{
textarea.focus();
var result = {};
function clearResult()
{
result = { compositionupdate: null, compositionend: null };
}
function handler(aEvent)
{
result[aEvent.type] = aEvent.data;
}
textarea.addEventListener("compositionupdate", handler, true);
textarea.addEventListener("compositionend", handler, true);
textarea.value = "";
var controlChars = String.fromCharCode.apply(null, Object.keys(Array.from({length:0x20}))) + "\x7F";
var allowedChars = "\t";
var data = "AB" + controlChars + "CD" + controlChars + "EF";
var removedData = "AB" + allowedChars + "CD" + allowedChars + "EF";
var DIndex = data.indexOf("D");
var removedDIndex = removedData.indexOf("D");
// input string contains control characters
clearResult();
synthesizeCompositionChange(
{ "composition":
{ "string": data,
"clauses":
[
{ "length": DIndex,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
{ "length": data.length - DIndex,
"attr": COMPOSITION_ATTR_CONVERTED_CLAUSE }
]
},
"caret": { "start": DIndex, "length": 0 }
});
checkSelection(removedDIndex, "", "runControlCharTest", "#1")
is(result.compositionupdate, removedData, "runControlCharTest: control characters in event.data should be removed in compositionupdate event #1");
is(textarea.value, removedData, "runControlCharTest: control characters should not appear in textarea #1");
synthesizeComposition({ type: "compositioncommit", data: data });
is(result.compositionend, removedData, "runControlCharTest: control characters in event.data should be removed in compositionend event #2");
is(textarea.value, removedData, "runControlCharTest: control characters should not appear in textarea #2");
textarea.value = "";
clearResult();
SpecialPowers.setBoolPref("dom.compositionevent.allow_control_characters", true);
// input string contains control characters, allowing control characters
clearResult();
synthesizeCompositionChange(
{ "composition":
{ "string": data,
"clauses":
[
{ "length": DIndex,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
{ "length": data.length - DIndex,
"attr": COMPOSITION_ATTR_CONVERTED_CLAUSE }
]
},
"caret": { "start": DIndex, "length": 0 }
});
checkSelection(DIndex - 1 + kLFLen, "", "runControlCharTest", "#3")
is(result.compositionupdate, data, "runControlCharTest: control characters in event.data should not be removed in compositionupdate event #3");
is(textarea.value, data.replace(/\r/g, "\n"), "runControlCharTest: control characters should appear in textarea #3");
synthesizeComposition({ type: "compositioncommit", data: data });
is(result.compositionend, data, "runControlCharTest: control characters in event.data should not be removed in compositionend event #4");
is(textarea.value, data.replace(/\r/g, "\n"), "runControlCharTest: control characters should appear in textarea #4");
SpecialPowers.clearUserPref("dom.compositionevent.allow_control_characters");
textarea.removeEventListener("compositionupdate", handler, true);
textarea.removeEventListener("compositionend", handler, true);
}
function runRemoveContentTest(aCallback)
{
var events = [];
function eventHandler(aEvent)
{
events.push(aEvent);
}
textarea.addEventListener("compositionstart", eventHandler, true);
textarea.addEventListener("compositionupdate", eventHandler, true);
textarea.addEventListener("compositionend", eventHandler, true);
textarea.addEventListener("input", eventHandler, true);
textarea.addEventListener("text", eventHandler, true);
textarea.focus();
textarea.value = "";
synthesizeCompositionChange(
{ "composition":
{ "string": "\u306E",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
var nextSibling = textarea.nextSibling;
var parent = textarea.parentElement;
events = [];
parent.removeChild(textarea);
hitEventLoop(function () {
// XXX Currently, "input" event isn't fired on removed content.
is(events.length, 3,
"runRemoveContentTest: wrong event count #1");
is(events[0].type, "compositionupdate",
"runRemoveContentTest: the 1st event must be compositionupdate #1");
is(events[1].type, "text",
"runRemoveContentTest: the 2nd event must be text #1");
is(events[2].type, "compositionend",
"runRemoveContentTest: the 3rd event must be compositionend #1");
is(events[0].data, "",
"runRemoveContentTest: compositionupdate has wrong data #1");
is(events[2].data, "",
"runRemoveContentTest: compositionend has wrong data #1");
is(events[0].target, textarea,
"runRemoveContentTest: The 1st event was fired on wrong event target #1");
is(events[1].target, textarea,
"runRemoveContentTest: The 2nd event was fired on wrong event target #1");
is(events[2].target, textarea,
"runRemoveContentTest: The 3rd event was fired on wrong event target #1");
ok(!getEditorIMESupport(textarea).isComposing,
"runRemoveContentTest: the textarea still has composition #1");
todo_is(textarea.value, "",
"runRemoveContentTest: the textarea has the committed text? #1");
parent.insertBefore(textarea, nextSibling);
textarea.focus();
textarea.value = "";
synthesizeComposition({ type: "compositionstart" });
events = [];
parent.removeChild(textarea);
hitEventLoop(function () {
// XXX Currently, "input" event isn't fired on removed content.
is(events.length, 1,
"runRemoveContentTest: wrong event count #2");
is(events[0].type, "compositionend",
"runRemoveContentTest: the 1st event must be compositionend #2");
is(events[0].data, "",
"runRemoveContentTest: compositionupdate has wrong data #2");
is(events[0].target, textarea,
"runRemoveContentTest: The 1st event was fired on wrong event target #2");
ok(!getEditorIMESupport(textarea).isComposing,
"runRemoveContentTest: the textarea still has composition #2");
is(textarea.value, "",
"runRemoveContentTest: the textarea has the committed text? #2");
parent.insertBefore(textarea, nextSibling);
textarea.removeEventListener("compositionstart", eventHandler, true);
textarea.removeEventListener("compositionupdate", eventHandler, true);
textarea.removeEventListener("compositionend", eventHandler, true);
textarea.removeEventListener("input", eventHandler, true);
textarea.removeEventListener("text", eventHandler, true);
SimpleTest.executeSoon(aCallback);
}, 50);
}, 50);
}
function runTestOnAnotherContext(aPanelOrFrame, aFocusedEditor, aTestName)
{
aFocusedEditor.value = "";
var editorRect = synthesizeQueryEditorRect();
if (!checkQueryContentResult(editorRect, aTestName + ": editorRect")) {
return;
}
var r = aPanelOrFrame.getBoundingClientRect();
var parentRect = { "left": r.left, "top": r.top, "width": r.right - r.left,
"height": r.bottom - r.top };
checkRectContainsRect(editorRect, parentRect, aTestName +
": the editor rect coordinates are wrong");
// input characters
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3078\u3093\u3057\u3093",
"clauses":
[
{ "length": 4, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 4, "length": 0 }
});
if (!checkContent("\u3078\u3093\u3057\u3093", aTestName, "#1-1") ||
!checkSelection(4, "", aTestName, "#1-1")) {
return;
}
// convert them #1
synthesizeCompositionChange(
{ "composition":
{ "string": "\u8FD4\u4FE1",
"clauses":
[
{ "length": 2,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
if (!checkContent("\u8FD4\u4FE1", aTestName, "#1-2") ||
!checkSelection(2, "", aTestName, "#1-2")) {
return;
}
// convert them #2
synthesizeCompositionChange(
{ "composition":
{ "string": "\u5909\u8EAB",
"clauses":
[
{ "length": 2,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
if (!checkContent("\u5909\u8EAB", aTestName, "#1-3") ||
!checkSelection(2, "", aTestName, "#1-3")) {
return;
}
// commit them
synthesizeComposition({ type: "compositioncommitasis" });
if (!checkContent("\u5909\u8EAB", aTestName, "#1-4") ||
!checkSelection(2, "", aTestName, "#1-4")) {
return;
}
is(aFocusedEditor.value, "\u5909\u8EAB",
aTestName + ": composition isn't in the focused editor");
if (aFocusedEditor.value != "\u5909\u8EAB") {
return;
}
var textRect = synthesizeQueryTextRect(0, 1);
var caretRect = synthesizeQueryCaretRect(2);
if (!checkQueryContentResult(textRect,
aTestName + ": synthesizeQueryTextRect") ||
!checkQueryContentResult(caretRect,
aTestName + ": synthesizeQueryCaretRect")) {
return;
}
checkRectContainsRect(textRect, editorRect, aTestName + ":testRect");
checkRectContainsRect(caretRect, editorRect, aTestName + ":caretRect");
}
function runFrameTest()
{
textareaInFrame.focus();
runTestOnAnotherContext(iframe, textareaInFrame, "runFrameTest");
runCharAtPointTest(textareaInFrame, "textarea in the iframe");
}
var gPanelShown = false;
var gPanelFocused = false;
function onPanelShown(aEvent)
{
gPanelShown = true;
textbox.focus();
setTimeout(doPanelTest, 0);
}
function onFocusPanelTextbox(aEvent)
{
gPanelFocused = true;
setTimeout(doPanelTest, 0);
}
var gIsPanelHiding = false;
var gIsRunPanelTestInternal = false;
function doPanelTest()
{
if (!gPanelFocused || !gPanelShown) {
return;
}
if (gIsRunPanelTestInternal) {
return;
}
gIsRunPanelTestInternal = true;
runTestOnAnotherContext(panel, textbox, "runPanelTest");
runCharAtPointTest(textbox, "textbox in the panel");
gIsPanelHiding = true;
panel.hidePopup();
}
function onPanelHidden(aEvent)
{
panel.hidden = true;
ok(gIsPanelHiding, "runPanelTest: the panel is hidden unexpectedly");
finish();
}
function runPanelTest()
{
panel.hidden = false;
panel.openPopupAtScreen(window.screenX + window.outerWidth, 0, false);
}
function runMaxLengthTest()
{
input.maxLength = 1;
input.value = "";
input.focus();
var kDesc ="runMaxLengthTest";
// input first character
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
if (!checkContent("\u3089", kDesc, "#1-1") ||
!checkSelection(1, "", kDesc, "#1-1")) {
return;
}
// input second character
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
if (!checkContent("\u3089\u30FC", kDesc, "#1-2") ||
!checkSelection(2, "", kDesc, "#1-2")) {
return;
}
// input third character
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC\u3081",
"clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 3, "length": 0 }
});
if (!checkContent("\u3089\u30FC\u3081", kDesc, "#1-3") ||
!checkSelection(3, "", kDesc, "#1-3")) {
return;
}
// input fourth character
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC\u3081\u3093",
"clauses":
[
{ "length": 4, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 4, "length": 0 }
});
if (!checkContent("\u3089\u30FC\u3081\u3093", kDesc, "#1-4") ||
!checkSelection(4, "", kDesc, "#1-4")) {
return;
}
// backspace
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC\u3081",
"clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 3, "length": 0 }
});
if (!checkContent("\u3089\u30FC\u3081", kDesc, "#1-5") ||
!checkSelection(3, "", kDesc, "#1-5")) {
return;
}
// re-input
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC\u3081\u3093",
"clauses":
[
{ "length": 4, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 4, "length": 0 }
});
if (!checkContent("\u3089\u30FC\u3081\u3093", kDesc, "#1-6") ||
!checkSelection(4, "", kDesc, "#1-6")) {
return;
}
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC\u3081\u3093\u3055",
"clauses":
[
{ "length": 5, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 5, "length": 0 }
});
if (!checkContent("\u3089\u30FC\u3081\u3093\u3055", kDesc, "#1-7") ||
!checkSelection(5, "", kDesc, "#1-7")) {
return;
}
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC\u3081\u3093\u3055\u3044",
"clauses":
[
{ "length": 6, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 6, "length": 0 }
});
if (!checkContent("\u3089\u30FC\u3081\u3093\u3055\u3044", kDesc, "#1-8") ||
!checkSelection(6, "", kDesc, "#1-8")) {
return;
}
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC\u3081\u3093\u3055\u3044\u3053",
"clauses":
[
{ "length": 7, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 7, "length": 0 }
});
if (!checkContent("\u3089\u30FC\u3081\u3093\u3055\u3044\u3053",
kDesc, "#1-8") ||
!checkSelection(7, "", kDesc, "#1-8")) {
return;
}
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3089\u30FC\u3081\u3093\u3055\u3044\u3053\u3046",
"clauses":
[
{ "length": 8, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 8, "length": 0 }
});
if (!checkContent("\u3089\u30FC\u3081\u3093\u3055\u3044\u3053\u3046",
kDesc, "#1-9") ||
!checkSelection(8, "", kDesc, "#1-9")) {
return;
}
// convert
synthesizeCompositionChange(
{ "composition":
{ "string": "\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8",
"clauses":
[
{ "length": 4,
"attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
{ "length": 2,
"attr": COMPOSITION_ATTR_CONVERTED_CLAUSE }
]
},
"caret": { "start": 4, "length": 0 }
});
if (!checkContent("\u30E9\u30FC\u30E1\u30F3\u6700\u9AD8", kDesc, "#1-10") ||
!checkSelection(4, "", kDesc, "#1-10")) {
return;
}
// commit the composition string
synthesizeComposition({ type: "compositioncommitasis" });
if (!checkContent("\u30E9", kDesc, "#1-11") ||
!checkSelection(1, "", kDesc, "#1-11")) {
return;
}
// input characters
synthesizeCompositionChange(
{ "composition":
{ "string": "\u3057",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
if (!checkContent("\u30E9\u3057", kDesc, "#2-1") ||
!checkSelection(1 + 1, "", kDesc, "#2-1")) {
return;
}
// commit the composition string
synthesizeComposition({ type: "compositioncommit", data: "\u3058" });
if (!checkContent("\u30E9", kDesc, "#2-2") ||
!checkSelection(1 + 0, "", kDesc, "#2-2")) {
return;
}
// Undo
synthesizeKey("Z", {accelKey: true});
// XXX this is unexpected behavior, see bug 258291
if (!checkContent("\u30E9", kDesc, "#3-1") ||
!checkSelection(1 + 0, "", kDesc, "#3-1")) {
return;
}
// Undo
synthesizeKey("Z", {accelKey: true});
if (!checkContent("", kDesc, "#3-2") ||
!checkSelection(0, "", kDesc, "#3-2")) {
return;
}
// Redo
synthesizeKey("Z", {accelKey: true, shiftKey: true});
if (!checkContent("\u30E9", kDesc, "#3-3") ||
!checkSelection(1, "", kDesc, "#3-3")) {
return;
}
// Redo
synthesizeKey("Z", {accelKey: true, shiftKey: true});
if (!checkContent("\u30E9", kDesc, "#3-4") ||
!checkSelection(1 + 0, "", kDesc, "#3-4")) {
return;
}
// The input element whose content length is already maxlength and
// the carest is at start of the content.
input.value = "X";
input.selectionStart = input.selectionEnd = 0;
// input characters
synthesizeCompositionChange(
{ "composition":
{ "string": "\u9B54",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
if (!checkContent("\u9B54X", kDesc, "#4-1") ||
!checkSelection(1, "", kDesc, "#4-1")) {
return;
}
// commit the composition string
synthesizeComposition({ type: "compositioncommitasis" });
// The input text must be discarded. Then, the caret position shouldn't be
// updated from its position at compositionstart.
if (!checkContent("X", kDesc, "#4-2") ||
!checkSelection(0, "", kDesc, "#4-2")) {
return;
}
// input characters
synthesizeCompositionChange(
{ "composition":
{ "string": "\u9B54\u6CD5",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
if (!checkContent("\u9B54\u6CD5X", kDesc, "#5-1") ||
!checkSelection(2, "", kDesc, "#5-1")) {
return;
}
// commit the composition string
synthesizeComposition({ type: "compositioncommitasis" });
if (!checkContent("X", kDesc, "#5-2") ||
!checkSelection(0, "", kDesc, "#5-2")) {
return;
}
}
function runEditorReframeTests(aCallback)
{
function runEditorReframeTest(aEditor, aWindow, aEventType, aNextTest)
{
function getValue()
{
return aEditor == contenteditable ?
aEditor.innerHTML.replace("<br>", "") : aEditor.value;
}
var description = "runEditorReframeTest(" + aEditor.id + ", \"" + aEventType + "\"): ";
var tests = [
{ test: function () {
synthesizeCompositionChange(
{ "composition":
{ "string": "a",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
},
check: function () {
is(getValue(aEditor), "a", description + "Typing 'a'");
},
},
{ test: function () {
synthesizeCompositionChange(
{ "composition":
{ "string": "ab",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
},
check: function () {
is(getValue(aEditor), "ab", description + "Typing 'b' next to 'a'");
},
},
{ test: function () {
synthesizeCompositionChange(
{ "composition":
{ "string": "abc",
"clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 3, "length": 0 }
});
},
check: function () {
is(getValue(aEditor), "abc", description + "Typing 'c' next to 'ab'");
},
},
{ test: function () {
synthesizeCompositionChange(
{ "composition":
{ "string": "abc",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
{ "length": 1, "attr": COMPOSITION_ATTR_CONVERTED_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
},
check: function () {
is(getValue(aEditor), "abc", description + "Starting to convert 'ab][c'");
},
},
{ test: function () {
synthesizeCompositionChange(
{ "composition":
{ "string": "ABc",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_SELECTED_CLAUSE },
{ "length": 1, "attr": COMPOSITION_ATTR_CONVERTED_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
},
check: function () {
is(getValue(aEditor), "ABc", description + "Starting to convert 'AB][c'");
},
},
{ test: function () {
synthesizeCompositionChange(
{ "composition":
{ "string": "ABC",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_CONVERTED_CLAUSE },
{ "length": 1, "attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
]
},
"caret": { "start": 3, "length": 0 }
});
},
check: function () {
is(getValue(aEditor), "ABC", description + "Starting to convert 'AB][C'");
},
},
{ test: function () {
// Commit composition
synthesizeComposition({ type: "compositioncommitasis" });
},
check: function () {
is(getValue(aEditor), "ABC", description + "Committed as 'ABC'");
},
},
{ test: function () {
synthesizeCompositionChange(
{ "composition":
{ "string": "d",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
},
check: function () {
is(getValue(aEditor), "ABCd", description + "Typing 'd' next to ABC");
},
},
{ test: function () {
synthesizeCompositionChange(
{ "composition":
{ "string": "de",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
},
check: function () {
is(getValue(aEditor), "ABCde", description + "Typing 'e' next to ABCd");
},
},
{ test: function () {
synthesizeCompositionChange(
{ "composition":
{ "string": "def",
"clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 3, "length": 0 }
});
},
check: function () {
is(getValue(aEditor), "ABCdef", description + "Typing 'f' next to ABCde");
},
},
{ test: function () {
// Commit composition
synthesizeComposition({ type: "compositioncommitasis" });
},
check: function () {
is(getValue(aEditor), "ABCdef", description + "Commit 'def' without convert");
},
},
{ test: function () {
// Select "Cd"
synthesizeKey("KEY_ArrowLeft", { code: "ArrowLeft" });
synthesizeKey("KEY_ArrowLeft", { code: "ArrowLeft" });
synthesizeKey("KEY_Shift", { type: "keydown", code: "ShiftLeft", shiftKey: true });
synthesizeKey("KEY_ArrowLeft", { code: "ArrowLeft", shiftKey: true });
synthesizeKey("KEY_ArrowLeft", { code: "ArrowLeft", shiftKey: true });
synthesizeKey("KEY_Shift", { type: "keyup", code: "ShiftLeft" });
},
check: function () {
},
},
{ test: function () {
synthesizeCompositionChange(
{ "composition":
{ "string": "g",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 1, "length": 0 }
});
},
check: function () {
is(getValue(aEditor), "ABgef", description + "Typing 'g' next to AB");
},
},
{ test: function () {
synthesizeCompositionChange(
{ "composition":
{ "string": "gh",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 2, "length": 0 }
});
},
check: function () {
is(getValue(aEditor), "ABghef", description + "Typing 'h' next to ABg");
},
},
{ test: function () {
synthesizeCompositionChange(
{ "composition":
{ "string": "ghi",
"clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_RAW_CLAUSE }
]
},
"caret": { "start": 3, "length": 0 }
});
},
check: function () {
is(getValue(aEditor), "ABghief", description + "Typing 'i' next to ABgh");
},
},
{ test: function () {
synthesizeCompositionChange(
{ "composition":
{ "string": "GHI",
"clauses":
[
{ "length": 3, "attr": COMPOSITION_ATTR_SELECTED_CLAUSE }
]
},
"caret": { "start": 3, "length": 0 }
});
},
check: function () {
is(getValue(aEditor), "ABGHIef", description + "Convert 'ghi' to 'GHI'");
},
},
{ test: function () {
// Commit composition
synthesizeComposition({ type: "compositioncommitasis" });
},
check: function () {
is(getValue(aEditor), "ABGHIef", description + "Commit 'GHI'");
},
},
];
var index = 0;
function doReframe(aEvent)
{
aEvent.target.style.overflow =
aEvent.target.style.overflow != "hidden" ? "hidden" : "auto";
}
aEditor.focus();
aEditor.addEventListener(aEventType, doReframe);
function doNext()
{
if (tests.length <= index) {
aEditor.style.overflow = "auto";
aEditor.removeEventListener(aEventType, doReframe);
requestAnimationFrame(function() { setTimeout(aNextTest); });
return;
}
tests[index].test();
hitEventLoop(function () {
tests[index].check();
index++;
setTimeout(doNext, 0);
}, 20);
}
doNext();
}
input.value = "";
runEditorReframeTest(input, window, "input", function () {
input.value = "";
runEditorReframeTest(input, window, "compositionupdate", function () {
textarea.value = "";
runEditorReframeTest(textarea, window, "input", function () {
textarea.value = "";
runEditorReframeTest(textarea, window, "compositionupdate", function () {
contenteditable.innerHTML = "";
runEditorReframeTest(contenteditable, windowOfContenteditable, "input", function () {
contenteditable.innerHTML = "";
runEditorReframeTest(contenteditable, windowOfContenteditable, "compositionupdate", function () {
aCallback();
});
});
});
});
});
});
}
function runTest()
{
contenteditable = document.getElementById("iframe4").contentDocument.getElementById("contenteditable");
windowOfContenteditable = document.getElementById("iframe4").contentWindow;
textareaInFrame = iframe.contentDocument.getElementById("textarea");
runUndoRedoTest();
runCompositionCommitAsIsTest();
runCompositionCommitTest();
runCompositionTest();
runCompositionEventTest();
runCharAtPointTest(textarea, "textarea in the document");
runCharAtPointAtOutsideTest();
runSetSelectionEventTest();
runQueryTextContentEventTest();
runCSSTransformTest();
runBug722639Test();
runForceCommitTest();
runNestedSettingValue();
runBug811755Test();
runIsComposingTest();
runRedundantChangeTest();
runNotRedundantChangeTest();
runControlCharTest();
runEditorReframeTests(function () {
runAsyncForceCommitTest(function () {
runRemoveContentTest(function () {
runFrameTest();
runPanelTest();
runMaxLengthTest();
});
});
});
}
]]>
</script>
</window>