Bug 722961 Add tests for autocomplete with composition r=m_kato

This commit is contained in:
Masayuki Nakano 2012-03-27 23:22:56 +09:00
parent 9db2c07418
commit 0582e6722b
7 changed files with 838 additions and 100 deletions

View File

@ -65,7 +65,6 @@ _TEST_FILES = \
test_bug645914.html \
test_bug681229.html \
test_bug692520.html \
test_bug717147.html \
test_dom_input_event_on_texteditor.html \
$(NULL)

View File

@ -1,99 +0,0 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=717147
-->
<head>
<title>Test for Bug 717147</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717147">Mozilla Bug 717147</a>
<p id="display"></p>
<div id="content">
<iframe id="formTarget" name="formTarget"></iframe>
<form action="data:text/html," target="formTarget">
<input name="test" id="initValue"><input type="submit">
</form>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 717147 **/
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(function() {
var formTarget = document.getElementById("formTarget");
var initValue = document.getElementById("initValue");
formTarget.addEventListener("load", function() {
var newInput = document.createElement("input");
newInput.setAttribute("name", "test");
document.body.appendChild(newInput);
setTimeout(function() {
var popupShown = false;
function listener() {
popupShown = true;
}
SpecialPowers.addAutoCompletePopupEventListener(window, listener);
newInput.value = "";
newInput.focus();
synthesizeComposition({ type: "compositionstart" });
synthesizeComposition({ type: "compositionupdate", data: "f" });
synthesizeText(
{ "composition":
{ "string": "f",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 1, "length": 0 }
});
hitEventLoop(function() {
ok(!popupShown, "Popup must not be opened during composition");
synthesizeText(
{ "composition":
{ "string": "f",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 1, "length": 0 }
});
synthesizeComposition({ type: "compositionend", data: "f" });
hitEventLoop(function () {
ok(popupShown, "Popup must be opened after compositionend");
SpecialPowers.removeAutoCompletePopupEventListener(window, listener);
SimpleTest.finish();
}, 100);
}, 100);
}, 0);
}, false);
initValue.focus();
initValue.value = "foo";
synthesizeKey("VK_ENTER", {});
});
function hitEventLoop(func, times) {
if (times > 0) {
setTimeout(hitEventLoop, 0, func, times - 1);
} else {
setTimeout(func, 0);
}
}
</script>
</pre>
</body>
</html>

View File

