diff options
Diffstat (limited to 'toolkit/components/places/tests/unifiedcomplete')
44 files changed, 5554 insertions, 0 deletions
diff --git a/toolkit/components/places/tests/unifiedcomplete/.eslintrc.js b/toolkit/components/places/tests/unifiedcomplete/.eslintrc.js new file mode 100644 index 000000000..d35787cd2 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/.eslintrc.js @@ -0,0 +1,7 @@ +"use strict"; + +module.exports = { + "extends": [ + "../../../../../testing/xpcshell/xpcshell.eslintrc.js" + ] +}; diff --git a/toolkit/components/places/tests/unifiedcomplete/data/engine-rel-searchform.xml b/toolkit/components/places/tests/unifiedcomplete/data/engine-rel-searchform.xml new file mode 100644 index 000000000..f4baad28a --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/data/engine-rel-searchform.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/"> +<ShortName>engine-rel-searchform.xml</ShortName> +<Url type="text/html" method="GET" template="http://example.com/?search" rel="searchform"/> +</SearchPlugin> diff --git a/toolkit/components/places/tests/unifiedcomplete/data/engine-suggestions.xml b/toolkit/components/places/tests/unifiedcomplete/data/engine-suggestions.xml new file mode 100644 index 000000000..a322a7c86 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/data/engine-suggestions.xml @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Any copyright is dedicated to the Public Domain. + - http://creativecommons.org/publicdomain/zero/1.0/ --> + +<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/"> +<ShortName>engine-suggestions.xml</ShortName> +<Url type="application/x-suggestions+json" + method="GET" + template="http://localhost:9000/suggest?{searchTerms}"/> +<Url type="text/html" + method="GET" + template="http://localhost:9000/search" + rel="searchform"/> +</SearchPlugin> diff --git a/toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js b/toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js new file mode 100644 index 000000000..11e917e18 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js @@ -0,0 +1,505 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var Ci = Components.interfaces; +var Cc = Components.classes; +var Cr = Components.results; +var Cu = Components.utils; + +const FRECENCY_DEFAULT = 10000; + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://testing-common/httpd.js"); + +// Import common head. +{ + let commonFile = do_get_file("../head_common.js", false); + let uri = Services.io.newFileURI(commonFile); + Services.scriptloader.loadSubScript(uri.spec, this); +} + +// Put any other stuff relative to this test folder below. + +const TITLE_SEARCH_ENGINE_SEPARATOR = " \u00B7\u2013\u00B7 "; + +function run_test() { + run_next_test(); +} + +function* cleanup() { + Services.prefs.clearUserPref("browser.urlbar.autocomplete.enabled"); + Services.prefs.clearUserPref("browser.urlbar.autoFill"); + Services.prefs.clearUserPref("browser.urlbar.autoFill.typed"); + Services.prefs.clearUserPref("browser.urlbar.autoFill.searchEngines"); + let suggestPrefs = [ + "history", + "bookmark", + "history.onlyTyped", + "openpage", + "searches", + ]; + for (let type of suggestPrefs) { + Services.prefs.clearUserPref("browser.urlbar.suggest." + type); + } + Services.prefs.clearUserPref("browser.search.suggest.enabled"); + yield PlacesUtils.bookmarks.eraseEverything(); + yield PlacesTestUtils.clearHistory(); +} +do_register_cleanup(cleanup); + +/** + * @param aSearches + * Array of AutoCompleteSearch names. + */ +function AutoCompleteInput(aSearches) { + this.searches = aSearches; +} +AutoCompleteInput.prototype = { + popup: { + selectedIndex: -1, + invalidate: function () {}, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIAutoCompletePopup]) + }, + popupOpen: false, + + disableAutoComplete: false, + completeDefaultIndex: true, + completeSelectedIndex: true, + forceComplete: false, + + minResultsForPopup: 0, + maxRows: 0, + + showCommentColumn: false, + showImageColumn: false, + + timeout: 10, + searchParam: "", + + get searchCount() { + return this.searches.length; + }, + getSearchAt: function(aIndex) { + return this.searches[aIndex]; + }, + + textValue: "", + // Text selection range + _selStart: 0, + _selEnd: 0, + get selectionStart() { + return this._selStart; + }, + get selectionEnd() { + return this._selEnd; + }, + selectTextRange: function(aStart, aEnd) { + this._selStart = aStart; + this._selEnd = aEnd; + }, + + onSearchBegin: function () {}, + onSearchComplete: function () {}, + + onTextEntered: () => false, + onTextReverted: () => false, + + QueryInterface: XPCOMUtils.generateQI([Ci.nsIAutoCompleteInput]) +} + +// A helper for check_autocomplete to check a specific match against data from +// the controller. +function _check_autocomplete_matches(match, result) { + let { uri, title, tags, style } = match; + if (tags) + title += " \u2013 " + tags.sort().join(", "); + if (style) + style = style.sort(); + else + style = ["favicon"]; + + do_print(`Checking against expected "${uri.spec}", "${title}"`); + // Got a match on both uri and title? + if (stripPrefix(uri.spec) != stripPrefix(result.value) || title != result.comment) { + return false; + } + + let actualStyle = result.style.split(/\s+/).sort(); + if (style) + Assert.equal(actualStyle.toString(), style.toString(), "Match should have expected style"); + if (uri.spec.startsWith("moz-action:")) { + Assert.ok(actualStyle.includes("action"), "moz-action results should always have 'action' in their style"); + } + + if (match.icon) + Assert.equal(result.image, match.icon, "Match should have expected image"); + + return true; +} + +function* check_autocomplete(test) { + // At this point frecency could still be updating due to latest pages + // updates. + // This is not a problem in real life, but autocomplete tests should + // return reliable resultsets, thus we have to wait. + yield PlacesTestUtils.promiseAsyncUpdates(); + + // Make an AutoCompleteInput that uses our searches and confirms results. + let input = new AutoCompleteInput(["unifiedcomplete"]); + input.textValue = test.search; + + if (test.searchParam) + input.searchParam = test.searchParam; + + // Caret must be at the end for autoFill to happen. + let strLen = test.search.length; + input.selectTextRange(strLen, strLen); + Assert.equal(input.selectionStart, strLen, "Selection starts at end"); + Assert.equal(input.selectionEnd, strLen, "Selection ends at the end"); + + let controller = Cc["@mozilla.org/autocomplete/controller;1"] + .getService(Ci.nsIAutoCompleteController); + controller.input = input; + + let numSearchesStarted = 0; + input.onSearchBegin = () => { + do_print("onSearchBegin received"); + numSearchesStarted++; + }; + let searchCompletePromise = new Promise(resolve => { + input.onSearchComplete = () => { + do_print("onSearchComplete received"); + resolve(); + } + }); + let expectedSearches = 1; + if (test.incompleteSearch) { + controller.startSearch(test.incompleteSearch); + expectedSearches++; + } + + do_print("Searching for: '" + test.search + "'"); + controller.startSearch(test.search); + yield searchCompletePromise; + + Assert.equal(numSearchesStarted, expectedSearches, "All searches started"); + + // Check to see the expected uris and titles match up. If 'enable-actions' + // is specified, we check that the first specified match is the first + // controller value (as this is the "special" always selected item), but the + // rest can match in any order. + // If 'enable-actions' is not specified, they can match in any order. + if (test.matches) { + // Do not modify the test original matches. + let matches = test.matches.slice(); + + if (matches.length) { + let firstIndexToCheck = 0; + if (test.searchParam && test.searchParam.includes("enable-actions")) { + firstIndexToCheck = 1; + do_print("Checking first match is first autocomplete entry") + let result = { + value: controller.getValueAt(0), + comment: controller.getCommentAt(0), + style: controller.getStyleAt(0), + image: controller.getImageAt(0), + } + do_print(`First match is "${result.value}", "${result.comment}"`); + Assert.ok(_check_autocomplete_matches(matches[0], result), "first item is correct"); + do_print("Checking rest of the matches"); + } + + for (let i = firstIndexToCheck; i < controller.matchCount; i++) { + let result = { + value: controller.getValueAt(i), + comment: controller.getCommentAt(i), + style: controller.getStyleAt(i), + image: controller.getImageAt(i), + } + do_print(`Looking for "${result.value}", "${result.comment}" in expected results...`); + let lowerBound = test.checkSorting ? i : firstIndexToCheck; + let upperBound = test.checkSorting ? i + 1 : matches.length; + let found = false; + for (let j = lowerBound; j < upperBound; ++j) { + // Skip processed expected results + if (matches[j] == undefined) + continue; + if (_check_autocomplete_matches(matches[j], result)) { + do_print("Got a match at index " + j + "!"); + // Make it undefined so we don't process it again + matches[j] = undefined; + found = true; + break; + } + } + + if (!found) + do_throw(`Didn't find the current result ("${result.value}", "${result.comment}") in matches`); // ' (Emacs syntax highlighting fix) + } + } + + Assert.equal(controller.matchCount, matches.length, + "Got as many results as expected"); + + // If we expect results, make sure we got matches. + do_check_eq(controller.searchStatus, matches.length ? + Ci.nsIAutoCompleteController.STATUS_COMPLETE_MATCH : + Ci.nsIAutoCompleteController.STATUS_COMPLETE_NO_MATCH); + } + + if (test.autofilled) { + // Check the autoFilled result. + Assert.equal(input.textValue, test.autofilled, + "Autofilled value is correct"); + + // Now force completion and check correct casing of the result. + // This ensures the controller is able to do its magic case-preserving + // stuff and correct replacement of the user's casing with result's one. + controller.handleEnter(false); + Assert.equal(input.textValue, test.completed, + "Completed value is correct"); + } +} + +var addBookmark = Task.async(function* (aBookmarkObj) { + Assert.ok(!!aBookmarkObj.uri, "Bookmark object contains an uri"); + let parentId = aBookmarkObj.parentId ? aBookmarkObj.parentId + : PlacesUtils.unfiledBookmarksFolderId; + + let bm = yield PlacesUtils.bookmarks.insert({ + parentGuid: (yield PlacesUtils.promiseItemGuid(parentId)), + title: aBookmarkObj.title || "A bookmark", + url: aBookmarkObj.uri + }); + yield PlacesUtils.promiseItemId(bm.guid); + + if (aBookmarkObj.keyword) { + yield PlacesUtils.keywords.insert({ keyword: aBookmarkObj.keyword, + url: aBookmarkObj.uri.spec, + postData: aBookmarkObj.postData + }); + } + + if (aBookmarkObj.tags) { + PlacesUtils.tagging.tagURI(aBookmarkObj.uri, aBookmarkObj.tags); + } +}); + +function addOpenPages(aUri, aCount=1, aUserContextId=0) { + let ac = Cc["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"] + .getService(Ci.mozIPlacesAutoComplete); + for (let i = 0; i < aCount; i++) { + ac.registerOpenPage(aUri, aUserContextId); + } +} + +function removeOpenPages(aUri, aCount=1, aUserContextId=0) { + let ac = Cc["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"] + .getService(Ci.mozIPlacesAutoComplete); + for (let i = 0; i < aCount; i++) { + ac.unregisterOpenPage(aUri, aUserContextId); + } +} + +function changeRestrict(aType, aChar) { + let branch = "browser.urlbar."; + // "title" and "url" are different from everything else, so special case them. + if (aType == "title" || aType == "url") + branch += "match."; + else + branch += "restrict."; + + do_print("changing restrict for " + aType + " to '" + aChar + "'"); + Services.prefs.setCharPref(branch + aType, aChar); +} + +function resetRestrict(aType) { + let branch = "browser.urlbar."; + // "title" and "url" are different from everything else, so special case them. + if (aType == "title" || aType == "url") + branch += "match."; + else + branch += "restrict."; + + Services.prefs.clearUserPref(branch + aType); +} + +/** + * Strip prefixes from the URI that we don't care about for searching. + * + * @param spec + * The text to modify. + * @return the modified spec. + */ +function stripPrefix(spec) +{ + ["http://", "https://", "ftp://"].some(scheme => { + if (spec.startsWith(scheme)) { + spec = spec.slice(scheme.length); + return true; + } + return false; + }); + + if (spec.startsWith("www.")) { + spec = spec.slice(4); + } + return spec; +} + +function makeActionURI(action, params) { + let encodedParams = {}; + for (let key in params) { + encodedParams[key] = encodeURIComponent(params[key]); + } + let url = "moz-action:" + action + "," + JSON.stringify(encodedParams); + return NetUtil.newURI(url); +} + +// Creates a full "match" entry for a search result, suitable for passing as +// an entry to check_autocomplete. +function makeSearchMatch(input, extra = {}) { + // Note that counter-intuitively, the order the object properties are defined + // in the object passed to makeActionURI is important for check_autocomplete + // to match them :( + let params = { + engineName: extra.engineName || "MozSearch", + input, + searchQuery: "searchQuery" in extra ? extra.searchQuery : input, + }; + if ("alias" in extra) { + // May be undefined, which is expected, but in that case make sure it's not + // included in the params of the moz-action URL. + params.alias = extra.alias; + } + let style = [ "action", "searchengine" ]; + if (Array.isArray(extra.style)) { + style.push(...extra.style); + } + if (extra.heuristic) { + style.push("heuristic"); + } + return { + uri: makeActionURI("searchengine", params), + title: params.engineName, + style, + } +} + +// Creates a full "match" entry for a search result, suitable for passing as +// an entry to check_autocomplete. +function makeVisitMatch(input, url, extra = {}) { + // Note that counter-intuitively, the order the object properties are defined + // in the object passed to makeActionURI is important for check_autocomplete + // to match them :( + let params = { + url, + input, + } + let style = [ "action", "visiturl" ]; + if (extra.heuristic) { + style.push("heuristic"); + } + return { + uri: makeActionURI("visiturl", params), + title: extra.title || url, + style, + } +} + +function makeSwitchToTabMatch(url, extra = {}) { + return { + uri: makeActionURI("switchtab", {url}), + title: extra.title || url, + style: [ "action", "switchtab" ], + } +} + +function makeExtensionMatch(extra = {}) { + let style = [ "action", "extension" ]; + if (extra.heuristic) { + style.push("heuristic"); + } + + return { + uri: makeActionURI("extension", { + content: extra.content, + keyword: extra.keyword, + }), + title: extra.description, + style, + }; +} + +function setFaviconForHref(href, iconHref) { + return new Promise(resolve => { + PlacesUtils.favicons.setAndFetchFaviconForPage( + NetUtil.newURI(href), + NetUtil.newURI(iconHref), + true, + PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE, + resolve, + Services.scriptSecurityManager.getSystemPrincipal() + ); + }); +} + +function makeTestServer(port=-1) { + let httpServer = new HttpServer(); + httpServer.start(port); + do_register_cleanup(() => httpServer.stop(() => {})); + return httpServer; +} + +function* addTestEngine(basename, httpServer=undefined) { + httpServer = httpServer || makeTestServer(); + httpServer.registerDirectory("/", do_get_cwd()); + let dataUrl = + "http://localhost:" + httpServer.identity.primaryPort + "/data/"; + + do_print("Adding engine: " + basename); + return yield new Promise(resolve => { + Services.obs.addObserver(function obs(subject, topic, data) { + let engine = subject.QueryInterface(Ci.nsISearchEngine); + do_print("Observed " + data + " for " + engine.name); + if (data != "engine-added" || engine.name != basename) { + return; + } + + Services.obs.removeObserver(obs, "browser-search-engine-modified"); + do_register_cleanup(() => Services.search.removeEngine(engine)); + resolve(engine); + }, "browser-search-engine-modified", false); + + do_print("Adding engine from URL: " + dataUrl + basename); + Services.search.addEngine(dataUrl + basename, null, null, false); + }); +} + +// Ensure we have a default search engine and the keyword.enabled preference +// set. +add_task(function* ensure_search_engine() { + // keyword.enabled is necessary for the tests to see keyword searches. + Services.prefs.setBoolPref("keyword.enabled", true); + + // Initialize the search service, but first set this geo IP pref to a dummy + // string. When the search service is initialized, it contacts the URI named + // in this pref, which breaks the test since outside connections aren't + // allowed. + let geoPref = "browser.search.geoip.url"; + Services.prefs.setCharPref(geoPref, ""); + do_register_cleanup(() => Services.prefs.clearUserPref(geoPref)); + yield new Promise(resolve => { + Services.search.init(resolve); + }); + + // Remove any existing engines before adding ours. + for (let engine of Services.search.getEngines()) { + Services.search.removeEngine(engine); + } + Services.search.addEngineWithDetails("MozSearch", "", "", "", "GET", + "http://s.example.com/search"); + let engine = Services.search.getEngineByName("MozSearch"); + Services.search.currentEngine = engine; +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_416211.js b/toolkit/components/places/tests/unifiedcomplete/test_416211.js new file mode 100644 index 000000000..e02906ddc --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_416211.js @@ -0,0 +1,22 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test bug 416211 to make sure results that match the tag show the bookmark + * title instead of the page title. + */ + +add_task(function* test_tag_match_has_bookmark_title() { + do_print("Make sure the tag match gives the bookmark title"); + let uri = NetUtil.newURI("http://theuri/"); + yield PlacesTestUtils.addVisits({ uri: uri, title: "Page title" }); + yield addBookmark({ uri: uri, + title: "Bookmark title", + tags: [ "superTag" ]}); + yield check_autocomplete({ + search: "superTag", + matches: [ { uri: uri, title: "Bookmark title", tags: [ "superTag" ], style: [ "bookmark-tag" ] } ] + }); + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_416214.js b/toolkit/components/places/tests/unifiedcomplete/test_416214.js new file mode 100644 index 000000000..a30b3fe74 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_416214.js @@ -0,0 +1,39 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test autocomplete for non-English URLs that match the tag bug 416214. Also + * test bug 417441 by making sure escaped ascii characters like "+" remain + * escaped. + * + * - add a visit for a page with a non-English URL + * - add a tag for the page + * - search for the tag + * - test number of matches (should be exactly one) + * - make sure the url is decoded + */ + +add_task(function* test_tag_match_url() { + do_print("Make sure tag matches return the right url as well as '+' remain escaped"); + let uri1 = NetUtil.newURI("http://escaped/ユニコード"); + let uri2 = NetUtil.newURI("http://asciiescaped/blocking-firefox3%2B"); + yield PlacesTestUtils.addVisits([ + { uri: uri1, title: "title" }, + { uri: uri2, title: "title" } + ]); + yield addBookmark({ uri: uri1, + title: "title", + tags: [ "superTag" ], + style: [ "bookmark-tag" ] }); + yield addBookmark({ uri: uri2, + title: "title", + tags: [ "superTag" ], + style: [ "bookmark-tag" ] }); + yield check_autocomplete({ + search: "superTag", + matches: [ { uri: uri1, title: "title", tags: [ "superTag" ], style: [ "bookmark-tag" ] }, + { uri: uri2, title: "title", tags: [ "superTag" ], style: [ "bookmark-tag" ] } ] + }); + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_417798.js b/toolkit/components/places/tests/unifiedcomplete/test_417798.js new file mode 100644 index 000000000..bed14b2ce --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_417798.js @@ -0,0 +1,51 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Test for bug 417798 to make sure javascript: URIs don't show up unless the + * user searches for javascript: explicitly. + */ + +add_task(function* test_javascript_match() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", false); + + let uri1 = NetUtil.newURI("http://abc/def"); + let uri2 = NetUtil.newURI("javascript:5"); + yield PlacesTestUtils.addVisits([ { uri: uri1, title: "Title with javascript:" } ]); + yield addBookmark({ uri: uri2, + title: "Title with javascript:" }); + + do_print("Match non-javascript: with plain search"); + yield check_autocomplete({ + search: "a", + matches: [ { uri: uri1, title: "Title with javascript:" } ] + }); + + do_print("Match non-javascript: with almost javascript:"); + yield check_autocomplete({ + search: "javascript", + matches: [ { uri: uri1, title: "Title with javascript:" } ] + }); + + do_print("Match javascript:"); + yield check_autocomplete({ + search: "javascript:", + matches: [ { uri: uri1, title: "Title with javascript:" }, + { uri: uri2, title: "Title with javascript:", style: [ "bookmark" ]} ] + }); + + do_print("Match nothing with non-first javascript:"); + yield check_autocomplete({ + search: "5 javascript:", + matches: [ ] + }); + + do_print("Match javascript: with multi-word search"); + yield check_autocomplete({ + search: "javascript: 5", + matches: [ { uri: uri2, title: "Title with javascript:", style: [ "bookmark" ]} ] + }); + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_418257.js b/toolkit/components/places/tests/unifiedcomplete/test_418257.js new file mode 100644 index 000000000..323c2a7af --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_418257.js @@ -0,0 +1,67 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Test bug 418257 by making sure tags are returned with the title as part of + * the "comment" if there are tags even if we didn't match in the tags. They + * are separated from the title by a endash. + */ + +add_task(function* test_javascript_match() { + let uri1 = NetUtil.newURI("http://page1"); + let uri2 = NetUtil.newURI("http://page2"); + let uri3 = NetUtil.newURI("http://page3"); + let uri4 = NetUtil.newURI("http://page4"); + yield PlacesTestUtils.addVisits([ + { uri: uri1, title: "tagged" }, + { uri: uri2, title: "tagged" }, + { uri: uri3, title: "tagged" }, + { uri: uri4, title: "tagged" } + ]); + yield addBookmark({ uri: uri1, + title: "tagged", + tags: [ "tag1" ] }); + yield addBookmark({ uri: uri2, + title: "tagged", + tags: [ "tag1", "tag2" ] }); + yield addBookmark({ uri: uri3, + title: "tagged", + tags: [ "tag1", "tag3" ] }); + yield addBookmark({ uri: uri4, + title: "tagged", + tags: [ "tag1", "tag2", "tag3" ] }); + + do_print("Make sure tags come back in the title when matching tags"); + yield check_autocomplete({ + search: "page1 tag", + matches: [ { uri: uri1, title: "tagged", tags: [ "tag1" ], style: [ "bookmark-tag" ] } ] + }); + + do_print("Check tags in title for page2"); + yield check_autocomplete({ + search: "page2 tag", + matches: [ { uri: uri2, title: "tagged", tags: [ "tag1", "tag2" ], style: [ "bookmark-tag" ] } ] + }); + + do_print("Make sure tags appear even when not matching the tag"); + yield check_autocomplete({ + search: "page3", + matches: [ { uri: uri3, title: "tagged", tags: [ "tag1", "tag3" ], style: [ "bookmark-tag" ] } ] + }); + + do_print("Multiple tags come in commas for page4"); + yield check_autocomplete({ + search: "page4", + matches: [ { uri: uri4, title: "tagged", tags: [ "tag1", "tag2", "tag3" ], style: [ "bookmark-tag" ] } ] + }); + + do_print("Extra test just to make sure we match the title"); + yield check_autocomplete({ + search: "tag2", + matches: [ { uri: uri2, title: "tagged", tags: [ "tag1", "tag2" ], style: [ "bookmark-tag" ] }, + { uri: uri4, title: "tagged", tags: [ "tag1", "tag2", "tag3" ], style: [ "bookmark-tag" ] } ] + }); + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_422277.js b/toolkit/components/places/tests/unifiedcomplete/test_422277.js new file mode 100644 index 000000000..df6f7601a --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_422277.js @@ -0,0 +1,19 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Test bug 422277 to make sure bad escaped uris don't get escaped. This makes + * sure we don't hit an assertion for "not a UTF8 string". + */ + +add_task(function* test_javascript_match() { + do_print("Bad escaped uri stays escaped"); + let uri1 = NetUtil.newURI("http://site/%EAid"); + yield PlacesTestUtils.addVisits([ { uri: uri1, title: "title" } ]); + yield check_autocomplete({ + search: "site", + matches: [ { uri: uri1, title: "title" } ] + }); + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_autocomplete_functional.js b/toolkit/components/places/tests/unifiedcomplete/test_autocomplete_functional.js new file mode 100644 index 000000000..cd2dfdb17 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_autocomplete_functional.js @@ -0,0 +1,171 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Functional tests for inline autocomplete + +const PREF_AUTOCOMPLETE_ENABLED = "browser.urlbar.autocomplete.enabled"; + +add_task(function* test_disabling_autocomplete() { + do_print("Check disabling autocomplete disables autofill"); + Services.prefs.setBoolPref(PREF_AUTOCOMPLETE_ENABLED, false); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://visit.mozilla.org"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "vis", + autofilled: "vis", + completed: "vis" + }); + yield cleanup(); +}); + +add_task(function* test_urls_order() { + do_print("Add urls, check for correct order"); + let places = [{ uri: NetUtil.newURI("http://visit1.mozilla.org") }, + { uri: NetUtil.newURI("http://visit2.mozilla.org"), + transition: TRANSITION_TYPED }]; + yield PlacesTestUtils.addVisits(places); + yield check_autocomplete({ + search: "vis", + autofilled: "visit2.mozilla.org/", + completed: "visit2.mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_ignore_prefix() { + do_print("Add urls, make sure www and http are ignored"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + yield PlacesTestUtils.addVisits(NetUtil.newURI("http://www.visit1.mozilla.org")); + yield check_autocomplete({ + search: "visit1", + autofilled: "visit1.mozilla.org/", + completed: "visit1.mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_after_host() { + do_print("Autocompleting after an existing host completes to the url"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + yield PlacesTestUtils.addVisits(NetUtil.newURI("http://www.visit3.mozilla.org")); + yield check_autocomplete({ + search: "visit3.mozilla.org/", + autofilled: "visit3.mozilla.org/", + completed: "visit3.mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_respect_www() { + do_print("Searching for www.me should yield www.me.mozilla.org/"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + yield PlacesTestUtils.addVisits(NetUtil.newURI("http://www.me.mozilla.org")); + yield check_autocomplete({ + search: "www.me", + autofilled: "www.me.mozilla.org/", + completed: "www.me.mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_bookmark_first() { + do_print("With a bookmark and history, the query result should be the bookmark"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + yield addBookmark({ uri: NetUtil.newURI("http://bookmark1.mozilla.org/") }); + yield PlacesTestUtils.addVisits(NetUtil.newURI("http://bookmark1.mozilla.org/foo")); + yield check_autocomplete({ + search: "bookmark", + autofilled: "bookmark1.mozilla.org/", + completed: "bookmark1.mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_full_path() { + do_print("Check to make sure we get the proper results with full paths"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + let places = [{ uri: NetUtil.newURI("http://smokey.mozilla.org/foo/bar/baz?bacon=delicious") }, + { uri: NetUtil.newURI("http://smokey.mozilla.org/foo/bar/baz?bacon=smokey") }]; + yield PlacesTestUtils.addVisits(places); + yield check_autocomplete({ + search: "smokey", + autofilled: "smokey.mozilla.org/", + completed: "smokey.mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_complete_to_slash() { + do_print("Check to make sure we autocomplete to the following '/'"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + let places = [{ uri: NetUtil.newURI("http://smokey.mozilla.org/foo/bar/baz?bacon=delicious") }, + { uri: NetUtil.newURI("http://smokey.mozilla.org/foo/bar/baz?bacon=smokey") }]; + yield PlacesTestUtils.addVisits(places); + yield check_autocomplete({ + search: "smokey.mozilla.org/fo", + autofilled: "smokey.mozilla.org/foo/", + completed: "http://smokey.mozilla.org/foo/", + }); + yield cleanup(); +}); + +add_task(function* test_complete_to_slash_with_www() { + do_print("Check to make sure we autocomplete to the following '/'"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + let places = [{ uri: NetUtil.newURI("http://www.smokey.mozilla.org/foo/bar/baz?bacon=delicious") }, + { uri: NetUtil.newURI("http://www.smokey.mozilla.org/foo/bar/baz?bacon=smokey") }]; + yield PlacesTestUtils.addVisits(places); + yield check_autocomplete({ + search: "smokey.mozilla.org/fo", + autofilled: "smokey.mozilla.org/foo/", + completed: "http://www.smokey.mozilla.org/foo/", + }); + yield cleanup(); +}); + +add_task(function* test_complete_querystring() { + do_print("Check to make sure we autocomplete after ?"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + yield PlacesTestUtils.addVisits(NetUtil.newURI("http://smokey.mozilla.org/foo?bacon=delicious")); + yield check_autocomplete({ + search: "smokey.mozilla.org/foo?", + autofilled: "smokey.mozilla.org/foo?bacon=delicious", + completed: "http://smokey.mozilla.org/foo?bacon=delicious", + }); + yield cleanup(); +}); + +add_task(function* test_complete_fragment() { + do_print("Check to make sure we autocomplete after #"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + yield PlacesTestUtils.addVisits(NetUtil.newURI("http://smokey.mozilla.org/foo?bacon=delicious#bar")); + yield check_autocomplete({ + search: "smokey.mozilla.org/foo?bacon=delicious#bar", + autofilled: "smokey.mozilla.org/foo?bacon=delicious#bar", + completed: "http://smokey.mozilla.org/foo?bacon=delicious#bar", + }); + yield cleanup(); +}); + +add_task(function* test_autocomplete_enabled_pref() { + Services.prefs.setBoolPref(PREF_AUTOCOMPLETE_ENABLED, false); + let types = ["history", "bookmark", "openpage"]; + for (type of types) { + do_check_eq(Services.prefs.getBoolPref("browser.urlbar.suggest." + type), false, + "suggest." + type + "pref should be false"); + } + Services.prefs.setBoolPref(PREF_AUTOCOMPLETE_ENABLED, true); + for (type of types) { + do_check_eq(Services.prefs.getBoolPref("browser.urlbar.suggest." + type), true, + "suggest." + type + "pref should be true"); + } + + // Clear prefs. + Services.prefs.clearUserPref(PREF_AUTOCOMPLETE_ENABLED); + for (type of types) { + Services.prefs.clearUserPref("browser.urlbar.suggest." + type); + } +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_autocomplete_on_value_removed_479089.js b/toolkit/components/places/tests/unifiedcomplete/test_autocomplete_on_value_removed_479089.js new file mode 100644 index 000000000..ecc96266b --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_autocomplete_on_value_removed_479089.js @@ -0,0 +1,39 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Need to test that removing a page from autocomplete actually removes a page + * Description From Shawn Wilsher :sdwilsh 2009-02-18 11:29:06 PST + * We don't test the code path of onValueRemoved + * for the autocomplete implementation + * Bug 479089 + */ + +add_task(function* test_autocomplete_on_value_removed() { + let listener = Cc["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"]. + getService(Components.interfaces.nsIAutoCompleteSimpleResultListener); + + let testUri = NetUtil.newURI("http://foo.mozilla.com/"); + yield PlacesTestUtils.addVisits({ + uri: testUri, + referrer: uri("http://mozilla.com/") + }); + + let query = PlacesUtils.history.getNewQuery(); + let options = PlacesUtils.history.getNewQueryOptions(); + // look for this uri only + query.uri = testUri; + + let root = PlacesUtils.history.executeQuery(query, options).root; + root.containerOpen = true; + Assert.equal(root.childCount, 1); + // call the untested code path + listener.onValueRemoved(null, testUri.spec, true); + // make sure it is GONE from the DB + Assert.equal(root.childCount, 0); + // close the container + root.containerOpen = false; +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_autofill_default_behavior.js b/toolkit/components/places/tests/unifiedcomplete/test_autofill_default_behavior.js new file mode 100644 index 000000000..482fcf485 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_autofill_default_behavior.js @@ -0,0 +1,310 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Test autoFill for different default behaviors. + */ + +add_task(function* test_default_behavior_host() { + let uri1 = NetUtil.newURI("http://typed/"); + let uri2 = NetUtil.newURI("http://visited/"); + let uri3 = NetUtil.newURI("http://bookmarked/"); + let uri4 = NetUtil.newURI("http://tpbk/"); + let uri5 = NetUtil.newURI("http://tagged/"); + + yield PlacesTestUtils.addVisits([ + { uri: uri1, title: "typed", transition: TRANSITION_TYPED }, + { uri: uri2, title: "visited" }, + { uri: uri4, title: "tpbk", transition: TRANSITION_TYPED }, + ]); + yield addBookmark( { uri: uri3, title: "bookmarked" } ); + yield addBookmark( { uri: uri4, title: "tpbk" } ); + yield addBookmark( { uri: uri5, title: "title", tags: ["foo"] } ); + + yield setFaviconForHref(uri1.spec, "chrome://global/skin/icons/information-16.png"); + yield setFaviconForHref(uri3.spec, "chrome://global/skin/icons/error-16.png"); + + // RESTRICT TO HISTORY. + Services.prefs.setBoolPref("browser.urlbar.suggest.history", true); + Services.prefs.setBoolPref("browser.urlbar.suggest.history.onlyTyped", false); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + + do_print("Restrict history, common visit, should not autoFill"); + yield check_autocomplete({ + search: "vi", + matches: [ { uri: uri2, title: "visited" } ], + autofilled: "vi", + completed: "vi" + }); + + do_print("Restrict history, typed visit, should autoFill"); + yield check_autocomplete({ + search: "ty", + matches: [ { uri: uri1, title: "typed", style: [ "autofill", "heuristic" ], + icon: "chrome://global/skin/icons/information-16.png" } ], + autofilled: "typed/", + completed: "typed/" + }); + + // Don't autoFill this one cause it's not typed. + do_print("Restrict history, bookmark, should not autoFill"); + yield check_autocomplete({ + search: "bo", + matches: [ ], + autofilled: "bo", + completed: "bo" + }); + + // Note we don't show this one cause it's not typed. + do_print("Restrict history, typed bookmark, should autoFill"); + yield check_autocomplete({ + search: "tp", + matches: [ { uri: uri4, title: "tpbk", style: [ "autofill", "heuristic" ] } ], + autofilled: "tpbk/", + completed: "tpbk/" + }); + + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + + // We are not restricting on typed, so we autoFill the bookmark even if we + // are restricted to history. We accept that cause not doing that + // would be a perf hit and the privacy implications are very weak. + do_print("Restrict history, bookmark, autoFill.typed = false, should autoFill"); + yield check_autocomplete({ + search: "bo", + matches: [ { uri: uri3, title: "bookmarked", style: [ "autofill", "heuristic" ], + icon: "chrome://global/skin/icons/error-16.png" } ], + autofilled: "bookmarked/", + completed: "bookmarked/" + }); + + do_print("Restrict history, common visit, autoFill.typed = false, should autoFill"); + yield check_autocomplete({ + search: "vi", + matches: [ { uri: uri2, title: "visited", style: [ "autofill", "heuristic" ] } ], + autofilled: "visited/", + completed: "visited/" + }); + + // RESTRICT TO TYPED. + // This should basically ignore autoFill.typed and acts as if it would be set. + Services.prefs.setBoolPref("browser.urlbar.suggest.history.onlyTyped", true); + + // Typed behavior basically acts like history, but filters on typed. + do_print("Restrict typed, common visit, autoFill.typed = false, should not autoFill"); + yield check_autocomplete({ + search: "vi", + matches: [ ], + autofilled: "vi", + completed: "vi" + }); + + do_print("Restrict typed, typed visit, autofill.typed = false, should autoFill"); + yield check_autocomplete({ + search: "ty", + matches: [ { uri: uri1, title: "typed", style: [ "autofill", "heuristic" ], + icon: "chrome://global/skin/icons/information-16.png"} ], + autofilled: "typed/", + completed: "typed/" + }); + + do_print("Restrict typed, bookmark, autofill.typed = false, should not autoFill"); + yield check_autocomplete({ + search: "bo", + matches: [ ], + autofilled: "bo", + completed: "bo" + }); + + do_print("Restrict typed, typed bookmark, autofill.typed = false, should autoFill"); + yield check_autocomplete({ + search: "tp", + matches: [ { uri: uri4, title: "tpbk", style: [ "autofill", "heuristic" ] } ], + autofilled: "tpbk/", + completed: "tpbk/" + }); + + // RESTRICT BOOKMARKS. + Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", true); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", true); + + do_print("Restrict bookmarks, common visit, should not autoFill"); + yield check_autocomplete({ + search: "vi", + matches: [ ], + autofilled: "vi", + completed: "vi" + }); + + do_print("Restrict bookmarks, typed visit, should not autoFill"); + yield check_autocomplete({ + search: "ty", + matches: [ ], + autofilled: "ty", + completed: "ty" + }); + + // Don't autoFill this one cause it's not typed. + do_print("Restrict bookmarks, bookmark, should not autoFill"); + yield check_autocomplete({ + search: "bo", + matches: [ { uri: uri3, title: "bookmarked", style: [ "bookmark" ], + icon: "chrome://global/skin/icons/error-16.png"} ], + autofilled: "bo", + completed: "bo" + }); + + // Note we don't show this one cause it's not typed. + do_print("Restrict bookmarks, typed bookmark, should autoFill"); + yield check_autocomplete({ + search: "tp", + matches: [ { uri: uri4, title: "tpbk", style: [ "autofill", "heuristic" ] } ], + autofilled: "tpbk/", + completed: "tpbk/" + }); + + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + + do_print("Restrict bookmarks, bookmark, autofill.typed = false, should autoFill"); + yield check_autocomplete({ + search: "bo", + matches: [ { uri: uri3, title: "bookmarked", style: [ "autofill", "heuristic" ], + icon: "chrome://global/skin/icons/error-16.png" } ], + autofilled: "bookmarked/", + completed: "bookmarked/" + }); + + // Don't autofill because it's a title. + do_print("Restrict bookmarks, title, autofill.typed = false, should not autoFill"); + yield check_autocomplete({ + search: "# ta", + matches: [ ], + autofilled: "# ta", + completed: "# ta" + }); + + // Don't autofill because it's a tag. + do_print("Restrict bookmarks, tag, autofill.typed = false, should not autoFill"); + yield check_autocomplete({ + search: "+ ta", + matches: [ { uri: uri5, title: "title", tags: [ "foo" ], style: [ "tag" ] } ], + autofilled: "+ ta", + completed: "+ ta" + }); + + yield cleanup(); +}); + +add_task(function* test_default_behavior_url() { + let uri1 = NetUtil.newURI("http://typed/ty/"); + let uri2 = NetUtil.newURI("http://visited/vi/"); + let uri3 = NetUtil.newURI("http://bookmarked/bo/"); + let uri4 = NetUtil.newURI("http://tpbk/tp/"); + + yield PlacesTestUtils.addVisits([ + { uri: uri1, title: "typed", transition: TRANSITION_TYPED }, + { uri: uri2, title: "visited" }, + { uri: uri4, title: "tpbk", transition: TRANSITION_TYPED }, + ]); + yield addBookmark( { uri: uri3, title: "bookmarked" } ); + yield addBookmark( { uri: uri4, title: "tpbk" } ); + + yield setFaviconForHref(uri1.spec, "chrome://global/skin/icons/information-16.png"); + yield setFaviconForHref(uri3.spec, "chrome://global/skin/icons/error-16.png"); + + // RESTRICT TO HISTORY. + Services.prefs.setBoolPref("browser.urlbar.suggest.history", true); + Services.prefs.setBoolPref("browser.urlbar.suggest.history.onlyTyped", false); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", true); + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", false); + + do_print("URL: Restrict history, common visit, should not autoFill"); + yield check_autocomplete({ + search: "visited/v", + matches: [ { uri: uri2, title: "visited" } ], + autofilled: "visited/v", + completed: "visited/v" + }); + + do_print("URL: Restrict history, typed visit, should autoFill"); + yield check_autocomplete({ + search: "typed/t", + matches: [ { uri: uri1, title: "typed/ty/", style: [ "autofill", "heuristic" ], + icon: "chrome://global/skin/icons/information-16.png"} ], + autofilled: "typed/ty/", + completed: "http://typed/ty/" + }); + + // Don't autoFill this one cause it's not typed. + do_print("URL: Restrict history, bookmark, should not autoFill"); + yield check_autocomplete({ + search: "bookmarked/b", + matches: [ ], + autofilled: "bookmarked/b", + completed: "bookmarked/b" + }); + + // Note we don't show this one cause it's not typed. + do_print("URL: Restrict history, typed bookmark, should autoFill"); + yield check_autocomplete({ + search: "tpbk/t", + matches: [ { uri: uri4, title: "tpbk/tp/", style: [ "autofill", "heuristic" ] } ], + autofilled: "tpbk/tp/", + completed: "http://tpbk/tp/" + }); + + // RESTRICT BOOKMARKS. + Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", true); + + do_print("URL: Restrict bookmarks, common visit, should not autoFill"); + yield check_autocomplete({ + search: "visited/v", + matches: [ ], + autofilled: "visited/v", + completed: "visited/v" + }); + + do_print("URL: Restrict bookmarks, typed visit, should not autoFill"); + yield check_autocomplete({ + search: "typed/t", + matches: [ ], + autofilled: "typed/t", + completed: "typed/t" + }); + + // Don't autoFill this one cause it's not typed. + do_print("URL: Restrict bookmarks, bookmark, should not autoFill"); + yield check_autocomplete({ + search: "bookmarked/b", + matches: [ { uri: uri3, title: "bookmarked", style: [ "bookmark" ], + icon: "chrome://global/skin/icons/error-16.png" } ], + autofilled: "bookmarked/b", + completed: "bookmarked/b" + }); + + // Note we don't show this one cause it's not typed. + do_print("URL: Restrict bookmarks, typed bookmark, should autoFill"); + yield check_autocomplete({ + search: "tpbk/t", + matches: [ { uri: uri4, title: "tpbk/tp/", style: [ "autofill", "heuristic" ] } ], + autofilled: "tpbk/tp/", + completed: "http://tpbk/tp/" + }); + + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + + do_print("URL: Restrict bookmarks, bookmark, autofill.typed = false, should autoFill"); + yield check_autocomplete({ + search: "bookmarked/b", + matches: [ { uri: uri3, title: "bookmarked/bo/", style: [ "autofill", "heuristic" ], + icon: "chrome://global/skin/icons/error-16.png" } ], + autofilled: "bookmarked/bo/", + completed: "http://bookmarked/bo/" + }); + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_avoid_middle_complete.js b/toolkit/components/places/tests/unifiedcomplete/test_avoid_middle_complete.js new file mode 100644 index 000000000..54fc343ca --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_avoid_middle_complete.js @@ -0,0 +1,179 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +add_task(function* test_prefix_space_noautofill() { + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://moz.org/test/"), + transition: TRANSITION_TYPED + }); + + do_print("Should not try to autoFill if search string contains a space"); + yield check_autocomplete({ + search: " mo", + autofilled: " mo", + completed: " mo" + }); + + yield cleanup(); +}); + +add_task(function* test_trailing_space_noautofill() { + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://moz.org/test/"), + transition: TRANSITION_TYPED + }); + + do_print("Should not try to autoFill if search string contains a space"); + yield check_autocomplete({ + search: "mo ", + autofilled: "mo ", + completed: "mo " + }); + + yield cleanup(); +}); + +add_task(function* test_searchEngine_autofill() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true); + Services.search.addEngineWithDetails("CakeSearch", "", "", "", + "GET", "http://cake.search/"); + let engine = Services.search.getEngineByName("CakeSearch"); + engine.addParam("q", "{searchTerms}", null); + do_register_cleanup(() => Services.search.removeEngine(engine)); + + do_print("Should autoFill search engine if search string does not contains a space"); + yield check_autocomplete({ + search: "ca", + autofilled: "cake.search", + completed: "http://cake.search" + }); + + yield cleanup(); +}); + +add_task(function* test_searchEngine_prefix_space_noautofill() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true); + Services.search.addEngineWithDetails("CupcakeSearch", "", "", "", + "GET", "http://cupcake.search/"); + let engine = Services.search.getEngineByName("CupcakeSearch"); + engine.addParam("q", "{searchTerms}", null); + do_register_cleanup(() => Services.search.removeEngine(engine)); + + do_print("Should not try to autoFill search engine if search string contains a space"); + yield check_autocomplete({ + search: " cu", + autofilled: " cu", + completed: " cu" + }); + + yield cleanup(); +}); + +add_task(function* test_searchEngine_trailing_space_noautofill() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true); + Services.search.addEngineWithDetails("BaconSearch", "", "", "", + "GET", "http://bacon.search/"); + let engine = Services.search.getEngineByName("BaconSearch"); + engine.addParam("q", "{searchTerms}", null); + do_register_cleanup(() => Services.search.removeEngine(engine)); + + do_print("Should not try to autoFill search engine if search string contains a space"); + yield check_autocomplete({ + search: "ba ", + autofilled: "ba ", + completed: "ba " + }); + + yield cleanup(); +}); + +add_task(function* test_searchEngine_www_noautofill() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true); + Services.search.addEngineWithDetails("HamSearch", "", "", "", + "GET", "http://ham.search/"); + let engine = Services.search.getEngineByName("HamSearch"); + engine.addParam("q", "{searchTerms}", null); + do_register_cleanup(() => Services.search.removeEngine(engine)); + + do_print("Should not autoFill search engine if search string contains www. but engine doesn't"); + yield check_autocomplete({ + search: "www.ham", + autofilled: "www.ham", + completed: "www.ham" + }); + + yield cleanup(); +}); + +add_task(function* test_searchEngine_different_scheme_noautofill() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true); + Services.search.addEngineWithDetails("PieSearch", "", "", "", + "GET", "https://pie.search/"); + let engine = Services.search.getEngineByName("PieSearch"); + engine.addParam("q", "{searchTerms}", null); + do_register_cleanup(() => Services.search.removeEngine(engine)); + + do_print("Should not autoFill search engine if search string has a different scheme."); + yield check_autocomplete({ + search: "http://pie", + autofilled: "http://pie", + completed: "http://pie" + }); + + yield cleanup(); +}); + +add_task(function* test_searchEngine_matching_prefix_autofill() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true); + Services.search.addEngineWithDetails("BeanSearch", "", "", "", + "GET", "http://www.bean.search/"); + let engine = Services.search.getEngineByName("BeanSearch"); + engine.addParam("q", "{searchTerms}", null); + do_register_cleanup(() => Services.search.removeEngine(engine)); + + + do_print("Should autoFill search engine if search string has matching prefix."); + yield check_autocomplete({ + search: "http://www.be", + autofilled: "http://www.bean.search", + completed: "http://www.bean.search" + }) + + do_print("Should autoFill search engine if search string has www prefix."); + yield check_autocomplete({ + search: "www.be", + autofilled: "www.bean.search", + completed: "http://www.bean.search" + }); + + do_print("Should autoFill search engine if search string has matching scheme."); + yield check_autocomplete({ + search: "http://be", + autofilled: "http://bean.search", + completed: "http://www.bean.search" + }); + + yield cleanup(); +}); + +add_task(function* test_prefix_autofill() { + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/test/"), + transition: TRANSITION_TYPED + }); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://moz.org/test/"), + transition: TRANSITION_TYPED + }); + + do_print("Should not try to autoFill in-the-middle if a search is canceled immediately"); + yield check_autocomplete({ + incompleteSearch: "moz", + search: "mozi", + autofilled: "mozilla.org/", + completed: "mozilla.org/" + }); + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_avoid_stripping_to_empty_tokens.js b/toolkit/components/places/tests/unifiedcomplete/test_avoid_stripping_to_empty_tokens.js new file mode 100644 index 000000000..1fcfe1c75 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_avoid_stripping_to_empty_tokens.js @@ -0,0 +1,41 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +add_task(function* test_protocol_trimming() { + for (let prot of ["http", "https", "ftp"]) { + let visit = { + // Include the protocol in the query string to ensure we get matches (see bug 1059395) + uri: NetUtil.newURI(prot + "://www.mozilla.org/test/?q=" + prot + encodeURIComponent("://") + "www.foo"), + title: "Test title", + transition: TRANSITION_TYPED + }; + yield PlacesTestUtils.addVisits(visit); + let matches = [{uri: visit.uri, title: visit.title}]; + + let inputs = [ + prot + "://", + prot + ":// ", + prot + ":// mo", + prot + "://mo te", + prot + "://www.", + prot + "://www. ", + prot + "://www. mo", + prot + "://www.mo te", + "www.", + "www. ", + "www. mo", + "www.mo te" + ]; + for (let input of inputs) { + do_print("Searching for: " + input); + yield check_autocomplete({ + search: input, + matches: matches + }); + } + + yield cleanup(); + } +}); + diff --git a/toolkit/components/places/tests/unifiedcomplete/test_casing.js b/toolkit/components/places/tests/unifiedcomplete/test_casing.js new file mode 100644 index 000000000..585b51be1 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_casing.js @@ -0,0 +1,157 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +add_task(function* test_casing_1() { + do_print("Searching for cased entry 1"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "MOZ", + autofilled: "MOZilla.org/", + completed: "mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_casing_2() { + do_print("Searching for cased entry 2"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "mozilla.org/T", + autofilled: "mozilla.org/T", + completed: "mozilla.org/T" + }); + yield cleanup(); +}); + +add_task(function* test_casing_3() { + do_print("Searching for cased entry 3"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/Test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "mozilla.org/T", + autofilled: "mozilla.org/Test/", + completed: "http://mozilla.org/Test/" + }); + yield cleanup(); +}); + +add_task(function* test_casing_4() { + do_print("Searching for cased entry 4"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/Test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "mOzilla.org/t", + autofilled: "mOzilla.org/t", + completed: "mOzilla.org/t" + }); + yield cleanup(); +}); + +add_task(function* test_casing_5() { + do_print("Searching for cased entry 5"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/Test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "mOzilla.org/T", + autofilled: "mOzilla.org/Test/", + completed: "http://mozilla.org/Test/" + }); + yield cleanup(); +}); + +add_task(function* test_untrimmed_casing() { + do_print("Searching for untrimmed cased entry"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/Test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "http://mOz", + autofilled: "http://mOzilla.org/", + completed: "http://mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_untrimmed_www_casing() { + do_print("Searching for untrimmed cased entry with www"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://www.mozilla.org/Test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "http://www.mOz", + autofilled: "http://www.mOzilla.org/", + completed: "http://www.mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_untrimmed_path_casing() { + do_print("Searching for untrimmed cased entry with path"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/Test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "http://mOzilla.org/t", + autofilled: "http://mOzilla.org/t", + completed: "http://mOzilla.org/t" + }); + yield cleanup(); +}); + +add_task(function* test_untrimmed_path_casing_2() { + do_print("Searching for untrimmed cased entry with path 2"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/Test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "http://mOzilla.org/T", + autofilled: "http://mOzilla.org/Test/", + completed: "http://mozilla.org/Test/" + }); + yield cleanup(); +}); + +add_task(function* test_untrimmed_path_www_casing() { + do_print("Searching for untrimmed cased entry with www and path"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://www.mozilla.org/Test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "http://www.mOzilla.org/t", + autofilled: "http://www.mOzilla.org/t", + completed: "http://www.mOzilla.org/t" + }); + yield cleanup(); +}); + +add_task(function* test_untrimmed_path_www_casing_2() { + do_print("Searching for untrimmed cased entry with www and path 2"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://www.mozilla.org/Test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "http://www.mOzilla.org/T", + autofilled: "http://www.mOzilla.org/Test/", + completed: "http://www.mozilla.org/Test/" + }); + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_do_not_trim.js b/toolkit/components/places/tests/unifiedcomplete/test_do_not_trim.js new file mode 100644 index 000000000..014d74998 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_do_not_trim.js @@ -0,0 +1,91 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Inline should never return matches shorter than the search string, since +// that largely confuses completeDefaultIndex + +add_task(function* test_not_autofill_ws_1() { + do_print("Do not autofill whitespaced entry 1"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/link/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "mozilla.org ", + autofilled: "mozilla.org ", + completed: "mozilla.org " + }); + yield cleanup(); +}); + +add_task(function* test_not_autofill_ws_2() { + do_print("Do not autofill whitespaced entry 2"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/link/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "mozilla.org/ ", + autofilled: "mozilla.org/ ", + completed: "mozilla.org/ " + }); + yield cleanup(); +}); + +add_task(function* test_not_autofill_ws_3() { + do_print("Do not autofill whitespaced entry 3"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/link/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "mozilla.org/link ", + autofilled: "mozilla.org/link ", + completed: "mozilla.org/link " + }); + yield cleanup(); +}); + +add_task(function* test_not_autofill_ws_4() { + do_print("Do not autofill whitespaced entry 4"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/link/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "mozilla.org/link/ ", + autofilled: "mozilla.org/link/ ", + completed: "mozilla.org/link/ " + }); + yield cleanup(); +}); + + +add_task(function* test_not_autofill_ws_5() { + do_print("Do not autofill whitespaced entry 5"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/link/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "moz illa ", + autofilled: "moz illa ", + completed: "moz illa " + }); + yield cleanup(); +}); + +add_task(function* test_not_autofill_ws_6() { + do_print("Do not autofill whitespaced entry 6"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/link/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: " mozilla", + autofilled: " mozilla", + completed: " mozilla" + }); + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_download_embed_bookmarks.js b/toolkit/components/places/tests/unifiedcomplete/test_download_embed_bookmarks.js new file mode 100644 index 000000000..72661d075 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_download_embed_bookmarks.js @@ -0,0 +1,71 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + * vim:set ts=2 sw=2 sts=2 et: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Tests bug 449406 to ensure that TRANSITION_DOWNLOAD, TRANSITION_EMBED and + * TRANSITION_FRAMED_LINK bookmarked uri's show up in the location bar. + */ + +add_task(function* test_download_embed_bookmarks() { + let uri1 = NetUtil.newURI("http://download/bookmarked"); + let uri2 = NetUtil.newURI("http://embed/bookmarked"); + let uri3 = NetUtil.newURI("http://framed/bookmarked"); + let uri4 = NetUtil.newURI("http://download"); + let uri5 = NetUtil.newURI("http://embed"); + let uri6 = NetUtil.newURI("http://framed"); + yield PlacesTestUtils.addVisits([ + { uri: uri1, title: "download-bookmark", transition: TRANSITION_DOWNLOAD }, + { uri: uri2, title: "embed-bookmark", transition: TRANSITION_EMBED }, + { uri: uri3, title: "framed-bookmark", transition: TRANSITION_FRAMED_LINK}, + { uri: uri4, title: "download2", transition: TRANSITION_DOWNLOAD }, + { uri: uri5, title: "embed2", transition: TRANSITION_EMBED }, + { uri: uri6, title: "framed2", transition: TRANSITION_FRAMED_LINK } + ]); + yield addBookmark({ uri: uri1, + title: "download-bookmark" }); + yield addBookmark({ uri: uri2, + title: "embed-bookmark" }); + yield addBookmark({ uri: uri3, + title: "framed-bookmark" }); + + do_print("Searching for bookmarked download uri matches"); + yield check_autocomplete({ + search: "download-bookmark", + matches: [ { uri: uri1, title: "download-bookmark", style: [ "bookmark" ] } ] + }); + + do_print("Searching for bookmarked embed uri matches"); + yield check_autocomplete({ + search: "embed-bookmark", + matches: [ { uri: uri2, title: "embed-bookmark", style: [ "bookmark" ] } ] + }); + + do_print("Searching for bookmarked framed uri matches"); + yield check_autocomplete({ + search: "framed-bookmark", + matches: [ { uri: uri3, title: "framed-bookmark", style: [ "bookmark" ] } ] + }); + + do_print("Searching for download uri does not match"); + yield check_autocomplete({ + search: "download2", + matches: [ ] + }); + + do_print("Searching for embed uri does not match"); + yield check_autocomplete({ + search: "embed2", + matches: [ ] + }); + + do_print("Searching for framed uri does not match"); + yield check_autocomplete({ + search: "framed2", + matches: [ ] + }); + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_dupe_urls.js b/toolkit/components/places/tests/unifiedcomplete/test_dupe_urls.js new file mode 100644 index 000000000..a39c15236 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_dupe_urls.js @@ -0,0 +1,23 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Ensure inline autocomplete doesn't return zero frecency pages. + +add_task(function* test_dupe_urls() { + do_print("Searching for urls with dupes should only show one"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/"), + transition: TRANSITION_TYPED + }, { + uri: NetUtil.newURI("http://mozilla.org/?") + }); + yield check_autocomplete({ + search: "moz", + autofilled: "mozilla.org/", + completed: "mozilla.org/", + matches: [ { uri: NetUtil.newURI("http://mozilla.org/"), + title: "mozilla.org", + style: [ "autofill", "heuristic" ] } ] + }); + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_empty_search.js b/toolkit/components/places/tests/unifiedcomplete/test_empty_search.js new file mode 100644 index 000000000..ef1159705 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_empty_search.js @@ -0,0 +1,98 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Test for bug 426864 that makes sure the empty search (drop down list) only + * shows typed pages from history. + */ + +add_task(function* test_javascript_match() { + let uri1 = NetUtil.newURI("http://t.foo/0"); + let uri2 = NetUtil.newURI("http://t.foo/1"); + let uri3 = NetUtil.newURI("http://t.foo/2"); + let uri4 = NetUtil.newURI("http://t.foo/3"); + let uri5 = NetUtil.newURI("http://t.foo/4"); + let uri6 = NetUtil.newURI("http://t.foo/5"); + let uri7 = NetUtil.newURI("http://t.foo/6"); + + yield PlacesTestUtils.addVisits([ + { uri: uri1, title: "title" }, + { uri: uri2, title: "title" }, + { uri: uri3, title: "title", transition: TRANSITION_TYPED}, + { uri: uri4, title: "title", transition: TRANSITION_TYPED }, + { uri: uri6, title: "title", transition: TRANSITION_TYPED }, + { uri: uri7, title: "title" } + ]); + + yield addBookmark({ uri: uri2, + title: "title" }); + yield addBookmark({ uri: uri4, + title: "title" }); + yield addBookmark({ uri: uri5, + title: "title" }); + yield addBookmark({ uri: uri6, + title: "title" }); + + addOpenPages(uri7, 1); + + // Now remove page 6 from history, so it is an unvisited bookmark. + PlacesUtils.history.removePage(uri6); + + do_print("Match everything"); + yield check_autocomplete({ + search: "foo", + searchParam: "enable-actions", + matches: [ makeSearchMatch("foo", { heuristic: true }), + { uri: uri1, title: "title" }, + { uri: uri2, title: "title", style: ["bookmark"] }, + { uri: uri3, title: "title" }, + { uri: uri4, title: "title", style: ["bookmark"] }, + { uri: uri5, title: "title", style: ["bookmark"] }, + { uri: uri6, title: "title", style: ["bookmark"] }, + makeSwitchToTabMatch("http://t.foo/6", { title: "title" }), + ] + }); + + // Note the next few tests do *not* get a search result as enable-actions + // isn't specified. + do_print("Match only typed history"); + yield check_autocomplete({ + search: "foo ^ ~", + matches: [ { uri: uri3, title: "title" }, + { uri: uri4, title: "title" } ] + }); + + do_print("Drop-down empty search matches only typed history"); + yield check_autocomplete({ + search: "", + matches: [ { uri: uri3, title: "title" }, + { uri: uri4, title: "title" } ] + }); + + do_print("Drop-down empty search matches only bookmarks"); + Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", true); + yield check_autocomplete({ + search: "", + matches: [ { uri: uri2, title: "title", style: ["bookmark"] }, + { uri: uri4, title: "title", style: ["bookmark"] }, + { uri: uri5, title: "title", style: ["bookmark"] }, + { uri: uri6, title: "title", style: ["bookmark"] } ] + }); + + do_print("Drop-down empty search matches only open tabs"); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + yield check_autocomplete({ + search: "", + searchParam: "enable-actions", + matches: [ + makeSwitchToTabMatch("http://t.foo/6", { title: "title" }), + ] + }); + + Services.prefs.clearUserPref("browser.urlbar.suggest.history"); + Services.prefs.clearUserPref("browser.urlbar.suggest.bookmark"); + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_enabled.js b/toolkit/components/places/tests/unifiedcomplete/test_enabled.js new file mode 100644 index 000000000..dee8df8ec --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_enabled.js @@ -0,0 +1,68 @@ +add_task(function* test_enabled() { + // Test for bug 471903 to make sure searching in autocomplete can be turned on + // and off. Also test bug 463535 for pref changing search. + let uri = NetUtil.newURI("http://url/0"); + yield PlacesTestUtils.addVisits([ { uri: uri, title: "title" } ]); + + do_print("plain search"); + yield check_autocomplete({ + search: "url", + matches: [ { uri: uri, title: "title" } ] + }); + + do_print("search disabled"); + Services.prefs.setBoolPref("browser.urlbar.autocomplete.enabled", false); + yield check_autocomplete({ + search: "url", + matches: [ ] + }); + + do_print("resume normal search"); + Services.prefs.setBoolPref("browser.urlbar.autocomplete.enabled", true); + yield check_autocomplete({ + search: "url", + matches: [ { uri: uri, title: "title" } ] + }); + + yield cleanup(); +}); + +add_task(function* test_sync_enabled() { + // Initialize unified complete. + Cc["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"] + .getService(Ci.mozIPlacesAutoComplete); + + let types = [ "history", "bookmark", "openpage", "searches" ]; + + // Test the service keeps browser.urlbar.autocomplete.enabled synchronized + // with browser.urlbar.suggest prefs. + for (let type of types) { + Services.prefs.setBoolPref("browser.urlbar.suggest." + type, true); + } + Assert.equal(Services.prefs.getBoolPref("browser.urlbar.autocomplete.enabled"), true); + + // Disable autocomplete and check all the suggest prefs are set to false. + Services.prefs.setBoolPref("browser.urlbar.autocomplete.enabled", false); + for (let type of types) { + Assert.equal(Services.prefs.getBoolPref("browser.urlbar.suggest." + type), false); + } + + // Setting even a single suggest pref to true should enable autocomplete. + Services.prefs.setBoolPref("browser.urlbar.suggest.history", true); + for (let type of types.filter(t => t != "history")) { + Assert.equal(Services.prefs.getBoolPref("browser.urlbar.suggest." + type), false); + } + Assert.equal(Services.prefs.getBoolPref("browser.urlbar.autocomplete.enabled"), true); + + // Disable autocoplete again, then re-enable it and check suggest prefs + // have been reset. + Services.prefs.setBoolPref("browser.urlbar.autocomplete.enabled", false); + Services.prefs.setBoolPref("browser.urlbar.autocomplete.enabled", true); + for (let type of types.filter(t => t != "history")) { + if (type == "searches") { + Assert.equal(Services.prefs.getBoolPref("browser.urlbar.suggest." + type), false); + } else { + Assert.equal(Services.prefs.getBoolPref("browser.urlbar.suggest." + type), true); + } + } +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_escape_self.js b/toolkit/components/places/tests/unifiedcomplete/test_escape_self.js new file mode 100644 index 000000000..ff6e5f929 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_escape_self.js @@ -0,0 +1,31 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Test bug 422698 to make sure searches with urls from the location bar + * correctly match itself when it contains escaped characters. + */ + +add_task(function* test_escape() { + let uri1 = NetUtil.newURI("http://unescapeduri/"); + let uri2 = NetUtil.newURI("http://escapeduri/%40/"); + yield PlacesTestUtils.addVisits([ + { uri: uri1, title: "title" }, + { uri: uri2, title: "title" } + ]); + + do_print("Unescaped location matches itself"); + yield check_autocomplete({ + search: "http://unescapeduri/", + matches: [ { uri: uri1, title: "title" } ] + }); + + do_print("Escaped location matches itself"); + yield check_autocomplete({ + search: "http://escapeduri/%40/", + matches: [ { uri: uri2, title: "title" } ] + }); + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_extension_matches.js b/toolkit/components/places/tests/unifiedcomplete/test_extension_matches.js new file mode 100644 index 000000000..76af20558 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_extension_matches.js @@ -0,0 +1,384 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + * vim:set ts=2 sw=2 sts=2 et: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +Cu.import("resource://gre/modules/ExtensionSearchHandler.jsm"); + +let controller = Cc["@mozilla.org/autocomplete/controller;1"].getService(Ci.nsIAutoCompleteController); + +add_task(function* test_correct_errors_are_thrown() { + let keyword = "foo"; + let anotherKeyword = "bar"; + let unregisteredKeyword = "baz"; + + // Register a keyword. + ExtensionSearchHandler.registerKeyword(keyword, { emit: () => {} }); + + // Try registering the keyword again. + Assert.throws(() => ExtensionSearchHandler.registerKeyword(keyword, { emit: () => {} })); + + // Register a different keyword. + ExtensionSearchHandler.registerKeyword(anotherKeyword, { emit: () => {} }); + + // Try calling handleSearch for an unregistered keyword. + Assert.throws(() => ExtensionSearchHandler.handleSearch(unregisteredKeyword, `${unregisteredKeyword} `, () => {})); + + // Try calling handleSearch without a callback. + Assert.throws(() => ExtensionSearchHandler.handleSearch(unregisteredKeyword, `${unregisteredKeyword} `)); + + // Try getting the description for a keyword which isn't registered. + Assert.throws(() => ExtensionSearchHandler.getDescription(unregisteredKeyword)); + + // Try getting the extension name for a keyword which isn't registered. + Assert.throws(() => ExtensionSearchHandler.getExtensionName(unregisteredKeyword)); + + // Try setting the default suggestion for a keyword which isn't registered. + Assert.throws(() => ExtensionSearchHandler.setDefaultSuggestion(unregisteredKeyword, "suggestion")); + + // Try calling handleInputCancelled when there is no active input session. + Assert.throws(() => ExtensionSearchHandler.handleInputCancelled()); + + // Try calling handleInputEntered when there is no active input session. + Assert.throws(() => ExtensionSearchHandler.handleInputEntered(anotherKeyword, `${anotherKeyword} test`, "tab")); + + // Start a session by calling handleSearch with the registered keyword. + ExtensionSearchHandler.handleSearch(keyword, `${keyword} test`, () => {}); + + // Try providing suggestions for an unregistered keyword. + Assert.throws(() => ExtensionSearchHandler.addSuggestions(unregisteredKeyword, 0, [])); + + // Try providing suggestions for an inactive keyword. + Assert.throws(() => ExtensionSearchHandler.addSuggestions(anotherKeyword, 0, [])); + + // Try calling handleSearch for an inactive keyword. + Assert.throws(() => ExtensionSearchHandler.handleSearch(anotherKeyword, `${anotherKeyword} `, () => {})); + + // Try calling addSuggestions with an old callback ID. + Assert.throws(() => ExtensionSearchHandler.addSuggestions(keyword, 0, [])); + + // Add suggestions with a valid callback ID. + ExtensionSearchHandler.addSuggestions(keyword, 1, []); + + // Add suggestions again with a valid callback ID. + ExtensionSearchHandler.addSuggestions(keyword, 1, []); + + // Try calling addSuggestions with a future callback ID. + Assert.throws(() => ExtensionSearchHandler.addSuggestions(keyword, 2, [])); + + // End the input session by calling handleInputCancelled. + ExtensionSearchHandler.handleInputCancelled(); + + // Try calling handleInputCancelled after the session has ended. + Assert.throws(() => ExtensionSearchHandler.handleInputCancelled()); + + // Try calling handleSearch that doesn't have a space after the keyword. + Assert.throws(() => ExtensionSearchHandler.handleSearch(anotherKeyword, `${anotherKeyword}`, () => {})); + + // Try calling handleSearch with text starting with the wrong keyword. + Assert.throws(() => ExtensionSearchHandler.handleSearch(anotherKeyword, `${keyword} test`, () => {})); + + // Start a new session by calling handleSearch with a different keyword + ExtensionSearchHandler.handleSearch(anotherKeyword, `${anotherKeyword} test`, () => {}); + + // Try adding suggestions again with the same callback ID now that the input session has ended. + Assert.throws(() => ExtensionSearchHandler.addSuggestions(keyword, 1, [])); + + // Add suggestions with a valid callback ID. + ExtensionSearchHandler.addSuggestions(anotherKeyword, 2, []); + + // Try adding suggestions with a valid callback ID but a different keyword. + Assert.throws(() => ExtensionSearchHandler.addSuggestions(keyword, 2, [])); + + // Try adding suggestions with a valid callback ID but an unregistered keyword. + Assert.throws(() => ExtensionSearchHandler.addSuggestions(unregisteredKeyword, 2, [])); + + // Set the default suggestion. + ExtensionSearchHandler.setDefaultSuggestion(anotherKeyword, {description: "test result"}); + + // Try ending the session using handleInputEntered with a different keyword. + Assert.throws(() => ExtensionSearchHandler.handleInputEntered(keyword, `${keyword} test`, "tab")); + + // Try calling handleInputEntered with invalid text. + Assert.throws(() => ExtensionSearchHandler.handleInputEntered(anotherKeyword, ` test`, "tab")); + + // Try calling handleInputEntered with an invalid disposition. + Assert.throws(() => ExtensionSearchHandler.handleInputEntered(anotherKeyword, `${anotherKeyword} test`, "invalid")); + + // End the session by calling handleInputEntered. + ExtensionSearchHandler.handleInputEntered(anotherKeyword, `${anotherKeyword} test`, "tab"); + + // Try calling handleInputEntered after the session has ended. + Assert.throws(() => ExtensionSearchHandler.handleInputEntered(anotherKeyword, `${anotherKeyword} test`, "tab")); + + // Unregister the keyword. + ExtensionSearchHandler.unregisterKeyword(keyword); + + // Try setting the default suggestion for the unregistered keyword. + Assert.throws(() => ExtensionSearchHandler.setDefaultSuggestion(keyword, {description: "test"})); + + // Try handling a search with the unregistered keyword. + Assert.throws(() => ExtensionSearchHandler.handleSearch(keyword, `${keyword} test`, () => {})); + + // Try unregistering the keyword again. + Assert.throws(() => ExtensionSearchHandler.unregisterKeyword(keyword)); + + // Unregister the other keyword. + ExtensionSearchHandler.unregisterKeyword(anotherKeyword); + + // Try unregistering the word which was never registered. + Assert.throws(() => ExtensionSearchHandler.unregisterKeyword(unregisteredKeyword)); + + // Try setting the default suggestion for a word that was never registered. + Assert.throws(() => ExtensionSearchHandler.setDefaultSuggestion(unregisteredKeyword, {description: "test"})); + + yield cleanup(); +}); + +add_task(function* test_correct_events_are_emitted() { + let events = []; + function checkEvents(expectedEvents) { + Assert.equal(events.length, expectedEvents.length, "The correct number of events fired"); + expectedEvents.forEach((e, i) => Assert.equal(e, events[i], `Expected "${e}" event to fire`)); + events = []; + } + + let mockExtension = { emit: message => events.push(message) }; + + let keyword = "foo"; + let anotherKeyword = "bar"; + + ExtensionSearchHandler.registerKeyword(keyword, mockExtension); + ExtensionSearchHandler.registerKeyword(anotherKeyword, mockExtension); + + ExtensionSearchHandler.handleSearch(keyword, `${keyword} `, () => {}); + checkEvents([ExtensionSearchHandler.MSG_INPUT_STARTED]); + + ExtensionSearchHandler.handleSearch(keyword, `${keyword} f`, () => {}); + checkEvents([ExtensionSearchHandler.MSG_INPUT_CHANGED]); + + ExtensionSearchHandler.handleInputEntered(keyword, `${keyword} f`, "tab"); + checkEvents([ExtensionSearchHandler.MSG_INPUT_ENTERED]); + + ExtensionSearchHandler.handleSearch(keyword, `${keyword} f`, () => {}); + checkEvents([ + ExtensionSearchHandler.MSG_INPUT_STARTED, + ExtensionSearchHandler.MSG_INPUT_CHANGED + ]); + + ExtensionSearchHandler.handleInputCancelled(); + checkEvents([ExtensionSearchHandler.MSG_INPUT_CANCELLED]); + + ExtensionSearchHandler.handleSearch(anotherKeyword, `${anotherKeyword} baz`, () => {}); + checkEvents([ + ExtensionSearchHandler.MSG_INPUT_STARTED, + ExtensionSearchHandler.MSG_INPUT_CHANGED + ]); + + ExtensionSearchHandler.handleInputEntered(anotherKeyword, `${anotherKeyword} baz`, "tab"); + checkEvents([ExtensionSearchHandler.MSG_INPUT_ENTERED]); + + ExtensionSearchHandler.unregisterKeyword(keyword); +}); + +add_task(function* test_removes_suggestion_if_its_content_is_typed_in() { + let keyword = "test"; + let extensionName = "Foo Bar"; + + let mockExtension = { + name: extensionName, + emit(message, text, id) { + if (message === ExtensionSearchHandler.MSG_INPUT_CHANGED) { + ExtensionSearchHandler.addSuggestions(keyword, id, [ + {content: "foo", description: "first suggestion"}, + {content: "bar", description: "second suggestion"}, + {content: "baz", description: "third suggestion"}, + ]); + controller.stopSearch(); + } + } + }; + + ExtensionSearchHandler.registerKeyword(keyword, mockExtension); + + yield check_autocomplete({ + search: `${keyword} unmatched`, + searchParam: "enable-actions", + matches: [ + makeExtensionMatch({heuristic: true, keyword, description: extensionName, content: `${keyword} unmatched`}), + makeExtensionMatch({keyword, content: `${keyword} foo`, description: "first suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} bar`, description: "second suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} baz`, description: "third suggestion"}) + ] + }); + + yield check_autocomplete({ + search: `${keyword} foo`, + searchParam: "enable-actions", + matches: [ + makeExtensionMatch({heuristic: true, keyword, description: extensionName, content: `${keyword} foo`}), + makeExtensionMatch({keyword, content: `${keyword} bar`, description: "second suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} baz`, description: "third suggestion"}) + ] + }); + + yield check_autocomplete({ + search: `${keyword} bar`, + searchParam: "enable-actions", + matches: [ + makeExtensionMatch({heuristic: true, keyword, description: extensionName, content: `${keyword} bar`}), + makeExtensionMatch({keyword, content: `${keyword} foo`, description: "first suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} baz`, description: "third suggestion"}) + ] + }); + + yield check_autocomplete({ + search: `${keyword} baz`, + searchParam: "enable-actions", + matches: [ + makeExtensionMatch({heuristic: true, keyword, description: extensionName, content: `${keyword} baz`}), + makeExtensionMatch({keyword, content: `${keyword} foo`, description: "first suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} bar`, description: "second suggestion"}) + ] + }); + + ExtensionSearchHandler.unregisterKeyword(keyword); + yield cleanup(); +}); + +add_task(function* test_extension_results_should_come_first() { + let keyword = "test"; + let extensionName = "Omnibox Example"; + + let uri = NetUtil.newURI(`http://a.com/b`); + yield PlacesTestUtils.addVisits([ + { uri, title: `${keyword} -` }, + ]); + + let mockExtension = { + name: extensionName, + emit(message, text, id) { + if (message === ExtensionSearchHandler.MSG_INPUT_CHANGED) { + ExtensionSearchHandler.addSuggestions(keyword, id, [ + {content: "foo", description: "first suggestion"}, + {content: "bar", description: "second suggestion"}, + {content: "baz", description: "third suggestion"}, + ]); + } + controller.stopSearch(); + } + }; + + ExtensionSearchHandler.registerKeyword(keyword, mockExtension); + + // Start an input session before testing MSG_INPUT_CHANGED. + ExtensionSearchHandler.handleSearch(keyword, `${keyword} `, () => {}); + + yield check_autocomplete({ + search: `${keyword} -`, + searchParam: "enable-actions", + matches: [ + makeExtensionMatch({heuristic: true, keyword, description: extensionName, content: `${keyword} -`}), + makeExtensionMatch({keyword, content: `${keyword} foo`, description: "first suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} bar`, description: "second suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} baz`, description: "third suggestion"}), + { uri, title: `${keyword} -` } + ] + }); + + ExtensionSearchHandler.unregisterKeyword(keyword); + yield cleanup(); +}); + +add_task(function* test_setting_the_default_suggestion() { + let keyword = "test"; + let extensionName = "Omnibox Example"; + + let mockExtension = { + name: extensionName, + emit(message, text, id) { + if (message === ExtensionSearchHandler.MSG_INPUT_CHANGED) { + ExtensionSearchHandler.addSuggestions(keyword, id, []); + } + controller.stopSearch(); + } + }; + + ExtensionSearchHandler.registerKeyword(keyword, mockExtension); + + ExtensionSearchHandler.setDefaultSuggestion(keyword, { + description: "hello world" + }); + + let searchString = `${keyword} search query`; + yield check_autocomplete({ + search: searchString, + searchParam: "enable-actions", + matches: [ + makeExtensionMatch({heuristic: true, keyword, description: "hello world", content: searchString}), + ] + }); + + ExtensionSearchHandler.setDefaultSuggestion(keyword, { + description: "foo bar" + }); + + yield check_autocomplete({ + search: searchString, + searchParam: "enable-actions", + matches: [ + makeExtensionMatch({heuristic: true, keyword, description: "foo bar", content: searchString}), + ] + }); + + ExtensionSearchHandler.unregisterKeyword(keyword); + yield cleanup(); +}); + +add_task(function* test_maximum_number_of_suggestions_is_enforced() { + let keyword = "test"; + let extensionName = "Omnibox Example"; + + let mockExtension = { + name: extensionName, + emit(message, text, id) { + if (message === ExtensionSearchHandler.MSG_INPUT_CHANGED) { + ExtensionSearchHandler.addSuggestions(keyword, id, [ + {content: "a", description: "first suggestion"}, + {content: "b", description: "second suggestion"}, + {content: "c", description: "third suggestion"}, + {content: "d", description: "fourth suggestion"}, + {content: "e", description: "fifth suggestion"}, + {content: "f", description: "sixth suggestion"}, + {content: "g", description: "seventh suggestion"}, + {content: "h", description: "eigth suggestion"}, + {content: "i", description: "ninth suggestion"}, + {content: "j", description: "tenth suggestion"}, + ]); + controller.stopSearch(); + } + } + }; + + ExtensionSearchHandler.registerKeyword(keyword, mockExtension); + + // Start an input session before testing MSG_INPUT_CHANGED. + ExtensionSearchHandler.handleSearch(keyword, `${keyword} `, () => {}); + + yield check_autocomplete({ + search: `${keyword} #`, + searchParam: "enable-actions", + matches: [ + makeExtensionMatch({heuristic: true, keyword, description: extensionName, content: `${keyword} #`}), + makeExtensionMatch({keyword, content: `${keyword} a`, description: "first suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} b`, description: "second suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} c`, description: "third suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} d`, description: "fourth suggestion"}), + makeExtensionMatch({keyword, content: `${keyword} e`, description: "fifth suggestion"}), + ] + }); + + ExtensionSearchHandler.unregisterKeyword(keyword); + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_ignore_protocol.js b/toolkit/components/places/tests/unifiedcomplete/test_ignore_protocol.js new file mode 100644 index 000000000..92e7f601a --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_ignore_protocol.js @@ -0,0 +1,24 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Test bug 424509 to make sure searching for "h" doesn't match "http" of urls. + */ + +add_task(function* test_escape() { + let uri1 = NetUtil.newURI("http://site/"); + let uri2 = NetUtil.newURI("http://happytimes/"); + yield PlacesTestUtils.addVisits([ + { uri: uri1, title: "title" }, + { uri: uri2, title: "title" } + ]); + + do_print("Searching for h matches site and not http://"); + yield check_autocomplete({ + search: "h", + matches: [ { uri: uri2, title: "title" } ] + }); + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_keyword_search.js b/toolkit/components/places/tests/unifiedcomplete/test_keyword_search.js new file mode 100644 index 000000000..12b7fea77 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_keyword_search.js @@ -0,0 +1,73 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Test for bug 392143 that puts keyword results into the autocomplete. Makes + * sure that multiple parameter queries get spaces converted to +, + converted + * to %2B, non-ascii become escaped, and pages in history that match the + * keyword uses the page's title. + * + * Also test for bug 249468 by making sure multiple keyword bookmarks with the + * same keyword appear in the list. + */ + +add_task(function* test_keyword_searc() { + let uri1 = NetUtil.newURI("http://abc/?search=%s"); + let uri2 = NetUtil.newURI("http://abc/?search=ThisPageIsInHistory"); + yield PlacesTestUtils.addVisits([ + { uri: uri1, title: "Generic page title" }, + { uri: uri2, title: "Generic page title" } + ]); + yield addBookmark({ uri: uri1, title: "Bookmark title", keyword: "key"}); + + do_print("Plain keyword query"); + yield check_autocomplete({ + search: "key term", + matches: [ { uri: NetUtil.newURI("http://abc/?search=term"), title: "abc", style: ["keyword", "heuristic"] } ] + }); + + do_print("Plain keyword UC"); + yield check_autocomplete({ + search: "key TERM", + matches: [ { uri: NetUtil.newURI("http://abc/?search=TERM"), title: "abc", style: ["keyword", "heuristic"] } ] + }); + + do_print("Multi-word keyword query"); + yield check_autocomplete({ + search: "key multi word", + matches: [ { uri: NetUtil.newURI("http://abc/?search=multi%20word"), title: "abc", style: ["keyword", "heuristic"] } ] + }); + + do_print("Keyword query with +"); + yield check_autocomplete({ + search: "key blocking+", + matches: [ { uri: NetUtil.newURI("http://abc/?search=blocking%2B"), title: "abc", style: ["keyword", "heuristic"] } ] + }); + + do_print("Unescaped term in query"); + yield check_autocomplete({ + search: "key ユニコード", + matches: [ { uri: NetUtil.newURI("http://abc/?search=ユニコード"), title: "abc", style: ["keyword", "heuristic"] } ] + }); + + do_print("Keyword that happens to match a page"); + yield check_autocomplete({ + search: "key ThisPageIsInHistory", + matches: [ { uri: NetUtil.newURI("http://abc/?search=ThisPageIsInHistory"), title: "abc", style: ["keyword", "heuristic"] } ] + }); + + do_print("Keyword without query (without space)"); + yield check_autocomplete({ + search: "key", + matches: [ { uri: NetUtil.newURI("http://abc/?search="), title: "abc", style: ["keyword", "heuristic"] } ] + }); + + do_print("Keyword without query (with space)"); + yield check_autocomplete({ + search: "key ", + matches: [ { uri: NetUtil.newURI("http://abc/?search="), title: "abc", style: ["keyword", "heuristic"] } ] + }); + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_keyword_search_actions.js b/toolkit/components/places/tests/unifiedcomplete/test_keyword_search_actions.js new file mode 100644 index 000000000..61d98f72d --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_keyword_search_actions.js @@ -0,0 +1,149 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Test for bug 392143 that puts keyword results into the autocomplete. Makes + * sure that multiple parameter queries get spaces converted to +, + converted + * to %2B, non-ascii become escaped, and pages in history that match the + * keyword uses the page's title. + * + * Also test for bug 249468 by making sure multiple keyword bookmarks with the + * same keyword appear in the list. + */ + +add_task(function* test_keyword_search() { + let uri1 = NetUtil.newURI("http://abc/?search=%s"); + let uri2 = NetUtil.newURI("http://abc/?search=ThisPageIsInHistory"); + let uri3 = NetUtil.newURI("http://abc/?search=%s&raw=%S"); + let uri4 = NetUtil.newURI("http://abc/?search=%s&raw=%S&mozcharset=ISO-8859-1"); + yield PlacesTestUtils.addVisits([{ uri: uri1 }, + { uri: uri2 }, + { uri: uri3 }]); + yield addBookmark({ uri: uri1, title: "Keyword", keyword: "key"}); + yield addBookmark({ uri: uri1, title: "Post", keyword: "post", postData: "post_search=%s"}); + yield addBookmark({ uri: uri3, title: "Encoded", keyword: "encoded"}); + yield addBookmark({ uri: uri4, title: "Charset", keyword: "charset"}); + yield addBookmark({ uri: uri2, title: "Noparam", keyword: "noparam"}); + yield addBookmark({ uri: uri2, title: "Noparam-Post", keyword: "post_noparam", postData: "noparam=1"}); + + do_print("Plain keyword query"); + yield check_autocomplete({ + search: "key term", + searchParam: "enable-actions", + matches: [ { uri: makeActionURI("keyword", {url: "http://abc/?search=term", input: "key term"}), + title: "abc", style: [ "action", "keyword", "heuristic" ] } ] + }); + + do_print("Plain keyword UC"); + yield check_autocomplete({ + search: "key TERM", + matches: [ { uri: NetUtil.newURI("http://abc/?search=TERM"), + title: "abc", style: ["keyword", "heuristic"] } ] + }); + + do_print("Multi-word keyword query"); + yield check_autocomplete({ + search: "key multi word", + searchParam: "enable-actions", + matches: [ { uri: makeActionURI("keyword", {url: "http://abc/?search=multi%20word", input: "key multi word"}), + title: "abc", style: [ "action", "keyword", "heuristic" ] } ] + }); + + do_print("Keyword query with +"); + yield check_autocomplete({ + search: "key blocking+", + searchParam: "enable-actions", + matches: [ { uri: makeActionURI("keyword", {url: "http://abc/?search=blocking%2B", input: "key blocking+"}), + title: "abc", style: [ "action", "keyword", "heuristic" ] } ] + }); + + do_print("Unescaped term in query"); + // ... but note that UnifiedComplete calls encodeURIComponent() on the query + // string when it builds the URL, so the expected result will have the + // ユニコード substring encoded in the URL. + yield check_autocomplete({ + search: "key ユニコード", + searchParam: "enable-actions", + matches: [ { uri: makeActionURI("keyword", {url: "http://abc/?search=" + encodeURIComponent("ユニコード"), input: "key ユニコード"}), + title: "abc", style: [ "action", "keyword", "heuristic" ] } ] + }); + + do_print("Keyword that happens to match a page"); + yield check_autocomplete({ + search: "key ThisPageIsInHistory", + searchParam: "enable-actions", + matches: [ { uri: makeActionURI("keyword", {url: "http://abc/?search=ThisPageIsInHistory", input: "key ThisPageIsInHistory"}), + title: "abc", style: [ "action", "keyword", "heuristic" ] } ] + }); + + do_print("Keyword without query (without space)"); + yield check_autocomplete({ + search: "key", + searchParam: "enable-actions", + matches: [ { uri: makeActionURI("keyword", {url: "http://abc/?search=", input: "key"}), + title: "abc", style: [ "action", "keyword", "heuristic" ] } ] + }); + + do_print("Keyword without query (with space)"); + yield check_autocomplete({ + search: "key ", + searchParam: "enable-actions", + matches: [ { uri: makeActionURI("keyword", {url: "http://abc/?search=", input: "key "}), + title: "abc", style: [ "action", "keyword", "heuristic" ] } ] + }); + + do_print("POST Keyword"); + yield check_autocomplete({ + search: "post foo", + searchParam: "enable-actions", + matches: [ { uri: makeActionURI("keyword", {url: "http://abc/?search=foo", input: "post foo", postData: "post_search=foo"}), + title: "abc", style: [ "action", "keyword", "heuristic" ] } ] + }); + + do_print("Bug 420328: no-param keyword with a param"); + yield check_autocomplete({ + search: "noparam foo", + searchParam: "enable-actions", + matches: [ makeSearchMatch("noparam foo", { heuristic: true }) ] + }); + yield check_autocomplete({ + search: "post_noparam foo", + searchParam: "enable-actions", + matches: [ makeSearchMatch("post_noparam foo", { heuristic: true }) ] + }); + + do_print("escaping with default UTF-8 charset"); + yield check_autocomplete({ + search: "encoded foé", + searchParam: "enable-actions", + matches: [ { uri: makeActionURI("keyword", {url: "http://abc/?search=fo%C3%A9&raw=foé", input: "encoded foé" }), + title: "abc", style: [ "action", "keyword", "heuristic" ] } ] + }); + + do_print("escaping with forced ISO-8859-1 charset"); + yield check_autocomplete({ + search: "charset foé", + searchParam: "enable-actions", + matches: [ { uri: makeActionURI("keyword", {url: "http://abc/?search=fo%E9&raw=foé", input: "charset foé" }), + title: "abc", style: [ "action", "keyword", "heuristic" ] } ] + }); + + do_print("Bug 359809: escaping +, / and @ with default UTF-8 charset"); + yield check_autocomplete({ + search: "encoded +/@", + searchParam: "enable-actions", + matches: [ { uri: makeActionURI("keyword", {url: "http://abc/?search=%2B%2F%40&raw=+/@", input: "encoded +/@" }), + title: "abc", style: [ "action", "keyword", "heuristic" ] } ] + }); + + do_print("Bug 359809: escaping +, / and @ with forced ISO-8859-1 charset"); + yield check_autocomplete({ + search: "charset +/@", + searchParam: "enable-actions", + matches: [ { uri: makeActionURI("keyword", {url: "http://abc/?search=%2B%2F%40&raw=+/@", input: "charset +/@" }), + title: "abc", style: [ "action", "keyword", "heuristic" ] } ] + }); + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_keywords.js b/toolkit/components/places/tests/unifiedcomplete/test_keywords.js new file mode 100644 index 000000000..93e8d7a6f --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_keywords.js @@ -0,0 +1,78 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +add_task(function* test_non_keyword() { + do_print("Searching for non-keyworded entry should autoFill it"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/test/"), + transition: TRANSITION_TYPED + }); + yield addBookmark({ uri: NetUtil.newURI("http://mozilla.org/test/") }); + yield check_autocomplete({ + search: "moz", + autofilled: "mozilla.org/", + completed: "mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_keyword() { + do_print("Searching for keyworded entry should not autoFill it"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/test/"), + transition: TRANSITION_TYPED + }); + yield addBookmark({ uri: NetUtil.newURI("http://mozilla.org/test/"), keyword: "moz" }); + yield check_autocomplete({ + search: "moz", + autofilled: "moz", + completed: "moz", + }); + yield cleanup(); +}); + +add_task(function* test_more_than_keyword() { + do_print("Searching for more than keyworded entry should autoFill it"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/test/"), + transition: TRANSITION_TYPED + }); + yield addBookmark({ uri: NetUtil.newURI("http://mozilla.org/test/"), keyword: "moz" }); + yield check_autocomplete({ + search: "mozi", + autofilled: "mozilla.org/", + completed: "mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_less_than_keyword() { + do_print("Searching for less than keyworded entry should autoFill it"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/test/"), + transition: TRANSITION_TYPED + }); + yield addBookmark({ uri: NetUtil.newURI("http://mozilla.org/test/"), keyword: "moz" }); + yield check_autocomplete({ + search: "mo", + autofilled: "mozilla.org/", + completed: "mozilla.org/", + }); + yield cleanup(); +}); + +add_task(function* test_keyword_casing() { + do_print("Searching for keyworded entry is case-insensitive"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/test/"), + transition: TRANSITION_TYPED + }); + yield addBookmark({ uri: NetUtil.newURI("http://mozilla.org/test/"), keyword: "moz" }); + yield check_autocomplete({ + search: "MoZ", + autofilled: "MoZ", + completed: "MoZ" + }); + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_match_beginning.js b/toolkit/components/places/tests/unifiedcomplete/test_match_beginning.js new file mode 100644 index 000000000..57a1efaeb --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_match_beginning.js @@ -0,0 +1,54 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Test bug 451760 which allows matching only at the beginning of urls or + * titles to simulate Firefox 2 functionality. + */ + +add_task(function* test_match_beginning() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", false); + + let uri1 = NetUtil.newURI("http://x.com/y"); + let uri2 = NetUtil.newURI("https://y.com/x"); + yield PlacesTestUtils.addVisits([ + { uri: uri1, title: "a b" }, + { uri: uri2, title: "b a" } + ]); + + do_print("Match at the beginning of titles"); + Services.prefs.setIntPref("browser.urlbar.matchBehavior", 3); + yield check_autocomplete({ + search: "a", + matches: [ { uri: uri1, title: "a b" } ] + }); + + do_print("Match at the beginning of titles"); + yield check_autocomplete({ + search: "b", + matches: [ { uri: uri2, title: "b a" } ] + }); + + do_print("Match at the beginning of urls"); + yield check_autocomplete({ + search: "x", + matches: [ { uri: uri1, title: "a b" } ] + }); + + do_print("Match at the beginning of urls"); + yield check_autocomplete({ + search: "y", + matches: [ { uri: uri2, title: "b a" } ] + }); + + do_print("Sanity check that matching anywhere finds more"); + Services.prefs.setIntPref("browser.urlbar.matchBehavior", 1); + yield check_autocomplete({ + search: "a", + matches: [ { uri: uri1, title: "a b" }, + { uri: uri2, title: "b a" } ] + }); + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_multi_word_search.js b/toolkit/components/places/tests/unifiedcomplete/test_multi_word_search.js new file mode 100644 index 000000000..c6c9e952e --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_multi_word_search.js @@ -0,0 +1,68 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Test for bug 401869 to allow multiple words separated by spaces to match in + * the page title, page url, or bookmark title to be considered a match. All + * terms must match but not all terms need to be in the title, etc. + * + * Test bug 424216 by making sure bookmark titles are always shown if one is + * available. Also bug 425056 makes sure matches aren't found partially in the + * page title and partially in the bookmark. + */ + +add_task(function* test_match_beginning() { + let uri1 = NetUtil.newURI("http://a.b.c/d-e_f/h/t/p"); + let uri2 = NetUtil.newURI("http://d.e.f/g-h_i/h/t/p"); + let uri3 = NetUtil.newURI("http://g.h.i/j-k_l/h/t/p"); + let uri4 = NetUtil.newURI("http://j.k.l/m-n_o/h/t/p"); + yield PlacesTestUtils.addVisits([ + { uri: uri1, title: "f(o)o b<a>r" }, + { uri: uri2, title: "b(a)r b<a>z" }, + { uri: uri3, title: "f(o)o b<a>r" }, + { uri: uri4, title: "f(o)o b<a>r" } + ]); + yield addBookmark({ uri: uri3, title: "f(o)o b<a>r" }); + yield addBookmark({ uri: uri4, title: "b(a)r b<a>z" }); + + do_print("Match 2 terms all in url"); + yield check_autocomplete({ + search: "c d", + matches: [ { uri: uri1, title: "f(o)o b<a>r" } ] + }); + + do_print("Match 1 term in url and 1 term in title"); + yield check_autocomplete({ + search: "b e", + matches: [ { uri: uri1, title: "f(o)o b<a>r" }, + { uri: uri2, title: "b(a)r b<a>z" } ] + }); + + do_print("Match 3 terms all in title; display bookmark title if matched"); + yield check_autocomplete({ + search: "b a z", + matches: [ { uri: uri2, title: "b(a)r b<a>z" }, + { uri: uri4, title: "b(a)r b<a>z", style: [ "bookmark" ] } ] + }); + + do_print("Match 2 terms in url and 1 in title; make sure bookmark title is used for search"); + yield check_autocomplete({ + search: "k f t", + matches: [ { uri: uri3, title: "f(o)o b<a>r", style: [ "bookmark" ] } ] + }); + + do_print("Match 3 terms in url and 1 in title"); + yield check_autocomplete({ + search: "d i g z", + matches: [ { uri: uri2, title: "b(a)r b<a>z" } ] + }); + + do_print("Match nothing"); + yield check_autocomplete({ + search: "m o z i", + matches: [ ] + }); + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_query_url.js b/toolkit/components/places/tests/unifiedcomplete/test_query_url.js new file mode 100644 index 000000000..915ba770e --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_query_url.js @@ -0,0 +1,68 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +add_task(function* test_no_slash() { + do_print("Searching for host match without slash should match host"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://file.org/test/"), + transition: TRANSITION_TYPED + }, { + uri: NetUtil.newURI("file:///c:/test.html"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "file", + autofilled: "file.org/", + completed: "file.org/" + }); + yield cleanup(); +}); + +add_task(function* test_w_slash() { + do_print("Searching match with slash at the end should do nothing"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://file.org/test/"), + transition: TRANSITION_TYPED + }, { + uri: NetUtil.newURI("file:///c:/test.html"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "file.org/", + autofilled: "file.org/", + completed: "file.org/" + }); + yield cleanup(); +}); + +add_task(function* test_middle() { + do_print("Searching match with slash in the middle should match url"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://file.org/test/"), + transition: TRANSITION_TYPED + }, { + uri: NetUtil.newURI("file:///c:/test.html"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "file.org/t", + autofilled: "file.org/test/", + completed: "http://file.org/test/" + }); + yield cleanup(); +}); + +add_task(function* test_nonhost() { + do_print("Searching for non-host match without slash should not match url"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("file:///c:/test.html"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "file", + autofilled: "file", + completed: "file" + }); + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_remote_tab_matches.js b/toolkit/components/places/tests/unifiedcomplete/test_remote_tab_matches.js new file mode 100644 index 000000000..56998d4d6 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_remote_tab_matches.js @@ -0,0 +1,203 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + * vim:set ts=2 sw=2 sts=2 et: +*/ +"use strict"; + +Cu.import("resource://services-sync/main.js"); + +Services.prefs.setCharPref("services.sync.username", "someone@somewhere.com"); + +// A mock "Tabs" engine which autocomplete will use instead of the real +// engine. We pass a constructor that Sync creates. +function MockTabsEngine() { + this.clients = null; // We'll set this dynamically +} + +MockTabsEngine.prototype = { + name: "tabs", + + getAllClients() { + return this.clients; + }, +} + +// A clients engine that doesn't need to be a constructor. +let MockClientsEngine = { + isMobile(guid) { + Assert.ok(guid.endsWith("desktop") || guid.endsWith("mobile")); + return guid.endsWith("mobile"); + }, +} + +// Tell Sync about the mocks. +Weave.Service.engineManager.register(MockTabsEngine); +Weave.Service.clientsEngine = MockClientsEngine; + +// Tell the Sync XPCOM service it is initialized. +let weaveXPCService = Cc["@mozilla.org/weave/service;1"] + .getService(Ci.nsISupports) + .wrappedJSObject; +weaveXPCService.ready = true; + +// Configure the singleton engine for a test. +function configureEngine(clients) { + // Configure the instance Sync created. + let engine = Weave.Service.engineManager.get("tabs"); + engine.clients = clients; + // Send an observer that pretends the engine just finished a sync. + Services.obs.notifyObservers(null, "weave:engine:sync:finish", "tabs"); +} + +// Make a match object suitable for passing to check_autocomplete. +function makeRemoteTabMatch(url, deviceName, extra = {}) { + return { + uri: makeActionURI("remotetab", {url, deviceName}), + title: extra.title || url, + style: [ "action", "remotetab" ], + icon: extra.icon, + } +} + +// The tests. +add_task(function* test_nomatch() { + // Nothing matches. + configureEngine({ + guid_desktop: { + clientName: "My Desktop", + tabs: [{ + urlHistory: ["http://foo.com/"], + }], + } + }); + + // No remote tabs match here, so we only expect search results. + yield check_autocomplete({ + search: "ex", + searchParam: "enable-actions", + matches: [ makeSearchMatch("ex", { heuristic: true }) ], + }); +}); + +add_task(function* test_minimal() { + // The minimal client and tabs info we can get away with. + configureEngine({ + guid_desktop: { + clientName: "My Desktop", + tabs: [{ + urlHistory: ["http://example.com/"], + }], + } + }); + + yield check_autocomplete({ + search: "ex", + searchParam: "enable-actions", + matches: [ makeSearchMatch("ex", { heuristic: true }), + makeRemoteTabMatch("http://example.com/", "My Desktop") ], + }); +}); + +add_task(function* test_maximal() { + // Every field that could possibly exist on a remote record. + configureEngine({ + guid_mobile: { + clientName: "My Phone", + tabs: [{ + urlHistory: ["http://example.com/"], + title: "An Example", + icon: "http://favicon", + }], + } + }); + + yield check_autocomplete({ + search: "ex", + searchParam: "enable-actions", + matches: [ makeSearchMatch("ex", { heuristic: true }), + makeRemoteTabMatch("http://example.com/", "My Phone", + { title: "An Example", + icon: "moz-anno:favicon:http://favicon/" + }), + ], + }); +}); + +add_task(function* test_noShowIcons() { + Services.prefs.setBoolPref("services.sync.syncedTabs.showRemoteIcons", false); + configureEngine({ + guid_mobile: { + clientName: "My Phone", + tabs: [{ + urlHistory: ["http://example.com/"], + title: "An Example", + icon: "http://favicon", + }], + } + }); + + yield check_autocomplete({ + search: "ex", + searchParam: "enable-actions", + matches: [ makeSearchMatch("ex", { heuristic: true }), + makeRemoteTabMatch("http://example.com/", "My Phone", + { title: "An Example", + // expecting the default favicon due to that pref. + icon: "", + }), + ], + }); + Services.prefs.clearUserPref("services.sync.syncedTabs.showRemoteIcons"); +}); + +add_task(function* test_matches_title() { + // URL doesn't match search expression, should still match the title. + configureEngine({ + guid_mobile: { + clientName: "My Phone", + tabs: [{ + urlHistory: ["http://foo.com/"], + title: "An Example", + }], + } + }); + + yield check_autocomplete({ + search: "ex", + searchParam: "enable-actions", + matches: [ makeSearchMatch("ex", { heuristic: true }), + makeRemoteTabMatch("http://foo.com/", "My Phone", + { title: "An Example" }), + ], + }); +}); + +add_task(function* test_localtab_matches_override() { + // We have an open tab to the same page on a remote device, only "switch to + // tab" should appear as duplicate detection removed the remote one. + + // First setup Sync to have the page as a remote tab. + configureEngine({ + guid_mobile: { + clientName: "My Phone", + tabs: [{ + urlHistory: ["http://foo.com/"], + title: "An Example", + }], + } + }); + + // Setup Places to think the tab is open locally. + let uri = NetUtil.newURI("http://foo.com/"); + yield PlacesTestUtils.addVisits([ + { uri: uri, title: "An Example" }, + ]); + addOpenPages(uri, 1); + + yield check_autocomplete({ + search: "ex", + searchParam: "enable-actions", + matches: [ makeSearchMatch("ex", { heuristic: true }), + makeSwitchToTabMatch("http://foo.com/", { title: "An Example" }), + ], + }); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_search_engine_alias.js b/toolkit/components/places/tests/unifiedcomplete/test_search_engine_alias.js new file mode 100644 index 000000000..f35242e21 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_search_engine_alias.js @@ -0,0 +1,51 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + + +add_task(function*() { + // Note that head_autocomplete.js has already added a MozSearch engine. + // Here we add another engine with a search alias. + Services.search.addEngineWithDetails("AliasedGETMozSearch", "", "get", "", + "GET", "http://s.example.com/search"); + Services.search.addEngineWithDetails("AliasedPOSTMozSearch", "", "post", "", + "POST", "http://s.example.com/search"); + + for (let alias of ["get", "post"]) { + yield check_autocomplete({ + search: alias, + searchParam: "enable-actions", + matches: [ makeSearchMatch(alias, { engineName: `Aliased${alias.toUpperCase()}MozSearch`, + searchQuery: "", alias, heuristic: true }) ] + }); + + yield check_autocomplete({ + search: `${alias} `, + searchParam: "enable-actions", + matches: [ makeSearchMatch(`${alias} `, { engineName: `Aliased${alias.toUpperCase()}MozSearch`, + searchQuery: "", alias, heuristic: true }) ] + }); + + yield check_autocomplete({ + search: `${alias} mozilla`, + searchParam: "enable-actions", + matches: [ makeSearchMatch(`${alias} mozilla`, { engineName: `Aliased${alias.toUpperCase()}MozSearch`, + searchQuery: "mozilla", alias, heuristic: true }) ] + }); + + yield check_autocomplete({ + search: `${alias} MoZiLlA`, + searchParam: "enable-actions", + matches: [ makeSearchMatch(`${alias} MoZiLlA`, { engineName: `Aliased${alias.toUpperCase()}MozSearch`, + searchQuery: "MoZiLlA", alias, heuristic: true }) ] + }); + + yield check_autocomplete({ + search: `${alias} mozzarella mozilla`, + searchParam: "enable-actions", + matches: [ makeSearchMatch(`${alias} mozzarella mozilla`, { engineName: `Aliased${alias.toUpperCase()}MozSearch`, + searchQuery: "mozzarella mozilla", alias, heuristic: true }) ] + }); + } + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_search_engine_current.js b/toolkit/components/places/tests/unifiedcomplete/test_search_engine_current.js new file mode 100644 index 000000000..b41d9884b --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_search_engine_current.js @@ -0,0 +1,45 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + + +add_task(function*() { + // Note that head_autocomplete.js has already added a MozSearch engine. + // Here we add another engine with a search alias. + Services.search.addEngineWithDetails("AliasedMozSearch", "", "doit", "", + "GET", "http://s.example.com/search"); + + do_print("search engine"); + yield check_autocomplete({ + search: "mozilla", + searchParam: "enable-actions", + matches: [ makeSearchMatch("mozilla", { heuristic: true }) ] + }); + + do_print("search engine, uri-like input"); + yield check_autocomplete({ + search: "http:///", + searchParam: "enable-actions", + matches: [ makeSearchMatch("http:///", { heuristic: true }) ] + }); + + do_print("search engine, multiple words"); + yield check_autocomplete({ + search: "mozzarella cheese", + searchParam: "enable-actions", + matches: [ makeSearchMatch("mozzarella cheese", { heuristic: true }) ] + }); + + do_print("search engine, after current engine has changed"); + Services.search.addEngineWithDetails("MozSearch2", "", "", "", "GET", + "http://s.example.com/search2"); + engine = Services.search.getEngineByName("MozSearch2"); + notEqual(Services.search.currentEngine, engine, "New engine shouldn't be the current engine yet"); + Services.search.currentEngine = engine; + yield check_autocomplete({ + search: "mozilla", + searchParam: "enable-actions", + matches: [ makeSearchMatch("mozilla", { engineName: "MozSearch2", heuristic: true }) ] + }); + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_search_engine_host.js b/toolkit/components/places/tests/unifiedcomplete/test_search_engine_host.js new file mode 100644 index 000000000..61b9826f7 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_search_engine_host.js @@ -0,0 +1,49 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +add_task(function* test_searchEngine_autoFill() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true); + Services.search.addEngineWithDetails("MySearchEngine", "", "", "", + "GET", "http://my.search.com/"); + let engine = Services.search.getEngineByName("MySearchEngine"); + do_register_cleanup(() => Services.search.removeEngine(engine)); + + // Add an uri that matches the search string with high frecency. + let uri = NetUtil.newURI("http://www.example.com/my/"); + let visits = []; + for (let i = 0; i < 100; ++i) { + visits.push({ uri, title: "Terms - SearchEngine Search" }); + } + yield PlacesTestUtils.addVisits(visits); + yield addBookmark({ uri: uri, title: "Example bookmark" }); + yield PlacesTestUtils.promiseAsyncUpdates(); + ok(frecencyForUrl(uri) > 10000, "Added URI should have expected high frecency"); + + do_print("Check search domain is autoFilled even if there's an higher frecency match"); + yield check_autocomplete({ + search: "my", + autofilled: "my.search.com", + completed: "http://my.search.com" + }); + + yield cleanup(); +}); + +add_task(function* test_searchEngine_noautoFill() { + let engineName = "engine-rel-searchform.xml"; + let engine = yield addTestEngine(engineName); + equal(engine.searchForm, "http://example.com/?search"); + + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + yield PlacesTestUtils.addVisits(NetUtil.newURI("http://example.com/my/")); + + do_print("Check search domain is not autoFilled if it matches a visited domain"); + yield check_autocomplete({ + search: "example", + autofilled: "example.com/", + completed: "example.com/" + }); + + yield cleanup(); +}); + diff --git a/toolkit/components/places/tests/unifiedcomplete/test_search_engine_restyle.js b/toolkit/components/places/tests/unifiedcomplete/test_search_engine_restyle.js new file mode 100644 index 000000000..2a5f2d78e --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_search_engine_restyle.js @@ -0,0 +1,43 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +add_task(function* test_searchEngine() { + Services.search.addEngineWithDetails("SearchEngine", "", "", "", + "GET", "http://s.example.com/search"); + let engine = Services.search.getEngineByName("SearchEngine"); + engine.addParam("q", "{searchTerms}", null); + do_register_cleanup(() => Services.search.removeEngine(engine)); + + let uri1 = NetUtil.newURI("http://s.example.com/search?q=Terms&client=1"); + let uri2 = NetUtil.newURI("http://s.example.com/search?q=Terms&client=2"); + yield PlacesTestUtils.addVisits({ uri: uri1, title: "Terms - SearchEngine Search" }); + yield addBookmark({ uri: uri2, title: "Terms - SearchEngine Search" }); + + do_print("Past search terms should be styled, unless bookmarked"); + Services.prefs.setBoolPref("browser.urlbar.restyleSearches", true); + yield check_autocomplete({ + search: "term", + matches: [ + makeSearchMatch("Terms", { + engineName: "SearchEngine", + style: ["favicon"] + }), + { + uri: uri2, + title: "Terms - SearchEngine Search", + style: ["bookmark"] + } + ] + }); + + do_print("Past search terms should not be styled if restyling is disabled"); + Services.prefs.setBoolPref("browser.urlbar.restyleSearches", false); + yield check_autocomplete({ + search: "term", + matches: [ { uri: uri1, title: "Terms - SearchEngine Search" }, + { uri: uri2, title: "Terms - SearchEngine Search", style: ["bookmark"] } ] + }); + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_search_suggestions.js b/toolkit/components/places/tests/unifiedcomplete/test_search_suggestions.js new file mode 100644 index 000000000..63b428cd4 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_search_suggestions.js @@ -0,0 +1,651 @@ +Cu.import("resource://gre/modules/FormHistory.jsm"); + +const ENGINE_NAME = "engine-suggestions.xml"; +const SERVER_PORT = 9000; +const SUGGEST_PREF = "browser.urlbar.suggest.searches"; +const SUGGEST_ENABLED_PREF = "browser.search.suggest.enabled"; +const SUGGEST_RESTRICT_TOKEN = "$"; + +var suggestionsFn; +var previousSuggestionsFn; + +function setSuggestionsFn(fn) { + previousSuggestionsFn = suggestionsFn; + suggestionsFn = fn; +} + +function* cleanUpSuggestions() { + yield cleanup(); + if (previousSuggestionsFn) { + suggestionsFn = previousSuggestionsFn; + previousSuggestionsFn = null; + } +} + +add_task(function* setUp() { + // Set up a server that provides some suggestions by appending strings onto + // the search query. + let server = makeTestServer(SERVER_PORT); + server.registerPathHandler("/suggest", (req, resp) => { + // URL query params are x-www-form-urlencoded, which converts spaces into + // plus signs, so un-convert any plus signs back to spaces. + let searchStr = decodeURIComponent(req.queryString.replace(/\+/g, " ")); + let suggestions = suggestionsFn(searchStr); + let data = [searchStr, suggestions]; + resp.setHeader("Content-Type", "application/json", false); + resp.write(JSON.stringify(data)); + }); + setSuggestionsFn(searchStr => { + let suffixes = ["foo", "bar"]; + return suffixes.map(s => searchStr + " " + s); + }); + + // Install the test engine. + let oldCurrentEngine = Services.search.currentEngine; + do_register_cleanup(() => Services.search.currentEngine = oldCurrentEngine); + let engine = yield addTestEngine(ENGINE_NAME, server); + Services.search.currentEngine = engine; +}); + +add_task(function* disabled_urlbarSuggestions() { + Services.prefs.setBoolPref(SUGGEST_PREF, false); + Services.prefs.setBoolPref(SUGGEST_ENABLED_PREF, true); + yield check_autocomplete({ + search: "hello", + searchParam: "enable-actions", + matches: [ + makeSearchMatch("hello", { engineName: ENGINE_NAME, heuristic: true }), + ], + }); + yield cleanUpSuggestions(); +}); + +add_task(function* disabled_allSuggestions() { + Services.prefs.setBoolPref(SUGGEST_PREF, true); + Services.prefs.setBoolPref(SUGGEST_ENABLED_PREF, false); + yield check_autocomplete({ + search: "hello", + searchParam: "enable-actions", + matches: [ + makeSearchMatch("hello", { engineName: ENGINE_NAME, heuristic: true }), + ], + }); + yield cleanUpSuggestions(); +}); + +add_task(function* disabled_privateWindow() { + Services.prefs.setBoolPref(SUGGEST_PREF, true); + Services.prefs.setBoolPref(SUGGEST_ENABLED_PREF, true); + yield check_autocomplete({ + search: "hello", + searchParam: "private-window enable-actions", + matches: [ + makeSearchMatch("hello", { engineName: ENGINE_NAME, heuristic: true }), + ], + }); + yield cleanUpSuggestions(); +}); + +add_task(function* singleWordQuery() { + Services.prefs.setBoolPref(SUGGEST_PREF, true); + Services.prefs.setBoolPref(SUGGEST_ENABLED_PREF, true); + + yield check_autocomplete({ + search: "hello", + searchParam: "enable-actions", + matches: [ + makeSearchMatch("hello", { engineName: ENGINE_NAME, heuristic: true }), + { uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "hello foo", + searchQuery: "hello", + searchSuggestion: "hello foo", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }, { + uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "hello bar", + searchQuery: "hello", + searchSuggestion: "hello bar", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }], + }); + + yield cleanUpSuggestions(); +}); + +add_task(function* multiWordQuery() { + Services.prefs.setBoolPref(SUGGEST_PREF, true); + Services.prefs.setBoolPref(SUGGEST_ENABLED_PREF, true); + + yield check_autocomplete({ + search: "hello world", + searchParam: "enable-actions", + matches: [ + makeSearchMatch("hello world", { engineName: ENGINE_NAME, heuristic: true }), + { uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "hello world foo", + searchQuery: "hello world", + searchSuggestion: "hello world foo", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }, { + uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "hello world bar", + searchQuery: "hello world", + searchSuggestion: "hello world bar", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }], + }); + + yield cleanUpSuggestions(); +}); + +add_task(function* suffixMatch() { + Services.prefs.setBoolPref(SUGGEST_PREF, true); + Services.prefs.setBoolPref(SUGGEST_ENABLED_PREF, true); + + setSuggestionsFn(searchStr => { + let prefixes = ["baz", "quux"]; + return prefixes.map(p => p + " " + searchStr); + }); + + yield check_autocomplete({ + search: "hello", + searchParam: "enable-actions", + matches: [ + makeSearchMatch("hello", { engineName: ENGINE_NAME, heuristic: true }), + { uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "baz hello", + searchQuery: "hello", + searchSuggestion: "baz hello", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }, { + uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "quux hello", + searchQuery: "hello", + searchSuggestion: "quux hello", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }], + }); + + yield cleanUpSuggestions(); +}); + +add_task(function* queryIsNotASubstring() { + Services.prefs.setBoolPref(SUGGEST_PREF, true); + + setSuggestionsFn(searchStr => { + return ["aaa", "bbb"]; + }); + + yield check_autocomplete({ + search: "hello", + searchParam: "enable-actions", + matches: [ + makeSearchMatch("hello", { engineName: ENGINE_NAME, heuristic: true }), + { uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "aaa", + searchQuery: "hello", + searchSuggestion: "aaa", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }, { + uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "bbb", + searchQuery: "hello", + searchSuggestion: "bbb", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }], + }); + + yield cleanUpSuggestions(); +}); + +add_task(function* restrictToken() { + Services.prefs.setBoolPref(SUGGEST_PREF, true); + Services.prefs.setBoolPref(SUGGEST_ENABLED_PREF, true); + + // Add a visit and a bookmark. Actually, make the bookmark visited too so + // that it's guaranteed, with its higher frecency, to appear above the search + // suggestions. + yield PlacesTestUtils.addVisits([ + { + uri: NetUtil.newURI("http://example.com/hello-visit"), + title: "hello visit", + }, + { + uri: NetUtil.newURI("http://example.com/hello-bookmark"), + title: "hello bookmark", + }, + ]); + + yield addBookmark({ + uri: NetUtil.newURI("http://example.com/hello-bookmark"), + title: "hello bookmark", + }); + + // Do an unrestricted search to make sure everything appears in it, including + // the visit and bookmark. + yield check_autocomplete({ + search: "hello", + searchParam: "enable-actions", + matches: [ + makeSearchMatch("hello", { engineName: ENGINE_NAME, heuristic: true }), + { + uri: NetUtil.newURI("http://example.com/hello-visit"), + title: "hello visit", + }, + { + uri: NetUtil.newURI("http://example.com/hello-bookmark"), + title: "hello bookmark", + style: ["bookmark"], + }, + { + uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "hello foo", + searchQuery: "hello", + searchSuggestion: "hello foo", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }, + { + uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "hello bar", + searchQuery: "hello", + searchSuggestion: "hello bar", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }, + ], + }); + + // Now do a restricted search to make sure only suggestions appear. + yield check_autocomplete({ + search: SUGGEST_RESTRICT_TOKEN + " hello", + searchParam: "enable-actions", + matches: [ + // TODO (bug 1177895) This is wrong. + makeSearchMatch(SUGGEST_RESTRICT_TOKEN + " hello", { engineName: ENGINE_NAME, heuristic: true }), + { + uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "hello foo", + searchQuery: "hello", + searchSuggestion: "hello foo", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }, + { + uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "hello bar", + searchQuery: "hello", + searchSuggestion: "hello bar", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + } + ], + }); + + yield cleanUpSuggestions(); +}); + +add_task(function* mixup_frecency() { + Services.prefs.setBoolPref(SUGGEST_PREF, true); + + // Add a visit and a bookmark. Actually, make the bookmark visited too so + // that it's guaranteed, with its higher frecency, to appear above the search + // suggestions. + yield PlacesTestUtils.addVisits([ + { uri: NetUtil.newURI("http://example.com/lo0"), + title: "low frecency 0" }, + { uri: NetUtil.newURI("http://example.com/lo1"), + title: "low frecency 1" }, + { uri: NetUtil.newURI("http://example.com/lo2"), + title: "low frecency 2" }, + { uri: NetUtil.newURI("http://example.com/lo3"), + title: "low frecency 3" }, + { uri: NetUtil.newURI("http://example.com/lo4"), + title: "low frecency 4" }, + ]); + + for (let i = 0; i < 4; i++) { + let href = `http://example.com/lo${i}`; + let frecency = frecencyForUrl(href); + Assert.ok(frecency < FRECENCY_DEFAULT, + `frecency for ${href}: ${frecency}, should be lower than ${FRECENCY_DEFAULT}`); + } + + for (let i = 0; i < 5; i++) { + yield PlacesTestUtils.addVisits([ + { uri: NetUtil.newURI("http://example.com/hi0"), + title: "high frecency 0", + transition: TRANSITION_TYPED }, + { uri: NetUtil.newURI("http://example.com/hi1"), + title: "high frecency 1", + transition: TRANSITION_TYPED }, + { uri: NetUtil.newURI("http://example.com/hi2"), + title: "high frecency 2", + transition: TRANSITION_TYPED }, + { uri: NetUtil.newURI("http://example.com/hi3"), + title: "high frecency 3", + transition: TRANSITION_TYPED }, + ]); + } + + for (let i = 0; i < 4; i++) { + let href = `http://example.com/hi${i}`; + yield addBookmark({ uri: href, title: `high frecency ${i}` }); + let frecency = frecencyForUrl(href); + Assert.ok(frecency > FRECENCY_DEFAULT, + `frecency for ${href}: ${frecency}, should be higher than ${FRECENCY_DEFAULT}`); + } + + // Do an unrestricted search to make sure everything appears in it, including + // the visit and bookmark. + yield check_autocomplete({ + checkSorting: true, + search: "frecency", + searchParam: "enable-actions", + matches: [ + makeSearchMatch("frecency", { engineName: ENGINE_NAME, heuristic: true }), + { uri: NetUtil.newURI("http://example.com/hi3"), + title: "high frecency 3", + style: [ "bookmark" ] }, + { uri: NetUtil.newURI("http://example.com/hi2"), + title: "high frecency 2", + style: [ "bookmark" ] }, + { uri: NetUtil.newURI("http://example.com/hi1"), + title: "high frecency 1", + style: [ "bookmark" ] }, + { uri: NetUtil.newURI("http://example.com/hi0"), + title: "high frecency 0", + style: [ "bookmark" ] }, + { uri: NetUtil.newURI("http://example.com/lo4"), + title: "low frecency 4" }, + { + uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "frecency foo", + searchQuery: "frecency", + searchSuggestion: "frecency foo", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }, + { + uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "frecency bar", + searchQuery: "frecency", + searchSuggestion: "frecency bar", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }, + { uri: NetUtil.newURI("http://example.com/lo3"), + title: "low frecency 3" }, + { uri: NetUtil.newURI("http://example.com/lo2"), + title: "low frecency 2" }, + { uri: NetUtil.newURI("http://example.com/lo1"), + title: "low frecency 1" }, + { uri: NetUtil.newURI("http://example.com/lo0"), + title: "low frecency 0" }, + ], + }); + + yield cleanUpSuggestions(); +}); + +add_task(function* prohibit_suggestions() { + Services.prefs.setBoolPref(SUGGEST_PREF, true); + + yield check_autocomplete({ + search: "localhost", + searchParam: "enable-actions", + matches: [ + makeSearchMatch("localhost", { engineName: ENGINE_NAME, heuristic: true }), + { + uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "localhost foo", + searchQuery: "localhost", + searchSuggestion: "localhost foo", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }, + { + uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "localhost bar", + searchQuery: "localhost", + searchSuggestion: "localhost bar", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }, + ], + }); + Services.prefs.setBoolPref("browser.fixup.domainwhitelist.localhost", true); + do_register_cleanup(() => { + Services.prefs.clearUserPref("browser.fixup.domainwhitelist.localhost"); + }); + yield check_autocomplete({ + search: "localhost", + searchParam: "enable-actions", + matches: [ + makeVisitMatch("localhost", "http://localhost/", { heuristic: true }), + makeSearchMatch("localhost", { engineName: ENGINE_NAME, heuristic: false }) + ], + }); + + // When using multiple words, we should still get suggestions: + yield check_autocomplete({ + search: "localhost other", + searchParam: "enable-actions", + matches: [ + makeSearchMatch("localhost other", { engineName: ENGINE_NAME, heuristic: true }), + { + uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "localhost other foo", + searchQuery: "localhost other", + searchSuggestion: "localhost other foo", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }, + { + uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "localhost other bar", + searchQuery: "localhost other", + searchSuggestion: "localhost other bar", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }, + ], + }); + + // Clear the whitelist for localhost, and try preferring DNS for any single + // word instead: + Services.prefs.clearUserPref("browser.fixup.domainwhitelist.localhost"); + Services.prefs.setBoolPref("browser.fixup.dns_first_for_single_words", true); + do_register_cleanup(() => { + Services.prefs.clearUserPref("browser.fixup.dns_first_for_single_words"); + }); + + yield check_autocomplete({ + search: "localhost", + searchParam: "enable-actions", + matches: [ + makeVisitMatch("localhost", "http://localhost/", { heuristic: true }), + makeSearchMatch("localhost", { engineName: ENGINE_NAME, heuristic: false }) + ], + }); + + yield check_autocomplete({ + search: "somethingelse", + searchParam: "enable-actions", + matches: [ + makeVisitMatch("somethingelse", "http://somethingelse/", { heuristic: true }), + makeSearchMatch("somethingelse", { engineName: ENGINE_NAME, heuristic: false }) + ], + }); + + // When using multiple words, we should still get suggestions: + yield check_autocomplete({ + search: "localhost other", + searchParam: "enable-actions", + matches: [ + makeSearchMatch("localhost other", { engineName: ENGINE_NAME, heuristic: true }), + { + uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "localhost other foo", + searchQuery: "localhost other", + searchSuggestion: "localhost other foo", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }, + { + uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "localhost other bar", + searchQuery: "localhost other", + searchSuggestion: "localhost other bar", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }, + ], + }); + + Services.prefs.clearUserPref("browser.fixup.dns_first_for_single_words"); + + yield check_autocomplete({ + search: "1.2.3.4", + searchParam: "enable-actions", + matches: [ + makeVisitMatch("1.2.3.4", "http://1.2.3.4/", { heuristic: true }), + ], + }); + yield check_autocomplete({ + search: "[2001::1]:30", + searchParam: "enable-actions", + matches: [ + makeVisitMatch("[2001::1]:30", "http://[2001::1]:30/", { heuristic: true }), + ], + }); + yield check_autocomplete({ + search: "user:pass@test", + searchParam: "enable-actions", + matches: [ + makeVisitMatch("user:pass@test", "http://user:pass@test/", { heuristic: true }), + ], + }); + yield check_autocomplete({ + search: "test/test", + searchParam: "enable-actions", + matches: [ + makeVisitMatch("test/test", "http://test/test", { heuristic: true }), + ], + }); + yield check_autocomplete({ + search: "data:text/plain,Content", + searchParam: "enable-actions", + matches: [ + makeVisitMatch("data:text/plain,Content", "data:text/plain,Content", { heuristic: true }), + ], + }); + + yield check_autocomplete({ + search: "a", + searchParam: "enable-actions", + matches: [ + makeSearchMatch("a", { engineName: ENGINE_NAME, heuristic: true }), + ], + }); + + yield cleanUpSuggestions(); +}); + +add_task(function* avoid_url_suggestions() { + Services.prefs.setBoolPref(SUGGEST_PREF, true); + + setSuggestionsFn(searchStr => { + let suffixes = [".com", "/test", ":1]", "@test", ". com"]; + return suffixes.map(s => searchStr + s); + }); + + yield check_autocomplete({ + search: "test", + searchParam: "enable-actions", + matches: [ + makeSearchMatch("test", { engineName: ENGINE_NAME, heuristic: true }), + { + uri: makeActionURI(("searchengine"), { + engineName: ENGINE_NAME, + input: "test. com", + searchQuery: "test", + searchSuggestion: "test. com", + }), + title: ENGINE_NAME, + style: ["action", "searchengine"], + icon: "", + }, + ], + }); + + yield cleanUpSuggestions(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_special_search.js b/toolkit/components/places/tests/unifiedcomplete/test_special_search.js new file mode 100644 index 000000000..21df7046c --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_special_search.js @@ -0,0 +1,447 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Test for bug 395161 that allows special searches that restrict results to + * history/bookmark/tagged items and title/url matches. + * + * Test 485122 by making sure results don't have tags when restricting result + * to just history either by default behavior or dynamic query restrict. + */ + +function setSuggestPrefsToFalse() { + Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); + Services.prefs.setBoolPref("browser.urlbar.suggest.history.onlyTyped", false); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); +} + +add_task(function* test_special_searches() { + let uri1 = NetUtil.newURI("http://url/"); + let uri2 = NetUtil.newURI("http://url/2"); + let uri3 = NetUtil.newURI("http://foo.bar/"); + let uri4 = NetUtil.newURI("http://foo.bar/2"); + let uri5 = NetUtil.newURI("http://url/star"); + let uri6 = NetUtil.newURI("http://url/star/2"); + let uri7 = NetUtil.newURI("http://foo.bar/star"); + let uri8 = NetUtil.newURI("http://foo.bar/star/2"); + let uri9 = NetUtil.newURI("http://url/tag"); + let uri10 = NetUtil.newURI("http://url/tag/2"); + let uri11 = NetUtil.newURI("http://foo.bar/tag"); + let uri12 = NetUtil.newURI("http://foo.bar/tag/2"); + yield PlacesTestUtils.addVisits([ + { uri: uri1, title: "title", transition: TRANSITION_TYPED }, + { uri: uri2, title: "foo.bar" }, + { uri: uri3, title: "title" }, + { uri: uri4, title: "foo.bar", transition: TRANSITION_TYPED }, + { uri: uri6, title: "foo.bar" }, + { uri: uri11, title: "title", transition: TRANSITION_TYPED } + ]); + yield addBookmark( { uri: uri5, title: "title" } ); + yield addBookmark( { uri: uri6, title: "foo.bar" } ); + yield addBookmark( { uri: uri7, title: "title" } ); + yield addBookmark( { uri: uri8, title: "foo.bar" } ); + yield addBookmark( { uri: uri9, title: "title", tags: [ "foo.bar" ] } ); + yield addBookmark( { uri: uri10, title: "foo.bar", tags: [ "foo.bar" ] } ); + yield addBookmark( { uri: uri11, title: "title", tags: [ "foo.bar" ] } ); + yield addBookmark( { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ] } ); + + // Test restricting searches + do_print("History restrict"); + yield check_autocomplete({ + search: "^", + matches: [ { uri: uri1, title: "title" }, + { uri: uri2, title: "foo.bar" }, + { uri: uri3, title: "title" }, + { uri: uri4, title: "foo.bar" }, + { uri: uri6, title: "foo.bar" }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("Star restrict"); + yield check_autocomplete({ + search: "*", + matches: [ { uri: uri5, title: "title", style: [ "bookmark" ] }, + { uri: uri6, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri7, title: "title", style: [ "bookmark" ] }, + { uri: uri8, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri9, title: "title", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri10, title: "foo.bar", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar"], style: [ "bookmark-tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] } ] + }); + + do_print("Tag restrict"); + yield check_autocomplete({ + search: "+", + matches: [ { uri: uri9, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri10, title: "foo.bar", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + // Test specials as any word position + do_print("Special as first word"); + yield check_autocomplete({ + search: "^ foo bar", + matches: [ { uri: uri2, title: "foo.bar" }, + { uri: uri3, title: "title" }, + { uri: uri4, title: "foo.bar" }, + { uri: uri6, title: "foo.bar" }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("Special as middle word"); + yield check_autocomplete({ + search: "foo ^ bar", + matches: [ { uri: uri2, title: "foo.bar" }, + { uri: uri3, title: "title" }, + { uri: uri4, title: "foo.bar" }, + { uri: uri6, title: "foo.bar" }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("Special as last word"); + yield check_autocomplete({ + search: "foo bar ^", + matches: [ { uri: uri2, title: "foo.bar" }, + { uri: uri3, title: "title" }, + { uri: uri4, title: "foo.bar" }, + { uri: uri6, title: "foo.bar" }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + // Test restricting and matching searches with a term + do_print("foo ^ -> history"); + yield check_autocomplete({ + search: "foo ^", + matches: [ { uri: uri2, title: "foo.bar" }, + { uri: uri3, title: "title" }, + { uri: uri4, title: "foo.bar" }, + { uri: uri6, title: "foo.bar" }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("foo | -> history (change pref)"); + changeRestrict("history", "|"); + yield check_autocomplete({ + search: "foo |", + matches: [ { uri: uri2, title: "foo.bar" }, + { uri: uri3, title: "title" }, + { uri: uri4, title: "foo.bar" }, + { uri: uri6, title: "foo.bar" }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("foo * -> is star"); + resetRestrict("history"); + yield check_autocomplete({ + search: "foo *", + matches: [ { uri: uri6, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri7, title: "title", style: [ "bookmark" ] }, + { uri: uri8, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri9, title: "title", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri10, title: "foo.bar", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] } ] + }); + + do_print("foo | -> is star (change pref)"); + changeRestrict("bookmark", "|"); + yield check_autocomplete({ + search: "foo |", + matches: [ { uri: uri6, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri7, title: "title", style: [ "bookmark" ] }, + { uri: uri8, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri9, title: "title", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri10, title: "foo.bar", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] } ] + }); + + do_print("foo # -> in title"); + resetRestrict("bookmark"); + yield check_autocomplete({ + search: "foo #", + matches: [ { uri: uri2, title: "foo.bar" }, + { uri: uri4, title: "foo.bar" }, + { uri: uri6, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri8, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri9, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri10, title: "foo.bar", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("foo | -> in title (change pref)"); + changeRestrict("title", "|"); + yield check_autocomplete({ + search: "foo |", + matches: [ { uri: uri2, title: "foo.bar" }, + { uri: uri4, title: "foo.bar" }, + { uri: uri6, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri8, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri9, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri10, title: "foo.bar", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("foo @ -> in url"); + resetRestrict("title"); + yield check_autocomplete({ + search: "foo @", + matches: [ { uri: uri3, title: "title" }, + { uri: uri4, title: "foo.bar" }, + { uri: uri7, title: "title", style: [ "bookmark" ] }, + { uri: uri8, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("foo | -> in url (change pref)"); + changeRestrict("url", "|"); + yield check_autocomplete({ + search: "foo |", + matches: [ { uri: uri3, title: "title" }, + { uri: uri4, title: "foo.bar" }, + { uri: uri7, title: "title", style: [ "bookmark" ] }, + { uri: uri8, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("foo + -> is tag"); + resetRestrict("url"); + yield check_autocomplete({ + search: "foo +", + matches: [ { uri: uri9, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri10, title: "foo.bar", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("foo | -> is tag (change pref)"); + changeRestrict("tag", "|"); + yield check_autocomplete({ + search: "foo |", + matches: [ { uri: uri9, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri10, title: "foo.bar", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("foo ~ -> is typed"); + resetRestrict("tag"); + yield check_autocomplete({ + search: "foo ~", + matches: [ { uri: uri4, title: "foo.bar" }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("foo | -> is typed (change pref)"); + changeRestrict("typed", "|"); + yield check_autocomplete({ + search: "foo |", + matches: [ { uri: uri4, title: "foo.bar" }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + // Test various pairs of special searches + do_print("foo ^ * -> history, is star"); + resetRestrict("typed"); + yield check_autocomplete({ + search: "foo ^ *", + matches: [ { uri: uri6, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] } ] + }); + + do_print("foo ^ # -> history, in title"); + yield check_autocomplete({ + search: "foo ^ #", + matches: [ { uri: uri2, title: "foo.bar" }, + { uri: uri4, title: "foo.bar" }, + { uri: uri6, title: "foo.bar" }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("foo ^ @ -> history, in url"); + yield check_autocomplete({ + search: "foo ^ @", + matches: [ { uri: uri3, title: "title" }, + { uri: uri4, title: "foo.bar" }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("foo ^ + -> history, is tag"); + yield check_autocomplete({ + search: "foo ^ +", + matches: [ { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("foo ^ ~ -> history, is typed"); + yield check_autocomplete({ + search: "foo ^ ~", + matches: [ { uri: uri4, title: "foo.bar" }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("foo * # -> is star, in title"); + yield check_autocomplete({ + search: "foo * #", + matches: [ { uri: uri6, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri8, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri9, title: "title", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri10, title: "foo.bar", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] } ] + }); + + do_print("foo * @ -> is star, in url"); + yield check_autocomplete({ + search: "foo * @", + matches: [ { uri: uri7, title: "title", style: [ "bookmark" ] }, + { uri: uri8, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] } ] + }); + + do_print("foo * + -> same as +"); + yield check_autocomplete({ + search: "foo * +", + matches: [ { uri: uri9, title: "title", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri10, title: "foo.bar", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] } ] + }); + + do_print("foo * ~ -> is star, is typed"); + yield check_autocomplete({ + search: "foo * ~", + matches: [ { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] } ] + }); + + do_print("foo # @ -> in title, in url"); + yield check_autocomplete({ + search: "foo # @", + matches: [ { uri: uri4, title: "foo.bar" }, + { uri: uri8, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("foo # + -> in title, is tag"); + yield check_autocomplete({ + search: "foo # +", + matches: [ { uri: uri9, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri10, title: "foo.bar", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("foo # ~ -> in title, is typed"); + yield check_autocomplete({ + search: "foo # ~", + matches: [ { uri: uri4, title: "foo.bar" }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("foo @ + -> in url, is tag"); + yield check_autocomplete({ + search: "foo @ +", + matches: [ { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("foo @ ~ -> in url, is typed"); + yield check_autocomplete({ + search: "foo @ ~", + matches: [ { uri: uri4, title: "foo.bar" }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + do_print("foo + ~ -> is tag, is typed"); + yield check_autocomplete({ + search: "foo + ~", + matches: [ { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "tag" ] } ] + }); + + // Disable autoFill for the next tests, see test_autoFill_default_behavior.js + // for specific tests. + Services.prefs.setBoolPref("browser.urlbar.autoFill", false); + + // Test default usage by setting certain browser.urlbar.suggest.* prefs + do_print("foo -> default history"); + setSuggestPrefsToFalse(); + Services.prefs.setBoolPref("browser.urlbar.suggest.history", true); + yield check_autocomplete({ + search: "foo", + matches: [ { uri: uri2, title: "foo.bar" }, + { uri: uri3, title: "title" }, + { uri: uri4, title: "foo.bar" }, + { uri: uri6, title: "foo.bar" }, + { uri: uri11, title: "title", tags: ["foo.bar"], style: [ "tag" ] } ] + }); + + do_print("foo -> default history, is star"); + setSuggestPrefsToFalse(); + Services.prefs.setBoolPref("browser.urlbar.suggest.history", true); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", true); + yield check_autocomplete({ + search: "foo", + matches: [ { uri: uri2, title: "foo.bar" }, + { uri: uri3, title: "title" }, + { uri: uri4, title: "foo.bar" }, + { uri: uri6, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri7, title: "title", style: [ "bookmark" ] }, + { uri: uri8, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri9, title: "title", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri10, title: "foo.bar", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar"], style: [ "bookmark-tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] } ] + }); + + do_print("foo -> default history, is star, is typed"); + setSuggestPrefsToFalse(); + Services.prefs.setBoolPref("browser.urlbar.suggest.history", true); + Services.prefs.setBoolPref("browser.urlbar.suggest.history.onlyTyped", true); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", true); + yield check_autocomplete({ + search: "foo", + matches: [ { uri: uri4, title: "foo.bar" }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] } ] + }); + + do_print("foo -> is star"); + setSuggestPrefsToFalse(); + Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", true); + yield check_autocomplete({ + search: "foo", + matches: [ { uri: uri6, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri7, title: "title", style: [ "bookmark" ] }, + { uri: uri8, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri9, title: "title", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri10, title: "foo.bar", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] } ] + }); + + do_print("foo -> is star, is typed"); + setSuggestPrefsToFalse(); + // only typed should be ignored + Services.prefs.setBoolPref("browser.urlbar.suggest.history.onlyTyped", true); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", true); + yield check_autocomplete({ + search: "foo", + matches: [ { uri: uri6, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri7, title: "title", style: [ "bookmark" ] }, + { uri: uri8, title: "foo.bar", style: [ "bookmark" ] }, + { uri: uri9, title: "title", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri10, title: "foo.bar", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri11, title: "title", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] }, + { uri: uri12, title: "foo.bar", tags: [ "foo.bar" ], style: [ "bookmark-tag" ] } ] + }); + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_swap_protocol.js b/toolkit/components/places/tests/unifiedcomplete/test_swap_protocol.js new file mode 100644 index 000000000..89ccc3206 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_swap_protocol.js @@ -0,0 +1,153 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Test bug 424717 to make sure searching with an existing location like + * http://site/ also matches https://site/ or ftp://site/. Same thing for + * ftp://site/ and https://site/. + * + * Test bug 461483 to make sure a search for "w" doesn't match the "www." from + * site subdomains. + */ + +add_task(function* test_swap_protocol() { + let uri1 = NetUtil.newURI("http://www.site/"); + let uri2 = NetUtil.newURI("http://site/"); + let uri3 = NetUtil.newURI("ftp://ftp.site/"); + let uri4 = NetUtil.newURI("ftp://site/"); + let uri5 = NetUtil.newURI("https://www.site/"); + let uri6 = NetUtil.newURI("https://site/"); + let uri7 = NetUtil.newURI("http://woohoo/"); + let uri8 = NetUtil.newURI("http://wwwwwwacko/"); + yield PlacesTestUtils.addVisits([ + { uri: uri1, title: "title" }, + { uri: uri2, title: "title" }, + { uri: uri3, title: "title" }, + { uri: uri4, title: "title" }, + { uri: uri5, title: "title" }, + { uri: uri6, title: "title" }, + { uri: uri7, title: "title" }, + { uri: uri8, title: "title" } + ]); + + let allMatches = [ + { uri: uri1, title: "title" }, + { uri: uri2, title: "title" }, + { uri: uri3, title: "title" }, + { uri: uri4, title: "title" }, + { uri: uri5, title: "title" }, + { uri: uri6, title: "title" } + ]; + + // Disable autoFill to avoid handling the first result. + Services.prefs.setBoolPref("browser.urlbar.autoFill", "false"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", false); + + do_print("http://www.site matches all site"); + yield check_autocomplete({ + search: "http://www.site", + matches: allMatches + }); + + do_print("http://site matches all site"); + yield check_autocomplete({ + search: "http://site", + matches: allMatches + }); + + do_print("ftp://ftp.site matches itself"); + yield check_autocomplete({ + search: "ftp://ftp.site", + matches: [ { uri: uri3, title: "title" } ] + }); + + do_print("ftp://site matches all site"); + yield check_autocomplete({ + search: "ftp://site", + matches: allMatches + }); + + do_print("https://www.site matches all site"); + yield check_autocomplete({ + search: "https://www.site", + matches: allMatches + }); + + do_print("https://site matches all site"); + yield check_autocomplete({ + search: "https://site", + matches: allMatches + }); + + do_print("www.site matches all site"); + yield check_autocomplete({ + search: "www.site", + matches: allMatches + }); + + do_print("w matches none of www."); + yield check_autocomplete({ + search: "w", + matches: [ { uri: uri7, title: "title" }, + { uri: uri8, title: "title" } ] + }); + + do_print("http://w matches none of www."); + yield check_autocomplete({ + search: "http://w", + matches: [ { uri: uri7, title: "title" }, + { uri: uri8, title: "title" } ] + }); + + do_print("http://w matches none of www."); + yield check_autocomplete({ + search: "http://www.w", + matches: [ { uri: uri7, title: "title" }, + { uri: uri8, title: "title" } ] + }); + + do_print("ww matches none of www."); + yield check_autocomplete({ + search: "ww", + matches: [ { uri: uri8, title: "title" } ] + }); + + do_print("ww matches none of www."); + yield check_autocomplete({ + search: "ww", + matches: [ { uri: uri8, title: "title" } ] + }); + + do_print("http://ww matches none of www."); + yield check_autocomplete({ + search: "http://ww", + matches: [ { uri: uri8, title: "title" } ] + }); + + do_print("http://www.ww matches none of www."); + yield check_autocomplete({ + search: "http://www.ww", + matches: [ { uri: uri8, title: "title" } ] + }); + + do_print("www matches none of www."); + yield check_autocomplete({ + search: "www", + matches: [ { uri: uri8, title: "title" } ] + }); + + do_print("http://www matches none of www."); + yield check_autocomplete({ + search: "http://www", + matches: [ { uri: uri8, title: "title" } ] + }); + + do_print("http://www.www matches none of www."); + yield check_autocomplete({ + search: "http://www.www", + matches: [ { uri: uri8, title: "title" } ] + }); + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_tab_matches.js b/toolkit/components/places/tests/unifiedcomplete/test_tab_matches.js new file mode 100644 index 000000000..740b8d8ed --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_tab_matches.js @@ -0,0 +1,164 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + * vim:set ts=2 sw=2 sts=2 et: + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var gTabRestrictChar = "%"; + +add_task(function* test_tab_matches() { + let uri1 = NetUtil.newURI("http://abc.com/"); + let uri2 = NetUtil.newURI("http://xyz.net/"); + let uri3 = NetUtil.newURI("about:mozilla"); + let uri4 = NetUtil.newURI("data:text/html,test"); + let uri5 = NetUtil.newURI("http://foobar.org"); + yield PlacesTestUtils.addVisits([ + { uri: uri1, title: "ABC rocks" }, + { uri: uri2, title: "xyz.net - we're better than ABC" }, + { uri: uri5, title: "foobar.org - much better than ABC, definitely better than XYZ" } + ]); + addOpenPages(uri1, 1); + // Pages that cannot be registered in history. + addOpenPages(uri3, 1); + addOpenPages(uri4, 1); + + do_print("two results, normal result is a tab match"); + yield check_autocomplete({ + search: "abc.com", + searchParam: "enable-actions", + matches: [ makeVisitMatch("abc.com", "http://abc.com/", { heuristic: true }), + makeSwitchToTabMatch("http://abc.com/", { title: "ABC rocks" }), + makeSearchMatch("abc.com", { heuristic: false }) ] + }); + + do_print("three results, one tab match"); + yield check_autocomplete({ + search: "abc", + searchParam: "enable-actions", + matches: [ makeSearchMatch("abc", { heuristic: true }), + makeSwitchToTabMatch("http://abc.com/", { title: "ABC rocks" }), + { uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] }, + { uri: uri5, title: "foobar.org - much better than ABC, definitely better than XYZ", style: [ "favicon" ] } ] + }); + + do_print("three results, both normal results are tab matches"); + addOpenPages(uri2, 1); + yield check_autocomplete({ + search: "abc", + searchParam: "enable-actions", + matches: [ makeSearchMatch("abc", { heuristic: true }), + makeSwitchToTabMatch("http://abc.com/", { title: "ABC rocks" }), + makeSwitchToTabMatch("http://xyz.net/", { title: "xyz.net - we're better than ABC" }), + { uri: uri5, title: "foobar.org - much better than ABC, definitely better than XYZ", style: [ "favicon" ] } ] + }); + + do_print("a container tab is not visible in 'switch to tab'"); + addOpenPages(uri5, 1, /* userContextId: */ 3); + yield check_autocomplete({ + search: "abc", + searchParam: "enable-actions", + matches: [ makeSearchMatch("abc", { heuristic: true }), + makeSwitchToTabMatch("http://abc.com/", { title: "ABC rocks" }), + makeSwitchToTabMatch("http://xyz.net/", { title: "xyz.net - we're better than ABC" }), + { uri: uri5, title: "foobar.org - much better than ABC, definitely better than XYZ", style: [ "favicon" ] } ] + }); + + do_print("a container tab should not see 'switch to tab' for other container tabs"); + yield check_autocomplete({ + search: "abc", + searchParam: "enable-actions user-context-id:3", + matches: [ makeSearchMatch("abc", { heuristic: true }), + makeSwitchToTabMatch("http://foobar.org/", { title: "foobar.org - much better than ABC, definitely better than XYZ" }), + { uri: uri1, title: "ABC rocks", style: [ "favicon" ] }, + { uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] } ] + }); + + do_print("a different container tab should not see any 'switch to tab'"); + yield check_autocomplete({ + search: "abc", + searchParam: "enable-actions user-context-id:2", + matches: [ makeSearchMatch("abc", { heuristic: true }), + { uri: uri1, title: "ABC rocks", style: [ "favicon" ] }, + { uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] }, + { uri: uri5, title: "foobar.org - much better than ABC, definitely better than XYZ", style: [ "favicon" ] } ] + }); + + do_print("three results, both normal results are tab matches, one has multiple tabs"); + addOpenPages(uri2, 5); + yield check_autocomplete({ + search: "abc", + searchParam: "enable-actions", + matches: [ makeSearchMatch("abc", { heuristic: true }), + makeSwitchToTabMatch("http://abc.com/", { title: "ABC rocks" }), + makeSwitchToTabMatch("http://xyz.net/", { title: "xyz.net - we're better than ABC" }), + { uri: uri5, title: "foobar.org - much better than ABC, definitely better than XYZ", style: [ "favicon" ] } ] + }); + + do_print("three results, no tab matches (disable-private-actions)"); + yield check_autocomplete({ + search: "abc", + searchParam: "enable-actions disable-private-actions", + matches: [ makeSearchMatch("abc", { heuristic: true }), + { uri: uri1, title: "ABC rocks", style: [ "favicon" ] }, + { uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] }, + { uri: uri5, title: "foobar.org - much better than ABC, definitely better than XYZ", style: [ "favicon" ] } ] + }); + + do_print("two results (actions disabled)"); + yield check_autocomplete({ + search: "abc", + searchParam: "", + matches: [ { uri: uri1, title: "ABC rocks", style: [ "favicon" ] }, + { uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] }, + { uri: uri5, title: "foobar.org - much better than ABC, definitely better than XYZ", style: [ "favicon" ] } ] + }); + + do_print("three results, no tab matches"); + removeOpenPages(uri1, 1); + removeOpenPages(uri2, 6); + yield check_autocomplete({ + search: "abc", + searchParam: "enable-actions", + matches: [ makeSearchMatch("abc", { heuristic: true }), + { uri: uri1, title: "ABC rocks", style: [ "favicon" ] }, + { uri: uri2, title: "xyz.net - we're better than ABC", style: [ "favicon" ] }, + { uri: uri5, title: "foobar.org - much better than ABC, definitely better than XYZ", style: [ "favicon" ] } ] + }); + + do_print("tab match search with restriction character"); + addOpenPages(uri1, 1); + yield check_autocomplete({ + search: gTabRestrictChar + " abc", + searchParam: "enable-actions", + matches: [ makeSearchMatch(gTabRestrictChar + " abc", { heuristic: true }), + makeSwitchToTabMatch("http://abc.com/", { title: "ABC rocks" }) ] + }); + + do_print("tab match with not-addable pages"); + yield check_autocomplete({ + search: "mozilla", + searchParam: "enable-actions", + matches: [ makeSearchMatch("mozilla", { heuristic: true }), + makeSwitchToTabMatch("about:mozilla") ] + }); + + do_print("tab match with not-addable pages and restriction character"); + yield check_autocomplete({ + search: gTabRestrictChar + " mozilla", + searchParam: "enable-actions", + matches: [ makeSearchMatch(gTabRestrictChar + " mozilla", { heuristic: true }), + makeSwitchToTabMatch("about:mozilla") ] + }); + + do_print("tab match with not-addable pages and only restriction character"); + yield check_autocomplete({ + search: gTabRestrictChar, + searchParam: "enable-actions", + matches: [ makeSearchMatch(gTabRestrictChar, { heuristic: true }), + makeSwitchToTabMatch("http://abc.com/", { title: "ABC rocks" }), + makeSwitchToTabMatch("about:mozilla"), + makeSwitchToTabMatch("data:text/html,test") ] + }); + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_trimming.js b/toolkit/components/places/tests/unifiedcomplete/test_trimming.js new file mode 100644 index 000000000..e55b009ff --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_trimming.js @@ -0,0 +1,313 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +add_task(function* test_untrimmed_secure_www() { + do_print("Searching for untrimmed https://www entry"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("https://www.mozilla.org/test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "mo", + autofilled: "mozilla.org/", + completed: "https://www.mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_untrimmed_secure_www_path() { + do_print("Searching for untrimmed https://www entry with path"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("https://www.mozilla.org/test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "mozilla.org/t", + autofilled: "mozilla.org/test/", + completed: "https://www.mozilla.org/test/" + }); + yield cleanup(); +}); + +add_task(function* test_untrimmed_secure() { + do_print("Searching for untrimmed https:// entry"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("https://mozilla.org/test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "mo", + autofilled: "mozilla.org/", + completed: "https://mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_untrimmed_secure_path() { + do_print("Searching for untrimmed https:// entry with path"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("https://mozilla.org/test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "mozilla.org/t", + autofilled: "mozilla.org/test/", + completed: "https://mozilla.org/test/" + }); + yield cleanup(); +}); + +add_task(function* test_untrimmed_www() { + do_print("Searching for untrimmed http://www entry"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://www.mozilla.org/test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "mo", + autofilled: "mozilla.org/", + completed: "www.mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_untrimmed_www_path() { + do_print("Searching for untrimmed http://www entry with path"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://www.mozilla.org/test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "mozilla.org/t", + autofilled: "mozilla.org/test/", + completed: "http://www.mozilla.org/test/" + }); + yield cleanup(); +}); + +add_task(function* test_untrimmed_ftp() { + do_print("Searching for untrimmed ftp:// entry"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("ftp://mozilla.org/test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "mo", + autofilled: "mozilla.org/", + completed: "ftp://mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_untrimmed_ftp_path() { + do_print("Searching for untrimmed ftp:// entry with path"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("ftp://mozilla.org/test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "mozilla.org/t", + autofilled: "mozilla.org/test/", + completed: "ftp://mozilla.org/test/" + }); + yield cleanup(); +}); + +add_task(function* test_priority_1() { + do_print("Ensuring correct priority 1"); + yield PlacesTestUtils.addVisits([ + { uri: NetUtil.newURI("https://www.mozilla.org/test/"), transition: TRANSITION_TYPED }, + { uri: NetUtil.newURI("https://mozilla.org/test/"), transition: TRANSITION_TYPED }, + { uri: NetUtil.newURI("ftp://mozilla.org/test/"), transition: TRANSITION_TYPED }, + { uri: NetUtil.newURI("http://www.mozilla.org/test/"), transition: TRANSITION_TYPED }, + { uri: NetUtil.newURI("http://mozilla.org/test/"), transition: TRANSITION_TYPED } + ]); + yield check_autocomplete({ + search: "mo", + autofilled: "mozilla.org/", + completed: "mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_periority_2() { + do_print( "Ensuring correct priority 2"); + yield PlacesTestUtils.addVisits([ + { uri: NetUtil.newURI("https://mozilla.org/test/"), transition: TRANSITION_TYPED }, + { uri: NetUtil.newURI("ftp://mozilla.org/test/"), transition: TRANSITION_TYPED }, + { uri: NetUtil.newURI("http://www.mozilla.org/test/"), transition: TRANSITION_TYPED }, + { uri: NetUtil.newURI("http://mozilla.org/test/"), transition: TRANSITION_TYPED } + ]); + yield check_autocomplete({ + search: "mo", + autofilled: "mozilla.org/", + completed: "mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_periority_3() { + do_print("Ensuring correct priority 3"); + yield PlacesTestUtils.addVisits([ + { uri: NetUtil.newURI("ftp://mozilla.org/test/"), transition: TRANSITION_TYPED }, + { uri: NetUtil.newURI("http://www.mozilla.org/test/"), transition: TRANSITION_TYPED }, + { uri: NetUtil.newURI("http://mozilla.org/test/"), transition: TRANSITION_TYPED } + ]); + yield check_autocomplete({ + search: "mo", + autofilled: "mozilla.org/", + completed: "mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_periority_4() { + do_print("Ensuring correct priority 4"); + yield PlacesTestUtils.addVisits([ + { uri: NetUtil.newURI("http://www.mozilla.org/test/"), transition: TRANSITION_TYPED }, + { uri: NetUtil.newURI("http://mozilla.org/test/"), transition: TRANSITION_TYPED } + ]); + yield check_autocomplete({ + search: "mo", + autofilled: "mozilla.org/", + completed: "mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_priority_5() { + do_print("Ensuring correct priority 5"); + yield PlacesTestUtils.addVisits([ + { uri: NetUtil.newURI("ftp://mozilla.org/test/"), transition: TRANSITION_TYPED }, + { uri: NetUtil.newURI("ftp://www.mozilla.org/test/"), transition: TRANSITION_TYPED } + ]); + yield check_autocomplete({ + search: "mo", + autofilled: "mozilla.org/", + completed: "ftp://mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_priority_6() { + do_print("Ensuring correct priority 6"); + yield PlacesTestUtils.addVisits([ + { uri: NetUtil.newURI("http://www.mozilla.org/test1/"), transition: TRANSITION_TYPED }, + { uri: NetUtil.newURI("http://www.mozilla.org/test2/"), transition: TRANSITION_TYPED } + ]); + yield check_autocomplete({ + search: "mo", + autofilled: "mozilla.org/", + completed: "www.mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_longer_domain() { + do_print("Ensuring longer domain can't match"); + // The .co should be preferred, but should not get the https from the .com. + // The .co domain must be added later to activate the trigger bug. + yield PlacesTestUtils.addVisits([ + { uri: NetUtil.newURI("https://mozilla.com/"), transition: TRANSITION_TYPED }, + { uri: NetUtil.newURI("http://mozilla.co/"), transition: TRANSITION_TYPED }, + { uri: NetUtil.newURI("http://mozilla.co/"), transition: TRANSITION_TYPED } + ]); + yield check_autocomplete({ + search: "mo", + autofilled: "mozilla.co/", + completed: "mozilla.co/" + }); + + yield cleanup(); +}); + +add_task(function* test_escaped_chars() { + do_print("Searching for URL with characters that are normally escaped"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("https://www.mozilla.org/啊-test"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "https://www.mozilla.org/啊-test", + autofilled: "https://www.mozilla.org/啊-test", + completed: "https://www.mozilla.org/啊-test" + }); + yield cleanup(); +}); + +add_task(function* test_unsecure_secure() { + do_print("Don't return unsecure URL when searching for secure ones"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://test.moz.org/test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "https://test.moz.org/t", + autofilled: "https://test.moz.org/test/", + completed: "https://test.moz.org/test/" + }); + yield cleanup(); +}); + +add_task(function* test_unsecure_secure_domain() { + do_print("Don't return unsecure domain when searching for secure ones"); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://test.moz.org/test/"), + transition: TRANSITION_TYPED + }); + yield check_autocomplete({ + search: "https://test.moz", + autofilled: "https://test.moz.org/", + completed: "https://test.moz.org/" + }); + yield cleanup(); +}); + +add_task(function* test_untyped_www() { + do_print("Untyped is not accounted for www"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + yield PlacesTestUtils.addVisits({ uri: NetUtil.newURI("http://www.moz.org/test/") }); + yield check_autocomplete({ + search: "mo", + autofilled: "moz.org/", + completed: "moz.org/" + }); + yield cleanup(); +}); + +add_task(function* test_untyped_ftp() { + do_print("Untyped is not accounted for ftp"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + yield PlacesTestUtils.addVisits({ uri: NetUtil.newURI("ftp://moz.org/test/") }); + yield check_autocomplete({ + search: "mo", + autofilled: "moz.org/", + completed: "moz.org/" + }); + yield cleanup(); +}); + +add_task(function* test_untyped_secure() { + do_print("Untyped is not accounted for https"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + yield PlacesTestUtils.addVisits({ uri: NetUtil.newURI("https://moz.org/test/") }); + yield check_autocomplete({ + search: "mo", + autofilled: "moz.org/", + completed: "moz.org/" + }); + yield cleanup(); +}); + +add_task(function* test_untyped_secure_www() { + do_print("Untyped is not accounted for https://www"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + yield PlacesTestUtils.addVisits({ uri: NetUtil.newURI("https://www.moz.org/test/") }); + yield check_autocomplete({ + search: "mo", + autofilled: "moz.org/", + completed: "moz.org/" + }); + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_typed.js b/toolkit/components/places/tests/unifiedcomplete/test_typed.js new file mode 100644 index 000000000..72f76159c --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_typed.js @@ -0,0 +1,84 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// First do searches with typed behavior forced to false, so later tests will +// ensure autocomplete is able to dinamically switch behavior. + +const FAVICON_HREF = NetUtil.newURI(do_get_file("../favicons/favicon-normal16.png")).spec; + +add_task(function* test_domain() { + do_print("Searching for domain should autoFill it"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + yield PlacesTestUtils.addVisits(NetUtil.newURI("http://mozilla.org/link/")); + yield setFaviconForHref("http://mozilla.org/link/", FAVICON_HREF); + yield check_autocomplete({ + search: "moz", + autofilled: "mozilla.org/", + completed: "mozilla.org/", + icon: "moz-anno:favicon:" + FAVICON_HREF + }); + yield cleanup(); +}); + +add_task(function* test_url() { + do_print("Searching for url should autoFill it"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + yield PlacesTestUtils.addVisits(NetUtil.newURI("http://mozilla.org/link/")); + yield setFaviconForHref("http://mozilla.org/link/", FAVICON_HREF); + yield check_autocomplete({ + search: "mozilla.org/li", + autofilled: "mozilla.org/link/", + completed: "http://mozilla.org/link/", + icon: "moz-anno:favicon:" + FAVICON_HREF + }); + yield cleanup(); +}); + +// Now do searches with typed behavior forced to true. + +add_task(function* test_untyped_domain() { + do_print("Searching for non-typed domain should not autoFill it"); + yield PlacesTestUtils.addVisits(NetUtil.newURI("http://mozilla.org/link/")); + yield check_autocomplete({ + search: "moz", + autofilled: "moz", + completed: "moz" + }); + yield cleanup(); +}); + +add_task(function* test_typed_domain() { + do_print("Searching for typed domain should autoFill it"); + yield PlacesTestUtils.addVisits({ uri: NetUtil.newURI("http://mozilla.org/typed/"), + transition: TRANSITION_TYPED }); + yield check_autocomplete({ + search: "moz", + autofilled: "mozilla.org/", + completed: "mozilla.org/" + }); + yield cleanup(); +}); + +add_task(function* test_untyped_url() { + do_print("Searching for non-typed url should not autoFill it"); + yield PlacesTestUtils.addVisits(NetUtil.newURI("http://mozilla.org/link/")); + yield check_autocomplete({ + search: "mozilla.org/li", + autofilled: "mozilla.org/li", + completed: "mozilla.org/li" + }); + yield cleanup(); +}); + +add_task(function* test_typed_url() { + do_print("Searching for typed url should autoFill it"); + yield PlacesTestUtils.addVisits({ uri: NetUtil.newURI("http://mozilla.org/link/"), + transition: TRANSITION_TYPED }); + yield check_autocomplete({ + search: "mozilla.org/li", + autofilled: "mozilla.org/link/", + completed: "http://mozilla.org/link/" + }); + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_visit_url.js b/toolkit/components/places/tests/unifiedcomplete/test_visit_url.js new file mode 100644 index 000000000..eaccb23e5 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_visit_url.js @@ -0,0 +1,186 @@ +add_task(function*() { + do_print("visit url, no protocol"); + yield check_autocomplete({ + search: "mozilla.org", + searchParam: "enable-actions", + matches: [ + { uri: makeActionURI("visiturl", {url: "http://mozilla.org/", input: "mozilla.org"}), title: "http://mozilla.org/", style: [ "action", "visiturl", "heuristic" ] }, + { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "mozilla.org", searchQuery: "mozilla.org"}), title: "MozSearch", style: ["action", "searchengine"] } + ] + }); + + do_print("visit url, no protocol but with 2 dots"); + yield check_autocomplete({ + search: "www.mozilla.org", + searchParam: "enable-actions", + matches: [ + { uri: makeActionURI("visiturl", {url: "http://www.mozilla.org/", input: "www.mozilla.org"}), title: "http://www.mozilla.org/", style: [ "action", "visiturl", "heuristic" ] }, + { uri: makeActionURI("searchengine", {engineName: "MozSearch", input: "www.mozilla.org", searchQuery: "www.mozilla.org"}), title: "MozSearch", style: ["action", "searchengine"] } + ] + }); + + do_print("visit url, no protocol but with 3 dots"); + yield check_autocomplete({ + search: "www.mozilla.org.tw", + searchParam: "enable-actions", + matches: [ { uri: makeActionURI("visiturl", {url: "http://www.mozilla.org.tw/", input: "www.mozilla.org.tw"}), title: "http://www.mozilla.org.tw/", style: [ "action", "visiturl", "heuristic" ] } ] + }); + + do_print("visit url, with protocol but with 2 dots"); + yield check_autocomplete({ + search: "https://www.mozilla.org", + searchParam: "enable-actions", + matches: [ { uri: makeActionURI("visiturl", {url: "https://www.mozilla.org/", input: "https://www.mozilla.org"}), title: "https://www.mozilla.org/", style: [ "action", "visiturl", "heuristic" ] } ] + }); + + do_print("visit url, with protocol but with 3 dots"); + yield check_autocomplete({ + search: "https://www.mozilla.org.tw", + searchParam: "enable-actions", + matches: [ { uri: makeActionURI("visiturl", {url: "https://www.mozilla.org.tw/", input: "https://www.mozilla.org.tw"}), title: "https://www.mozilla.org.tw/", style: [ "action", "visiturl", "heuristic" ] } ] + }); + + do_print("visit url, with protocol"); + yield check_autocomplete({ + search: "https://mozilla.org", + searchParam: "enable-actions", + matches: [ { uri: makeActionURI("visiturl", {url: "https://mozilla.org/", input: "https://mozilla.org"}), title: "https://mozilla.org/", style: [ "action", "visiturl", "heuristic" ] } ] + }); + + do_print("visit url, about: protocol (no host)"); + yield check_autocomplete({ + search: "about:config", + searchParam: "enable-actions", + matches: [ { uri: makeActionURI("visiturl", {url: "about:config", input: "about:config"}), title: "about:config", style: [ "action", "visiturl", "heuristic" ] } ] + }); + + // This is distinct because of how we predict being able to url autofill via + // host lookups. + do_print("visit url, host matching visited host but not visited url"); + yield PlacesTestUtils.addVisits([ + { uri: NetUtil.newURI("http://mozilla.org/wine/"), title: "Mozilla Wine", transition: TRANSITION_TYPED }, + ]); + yield check_autocomplete({ + search: "mozilla.org/rum", + searchParam: "enable-actions", + matches: [ makeVisitMatch("mozilla.org/rum", "http://mozilla.org/rum", { heuristic: true }) ] + }); + + // And hosts with no dot in them are special, due to requiring whitelisting. + do_print("non-whitelisted host"); + yield check_autocomplete({ + search: "firefox", + searchParam: "enable-actions", + matches: [ makeSearchMatch("firefox", { heuristic: true }) ] + }); + + do_print("url with non-whitelisted host"); + yield check_autocomplete({ + search: "firefox/get", + searchParam: "enable-actions", + matches: [ makeVisitMatch("firefox/get", "http://firefox/get", { heuristic: true }) ] + }); + + Services.prefs.setBoolPref("browser.fixup.domainwhitelist.firefox", true); + do_register_cleanup(() => { + Services.prefs.clearUserPref("browser.fixup.domainwhitelist.firefox"); + }); + + do_print("whitelisted host"); + yield check_autocomplete({ + search: "firefox", + searchParam: "enable-actions", + matches: [ + makeVisitMatch("firefox", "http://firefox/", { heuristic: true }), + makeSearchMatch("firefox", { heuristic: false }) + ] + }); + + do_print("url with whitelisted host"); + yield check_autocomplete({ + search: "firefox/get", + searchParam: "enable-actions", + matches: [ makeVisitMatch("firefox/get", "http://firefox/get", { heuristic: true }) ] + }); + + do_print("visit url, host matching visited host but not visited url, whitelisted host"); + Services.prefs.setBoolPref("browser.fixup.domainwhitelist.mozilla", true); + do_register_cleanup(() => { + Services.prefs.clearUserPref("browser.fixup.domainwhitelist.mozilla"); + }); + yield check_autocomplete({ + search: "mozilla/rum", + searchParam: "enable-actions", + matches: [ makeVisitMatch("mozilla/rum", "http://mozilla/rum", { heuristic: true }) ] + }); + + // ipv4 and ipv6 literal addresses should offer to visit. + do_print("visit url, ipv4 literal"); + yield check_autocomplete({ + search: "127.0.0.1", + searchParam: "enable-actions", + matches: [ makeVisitMatch("127.0.0.1", "http://127.0.0.1/", { heuristic: true }) ] + }); + + do_print("visit url, ipv6 literal"); + yield check_autocomplete({ + search: "[2001:db8::1]", + searchParam: "enable-actions", + matches: [ makeVisitMatch("[2001:db8::1]", "http://[2001:db8::1]/", { heuristic: true }) ] + }); + + // Setting keyword.enabled to false should always try to visit. + let keywordEnabled = Services.prefs.getBoolPref("keyword.enabled"); + Services.prefs.setBoolPref("keyword.enabled", false); + do_register_cleanup(() => { + Services.prefs.clearUserPref("keyword.enabled"); + }); + do_print("visit url, keyword.enabled = false"); + yield check_autocomplete({ + search: "bacon", + searchParam: "enable-actions", + matches: [ makeVisitMatch("bacon", "http://bacon/", { heuristic: true }) ] + }); + do_print("visit two word query, keyword.enabled = false"); + yield check_autocomplete({ + search: "bacon lovers", + searchParam: "enable-actions", + matches: [ makeVisitMatch("bacon lovers", "bacon lovers", { heuristic: true }) ] + }); + Services.prefs.setBoolPref("keyword.enabled", keywordEnabled); + + do_print("visit url, scheme+host"); + yield check_autocomplete({ + search: "http://example", + searchParam: "enable-actions", + matches: [ makeVisitMatch("http://example", "http://example/", { heuristic: true }) ] + }); + + do_print("visit url, scheme+host"); + yield check_autocomplete({ + search: "ftp://example", + searchParam: "enable-actions", + matches: [ makeVisitMatch("ftp://example", "ftp://example/", { heuristic: true }) ] + }); + + do_print("visit url, host+port"); + yield check_autocomplete({ + search: "example:8080", + searchParam: "enable-actions", + matches: [ makeVisitMatch("example:8080", "http://example:8080/", { heuristic: true }) ] + }); + + do_print("numerical operations that look like urls should search"); + yield check_autocomplete({ + search: "123/12", + searchParam: "enable-actions", + matches: [ makeSearchMatch("123/12", { heuristic: true }) ] + }); + + do_print("numerical operations that look like urls should search"); + yield check_autocomplete({ + search: "123.12/12.1", + searchParam: "enable-actions", + matches: [ makeSearchMatch("123.12/12.1", { heuristic: true }) ] + }); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_word_boundary_search.js b/toolkit/components/places/tests/unifiedcomplete/test_word_boundary_search.js new file mode 100644 index 000000000..f79573ae6 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_word_boundary_search.js @@ -0,0 +1,175 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * Test bug 393678 to make sure matches against the url, title, tags are only + * made on word boundaries instead of in the middle of words. + * + * Make sure we don't try matching one after a CamelCase because the upper-case + * isn't really a word boundary. (bug 429498) + * + * Bug 429531 provides switching between "must match on word boundary" and "can + * match," so leverage "must match" pref for checking word boundary logic and + * make sure "can match" matches anywhere. + */ + +var katakana = ["\u30a8", "\u30c9"]; // E, Do +var ideograph = ["\u4efb", "\u5929", "\u5802"]; // Nin Ten Do + +add_task(function* test_escape() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", false); + + let uri1 = NetUtil.newURI("http://matchme/"); + let uri2 = NetUtil.newURI("http://dontmatchme/"); + let uri3 = NetUtil.newURI("http://title/1"); + let uri4 = NetUtil.newURI("http://title/2"); + let uri5 = NetUtil.newURI("http://tag/1"); + let uri6 = NetUtil.newURI("http://tag/2"); + let uri7 = NetUtil.newURI("http://crazytitle/"); + let uri8 = NetUtil.newURI("http://katakana/"); + let uri9 = NetUtil.newURI("http://ideograph/"); + let uri10 = NetUtil.newURI("http://camel/pleaseMatchMe/"); + + yield PlacesTestUtils.addVisits([ + { uri: uri1, title: "title1" }, + { uri: uri2, title: "title1" }, + { uri: uri3, title: "matchme2" }, + { uri: uri4, title: "dontmatchme3" }, + { uri: uri5, title: "title1" }, + { uri: uri6, title: "title1" }, + { uri: uri7, title: "!@#$%^&*()_+{}|:<>?word" }, + { uri: uri8, title: katakana.join("") }, + { uri: uri9, title: ideograph.join("") }, + { uri: uri10, title: "title1" } + ]); + yield addBookmark( { uri: uri5, title: "title1", tags: [ "matchme2" ] } ); + yield addBookmark( { uri: uri6, title: "title1", tags: [ "dontmatchme3" ] } ); + + // match only on word boundaries + Services.prefs.setIntPref("browser.urlbar.matchBehavior", 2); + + do_print("Match 'match' at the beginning or after / or on a CamelCase"); + yield check_autocomplete({ + search: "match", + matches: [ { uri: uri1, title: "title1" }, + { uri: uri3, title: "matchme2" }, + { uri: uri5, title: "title1", tags: [ "matchme2" ], style: [ "bookmark-tag" ] }, + { uri: uri10, title: "title1" } ] + }); + + do_print("Match 'dont' at the beginning or after /"); + yield check_autocomplete({ + search: "dont", + matches: [ { uri: uri2, title: "title1" }, + { uri: uri4, title: "dontmatchme3" }, + { uri: uri6, title: "title1", tags: [ "dontmatchme3" ], style: [ "bookmark-tag" ] } ] + }); + + do_print("Match 'match' at the beginning or after / or on a CamelCase"); + yield check_autocomplete({ + search: "2", + matches: [ { uri: uri3, title: "matchme2" }, + { uri: uri4, title: "dontmatchme3" }, + { uri: uri5, title: "title1", tags: [ "matchme2" ], style: [ "bookmark-tag" ] }, + { uri: uri6, title: "title1", tags: [ "dontmatchme3" ], style: [ "bookmark-tag" ] } ] + }); + + do_print("Match 't' at the beginning or after /"); + yield check_autocomplete({ + search: "t", + matches: [ { uri: uri1, title: "title1" }, + { uri: uri2, title: "title1" }, + { uri: uri3, title: "matchme2" }, + { uri: uri4, title: "dontmatchme3" }, + { uri: uri5, title: "title1", tags: [ "matchme2" ], style: [ "bookmark-tag" ] }, + { uri: uri6, title: "title1", tags: [ "dontmatchme3" ], style: [ "bookmark-tag" ] }, + { uri: uri10, title: "title1" } ] + }); + + do_print("Match 'word' after many consecutive word boundaries"); + yield check_autocomplete({ + search: "word", + matches: [ { uri: uri7, title: "!@#$%^&*()_+{}|:<>?word" } ] + }); + + do_print("Match a word boundary '/' for everything"); + yield check_autocomplete({ + search: "/", + matches: [ { uri: uri1, title: "title1" }, + { uri: uri2, title: "title1" }, + { uri: uri3, title: "matchme2" }, + { uri: uri4, title: "dontmatchme3" }, + { uri: uri5, title: "title1", tags: [ "matchme2" ], style: [ "bookmark-tag" ] }, + { uri: uri6, title: "title1", tags: [ "dontmatchme3" ], style: [ "bookmark-tag" ] }, + { uri: uri7, title: "!@#$%^&*()_+{}|:<>?word" }, + { uri: uri8, title: katakana.join("") }, + { uri: uri9, title: ideograph.join("") }, + { uri: uri10, title: "title1" } ] + }); + + do_print("Match word boundaries '()_+' that are among word boundaries"); + yield check_autocomplete({ + search: "()_+", + matches: [ { uri: uri7, title: "!@#$%^&*()_+{}|:<>?word" } ] + }); + + do_print("Katakana characters form a string, so match the beginning"); + yield check_autocomplete({ + search: katakana[0], + matches: [ { uri: uri8, title: katakana.join("") } ] + }); + +/* + do_print("Middle of a katakana word shouldn't be matched"); + yield check_autocomplete({ + search: katakana[1], + matches: [ ] + }); +*/ + do_print("Ideographs are treated as words so 'nin' is one word"); + yield check_autocomplete({ + search: ideograph[0], + matches: [ { uri: uri9, title: ideograph.join("") } ] + }); + + do_print("Ideographs are treated as words so 'ten' is another word"); + yield check_autocomplete({ + search: ideograph[1], + matches: [ { uri: uri9, title: ideograph.join("") } ] + }); + + do_print("Ideographs are treated as words so 'do' is yet another word"); + yield check_autocomplete({ + search: ideograph[2], + matches: [ { uri: uri9, title: ideograph.join("") } ] + }); + + do_print("Extra negative assert that we don't match in the middle"); + yield check_autocomplete({ + search: "ch", + matches: [ ] + }); + + do_print("Don't match one character after a camel-case word boundary (bug 429498)"); + yield check_autocomplete({ + search: "atch", + matches: [ ] + }); + + // match against word boundaries and anywhere + Services.prefs.setIntPref("browser.urlbar.matchBehavior", 1); + + yield check_autocomplete({ + search: "tch", + matches: [ { uri: uri1, title: "title1" }, + { uri: uri2, title: "title1" }, + { uri: uri3, title: "matchme2" }, + { uri: uri4, title: "dontmatchme3" }, + { uri: uri5, title: "title1", tags: [ "matchme2" ], style: [ "bookmark-tag" ] }, + { uri: uri6, title: "title1", tags: [ "dontmatchme3" ], style: [ "bookmark-tag" ] }, + { uri: uri10, title: "title1" } ] + }); + + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_zero_frecency.js b/toolkit/components/places/tests/unifiedcomplete/test_zero_frecency.js new file mode 100644 index 000000000..adf638886 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_zero_frecency.js @@ -0,0 +1,35 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Ensure inline autocomplete doesn't return zero frecency pages. + +add_task(function* test_zzero_frec_domain() { + do_print("Searching for zero frecency domain should not autoFill it"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/framed_link/"), + transition: TRANSITION_FRAMED_LINK + }); + yield check_autocomplete({ + search: "moz", + autofilled: "moz", + completed: "moz" + }); + yield cleanup(); +}); + +add_task(function* test_zzero_frec_url() { + do_print("Searching for zero frecency url should not autoFill it"); + Services.prefs.setBoolPref("browser.urlbar.autoFill.typed", false); + yield PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/framed_link/"), + transition: TRANSITION_FRAMED_LINK + }); + yield check_autocomplete({ + search: "mozilla.org/f", + autofilled: "mozilla.org/f", + completed: "mozilla.org/f" + }); + yield cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/xpcshell.ini b/toolkit/components/places/tests/unifiedcomplete/xpcshell.ini new file mode 100644 index 000000000..60ef8c48a --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/xpcshell.ini @@ -0,0 +1,49 @@ +[DEFAULT] +head = head_autocomplete.js +tail = +skip-if = toolkit == 'android' +support-files = + data/engine-rel-searchform.xml + data/engine-suggestions.xml + !/toolkit/components/places/tests/favicons/favicon-normal16.png + +[test_416211.js] +[test_416214.js] +[test_417798.js] +[test_418257.js] +[test_422277.js] +[test_autocomplete_functional.js] +[test_autocomplete_on_value_removed_479089.js] +[test_autofill_default_behavior.js] +[test_avoid_middle_complete.js] +[test_avoid_stripping_to_empty_tokens.js] +[test_casing.js] +[test_do_not_trim.js] +[test_download_embed_bookmarks.js] +[test_dupe_urls.js] +[test_empty_search.js] +[test_enabled.js] +[test_escape_self.js] +[test_extension_matches.js] +[test_ignore_protocol.js] +[test_keyword_search.js] +[test_keyword_search_actions.js] +[test_keywords.js] +[test_match_beginning.js] +[test_multi_word_search.js] +[test_query_url.js] +[test_remote_tab_matches.js] +skip-if = !sync +[test_search_engine_alias.js] +[test_search_engine_current.js] +[test_search_engine_host.js] +[test_search_engine_restyle.js] +[test_search_suggestions.js] +[test_special_search.js] +[test_swap_protocol.js] +[test_tab_matches.js] +[test_trimming.js] +[test_typed.js] +[test_visit_url.js] +[test_word_boundary_search.js] +[test_zero_frecency.js] |