mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-28 05:10:49 +00:00
Bug 401660 - when showing autocomplete result, show tags that partially match. r=dietrich, a1.9=damons
This commit is contained in:
parent
842a155362
commit
bb3a557610
@ -283,9 +283,9 @@ const PRInt32 nsNavHistory::kGetInfoIndex_ItemLastModified = 10;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_URL = 0;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_Title = 1;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_FaviconURL = 2;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_ItemId = 3;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_ParentId = 4;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_BookmarkTitle = 5;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_ParentId = 3;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_BookmarkTitle = 4;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_Tags = 5;
|
||||
|
||||
static const char* gQuitApplicationMessage = "quit-application";
|
||||
static const char* gXpcomShutdown = "xpcom-shutdown";
|
||||
|
@ -662,9 +662,9 @@ protected:
|
||||
static const PRInt32 kAutoCompleteIndex_URL;
|
||||
static const PRInt32 kAutoCompleteIndex_Title;
|
||||
static const PRInt32 kAutoCompleteIndex_FaviconURL;
|
||||
static const PRInt32 kAutoCompleteIndex_ItemId;
|
||||
static const PRInt32 kAutoCompleteIndex_ParentId;
|
||||
static const PRInt32 kAutoCompleteIndex_BookmarkTitle;
|
||||
static const PRInt32 kAutoCompleteIndex_Tags;
|
||||
nsCOMPtr<mozIStorageStatement> mDBAutoCompleteQuery; // kAutoCompleteIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBFeedbackIncrease;
|
||||
|
||||
@ -698,13 +698,14 @@ protected:
|
||||
nsDataHashtable<nsStringHashKey, PRBool> mLivemarkFeedURIs;
|
||||
|
||||
nsresult AutoCompleteFullHistorySearch(PRBool* aHasMoreResults);
|
||||
nsresult AutoCompleteTagsSearch();
|
||||
|
||||
/**
|
||||
* Query type passed to AutoCompleteProcessSearch to determine what style to
|
||||
* use and if results should be filtered
|
||||
*/
|
||||
enum QueryType { QUERY_TAGS, QUERY_FULL };
|
||||
enum QueryType {
|
||||
QUERY_FULL
|
||||
};
|
||||
nsresult AutoCompleteProcessSearch(mozIStorageStatement* aQuery,
|
||||
const QueryType aType,
|
||||
PRBool *aHasMoreResults = nsnull);
|
||||
|
@ -106,11 +106,30 @@ nsNavHistory::InitAutoComplete()
|
||||
nsresult
|
||||
nsNavHistory::CreateAutoCompleteQueries()
|
||||
{
|
||||
// Helper to get a particular column from the bookmark/tags table based on if
|
||||
// we want to include tags or not
|
||||
#define SQL_STR_FRAGMENT_GET_BOOK_TAG(column, comparison, getMostRecent) \
|
||||
NS_LITERAL_CSTRING( \
|
||||
"(SELECT " column " " \
|
||||
"FROM moz_bookmarks b " \
|
||||
"JOIN moz_bookmarks t ON t.id = b.parent AND t.parent " comparison " ?1 " \
|
||||
"WHERE b.type = ") + nsPrintfCString("%d", \
|
||||
nsINavBookmarksService::TYPE_BOOKMARK) + \
|
||||
NS_LITERAL_CSTRING(" AND b.fk = h.id") + \
|
||||
(getMostRecent ? NS_LITERAL_CSTRING(" " \
|
||||
"ORDER BY b.lastModified DESC LIMIT 1), ") : NS_LITERAL_CSTRING("), "))
|
||||
|
||||
// This gets three columns from the bookmarks and tags table followed by ", "
|
||||
const nsCString &bookTag =
|
||||
SQL_STR_FRAGMENT_GET_BOOK_TAG("b.parent", "!=", PR_TRUE) +
|
||||
SQL_STR_FRAGMENT_GET_BOOK_TAG("b.title", "!=", PR_TRUE) +
|
||||
SQL_STR_FRAGMENT_GET_BOOK_TAG("GROUP_CONCAT(t.title, ' ')", "=", PR_FALSE);
|
||||
|
||||
nsCString sql = NS_LITERAL_CSTRING(
|
||||
"SELECT h.url, h.title, f.url, b.id, b.parent, b.title "
|
||||
"SELECT h.url, h.title, f.url, ") + bookTag +
|
||||
NS_LITERAL_CSTRING("NULL "
|
||||
"FROM moz_places h "
|
||||
"LEFT OUTER JOIN moz_bookmarks b ON b.fk = h.id "
|
||||
"LEFT OUTER JOIN moz_favicons f ON h.favicon_id = f.id "
|
||||
"LEFT OUTER JOIN moz_favicons f ON f.id = h.favicon_id "
|
||||
"WHERE h.frecency <> 0 ");
|
||||
|
||||
if (mAutoCompleteOnlyTyped)
|
||||
@ -124,7 +143,7 @@ nsNavHistory::CreateAutoCompleteQueries()
|
||||
// in the case of a frecency tie, break it with h.typed and h.visit_count
|
||||
// which is better than nothing. but this is slow, so not doing it yet.
|
||||
sql += NS_LITERAL_CSTRING(
|
||||
"ORDER BY h.frecency DESC LIMIT ?1 OFFSET ?2");
|
||||
"ORDER BY h.frecency DESC LIMIT ?2 OFFSET ?3");
|
||||
|
||||
nsresult rv = mDBConn->CreateStatement(sql,
|
||||
getter_AddRefs(mDBAutoCompleteQuery));
|
||||
@ -184,11 +203,6 @@ nsNavHistory::PerformAutoComplete()
|
||||
nsresult rv;
|
||||
// Only do some extra searches on the first chunk
|
||||
if (!mCurrentChunkOffset) {
|
||||
// No need to search for tags if there's nothing to search
|
||||
if (!mCurrentSearchString.IsEmpty()) {
|
||||
rv = AutoCompleteTagsSearch();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
PRBool moreChunksToSearch = PR_FALSE;
|
||||
@ -348,59 +362,6 @@ nsNavHistory::AddSearchToken(nsAutoString &aToken)
|
||||
mCurrentSearchTokens.AppendString(aToken);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNavHistory::AutoCompleteTagsSearch()
|
||||
{
|
||||
// NOTE:
|
||||
// after migration or clear all private data, we might end up with
|
||||
// a lot of places with frecency = -1 (until idle)
|
||||
//
|
||||
// XXX bug 412736
|
||||
// in the case of a frecency tie, break it with h.typed and h.visit_count
|
||||
// which is better than nothing. but this is slow, so not doing it yet.
|
||||
nsCString sql = NS_LITERAL_CSTRING(
|
||||
"SELECT h.url, h.title, f.url, b.id, b.parent, b.title "
|
||||
"FROM moz_places h "
|
||||
"JOIN moz_bookmarks b ON b.fk = h.id "
|
||||
"LEFT OUTER JOIN moz_favicons f ON f.id = h.favicon_id "
|
||||
"WHERE h.frecency <> 0 AND (b.parent IN "
|
||||
"(SELECT t.id FROM moz_bookmarks t WHERE t.parent = ?1 AND (");
|
||||
|
||||
nsStringArray terms;
|
||||
CreateTermsFromTokens(mCurrentSearchTokens, terms);
|
||||
|
||||
for (PRInt32 i = 0; i < terms.Count(); i++) {
|
||||
if (i)
|
||||
sql += NS_LITERAL_CSTRING(" OR");
|
||||
|
||||
// +2 to skip over the "?1", which is the tag root parameter
|
||||
sql += NS_LITERAL_CSTRING(" LOWER(t.title) = ") +
|
||||
nsPrintfCString("LOWER(?%d)", i + 2);
|
||||
}
|
||||
|
||||
sql += NS_LITERAL_CSTRING("))) "
|
||||
"ORDER BY h.frecency DESC");
|
||||
|
||||
nsCOMPtr<mozIStorageStatement> tagAutoCompleteQuery;
|
||||
nsresult rv = mDBConn->CreateStatement(sql,
|
||||
getter_AddRefs(tagAutoCompleteQuery));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = tagAutoCompleteQuery->BindInt64Parameter(0, GetTagsFolder());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRInt32 i = 0; i < terms.Count(); i++) {
|
||||
// +1 to skip over the "?1", which is the tag root parameter
|
||||
rv = tagAutoCompleteQuery->BindStringParameter(i + 1, *(terms.StringAt(i)));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = AutoCompleteProcessSearch(tagAutoCompleteQuery, QUERY_TAGS);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsNavHistory::AutoCompleteFullHistorySearch
|
||||
//
|
||||
// Search for places that have a title, url,
|
||||
@ -415,10 +376,13 @@ nsNavHistory::AutoCompleteFullHistorySearch(PRBool* aHasMoreResults)
|
||||
{
|
||||
mozStorageStatementScoper scope(mDBAutoCompleteQuery);
|
||||
|
||||
nsresult rv = mDBAutoCompleteQuery->BindInt32Parameter(0, mAutoCompleteSearchChunkSize);
|
||||
nsresult rv = mDBAutoCompleteQuery->BindInt32Parameter(0, GetTagsFolder());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mDBAutoCompleteQuery->BindInt32Parameter(1, mCurrentChunkOffset);
|
||||
rv = mDBAutoCompleteQuery->BindInt32Parameter(1, mAutoCompleteSearchChunkSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mDBAutoCompleteQuery->BindInt32Parameter(2, mCurrentChunkOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = AutoCompleteProcessSearch(mDBAutoCompleteQuery, QUERY_FULL, aHasMoreResults);
|
||||
@ -468,83 +432,92 @@ nsNavHistory::AutoCompleteProcessSearch(mozIStorageStatement* aQuery,
|
||||
NS_UnescapeURL(cEntryURL);
|
||||
NS_ConvertUTF8toUTF16 entryURL(cEntryURL);
|
||||
|
||||
PRInt64 parentId = 0;
|
||||
nsAutoString entryTitle, entryFavicon, entryBookmarkTitle;
|
||||
rv = aQuery->GetString(kAutoCompleteIndex_Title, entryTitle);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = aQuery->GetString(kAutoCompleteIndex_FaviconURL, entryFavicon);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
PRInt64 itemId = 0;
|
||||
rv = aQuery->GetInt64(kAutoCompleteIndex_ItemId, &itemId);
|
||||
rv = aQuery->GetInt64(kAutoCompleteIndex_ParentId, &parentId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRInt64 parentId = 0;
|
||||
// Only bother to fetch parent id and bookmark title if we have a bookmark
|
||||
if (itemId) {
|
||||
rv = aQuery->GetInt64(kAutoCompleteIndex_ParentId, &parentId);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Only fetch the bookmark title if we have a bookmark
|
||||
if (parentId) {
|
||||
rv = aQuery->GetString(kAutoCompleteIndex_BookmarkTitle, entryBookmarkTitle);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsAutoString entryTags;
|
||||
rv = aQuery->GetString(kAutoCompleteIndex_Tags, entryTags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool useBookmark = PR_FALSE;
|
||||
PRBool showTags = PR_FALSE;
|
||||
nsString style;
|
||||
switch (aType) {
|
||||
case QUERY_TAGS: {
|
||||
// Always prefer the bookmark title unless we don't have one
|
||||
useBookmark = !entryBookmarkTitle.IsEmpty();
|
||||
|
||||
// Tags have a special stype to show a tag icon
|
||||
style = NS_LITERAL_STRING("tag");
|
||||
|
||||
break;
|
||||
}
|
||||
case QUERY_FULL: {
|
||||
// If we get any results, there's potentially another chunk to proces
|
||||
if (aHasMoreResults)
|
||||
*aHasMoreResults = PR_TRUE;
|
||||
|
||||
// Determine if every token matches either the bookmark, title, or url
|
||||
// Determine if every token matches either the bookmark title, tags,
|
||||
// page title, or page url
|
||||
PRBool matchAll = PR_TRUE;
|
||||
for (PRInt32 i = 0; i < mCurrentSearchTokens.Count() && matchAll; i++) {
|
||||
const nsString *token = mCurrentSearchTokens.StringAt(i);
|
||||
|
||||
// Check if the current token matches the bookmark
|
||||
PRBool bookmarkMatch = itemId &&
|
||||
PRBool bookmarkMatch = parentId &&
|
||||
CaseInsensitiveFindInReadable(*token, entryBookmarkTitle);
|
||||
// If any part of the search string is in the bookmark title, show
|
||||
// that in the result instead of the page title
|
||||
useBookmark |= bookmarkMatch;
|
||||
|
||||
// If the token is in any of the tags, remember to show tags
|
||||
PRBool tagsMatch = CaseInsensitiveFindInReadable(*token, entryTags);
|
||||
showTags |= tagsMatch;
|
||||
|
||||
// True if any of them match; false makes us quit the loop
|
||||
matchAll = bookmarkMatch ||
|
||||
matchAll = bookmarkMatch || tagsMatch ||
|
||||
CaseInsensitiveFindInReadable(*token, entryTitle) ||
|
||||
CaseInsensitiveFindInReadable(*token, entryURL);
|
||||
}
|
||||
|
||||
// Skip if we don't match all terms in the bookmark, title or url
|
||||
// Skip if we don't match all terms in the bookmark, tag, title or url
|
||||
if (!matchAll)
|
||||
continue;
|
||||
|
||||
// Style bookmarks that aren't feed items and feed URIs as bookmark
|
||||
style = (itemId && !mLivemarkFeedItemIds.Get(parentId, &dummy)) ||
|
||||
mLivemarkFeedURIs.Get(escapedEntryURL, &dummy) ?
|
||||
NS_LITERAL_STRING("bookmark") : NS_LITERAL_STRING("favicon");
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// Always prefer the bookmark title unless we don't have one
|
||||
useBookmark = !entryBookmarkTitle.IsEmpty();
|
||||
|
||||
// Style bookmarks that aren't feed items and feed URIs as bookmark
|
||||
style = (itemId && !mLivemarkFeedItemIds.Get(parentId, &dummy)) ||
|
||||
mLivemarkFeedURIs.Get(escapedEntryURL, &dummy) ?
|
||||
NS_LITERAL_STRING("bookmark") : NS_LITERAL_STRING("favicon");
|
||||
// Always prefer to show tags if we have them; otherwise, prefer the
|
||||
// bookmark title if we have it
|
||||
if (!entryTags.IsEmpty())
|
||||
showTags = PR_TRUE;
|
||||
else
|
||||
useBookmark = !entryBookmarkTitle.IsEmpty();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add the tags to the title if necessary
|
||||
if (showTags) {
|
||||
// Always show the bookmark if possible when we have tags
|
||||
useBookmark = !entryBookmarkTitle.IsEmpty();
|
||||
/* XXX bug 418257 to look at RTL issues of appending tags
|
||||
(useBookmark ? entryBookmarkTitle : entryTitle)
|
||||
+= NS_LITERAL_STRING(" (") + entryTags + NS_LITERAL_STRING(")");
|
||||
*/
|
||||
}
|
||||
|
||||
// Tags have a special style to show a tag icon; otherwise, style the
|
||||
// bookmarks that aren't feed items and feed URIs as bookmark
|
||||
style = showTags ? NS_LITERAL_STRING("tag") : (parentId &&
|
||||
!mLivemarkFeedItemIds.Get(parentId, &dummy)) ||
|
||||
mLivemarkFeedURIs.Get(escapedEntryURL, &dummy) ?
|
||||
NS_LITERAL_STRING("bookmark") : NS_LITERAL_STRING("favicon");
|
||||
|
||||
// Pick the right title to show based on the result of the query type
|
||||
const nsAString &title = useBookmark ? entryBookmarkTitle : entryTitle;
|
||||
|
||||
|
@ -24,6 +24,7 @@ version(180);
|
||||
* Matt Crocker <matt@songbirdnest.com>
|
||||
* Seth Spitzer <sspitzer@mozilla.org>
|
||||
* Dietrich Ayala <dietrich@mozilla.com>
|
||||
* Edward Lee <edward.lee@engineering.uiuc.edu>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -253,8 +254,19 @@ function run_test() {
|
||||
|
||||
// test that matches are sorted by frecency
|
||||
for (var i = 0; i < controller.matchCount; i++) {
|
||||
do_check_eq(controller.getValueAt(i), results[i][0].spec);
|
||||
do_check_eq(controller.getCommentAt(i), results[i][2]);
|
||||
let searchURL = controller.getValueAt(i);
|
||||
let expectURL = results[i][0].spec;
|
||||
if (searchURL == expectURL) {
|
||||
do_check_eq(controller.getValueAt(i), results[i][0].spec);
|
||||
do_check_eq(controller.getCommentAt(i), results[i][2]);
|
||||
} else {
|
||||
// If the results didn't match exactly, perhaps it's still the right
|
||||
// frecency just in the wrong "order" (order of same frecency is
|
||||
// undefined), so check if frecency matches. This is okay because we
|
||||
// can still ensure the correct number of expected frecencies.
|
||||
let getFrecency = function(aURL) aURL.match(/frecency:(-?\d+)$/)[1];
|
||||
do_check_eq(getFrecency(searchURL), getFrecency(expectURL));
|
||||
}
|
||||
}
|
||||
|
||||
do_test_finished();
|
||||
|
@ -22,6 +22,7 @@
|
||||
* Contributor(s):
|
||||
* Matt Crocker <matt@songbirdnest.com>
|
||||
* Seth Spitzer <sspitzer@mozilla.org>
|
||||
* Edward Lee <edward.lee@engineering.uiuc.edu>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -124,10 +125,14 @@ function ensure_tag_results(uris, searchTerm)
|
||||
do_check_eq(controller.searchStatus,
|
||||
Ci.nsIAutoCompleteController.STATUS_COMPLETE_MATCH);
|
||||
do_check_eq(controller.matchCount, uris.length);
|
||||
let vals = [];
|
||||
for (var i=0; i<controller.matchCount; i++) {
|
||||
do_check_eq(controller.getValueAt(i), uris[i].spec);
|
||||
// Keep the URL for later because order of tag results is undefined
|
||||
vals.push(controller.getValueAt(i));
|
||||
do_check_eq(controller.getStyleAt(i), "tag");
|
||||
}
|
||||
// Sort the results then check if we have the right items
|
||||
vals.sort().forEach(function(val, i) do_check_eq(val, uris[i].spec))
|
||||
|
||||
if (current_test < (tests.length - 1)) {
|
||||
current_test++;
|
||||
|
@ -22,6 +22,7 @@
|
||||
* Contributor(s):
|
||||
* Matt Crocker <matt@songbirdnest.com>
|
||||
* Seth Spitzer <sspitzer@mozilla.org>
|
||||
* Edward Lee <edward.lee@engineering.uiuc.edu>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
@ -101,6 +102,7 @@ try {
|
||||
|
||||
function ensure_tag_results(uris, searchTerm)
|
||||
{
|
||||
print("Searching for '" + searchTerm + "'");
|
||||
var controller = Components.classes["@mozilla.org/autocomplete/controller;1"].
|
||||
getService(Components.interfaces.nsIAutoCompleteController);
|
||||
|
||||
@ -122,12 +124,18 @@ function ensure_tag_results(uris, searchTerm)
|
||||
input.onSearchComplete = function() {
|
||||
do_check_eq(numSearchesStarted, 1);
|
||||
do_check_eq(controller.searchStatus,
|
||||
Ci.nsIAutoCompleteController.STATUS_COMPLETE_MATCH);
|
||||
uris.length ?
|
||||
Ci.nsIAutoCompleteController.STATUS_COMPLETE_MATCH :
|
||||
Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH);
|
||||
do_check_eq(controller.matchCount, uris.length);
|
||||
let vals = [];
|
||||
for (var i=0; i<controller.matchCount; i++) {
|
||||
do_check_eq(controller.getValueAt(i), uris[i].spec);
|
||||
// Keep the URL for later because order of tag results is undefined
|
||||
vals.push(controller.getValueAt(i));
|
||||
do_check_eq(controller.getStyleAt(i), "tag");
|
||||
}
|
||||
// Sort the results then check if we have the right items
|
||||
vals.sort().forEach(function(val, i) do_check_eq(val, uris[i].spec))
|
||||
|
||||
if (current_test < (tests.length - 1)) {
|
||||
current_test++;
|
||||
@ -140,21 +148,20 @@ function ensure_tag_results(uris, searchTerm)
|
||||
controller.startSearch(searchTerm);
|
||||
}
|
||||
|
||||
var uri1 = uri("http://site.tld/1");
|
||||
var uri2 = uri("http://site.tld/2");
|
||||
var uri3 = uri("http://site.tld/3");
|
||||
var uri4 = uri("http://site.tld/4");
|
||||
var uri5 = uri("http://site.tld/5");
|
||||
var uri6 = uri("http://site.tld/6");
|
||||
var uri1 = uri("http://site.tld/1/aaa");
|
||||
var uri2 = uri("http://site.tld/2/bbb");
|
||||
var uri3 = uri("http://site.tld/3/aaa");
|
||||
var uri4 = uri("http://site.tld/4/bbb");
|
||||
var uri5 = uri("http://site.tld/5/aaa");
|
||||
var uri6 = uri("http://site.tld/6/bbb");
|
||||
|
||||
var tests = [function() { ensure_tag_results([uri1], "foo"); },
|
||||
function() { ensure_tag_results([uri2], "bar"); },
|
||||
function() { ensure_tag_results([uri3], "cheese"); },
|
||||
function() { ensure_tag_results([uri1, uri2, uri4], "foo bar"); },
|
||||
function() { ensure_tag_results([uri1, uri2], "bar foo"); },
|
||||
function() { ensure_tag_results([uri2, uri3, uri5], "bar cheese"); },
|
||||
function() { ensure_tag_results([uri2, uri3], "cheese bar"); },
|
||||
function() { ensure_tag_results([uri1, uri2, uri3, uri4, uri5, uri6], "foo bar cheese"); }];
|
||||
var tests = [
|
||||
function() ensure_tag_results([uri1, uri4, uri6], "foo"),
|
||||
function() ensure_tag_results([uri2, uri4, uri5, uri6], "bar"),
|
||||
function() ensure_tag_results([uri3, uri5, uri6], "cheese"),
|
||||
function() ensure_tag_results([uri4, uri6], "fo bar"),
|
||||
function() ensure_tag_results([uri5, uri6], "ba chee"),
|
||||
];
|
||||
|
||||
/**
|
||||
* Test history autocomplete
|
||||
|
Loading…
x
Reference in New Issue
Block a user