@ -704,6 +704,18 @@ SpecialPowersAPI.prototype = {
listener,
false);
},
getFormFillController: function(window) {
return Components.classes["@mozilla.org/satchel/form-fill-controller;1"]
.getService(Components.interfaces.nsIFormFillController);
},
attachFormFillControllerTo: function(window) {
this.getFormFillController()
.attachToBrowser(this._getDocShell(window),
this._getAutoCompletePopup(window));
},
detachFormFillControllerFrom: function(window) {
this.getFormFillController().detachFromBrowser(this._getDocShell(window));
},
isBackButtonEnabled: function(window) {
return !this._getTopChromeWindow(window).document
.getElementById("Browser:Back")

View File

@ -89,6 +89,9 @@ _TEST_FILES = findbar_window.xul \
test_autocomplete4.xul \
test_autocomplete5.xul \
test_autocomplete_delayOnPaste.xul \
file_autocomplete_with_composition.js \
test_autocomplete_with_composition_on_input.html \
test_autocomplete_with_composition_on_textbox.xul \
test_keys.xul \
window_keys.xul \
test_showcaret.xul \

View File

@ -0,0 +1,633 @@
// nsDoTestsForAutoCompleteWithComposition tests autocomplete with composition.
// Users must include SimpleTest.js and EventUtils.js.
function nsDoTestsForAutoCompleteWithComposition(aDescription,
aWindow,
aTarget,
aAutoCompleteController,
aIsFunc,
aGetTargetValueFunc,
aOnFinishFunc)
{
this._description = aDescription;
this._window = aWindow;
this._target = aTarget;
this._controller = aAutoCompleteController;
this._is = aIsFunc;
this._getTargetValue = aGetTargetValueFunc;
this._onFinish = aOnFinishFunc;
this._target.focus();
this._DefaultCompleteDefaultIndex =
this._controller.input.completeDefaultIndex;
this._doTests();
}
nsDoTestsForAutoCompleteWithComposition.prototype = {
_window: null,
_target: null,
_controller: null,
_DefaultCompleteDefaultIndex: false,
_description: "",
_is: null,
_getTargetValue: function () { return "not initialized"; },
_onFinish: null,
_doTests: function ()
{
if (++this._testingIndex == this._tests.length) {
this._controller.input.completeDefaultIndex =
this._DefaultCompleteDefaultIndex;
this._onFinish();
return;
}
var test = this._tests[this._testingIndex];
if (this._controller.input.completeDefaultIndex != test.completeDefaultIndex) {
this._controller.input.completeDefaultIndex = test.completeDefaultIndex;
}
test.execute(this._window);
var timeout = this._controller.input.timeout + 10;
this._waitResult(timeout);
},
_waitResult: function (aTimes)
{
var obj = this;
if (aTimes-- > 0) {
setTimeout(function () { obj._waitResult(aTimes); }, 0);
} else {
setTimeout(function () { obj._checkResult(); }, 0);
}
},
_checkResult: function ()
{
var test = this._tests[this._testingIndex];
this._is(this._getTargetValue(), test.value,
this._description + ", " + test.description + ": value");
this._is(this._controller.searchString, test.searchString,
this._description + ", " + test.description +": searchString");
this._is(this._controller.input.popupOpen, test.popup,
this._description + ", " + test.description + ": popupOpen");
this._doTests();
},
_testingIndex: -1,
_tests: [
// Simple composition when popup hasn't been shown.
// The autocomplete popup should not be shown during composition, but
// after compositionend, the popup should be shown.
{ description: "compositionstart shouldn't open the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeKey("m", { type: "keydown", shiftKey: true }, aWindow);
synthesizeComposition({ type: "compositionstart" }, aWindow);
synthesizeComposition({ type: "compositionupdate", data: "M" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "M",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 1, "length": 0 }
}, aWindow);
}, popup: false, value: "M", searchString: ""
},
{ description: "compositionupdate shouldn't open the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeComposition({ type: "compositionupdate", data: "Mo" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "Mo",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 2, "length": 0 }
}, aWindow);
}, popup: false, value: "Mo", searchString: ""
},
{ description: "compositionend should open the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeText(
{ "composition":
{ "string": "Mo",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 2, "length": 0 }
}, aWindow);
synthesizeComposition({ type: "compositionend", data: "Mo" }, aWindow);
synthesizeKey("VK_ENTER", { type: "keyup" }, aWindow);
}, popup: true, value: "Mo", searchString: "Mo"
},
// If composition starts when popup is shown, the compositionstart event
// should cause closing the popup.
{ description: "compositionstart should close the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeKey("z", { type: "keydown" }, aWindow);
synthesizeComposition({ type: "compositionstart" }, aWindow);
synthesizeComposition({ type: "compositionupdate", data: "z" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "z",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 1, "length": 0 }
}, aWindow);
}, popup: false, value: "Moz", searchString: "Mo"
},
{ description: "compositionupdate shouldn't reopen the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeComposition({ type: "compositionupdate", data: "zi" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "zi",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 2, "length": 0 }
}, aWindow);
}, popup: false, value: "Mozi", searchString: "Mo"
},
{ description: "compositionend should research the result and open the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeText(
{ "composition":
{ "string": "zi",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 2, "length": 0 }
});
synthesizeComposition({ type: "compositionend", data: "zi" }, aWindow);
synthesizeKey("VK_ENTER", { type: "keyup" }, aWindow);
}, popup: true, value: "Mozi", searchString: "Mozi"
},
// If composition is cancelled, the value shouldn't be changed.
{ description: "compositionstart should reclose the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeKey("l", { type: "keydown" }, aWindow);
synthesizeComposition({ type: "compositionstart" }, aWindow);
synthesizeComposition({ type: "compositionupdate", data: "l" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "l",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 1, "length": 0 }
}, aWindow);
}, popup: false, value: "Mozil", searchString: "Mozi"
},
{ description: "compositionupdate shouldn't reopen the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeComposition({ type: "compositionupdate", data: "ll" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "ll",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 2, "length": 0 }
}, aWindow);
}, popup: false, value: "Mozill", searchString: "Mozi"
},
{ description: "empty compositionupdate shouldn't reopen the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeComposition({ type: "compositionupdate", data: "" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 0, "length": 0 }
}, aWindow);
}, popup: false, value: "Mozi", searchString: "Mozi"
},
{ description: "cancled compositionend should reopen the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeText(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 0, "length": 0 }
}, aWindow);
synthesizeComposition({ type: "compositionend", data: "" }, aWindow);
synthesizeKey("VK_ESCAPE", { type: "keyup" }, aWindow);
}, popup: true, value: "Mozi", searchString: "Mozi"
},
// But if composition replaces some characters and canceled, the search
// string should be the latest value.
{ description: "compositionstart with selected string should close the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeKey("VK_LEFT", { shiftKey: true }, aWindow);
synthesizeKey("VK_LEFT", { shiftKey: true }, aWindow);
synthesizeKey("z", { type: "keydown" }, aWindow);
synthesizeComposition({ type: "compositionstart" }, aWindow);
synthesizeComposition({ type: "compositionupdate", data: "z" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "z",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 1, "length": 0 }
}, aWindow);
}, popup: false, value: "Moz", searchString: "Mozi"
},
{ description: "compositionupdate shouldn't reopen the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeComposition({ type: "compositionupdate", data: "ll" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "zi",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 2, "length": 0 }
}, aWindow);
}, popup: false, value: "Mozi", searchString: "Mozi"
},
{ description: "empty compositionupdate shouldn't reopen the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeComposition({ type: "compositionupdate", data: "" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 0, "length": 0 }
}, aWindow);
}, popup: false, value: "Mo", searchString: "Mozi"
},
{ description: "canceled compositionend should seach the result with the latest value",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeText(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 0, "length": 0 }
}, aWindow);
synthesizeComposition({ type: "compositionend", data: "" }, aWindow);
synthesizeKey("VK_ESCAPE", { type: "keyup" }, aWindow);
}, popup: true, value: "Mo", searchString: "Mo"
},
//If all characters are removed, the popup should be closed.
{ description: "the value becomes empty by backspace, the popup should be closed",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeKey("VK_BACK_SPACE", {}, aWindow);
synthesizeKey("VK_BACK_SPACE", {}, aWindow);
}, popup: false, value: "", searchString: ""
},
// composition which is canceled shouldn't cause opening the popup.
{ description: "compositionstart shouldn't open the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeKey("m", { type: "keydown", shiftKey: true }, aWindow);
synthesizeComposition({ type: "compositionstart" }, aWindow);
synthesizeComposition({ type: "compositionupdate", data: "M" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "M",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 1, "length": 0 }
}, aWindow);
}, popup: false, value: "M", searchString: ""
},
{ description: "compositionupdate shouldn't open the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeComposition({ type: "compositionupdate", data: "Mo" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "Mo",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 2, "length": 0 }
}, aWindow);
}, popup: false, value: "Mo", searchString: ""
},
{ description: "empty compositionupdate shouldn't open the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeComposition({ type: "compositionupdate", data: "" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 0, "length": 0 }
}, aWindow);
}, popup: false, value: "", searchString: ""
},
{ description: "canceled compositionend shouldn't open the popup if it was closed",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeText(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 0, "length": 0 }
}, aWindow);
synthesizeComposition({ type: "compositionend", data: "" }, aWindow);
synthesizeKey("VK_ESCAPE", { type: "keyup" }, aWindow);
}, popup: false, value: "", searchString: ""
},
// Down key should open the popup even if the editor is empty.
{ description: "DOWN key should open the popup even if the value is empty",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeKey("VK_DOWN", {}, aWindow);
}, popup: true, value: "", searchString: ""
},
// If popup is open at starting composition, the popup should be reopened
// after composition anyway.
{ description: "compositionstart shouldn't open the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeKey("m", { type: "keydown", shiftKey: true }, aWindow);
synthesizeComposition({ type: "compositionstart" }, aWindow);
synthesizeComposition({ type: "compositionupdate", data: "M" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "M",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 1, "length": 0 }
}, aWindow);
}, popup: false, value: "M", searchString: ""
},
{ description: "compositionupdate shouldn't open the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeComposition({ type: "compositionupdate", data: "Mo" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "Mo",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 2, "length": 0 }
}, aWindow);
}, popup: false, value: "Mo", searchString: ""
},
{ description: "empty compositionupdate shouldn't open the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeComposition({ type: "compositionupdate", data: "" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 0, "length": 0 }
}, aWindow);
}, popup: false, value: "", searchString: ""
},
{ description: "canceled compositionend should open the popup if it was opened",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeText(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 0, "length": 0 }
}, aWindow);
synthesizeComposition({ type: "compositionend", data: "" }, aWindow);
synthesizeKey("VK_ESCAPE", { type: "keyup" }, aWindow);
}, popup: true, value: "", searchString: ""
},
// Type normally, and hit escape, the popup should be closed.
{ description: "ESCAPE should close the popup after typing something",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeKey("M", { shiftKey: true }, aWindow);
synthesizeKey("o", { shiftKey: true }, aWindow);
synthesizeKey("VK_ESCAPE", {}, aWindow);
}, popup: false, value: "Mo", searchString: "Mo"
},
// Even if the popup is closed, composition which is canceled should open
// the popup if the value isn't empty.
// XXX This might not be good behavior, but anyway, this is minor issue...
{ description: "compositionstart shouldn't open the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeKey("z", { type: "keydown", shiftKey: true }, aWindow);
synthesizeComposition({ type: "compositionstart" }, aWindow);
synthesizeComposition({ type: "compositionupdate", data: "z" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "z",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 1, "length": 0 }
}, aWindow);
}, popup: false, value: "Moz", searchString: "Mo"
},
{ description: "compositionupdate shouldn't open the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeComposition({ type: "compositionupdate", data: "zi" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "zi",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 2, "length": 0 }
}, aWindow);
}, popup: false, value: "Mozi", searchString: "Mo"
},
{ description: "empty compositionupdate shouldn't open the popup",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeComposition({ type: "compositionupdate", data: "" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 0, "length": 0 }
}, aWindow);
}, popup: false, value: "Mo", searchString: "Mo"
},
{ description: "canceled compositionend shouldn't open the popup if the popup was closed",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeText(
{ "composition":
{ "string": "",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 0, "length": 0 }
}, aWindow);
synthesizeComposition({ type: "compositionend", data: "" }, aWindow);
synthesizeKey("VK_ESCAPE", { type: "keyup" }, aWindow);
}, popup: true, value: "Mo", searchString: "Mo"
},
// House keeping...
{ description: "house keeping for next tests",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeKey("VK_BACK_SPACE", {}, aWindow);
synthesizeKey("VK_BACK_SPACE", {}, aWindow);
}, popup: false, value: "", searchString: ""
},
// Testing for nsIAutoCompleteInput.completeDefaultIndex being true.
{ description: "compositionstart shouldn't open the popup (completeDefaultIndex is true)",
completeDefaultIndex: true,
execute: function (aWindow) {
synthesizeKey("m", { type: "keydown", shiftKey: true }, aWindow);
synthesizeComposition({ type: "compositionstart" }, aWindow);
synthesizeComposition({ type: "compositionupdate", data: "M" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "M",
"clauses":
[
{ "length": 1, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 1, "length": 0 }
}, aWindow);
}, popup: false, value: "M", searchString: ""
},
{ description: "compositionupdate shouldn't open the popup (completeDefaultIndex is true)",
completeDefaultIndex: true,
execute: function (aWindow) {
synthesizeComposition({ type: "compositionupdate", data: "Mo" }, aWindow);
synthesizeText(
{ "composition":
{ "string": "Mo",
"clauses":
[
{ "length": 2, "attr": COMPOSITION_ATTR_RAWINPUT }
]
},
"caret": { "start": 2, "length": 0 }
}, aWindow);
}, popup: false, value: "Mo", searchString: ""
},
{ description: "compositionend should open the popup (completeDefaultIndex is true)",
completeDefaultIndex: true,
execute: function (aWindow) {
synthesizeText(
{ "composition":
{ "string": "Mo",
"clauses":
[
{ "length": 0, "attr": 0 }
]
},
"caret": { "start": 2, "length": 0 }
}, aWindow);
synthesizeComposition({ type: "compositionend", data: "Mo" }, aWindow);
synthesizeKey("VK_ENTER", { type: "keyup" }, aWindow);
}, popup: true, value: "Mozilla", searchString: "Mo"
},
// House keeping...
{ description: "house keeping for next tests",
completeDefaultIndex: false,
execute: function (aWindow) {
synthesizeKey("VK_BACK_SPACE", {}, aWindow);
synthesizeKey("VK_BACK_SPACE", {}, aWindow);
synthesizeKey("VK_BACK_SPACE", {}, aWindow);
synthesizeKey("VK_BACK_SPACE", {}, aWindow);
synthesizeKey("VK_BACK_SPACE", {}, aWindow);
synthesizeKey("VK_BACK_SPACE", {}, aWindow);
}, popup: false, value: "", searchString: ""
}
]
};

