Bug 970456 - "Be" doesn't autocomplete to my friend "Ben" in my compose window anymore (because I have frequently-contacted holBErt contacts, with "be" in the middle of their last name). r=neil, a=mkmelin
This commit is contained in:
Родитель
b553eaefce
Коммит
29d5933ce3
|
@ -124,6 +124,42 @@ nsAbAutoCompleteSearch.prototype = {
|
|||
return popularityIndex;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the score of the (full) address, given the search input. We want
|
||||
* results that match the beginning of a "word" in the result to score better
|
||||
* than a result that matches only in the middle of the word.
|
||||
*
|
||||
* @param aAddress - full lower-cased address, including display name and address
|
||||
* @param aSearchString - search string provided by user
|
||||
* @return a score; a higher score is better than a lower one
|
||||
*/
|
||||
_getScore: function(aAddress, aSearchString) {
|
||||
const BEST = 100;
|
||||
// We'll do this case-insensitively and ignore the domain.
|
||||
let atIdx = aAddress.lastIndexOf("@");
|
||||
if (atIdx != -1) // mail lists don't have an @
|
||||
aAddress = aAddress.substr(0, atIdx);
|
||||
aSearchString = aSearchString.toLocaleLowerCase();
|
||||
let idx = aAddress.indexOf(aSearchString);
|
||||
if (idx == 0)
|
||||
return BEST;
|
||||
if (idx == -1)
|
||||
return 0;
|
||||
|
||||
// We want to treat firstname, lastname and word boundary(ish) parts of
|
||||
// the email address the same. E.g. for "John Doe (:xx) <jd.who@example.com>"
|
||||
// all of these should score (almost) the same: "John", "Doe", "xx",
|
||||
// ":xx:", "jd", "who".
|
||||
let prevCh = aAddress.charAt(idx - 1);
|
||||
if (/[ :."'(\-_<&]/.test(prevCh)) {
|
||||
// -1, so exact begins-with match will still be the first hit.
|
||||
return BEST - 1;
|
||||
}
|
||||
|
||||
// The match was inside a word -> we don't care about the position.
|
||||
return 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Searches cards in the given directory. If a card is matched (and isn't
|
||||
* a mailing list) then the function will add a result for each email address
|
||||
|
@ -201,30 +237,26 @@ nsAbAutoCompleteSearch.prototype = {
|
|||
*
|
||||
* @param directory The directory that the card is in.
|
||||
* @param card The card that could be a duplicate.
|
||||
* @param emailAddress The emailAddress (name/address combination) to check
|
||||
* for duplicates against.
|
||||
* @param lcEmailAddress The emailAddress (name/address combination) to check
|
||||
* for duplicates against. Lowercased.
|
||||
* @param currentResults The current results list.
|
||||
*/
|
||||
_checkDuplicate: function _checkDuplicate(directory, card, emailAddress,
|
||||
currentResults) {
|
||||
let lcEmailAddress = emailAddress.toLocaleLowerCase();
|
||||
_checkDuplicate: function (directory, card, lcEmailAddress, currentResults) {
|
||||
let existingResult = currentResults._collectedValues.get(lcEmailAddress);
|
||||
if (!existingResult)
|
||||
return false;
|
||||
|
||||
let popIndex = this._getPopularityIndex(directory, card);
|
||||
|
||||
if (existingResult) {
|
||||
// It's a duplicate, is the new one more popular?
|
||||
if (popIndex > existingResult.popularity) {
|
||||
// Yes it is, so delete this element, return false and allow
|
||||
// _addToResult to sort the new element into the correct place.
|
||||
currentResults._collectedValues.delete(lcEmailAddress);
|
||||
return false;
|
||||
}
|
||||
// Not more popular, but still a duplicate. Return true and _addToResult
|
||||
// will just forget about it.
|
||||
return true;
|
||||
// It's a duplicate, is the new one more popular?
|
||||
if (popIndex > existingResult.popularity) {
|
||||
// Yes it is, so delete this element, return false and allow
|
||||
// _addToResult to sort the new element into the correct place.
|
||||
currentResults._collectedValues.delete(lcEmailAddress);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
// Not more popular, but still a duplicate. Return true and _addToResult
|
||||
// will just forget about it.
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -250,19 +282,21 @@ nsAbAutoCompleteSearch.prototype = {
|
|||
return;
|
||||
|
||||
let emailAddress = mbox.toString();
|
||||
let lcEmailAddress = emailAddress.toLocaleLowerCase();
|
||||
|
||||
// If it is a duplicate, then just return and don't add it. The
|
||||
// _checkDuplicate function deals with it all for us.
|
||||
if (this._checkDuplicate(directory, card, emailAddress, result))
|
||||
if (this._checkDuplicate(directory, card, lcEmailAddress, result))
|
||||
return;
|
||||
|
||||
result._collectedValues.set(emailAddress.toLocaleLowerCase(), {
|
||||
result._collectedValues.set(lcEmailAddress, {
|
||||
value: emailAddress,
|
||||
comment: commentColumn,
|
||||
card: card,
|
||||
isPrimaryEmail: isPrimaryEmail,
|
||||
emailToUse: emailToUse,
|
||||
popularity: this._getPopularityIndex(directory, card)
|
||||
popularity: this._getPopularityIndex(directory, card),
|
||||
score: this._getScore(lcEmailAddress, result.searchString)
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -361,15 +395,16 @@ nsAbAutoCompleteSearch.prototype = {
|
|||
}
|
||||
|
||||
result._searchResults = [...result._collectedValues.values()];
|
||||
// Order by descending popularity, then primary email before secondary
|
||||
// for the same card, then for differing cards sort by email.
|
||||
let order_by_popularity_and_email = function(a, b) {
|
||||
return (b.popularity - a.popularity) ||
|
||||
result._searchResults.sort(function(a, b) {
|
||||
// Order by 1) descending score, then 2) descending popularity,
|
||||
// then 3) primary email before secondary for the same card, then
|
||||
// 4) by differing cards sort by email.
|
||||
return (b.score - a.score) ||
|
||||
(b.popularity - a.popularity) ||
|
||||
((a.card == b.card && a.isPrimaryEmail) ? -1 : 0) ||
|
||||
((a.value < b.value) ? -1 : (a.value == b.value) ? 0 : 1);
|
||||
// TODO: this should actually use a.value.localeCompare(b.value) .
|
||||
}
|
||||
result._searchResults.sort(order_by_popularity_and_email);
|
||||
});
|
||||
}
|
||||
|
||||
if (result.matchCount) {
|
||||
|
|
|
@ -12,19 +12,19 @@ const ACR = Components.interfaces.nsIAutoCompleteResult;
|
|||
// on a pattern rather just doing the odd spot check.
|
||||
//
|
||||
// Note the expected arrays are in expected sort order as well.
|
||||
const results = [ { email: "d <ema@foo.invalid>", dirName: kPABData.dirName },
|
||||
{ email: "di <emai@foo.invalid>", dirName: kPABData.dirName },
|
||||
{ email: "dis <email@foo.invalid>", dirName: kPABData.dirName },
|
||||
{ email: "disp <e@foo.invalid>", dirName: kPABData.dirName },
|
||||
{ email: "displ <em@foo.invalid>", dirName: kPABData.dirName },
|
||||
{ email: "DisplayName1 <PrimaryEmail1@test.invalid>",
|
||||
const results = [ { email: "d <ema@foo.invalid>", dirName: kPABData.dirName }, // 0
|
||||
{ email: "di <emai@foo.invalid>", dirName: kPABData.dirName }, // 1
|
||||
{ email: "dis <email@foo.invalid>", dirName: kPABData.dirName }, // 2
|
||||
{ email: "disp <e@foo.invalid>", dirName: kPABData.dirName }, // 3
|
||||
{ email: "displ <em@foo.invalid>", dirName: kPABData.dirName }, // 4
|
||||
{ email: "DisplayName1 <PrimaryEmail1@test.invalid>", // 5
|
||||
dirName: kCABData.dirName },
|
||||
{ email: "t <list>", dirName: kPABData.dirName },
|
||||
{ email: "te <lis>", dirName: kPABData.dirName },
|
||||
{ email: "tes <li>", dirName: kPABData.dirName },
|
||||
{ email: "t <list>", dirName: kPABData.dirName }, // 6
|
||||
{ email: "te <lis>", dirName: kPABData.dirName }, // 7
|
||||
{ email: "tes <li>", dirName: kPABData.dirName }, // 8
|
||||
// this contact has a nickname of "abcdef"
|
||||
{ email: "test <l>", dirName: kPABData.dirName } ];
|
||||
|
||||
{ email: "test <l>", dirName: kPABData.dirName } // 9
|
||||
];
|
||||
const firstNames = [ { search: "f", expected: [5, 0, 1, 2, 3, 4, 9] },
|
||||
{ search: "fi", expected: [5, 0, 1, 3, 4] },
|
||||
{ search: "fir", expected: [5, 0, 1, 4] },
|
||||
|
@ -32,7 +32,7 @@ const firstNames = [ { search: "f", expected: [5, 0, 1, 2, 3, 4, 9] },
|
|||
{ search: "first", expected: [5, 1] },
|
||||
{ search: "firstn", expected: [5] } ];
|
||||
|
||||
const lastNames = [ { search: "l", expected: [5, 0, 1, 2, 3, 4, 6, 7, 8, 9] },
|
||||
const lastNames = [ { search: "l", expected: [6, 7, 8, 9, 5, 0, 1, 2, 3, 4] },
|
||||
{ search: "la", expected: [5, 0, 2, 3, 4] },
|
||||
{ search: "las", expected: [5, 0, 3, 4] },
|
||||
{ search: "last", expected: [5, 0, 4] },
|
||||
|
@ -53,20 +53,20 @@ const nickNames = [ { search: "n", expected: [5, 0, 1, 2, 3, 4] },
|
|||
{ search: "nickn", expected: [5, 3] },
|
||||
{ search: "nickna", expected: [5] } ];
|
||||
|
||||
const emails = [ { search: "e", expected: [5, 0, 1, 2, 3, 4, 7, 8, 9] },
|
||||
{ search: "em", expected: [5, 0, 1, 2, 4] },
|
||||
{ search: "ema", expected: [5, 0, 1, 2] },
|
||||
{ search: "emai", expected: [5, 1, 2] },
|
||||
{ search: "email", expected: [5, 2] } ];
|
||||
const emails = [ { search: "e", expected: [0, 1, 2, 3, 4, 5, 7, 8, 9] },
|
||||
{ search: "em", expected: [0, 1, 2, 4, 5] },
|
||||
{ search: "ema", expected: [0, 1, 2, 5] },
|
||||
{ search: "emai", expected: [1, 2, 5] },
|
||||
{ search: "email", expected: [2, 5] } ];
|
||||
|
||||
// "l" case tested above
|
||||
const lists = [ { search: "li", expected: [5, 0, 1, 2, 3, 4, 6, 7, 8] },
|
||||
const lists = [ { search: "li", expected: [6, 7, 8, 5, 0, 1, 2, 3, 4] },
|
||||
{ search: "lis", expected: [6, 7] },
|
||||
{ search: "list", expected: [6] },
|
||||
{ search: "t", expected: [5, 0, 1, 4, 6, 7, 8, 9] },
|
||||
{ search: "te", expected: [5, 7, 8, 9] },
|
||||
{ search: "tes", expected: [5, 8, 9] },
|
||||
{ search: "test", expected: [5, 9] },
|
||||
{ search: "t", expected: [6, 7, 8, 9, 5, 0, 1, 4] },
|
||||
{ search: "te", expected: [7, 8, 9, 5] },
|
||||
{ search: "tes", expected: [8, 9, 5] },
|
||||
{ search: "test", expected: [9, 5] },
|
||||
{ search: "abcdef", expected: [9] } // Bug 441586
|
||||
];
|
||||
|
||||
|
@ -172,8 +172,8 @@ function run_test() {
|
|||
do_check_eq(obs._result.matchCount, 2);
|
||||
do_check_eq(obs._result.defaultIndex, 0);
|
||||
|
||||
do_check_eq(obs._result.getValueAt(0), "DisplayName1 <PrimaryEmail1@test.invalid>");
|
||||
do_check_eq(obs._result.getLabelAt(0), "DisplayName1 <PrimaryEmail1@test.invalid>");
|
||||
do_check_eq(obs._result.getValueAt(0), "dis <email@foo.invalid>");
|
||||
do_check_eq(obs._result.getLabelAt(0), "dis <email@foo.invalid>");
|
||||
do_check_eq(obs._result.getCommentAt(0), "");
|
||||
do_check_eq(obs._result.getStyleAt(0), "local-abook");
|
||||
do_check_eq(obs._result.getImageAt(0), "");
|
||||
|
@ -198,9 +198,9 @@ function run_test() {
|
|||
do_check_eq(obs._result.matchCount, 2);
|
||||
do_check_eq(obs._result.defaultIndex, 0);
|
||||
|
||||
do_check_eq(obs._result.getValueAt(0), "DisplayName1 <PrimaryEmail1@test.invalid>");
|
||||
do_check_eq(obs._result.getLabelAt(0), "DisplayName1 <PrimaryEmail1@test.invalid>");
|
||||
do_check_eq(obs._result.getCommentAt(0), kCABData.dirName);
|
||||
do_check_eq(obs._result.getValueAt(0), "dis <email@foo.invalid>");
|
||||
do_check_eq(obs._result.getLabelAt(0), "dis <email@foo.invalid>");
|
||||
do_check_eq(obs._result.getCommentAt(0), kPABData.dirName);
|
||||
do_check_eq(obs._result.getStyleAt(0), "local-abook");
|
||||
do_check_eq(obs._result.getImageAt(0), "");
|
||||
|
||||
|
@ -214,18 +214,27 @@ function run_test() {
|
|||
do_check_eq(obs._result.matchCount, 2);
|
||||
do_check_eq(obs._result.defaultIndex, 0);
|
||||
|
||||
do_check_eq(obs._result.getValueAt(0), "DisplayName1 <PrimaryEmail1@test.invalid>");
|
||||
do_check_eq(obs._result.getLabelAt(0), "DisplayName1 <PrimaryEmail1@test.invalid>");
|
||||
do_check_eq(obs._result.getCommentAt(0), kCABData.dirName);
|
||||
do_check_eq(obs._result.getValueAt(0), "dis <email@foo.invalid>");
|
||||
do_check_eq(obs._result.getLabelAt(0), "dis <email@foo.invalid>");
|
||||
do_check_eq(obs._result.getCommentAt(0), kPABData.dirName);
|
||||
do_check_eq(obs._result.getStyleAt(0), "local-abook");
|
||||
do_check_eq(obs._result.getImageAt(0), "");
|
||||
|
||||
|
||||
// Now check multiple matches
|
||||
function checkInputItem(element, index, array) {
|
||||
print("Checking " + element.search);
|
||||
print("Search #" + index + ": search=" + element.search);
|
||||
acs.startSearch(element.search, param, null, obs);
|
||||
|
||||
for (var i = 0; i < obs._result.matchCount; i++) {
|
||||
print("... got " + i + ": " + obs._result.getValueAt(i));
|
||||
}
|
||||
|
||||
for (var i = 0; i < element.expected.length; i++) {
|
||||
print("... expected " + i + " (result " + element.expected[i] + "): " +
|
||||
results[element.expected[i]].email);
|
||||
}
|
||||
|
||||
do_check_eq(obs._search, acs);
|
||||
do_check_eq(obs._result.searchString, element.search);
|
||||
do_check_eq(obs._result.searchResult, ACR.RESULT_SUCCESS);
|
||||
|
|
|
@ -30,7 +30,7 @@ const cards = [
|
|||
];
|
||||
|
||||
const duplicates = [
|
||||
{ search: "test", expected: [2, 1] },
|
||||
{ search: "test", expected: [1, 2] },
|
||||
{ search: "first", expected: [6, 5, 3] },
|
||||
{ search: "(bracket)", expected: [7, 8] }
|
||||
];
|
||||
|
@ -80,18 +80,24 @@ function run_test()
|
|||
var obs = new acObserver();
|
||||
|
||||
function checkInputItem(element, index, array) {
|
||||
print("Checking " + element.search);
|
||||
print("Search #" + index + ": search=" + element.search);
|
||||
acs.startSearch(element.search, JSON.stringify({ type: "addr_to" }), null, obs);
|
||||
|
||||
for (var i = 0; i < obs._result.matchCount; i++) {
|
||||
print("... got " + i + ": " + obs._result.getValueAt(i));
|
||||
}
|
||||
|
||||
for (var i = 0; i < element.expected.length; i++) {
|
||||
print("... expected " + i + " (card " + element.expected[i] + "): " +
|
||||
cards[element.expected[i]].value);
|
||||
}
|
||||
|
||||
do_check_eq(obs._search, acs);
|
||||
do_check_eq(obs._result.searchString, element.search);
|
||||
do_check_eq(obs._result.searchResult, ACR.RESULT_SUCCESS);
|
||||
do_check_eq(obs._result.errorDescription, null);
|
||||
do_check_eq(obs._result.matchCount, element.expected.length);
|
||||
|
||||
for (var i = 0; i < element.expected.length; ++i)
|
||||
print(obs._result.getValueAt(i));
|
||||
|
||||
for (var i = 0; i < element.expected.length; ++i) {
|
||||
do_check_eq(obs._result.getValueAt(i), cards[element.expected[i]].value);
|
||||
do_check_eq(obs._result.getLabelAt(i), cards[element.expected[i]].value);
|
||||
|
|
|
@ -42,27 +42,27 @@ const searches = [ "primary", "second", "firstName", "thename", "sortbasic",
|
|||
"testsort", "2testsort", "3testsort" ];
|
||||
|
||||
const expectedResults = [ [ "primary@test.invalid",
|
||||
"second@test.invalid" ], // searching for primary/second returns
|
||||
[ "primary@test.invalid", // both the emails as the new search query
|
||||
"second@test.invalid" ], // looks in both the fields.
|
||||
"second@test.invalid"], // searching for primary/second returns
|
||||
[ "second@test.invalid", // both the emails as the new search query
|
||||
"primary@test.invalid" ], // looks in both the fields.
|
||||
[ "test1@test.invalid",
|
||||
"test2@test.invalid" ],
|
||||
[ "name@test.invalid",
|
||||
"thename@test.invalid" ],
|
||||
[ "thename@test.invalid",
|
||||
"name@test.invalid"],
|
||||
[ "sortbasic <foo_b@test.invalid>",
|
||||
"sortbasic <foo_a@test.invalid>" ],
|
||||
[ "3testsort <j@test.invalid>",
|
||||
[ "testsort <c@test.invalid>",
|
||||
"testsort <a@test.invalid>",
|
||||
"testsort <d@test.invalid>",
|
||||
"testsort <e@test.invalid>",
|
||||
"3testsort <j@test.invalid>",
|
||||
"3testsort <h@test.invalid>",
|
||||
"3testsort <g@test.invalid>",
|
||||
"3testsort <f@test.invalid>",
|
||||
"2testsort <c@test.invalid>",
|
||||
"2testsort <a@test.invalid>",
|
||||
"2testsort <d@test.invalid>",
|
||||
"2testsort <e@test.invalid>",
|
||||
"testsort <c@test.invalid>",
|
||||
"testsort <a@test.invalid>",
|
||||
"testsort <d@test.invalid>",
|
||||
"testsort <e@test.invalid>" ],
|
||||
"2testsort <e@test.invalid>"],
|
||||
[ "2testsort <c@test.invalid>",
|
||||
"2testsort <a@test.invalid>",
|
||||
"2testsort <d@test.invalid>",
|
||||
|
@ -131,7 +131,7 @@ function run_test()
|
|||
print("Checking Initial Searches");
|
||||
|
||||
function checkSearch(element, index, array) {
|
||||
print("Checking " + element);
|
||||
print("Search #" + index + ": search=" + element);
|
||||
acs.startSearch(element, JSON.stringify({ type: "addr_to" }), null, obs);
|
||||
|
||||
do_check_eq(obs._search, acs);
|
||||
|
|
|
@ -23,7 +23,7 @@ const firstNames = [ { search: "f", expected: [4, 0, 1, 2, 3, 8] },
|
|||
{ search: "firs", expected: [0, 1] },
|
||||
{ search: "first", expected: [1] } ];
|
||||
|
||||
const lastNames = [ { search: "l", expected: [4, 0, 1, 2, 3, 5, 6, 7, 8] },
|
||||
const lastNames = [ { search: "l", expected: [5, 6, 7, 8, 4, 0, 1, 2, 3] },
|
||||
{ search: "la", expected: [4, 0, 2, 3] },
|
||||
{ search: "las", expected: [4, 0, 3] },
|
||||
{ search: "last", expected: [4, 0] },
|
||||
|
@ -63,9 +63,18 @@ function run_test() {
|
|||
|
||||
// Now check multiple matches
|
||||
function checkInputItem(element, index, array) {
|
||||
print("Checking " + element.search);
|
||||
print("Search #" + index + ": search=" + element.search);
|
||||
acs.startSearch(element.search, JSON.stringify({ type: "addr_to" }), null, obs);
|
||||
|
||||
for (var i = 0; i < obs._result.matchCount; i++) {
|
||||
print("... got " + i + ": " + obs._result.getValueAt(i));
|
||||
}
|
||||
|
||||
for (var i = 0; i < element.expected.length; i++) {
|
||||
print("... expected " + i + " (card " + element.expected[i] + "): " +
|
||||
results[element.expected[i]].email);
|
||||
}
|
||||
|
||||
do_check_eq(obs._search, acs);
|
||||
do_check_eq(obs._result.searchString, element.search);
|
||||
do_check_eq(obs._result.searchResult, ACR.RESULT_SUCCESS);
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/**
|
||||
* Tests for for nsAbAutoCompleteSearch scoring.
|
||||
*/
|
||||
|
||||
const ACR = Components.interfaces.nsIAutoCompleteResult;
|
||||
|
||||
const cards = [
|
||||
{ // 0
|
||||
email: "jd.who@example.com", displayName: "John Doe (:xx)",
|
||||
popularityIndex: 0, firstName: "John", value: "John Doe (:xx) <jd.who@example.com>"
|
||||
},
|
||||
|
||||
{ // 1
|
||||
email: "janey_who@example.com", displayName: "Jane Doe",
|
||||
popularityIndex: 0, value: "Jane Doe <janey_who@example.com>"
|
||||
},
|
||||
|
||||
{ // 2
|
||||
email: "pf@example.com", displayName: "Paul \"Shitbreak\" Finch",
|
||||
popularityIndex: 0, value: "Paul \"Shitbreak\" Finch <pf@example.com>"
|
||||
},
|
||||
|
||||
{ // 3
|
||||
email: "js@example.com", displayName: "Janine (Stifflers Mom)",
|
||||
popularityIndex: 0, value: "Janine (Stifflers Mom) <js@example.com>"
|
||||
},
|
||||
|
||||
{ // 4
|
||||
email: "ex0@example.com", displayName: "Ajden",
|
||||
popularityIndex: 0, value: "Ajden <ex0@example.com>"
|
||||
},
|
||||
|
||||
{ // 5
|
||||
email: "5@example.com", displayName: "Foxx",
|
||||
popularityIndex: 0, value: "Foxx <5@example.com>"
|
||||
},
|
||||
|
||||
{ // 6
|
||||
email: "6@example.com", displayName: "thewho",
|
||||
popularityIndex: 0, value: "thewho <6@example.com>"
|
||||
},
|
||||
|
||||
{ // 7
|
||||
email: "7@example.com", displayName: "fakeshit",
|
||||
popularityIndex: 0, value: "fakeshit <7@example.com>"
|
||||
},
|
||||
|
||||
{ // 8
|
||||
email: "8@example.com", displayName: "mastiff",
|
||||
popularityIndex: 0, value: "mastiff <8@example.com>"
|
||||
},
|
||||
|
||||
{ // 9
|
||||
email: "9@example.com", displayName: "anyjohn",
|
||||
popularityIndex: 0, value: "anyjohn <9@example.com>"
|
||||
},
|
||||
|
||||
{ // 10
|
||||
email: "10@example.com", displayName: "däsh l18n",
|
||||
popularityIndex: 0, value: "däsh l18n <10@example.com>"
|
||||
}
|
||||
];
|
||||
|
||||
const inputs = [
|
||||
{ search: "john", expected: [0, 9] },
|
||||
{ search: "doe", expected: [1, 0] },
|
||||
{ search: "jd", expected: [0, 4] },
|
||||
{ search: "who", expected: [1, 0, 6] },
|
||||
{ search: "xx", expected: [0, 5] },
|
||||
{ search: "jan", expected: [1, 3] },
|
||||
{ search: "sh", expected: [2, 10, 7] },
|
||||
{ search: "st", expected: [3,8] }
|
||||
];
|
||||
|
||||
function acObserver() {}
|
||||
|
||||
acObserver.prototype = {
|
||||
_search: null,
|
||||
_result: null,
|
||||
|
||||
onSearchResult: function (aSearch, aResult) {
|
||||
this._search = aSearch;
|
||||
this._result = aResult;
|
||||
}
|
||||
};
|
||||
|
||||
function run_test()
|
||||
{
|
||||
// We set up the cards for this test manually as it is easier to set the
|
||||
// popularity index and we don't need many.
|
||||
|
||||
// Ensure all the directories are initialised.
|
||||
MailServices.ab.directories;
|
||||
|
||||
let ab = MailServices.ab.getDirectory(kPABData.URI);
|
||||
|
||||
function createAndAddCard(element) {
|
||||
var card = Cc["@mozilla.org/addressbook/cardproperty;1"]
|
||||
.createInstance(Ci.nsIAbCard);
|
||||
|
||||
card.primaryEmail = element.email;
|
||||
card.displayName = element.displayName;
|
||||
card.setProperty("PopularityIndex", element.popularityIndex);
|
||||
card.firstName = element.firstName;
|
||||
|
||||
ab.addCard(card);
|
||||
}
|
||||
|
||||
cards.forEach(createAndAddCard);
|
||||
|
||||
// Test - duplicate elements
|
||||
|
||||
var acs = Components.classes["@mozilla.org/autocomplete/search;1?name=addrbook"]
|
||||
.getService(Components.interfaces.nsIAutoCompleteSearch);
|
||||
|
||||
var obs = new acObserver();
|
||||
|
||||
function checkInputItem(element, index, array) {
|
||||
print("Search #" + index + ": search=" + element.search);
|
||||
acs.startSearch(element.search, JSON.stringify({ type: "addr_to" }), null, obs);
|
||||
|
||||
for (var i = 0; i < obs._result.matchCount; i++) {
|
||||
print("... got " + i + ": " + obs._result.getValueAt(i));
|
||||
}
|
||||
|
||||
for (var i = 0; i < element.expected.length; i++) {
|
||||
print("... expected " + i + " (card " + element.expected[i] + "): " +
|
||||
cards[element.expected[i]].value);
|
||||
}
|
||||
|
||||
do_check_eq(obs._search, acs);
|
||||
do_check_eq(obs._result.searchString, element.search);
|
||||
do_check_eq(obs._result.searchResult, ACR.RESULT_SUCCESS);
|
||||
do_check_eq(obs._result.errorDescription, null);
|
||||
do_check_eq(obs._result.matchCount, element.expected.length);
|
||||
|
||||
for (var i = 0; i < element.expected.length; ++i) {
|
||||
do_check_eq(obs._result.getValueAt(i), cards[element.expected[i]].value);
|
||||
do_check_eq(obs._result.getLabelAt(i), cards[element.expected[i]].value);
|
||||
}
|
||||
}
|
||||
|
||||
inputs.forEach(checkInputItem);
|
||||
}
|
|
@ -23,6 +23,7 @@ support-files = data/*
|
|||
[test_nsAbAutoCompleteSearch3.js]
|
||||
[test_nsAbAutoCompleteSearch4.js]
|
||||
[test_nsAbAutoCompleteSearch5.js]
|
||||
[test_nsAbAutoCompleteSearch6.js]
|
||||
[test_nsAbManager1.js]
|
||||
[test_nsAbManager2.js]
|
||||
[test_nsIAbCard.js]
|
||||
|
|
Загрузка…
Ссылка в новой задаче