mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-09-30 03:58:07 +00:00
310 lines
9.9 KiB
XML
310 lines
9.9 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="Autocomplete Widget Test"
|
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
|
onload="runTest();">
|
|
|
|
<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="application/javascript"
|
|
src="chrome://global/content/globalOverlay.js"/>
|
|
|
|
<textbox id="autocomplete"
|
|
type="autocomplete"
|
|
completedefaultindex="true"
|
|
timeout="0"
|
|
autocompletesearch="simple"/>
|
|
|
|
<script class="testbody" type="application/javascript">
|
|
<![CDATA[
|
|
|
|
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
|
|
function autoCompleteSimpleResult(aString, searchId) {
|
|
this.searchString = aString;
|
|
this.searchResult = Components.interfaces.nsIAutoCompleteResult.RESULT_SUCCESS;
|
|
this.matchCount = 1;
|
|
if (aString.startsWith('ret')) {
|
|
this._param = autoCompleteSimpleResult.retireCompletion;
|
|
} else {
|
|
this._param = "Result";
|
|
}
|
|
this._searchId = searchId;
|
|
}
|
|
autoCompleteSimpleResult.retireCompletion = "Retire";
|
|
autoCompleteSimpleResult.prototype = {
|
|
_param: "",
|
|
searchString: null,
|
|
searchResult: Components.interfaces.nsIAutoCompleteResult.RESULT_FAILURE,
|
|
defaultIndex: 0,
|
|
errorDescription: null,
|
|
matchCount: 0,
|
|
getValueAt: function() { return this._param; },
|
|
getCommentAt: function() { return null; },
|
|
getStyleAt: function() { return null; },
|
|
getImageAt: function() { return null; },
|
|
getLabelAt: function() { return null; },
|
|
removeValueAt: function() {}
|
|
};
|
|
|
|
var searchCounter = 0;
|
|
|
|
// A basic autocomplete implementation that returns one result.
|
|
let autoCompleteSimple = {
|
|
classID: Components.ID("0a2afbdb-f30e-47d1-9cb1-0cd160240aca"),
|
|
contractID: "@mozilla.org/autocomplete/search;1?name=simple",
|
|
searchAsync: false,
|
|
pendingSearch: null,
|
|
|
|
QueryInterface: XPCOMUtils.generateQI([
|
|
Components.interfaces.nsIFactory,
|
|
Components.interfaces.nsIAutoCompleteSearch
|
|
]),
|
|
createInstance: function (outer, iid) {
|
|
return this.QueryInterface(iid);
|
|
},
|
|
|
|
registerFactory: function () {
|
|
let registrar =
|
|
Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
|
|
registrar.registerFactory(this.classID, "Test Simple Autocomplete",
|
|
this.contractID, this);
|
|
},
|
|
unregisterFactory: function () {
|
|
let registrar =
|
|
Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
|
|
registrar.unregisterFactory(this.classID, this);
|
|
},
|
|
|
|
startSearch: function (aString, aParam, aResult, aListener) {
|
|
let result = new autoCompleteSimpleResult(aString);
|
|
|
|
if (this.searchAsync) {
|
|
// Simulate an async search by using a timeout before invoking the
|
|
// |onSearchResult| callback.
|
|
// Store the searchTimeout such that it can be canceled if stopSearch is called.
|
|
this.pendingSearch = setTimeout(() => {
|
|
this.pendingSearch = null;
|
|
|
|
aListener.onSearchResult(this, result);
|
|
|
|
// Move to the next step in the async test.
|
|
asyncTest.next();
|
|
}, 0);
|
|
} else {
|
|
aListener.onSearchResult(this, result);
|
|
}
|
|
},
|
|
stopSearch: function () {
|
|
clearTimeout(this.pendingSearch);
|
|
}
|
|
};
|
|
|
|
SimpleTest.waitForExplicitFinish();
|
|
|
|
// XPFE AutoComplete needs to register early.
|
|
autoCompleteSimple.registerFactory();
|
|
|
|
let gACTimer;
|
|
let gAutoComplete;
|
|
let asyncTest;
|
|
|
|
let searchCompleteTimeoutId = null;
|
|
|
|
function finishTest() {
|
|
// Unregister the factory so that we don't get in the way of other tests
|
|
autoCompleteSimple.unregisterFactory();
|
|
SimpleTest.finish();
|
|
}
|
|
|
|
function runTest() {
|
|
gAutoComplete = $("autocomplete");
|
|
gAutoComplete.focus();
|
|
|
|
// Return the search results synchronous, which also makes the completion
|
|
// happen synchronous.
|
|
autoCompleteSimple.searchAsync = false;
|
|
|
|
synthesizeKey("r", {});
|
|
is(gAutoComplete.value, "result", "Value should be autocompleted immediately");
|
|
|
|
synthesizeKey("e", {});
|
|
is(gAutoComplete.value, "result", "Value should be autocompleted immediately");
|
|
|
|
synthesizeKey("VK_DELETE", {});
|
|
is(gAutoComplete.value, "re", "Deletion should not complete value");
|
|
|
|
synthesizeKey("VK_BACK_SPACE", {});
|
|
is(gAutoComplete.value, "r", "Backspace should not complete value");
|
|
|
|
synthesizeKey("VK_LEFT", {});
|
|
is(gAutoComplete.value, "r", "Value should stay same when navigating with cursor");
|
|
|
|
runAsyncTest();
|
|
}
|
|
|
|
function* asyncTestGenerator() {
|
|
synthesizeKey("r", {});
|
|
synthesizeKey("e", {});
|
|
is(gAutoComplete.value, "re", "Value should not be autocompleted immediately");
|
|
|
|
// Calling |yield undefined| makes this generator function wait until
|
|
// |asyncTest.next();| is called. This happens from within the
|
|
// |autoCompleteSimple.startSearch()| function once the simulated async
|
|
// search has finished.
|
|
// Therefore, the effect of the |yield undefined;| here (and the ones) below
|
|
// is to wait until the async search result comes back.
|
|
yield undefined;
|
|
|
|
is(gAutoComplete.value, "result", "Value should be autocompleted");
|
|
|
|
// Test if typing the `s` character completes directly based on the last
|
|
// completion
|
|
synthesizeKey("s", {});
|
|
is(gAutoComplete.value, "result", "Value should be completed immediately");
|
|
|
|
yield undefined;
|
|
|
|
is(gAutoComplete.value, "result", "Value should be autocompleted to same value");
|
|
synthesizeKey("VK_DELETE", {});
|
|
is(gAutoComplete.value, "res", "Deletion should not complete value");
|
|
|
|
// No |yield undefined| needed here as no completion is triggered by the deletion.
|
|
|
|
is(gAutoComplete.value, "res", "Still no complete value after deletion");
|
|
|
|
synthesizeKey("VK_BACK_SPACE", {});
|
|
is(gAutoComplete.value, "re", "Backspace should not complete value");
|
|
|
|
yield undefined;
|
|
|
|
is(gAutoComplete.value, "re", "Value after search due to backspace should stay the same"); (3)
|
|
|
|
// Typing a character that is not like the previous match. In this case, the
|
|
// completion cannot happen directly and therefore the value will be completed
|
|
// only after the search has finished.
|
|
synthesizeKey("t", {});
|
|
is(gAutoComplete.value, "ret", "Value should not be autocompleted immediately");
|
|
|
|
yield undefined;
|
|
|
|
is(gAutoComplete.value, "retire", "Value should be autocompleted");
|
|
|
|
synthesizeKey("i", {});
|
|
is(gAutoComplete.value, "retire", "Value should be autocompleted immediately");
|
|
|
|
yield undefined;
|
|
|
|
is(gAutoComplete.value, "retire", "Value should be autocompleted to the same value");
|
|
|
|
// Setup the scene to test how the completion behaves once the placeholder
|
|
// completion and the result from the search do not agree with each other.
|
|
gAutoComplete.value = 'r';
|
|
// Need to type two characters as the input was reset and the autocomplete
|
|
// controller things, ther user hit the backspace button, in which case
|
|
// no completion is performed. But as a completion is desired, another
|
|
// character `t` is typed afterwards.
|
|
synthesizeKey("e", {});
|
|
yield undefined;
|
|
synthesizeKey("t", {});
|
|
is(gAutoComplete.value, "ret", "Value should not be autocompleted");
|
|
|
|
yield undefined;
|
|
|
|
is(gAutoComplete.value, "retire", "Value should be autocompleted");
|
|
|
|
// The placeholder string is now set to "retire". Changing the completion
|
|
// string to "retirement" and see what the completion will turn out like.
|
|
autoCompleteSimpleResult.retireCompletion = "Retirement";
|
|
synthesizeKey("i", {});
|
|
is(gAutoComplete.value, "retire", "Value should be autocompleted based on placeholder");
|
|
|
|
yield undefined;
|
|
|
|
is(gAutoComplete.value, "retirement", "Value should be autocompleted based on search result");
|
|
|
|
// Change the search result to `Retire` again and see if the new result is
|
|
// complited.
|
|
autoCompleteSimpleResult.retireCompletion = "Retire";
|
|
synthesizeKey("r", {});
|
|
is(gAutoComplete.value, "retirement", "Value should be autocompleted based on placeholder");
|
|
|
|
yield undefined;
|
|
|
|
is(gAutoComplete.value, "retire", "Value should be autocompleted based on search result");
|
|
|
|
// Complete the value
|
|
gAutoComplete.value = 're';
|
|
synthesizeKey("t", {});
|
|
yield undefined;
|
|
synthesizeKey("i", {});
|
|
is(gAutoComplete.value, "reti", "Value should not be autocompleted");
|
|
|
|
yield undefined;
|
|
|
|
is(gAutoComplete.value, "retire", "Value should be autocompleted");
|
|
|
|
// Remove the selected text "re" (1) and the "et" (2). Afterwards, add it again (3).
|
|
// This should not cause the completion to kick in.
|
|
synthesizeKey("VK_DELETE", {}); // (1)
|
|
|
|
is(gAutoComplete.value, "reti", "Value should not complete after deletion");
|
|
|
|
gAutoComplete.selectionStart = 1;
|
|
gAutoComplete.selectionEnd = 3;
|
|
synthesizeKey("VK_DELETE", {}); // (2)
|
|
|
|
is(gAutoComplete.value, "ri", "Value should stay unchanged after removing character in the middle");
|
|
|
|
yield undefined;
|
|
|
|
synthesizeKey("e", {}); // (3.1)
|
|
is(gAutoComplete.value, "rei", "Inserting a character in the middle should not complete the value");
|
|
|
|
yield undefined;
|
|
|
|
synthesizeKey("t", {}); // (3.2)
|
|
is(gAutoComplete.value, "reti", "Inserting a character in the middle should not complete the value");
|
|
|
|
yield undefined;
|
|
|
|
// Adding a new character at the end should not cause the completion to happen again
|
|
// as the completion failed before.
|
|
gAutoComplete.selectionStart = 4;
|
|
gAutoComplete.selectionEnd = 4;
|
|
synthesizeKey("r", {});
|
|
is(gAutoComplete.value, "retir", "Value should not be autocompleted immediately");
|
|
|
|
yield undefined;
|
|
|
|
is(gAutoComplete.value, "retire", "Value should be autocompleted");
|
|
|
|
finishTest();
|
|
yield undefined;
|
|
}
|
|
|
|
function runAsyncTest() {
|
|
gAutoComplete.value = '';
|
|
autoCompleteSimple.searchAsync = true;
|
|
|
|
asyncTest = asyncTestGenerator();
|
|
asyncTest.next();
|
|
}
|
|
]]>
|
|
</script>
|
|
|
|
<body xmlns="http://www.w3.org/1999/xhtml">
|
|
<p id="display">
|
|
</p>
|
|
<div id="content" style="display: none">
|
|
</div>
|
|
<pre id="test">
|
|
</pre>
|
|
</body>
|
|
|
|
</window>
|