View File

@ -0,0 +1,65 @@
<!DOCTYPE HTML>
<html>
<head>
<title>autocomplete with composition tests on HTML input element</title>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/ChromeUtils.js"></script>
<script type="text/javascript" src="file_autocomplete_with_composition.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content">
<iframe id="formTarget" name="formTarget"></iframe>
<form action="data:text/html," target="formTarget">
<input name="test" id="input"><input type="submit">
</form>
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
function runTests()
{
var formFillController =
SpecialPowers.getFormFillController()
.QueryInterface(Components.interfaces.nsIAutoCompleteInput);
var originalFormFillTimeout = formFillController.timeout;
SpecialPowers.attachFormFillControllerTo(window);
var target = document.getElementById("input");
// Register a word to the form history.
target.focus();
target.value = "Mozilla";
synthesizeKey("VK_ENTER", {});
target.value = "";
var test1 = new nsDoTestsForAutoCompleteWithComposition(
"Testing on HTML input (asynchronously search)",
window, target, formFillController.controller, is,
function () { return target.value; },
function () {
target.setAttribute("timeout", 0);
var test2 = new nsDoTestsForAutoCompleteWithComposition(
"Testing on HTML input (synchronously search)",
window, target, formFillController.controller, is,
function () { return target.value; },
function () {
formFillController.timeout = originalFormFillTimeout;
SpecialPowers.detachFormFillControllerFrom(window);
SimpleTest.finish();
});
});
}
SimpleTest.waitForFocus(runTests);
</script>
</pre>
</body>
</html>

View File

@ -0,0 +1,125 @@
<?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 autocomplete with composition"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<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 type="text/javascript"
src="file_autocomplete_with_composition.js" />
<textbox id="textbox" type="autocomplete"
autocompletesearch="simpleForComposition"/>
<body xmlns="http://www.w3.org/1999/xhtml">
<div id="content" style="display: none">
</div>
<pre id="test">
</pre>
</body>
<script class="testbody" type="application/javascript">
<![CDATA[
SimpleTest.waitForExplicitFinish();
const nsIAutoCompleteResult = Components.interfaces.nsIAutoCompleteResult;
// This result can't be constructed in-line, because otherwise we leak memory.
function nsAutoCompleteSimpleResult(aString)
{
this.searchString = aString;
if (aString == "" || aString == "Mozilla".substr(0, aString.length)) {
this.searchResult = nsIAutoCompleteResult.RESULT_SUCCESS;
this.matchCount = 1;
this._value = "Mozilla";
} else {
this.searchResult = nsIAutoCompleteResult.RESULT_NOMATCH;
this.matchCount = 0;
this._value = "";
}
}
nsAutoCompleteSimpleResult.prototype = {
_value: "",
searchString: null,
searchResult: nsIAutoCompleteResult.RESULT_FAILURE,
defaultIndex: 0,
errorDescription: null,
matchCount: 0,
getValueAt: function(aIndex) { return aIndex == 0 ? this._value : null; },
getCommentAt: function() { return null; },
getStyleAt: function() { return null; },
getImageAt: function() { return null; },
getLabelAt: function() { return null; },
removeValueAt: function() {}
};
// A basic autocomplete implementation that either returns one result or none
var autoCompleteSimpleID =
Components.ID("0a2afbdb-f30e-47d1-9cb1-0cd160240aca");
var autoCompleteSimpleName =
"@mozilla.org/autocomplete/search;1?name=simpleForComposition"
var autoCompleteSimple = {
QueryInterface: function(iid) {
if (iid.equals(Components.interfaces.nsISupports) ||
iid.equals(Components.interfaces.nsIFactory) ||
iid.equals(Components.interfaces.nsIAutoCompleteSearch))
return this;
throw Components.results.NS_ERROR_NO_INTERFACE;
},
createInstance: function(outer, iid) {
return this.QueryInterface(iid);
},
startSearch: function(aString, aParam, aResult, aListener) {
var result = new nsAutoCompleteSimpleResult(aString);
aListener.onSearchResult(this, result);
},
stopSearch: function() {}
};
var componentManager =
Components.manager
.QueryInterface(Components.interfaces.nsIComponentRegistrar);
componentManager.registerFactory(autoCompleteSimpleID,
"Test Simple Autocomplete for composition",
autoCompleteSimpleName, autoCompleteSimple);
function runTests()
{
var target = document.getElementById("textbox");
target.setAttribute("timeout", 1);
var test1 = new nsDoTestsForAutoCompleteWithComposition(
"Testing on XUL textbox (asynchronously search)",
window, target, target.controller, is,
function () { return target.value; },
function () {
target.setAttribute("timeout", 0);
var test2 = new nsDoTestsForAutoCompleteWithComposition(
"Testing on XUL textbox (synchronously search)",
window, target, target.controller, is,
function () { return target.value; },
function () {
// Unregister the factory so that we don't get in the way of other
// tests
componentManager.unregisterFactory(autoCompleteSimpleID,
autoCompleteSimple);
SimpleTest.finish();
});
});
}
SimpleTest.waitForFocus(runTests);
]]>
</script>
</window>