Bug 1677126 - Part 4 - Port remote tab tests and update them to expect result flex. r=adw

Differential Revision: https://phabricator.services.mozilla.com/D114895
This commit is contained in:
Harry Twyford 2021-06-02 22:43:29 +00:00
parent 2ae48118ca
commit 8c2a61dafd
11 changed files with 663 additions and 416 deletions

View File

@ -230,6 +230,7 @@ add_task(async function test_onProviderResultsRequested() {
title: "Test remote_tab-tabs result",
url: "https://example.com/remote_tab-tabs",
device: "device",
lastUsed: 1621366890,
},
},
{
@ -327,6 +328,7 @@ add_task(async function test_onProviderResultsRequested() {
url: "https://example.com/remote_tab-tabs",
displayUrl: "example.com/remote_tab-tabs",
device: "device",
lastUsed: 1621366890,
},
},
{

View File

@ -166,7 +166,7 @@ class ProviderRemoteTabs extends UrlbarProvider {
title: [tab.title, UrlbarUtils.HIGHLIGHT.TYPED],
device: client.name,
icon: showRemoteIconsPref ? tab.icon : "",
lastUsed: tab.lastUsed * 1000,
lastUsed: (tab.lastUsed || 0) * 1000,
})
)
);

View File

@ -27,7 +27,7 @@ const REMOTE_TAB = {
url: TEST_URL,
icon: UrlbarUtils.ICON.DEFAULT,
client: "7cqCr77ptzX3",
lastUsed: 1452124677,
lastUsed: Math.floor(Date.now() / 1000),
},
],
};

View File

@ -50,7 +50,7 @@ add_task(async function setup() {
url: "https://example.com",
icon: UrlbarUtils.ICON.DEFAULT,
client: "7cqCr77ptzX3",
lastUsed: 1452124677,
lastUsed: Math.floor(Date.now() / 1000),
},
{
type: "tab",
@ -58,7 +58,7 @@ add_task(async function setup() {
url: "https://example-2.com",
icon: UrlbarUtils.ICON.DEFAULT,
client: "7cqCr77ptzX3",
lastUsed: 1452124677,
lastUsed: Math.floor(Date.now() / 1000),
},
],
};

View File

@ -136,7 +136,7 @@ add_task(async function setup() {
url: "http://example.com",
icon: UrlbarUtils.ICON.DEFAULT,
client: "7cqCr77ptzX3",
lastUsed: 1452124677,
lastUsed: Math.floor(Date.now() / 1000),
},
],
};

View File

@ -261,7 +261,7 @@ add_task(async function test_remote_tab_result() {
url: "http://example.com",
icon: UrlbarUtils.ICON.DEFAULT,
client: "7cqCr77ptzX3",
lastUsed: parseInt(Date.now() / 1000),
lastUsed: Math.floor(Date.now() / 1000),
},
],
};

View File

@ -295,6 +295,18 @@ async function addTestTailSuggestionsEngine(suggestionsFn = null) {
return engine;
}
async function addOpenPages(uri, count = 1, userContextId = 0) {
for (let i = 0; i < count; i++) {
await UrlbarProviderOpenTabs.registerOpenTab(uri.spec, userContextId);
}
}
async function removeOpenPages(aUri, aCount = 1, aUserContextId = 0) {
for (let i = 0; i < aCount; i++) {
await UrlbarProviderOpenTabs.unregisterOpenTab(aUri.spec, aUserContextId);
}
}
/**
* Helper for tests that generate search results but aren't interested in
* suggestions, such as autofill tests. Installs a test engine and disables
@ -457,6 +469,31 @@ function makeOmniboxResult(
return result;
}
/**
* Creates a UrlbarResult for an switch-to-tab result.
* @param {UrlbarQueryContext} queryContext
* The context that this result will be displayed in.
* @param {string} options.uri
* The page URI.
* @param {string} [options.title]
* The page title.
* @param {string} [options.iconUri]
* A URI for the page icon.
* @returns {UrlbarResult}
*/
function makeTabSwitchResult(queryContext, { uri, title, iconUri }) {
return new UrlbarResult(
UrlbarUtils.RESULT_TYPE.TAB_SWITCH,
UrlbarUtils.RESULT_SOURCE.TABS,
...UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, {
url: [uri, UrlbarUtils.HIGHLIGHT.TYPED],
title: [title, UrlbarUtils.HIGHLIGHT.TYPED],
// Check against undefined so consumers can pass in the empty string.
icon: typeof iconUri != "undefined" ? iconUri : `page-icon:${uri}`,
})
);
}
/**
* Creates a UrlbarResult for a keyword search result.
* @param {UrlbarQueryContext} queryContext
@ -530,6 +567,54 @@ function makePrioritySearchResult(
return result;
}
/**
* Creates a UrlbarResult for a remote tab result.
* @param {UrlbarQueryContext} queryContext
* The context that this result will be displayed in.
* @param {string} options.uri
* The page URI.
* @param {string} options.device
* The name of the device that the remote tab comes from.
* @param {string} [options.title]
* The page title.
* @param {number} [options.lastUsed]
* The last time the remote tab was visited, in epoch seconds. Defaults
* to 0.
* @param {string} [options.iconUri]
* A URI for the page's icon.
* @returns {UrlbarResult}
*/
function makeRemoteTabResult(
queryContext,
{ uri, device, title, iconUri, lastUsed = 0 }
) {
let payload = {
url: [uri, UrlbarUtils.HIGHLIGHT.TYPED],
device: [device, UrlbarUtils.HIGHLIGHT.TYPED],
// Check against undefined so consumers can pass in the empty string.
icon:
typeof iconUri != "undefined"
? iconUri
: `moz-anno:favicon:page-icon:${uri}`,
lastUsed: lastUsed * 1000,
};
// Check against undefined so consumers can pass in the empty string.
if (typeof title != "undefined") {
payload.title = [title, UrlbarUtils.HIGHLIGHT.TYPED];
} else {
payload.title = [uri, UrlbarUtils.HIGHLIGHT.TYPED];
}
let result = new UrlbarResult(
UrlbarUtils.RESULT_TYPE.REMOTE_TAB,
UrlbarUtils.RESULT_SOURCE.TABS,
...UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, payload)
);
return result;
}
/**
* Creates a UrlbarResult for a search result.
* @param {UrlbarQueryContext} queryContext

View File

@ -0,0 +1,568 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
* vim:set ts=2 sw=2 sts=2 et:
*/
"use strict";
const { Weave } = ChromeUtils.import("resource://services-sync/main.js");
// 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",
startTracking() {},
getAllClients() {
return this.clients;
},
};
// A clients engine that doesn't need to be a constructor.
let MockClientsEngine = {
getClientType(guid) {
Assert.ok(guid.endsWith("desktop") || guid.endsWith("mobile"));
return guid.endsWith("mobile") ? "phone" : "desktop";
},
remoteClientExists(id) {
return true;
},
getClientName(id) {
return id.endsWith("mobile") ? "My Phone" : "My Desktop";
},
};
// 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;
Weave.Service.clientsEngine = MockClientsEngine;
// Send an observer that pretends the engine just finished a sync.
Services.obs.notifyObservers(null, "weave:engine:sync:finish", "tabs");
}
add_task(async function setup() {
// Tell Sync about the mocks.
Weave.Service.engineManager.register(MockTabsEngine);
// Tell the Sync XPCOM service it is initialized.
let weaveXPCService = Cc["@mozilla.org/weave/service;1"].getService(
Ci.nsISupports
).wrappedJSObject;
weaveXPCService.ready = true;
// Install a test engine.
let engine = await addTestSuggestionsEngine();
let oldDefaultEngine = await Services.search.getDefault();
registerCleanupFunction(async () => {
Services.search.setDefault(oldDefaultEngine);
Services.prefs.clearUserPref("services.sync.username");
Services.prefs.clearUserPref("services.sync.registerEngines");
Services.prefs.clearUserPref("browser.urlbar.suggest.searches");
await cleanupPlaces();
});
Services.search.setDefault(engine);
Services.prefs.setCharPref("services.sync.username", "someone@somewhere.com");
Services.prefs.setCharPref("services.sync.registerEngines", "");
// Avoid hitting the network.
Services.prefs.setBoolPref("browser.urlbar.suggest.searches", false);
});
add_task(async function test_minimal() {
// The minimal client and tabs info we can get away with.
configureEngine({
guid_desktop: {
id: "desktop",
tabs: [
{
urlHistory: ["http://example.com/"],
},
],
},
});
let query = "ex";
let context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
}),
makeRemoteTabResult(context, {
uri: "http://example.com/",
device: "My Desktop",
}),
],
});
});
add_task(async function test_maximal() {
// Every field that could possibly exist on a remote record.
configureEngine({
guid_mobile: {
id: "mobile",
tabs: [
{
urlHistory: ["http://example.com/"],
title: "An Example",
icon: "http://favicon",
},
],
},
});
let query = "ex";
let context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
}),
makeRemoteTabResult(context, {
uri: "http://example.com/",
device: "My Phone",
title: "An Example",
iconUri: "moz-anno:favicon:http://favicon/",
}),
],
});
});
add_task(async function test_noShowIcons() {
Services.prefs.setBoolPref("services.sync.syncedTabs.showRemoteIcons", false);
configureEngine({
guid_mobile: {
id: "mobile",
tabs: [
{
urlHistory: ["http://example.com/"],
title: "An Example",
icon: "http://favicon",
},
],
},
});
let query = "ex";
let context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
}),
makeRemoteTabResult(context, {
uri: "http://example.com/",
device: "My Phone",
title: "An Example",
// expecting the default favicon due to that pref.
iconUri: "",
}),
],
});
Services.prefs.clearUserPref("services.sync.syncedTabs.showRemoteIcons");
});
add_task(async function test_dontMatchSyncedTabs() {
Services.prefs.setBoolPref("services.sync.syncedTabs.showRemoteTabs", false);
configureEngine({
guid_mobile: {
id: "mobile",
tabs: [
{
urlHistory: ["http://example.com/"],
title: "An Example",
icon: "http://favicon",
},
],
},
});
let context = createContext("ex", { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
}),
],
});
Services.prefs.clearUserPref("services.sync.syncedTabs.showRemoteTabs");
});
add_task(async function test_matches_title() {
// URL doesn't match search expression, should still match the title.
configureEngine({
guid_mobile: {
id: "mobile",
tabs: [
{
urlHistory: ["http://foo.com/"],
title: "An Example",
},
],
},
});
let query = "ex";
let context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
}),
makeRemoteTabResult(context, {
uri: "http://foo.com/",
device: "My Phone",
title: "An Example",
}),
],
});
});
add_task(async 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 set up Sync to have the page as a remote tab.
configureEngine({
guid_mobile: {
id: "mobile",
tabs: [
{
urlHistory: ["http://foo.com/"],
title: "An Example",
},
],
},
});
// Set up Places to think the tab is open locally.
let uri = Services.io.newURI("http://foo.com/");
await PlacesTestUtils.addVisits([{ uri, title: "An Example" }]);
await addOpenPages(uri, 1);
let query = "ex";
let context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
}),
makeTabSwitchResult(context, {
uri: "http://foo.com/",
title: "An Example",
}),
],
});
await removeOpenPages(uri, 1);
await cleanupPlaces();
});
add_task(async function test_remotetab_matches_override() {
// If we have an history result to the same page, we should only get the
// remote tab match.
let url = "http://foo.remote.com/";
// First set up Sync to have the page as a remote tab.
configureEngine({
guid_mobile: {
id: "mobile",
tabs: [
{
urlHistory: [url],
title: "An Example",
},
],
},
});
// Set up Places to think the tab is in history.
await PlacesTestUtils.addVisits(url);
let query = "ex";
let context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
}),
makeRemoteTabResult(context, {
uri: "http://foo.remote.com/",
device: "My Phone",
title: "An Example",
}),
],
});
await cleanupPlaces();
});
add_task(async function test_mixed_result_types() {
// In case we have many results, non-remote results should flex to the bottom.
let url = "http://foo.remote.com/";
let tabs = Array(5)
.fill(0)
.map((e, i) => ({
urlHistory: [`${url}${i}`],
title: "A title",
lastUsed: Math.floor(Date.now() / 1000) - i * 86400, // i days ago.
}));
// First set up Sync to have the page as a remote tab.
configureEngine({
guid_mobile: {
id: "mobile",
tabs,
},
});
// Register the page as an open tab.
let openTabUrl = url + "openpage/";
let uri = Services.io.newURI(openTabUrl);
await PlacesTestUtils.addVisits([{ uri, title: "An Example" }]);
await addOpenPages(uri, 1);
// Also add a local history result.
let historyUrl = url + "history/";
await PlacesTestUtils.addVisits(historyUrl);
let query = "rem";
let context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
}),
makeRemoteTabResult(context, {
uri: "http://foo.remote.com/0",
device: "My Phone",
title: "A title",
lastUsed: tabs[0].lastUsed,
}),
makeRemoteTabResult(context, {
uri: "http://foo.remote.com/1",
device: "My Phone",
title: "A title",
lastUsed: tabs[1].lastUsed,
}),
makeRemoteTabResult(context, {
uri: "http://foo.remote.com/2",
device: "My Phone",
title: "A title",
lastUsed: tabs[2].lastUsed,
}),
// We expect to not see /3 and /4 because they are older than the 72 hour
// cutoff.
makeVisitResult(context, {
uri: historyUrl,
title: "test visit for " + historyUrl,
}),
makeTabSwitchResult(context, {
uri: openTabUrl,
title: "An Example",
}),
],
});
await removeOpenPages(uri, 1);
await cleanupPlaces();
});
add_task(async function test_many_remotetab_results() {
let url = "http://foo.remote.com/";
let tabs = Array(6)
.fill(0)
.map((e, i) => ({
urlHistory: [`${url}${i}`],
title: "A title",
// All the results in this array are fresh (< 72 hours old.)
lastUsed: Math.floor(Date.now() / 1000),
}));
tabs.push({
urlHistory: [`${url}5`],
title: "A title",
// This result is older than the 72 hour cutoff.
lastUsed: Math.floor(Date.now() / 1000) - 4 * 86400,
});
// First set up Sync to have the page as a remote tab.
configureEngine({
guid_mobile: {
id: "mobile",
tabs,
},
});
let query = "rem";
let context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
}),
makeRemoteTabResult(context, {
uri: "http://foo.remote.com/0",
device: "My Phone",
title: "A title",
lastUsed: tabs[0].lastUsed,
}),
makeRemoteTabResult(context, {
uri: "http://foo.remote.com/1",
device: "My Phone",
title: "A title",
lastUsed: tabs[1].lastUsed,
}),
makeRemoteTabResult(context, {
uri: "http://foo.remote.com/2",
device: "My Phone",
title: "A title",
lastUsed: tabs[2].lastUsed,
}),
makeRemoteTabResult(context, {
uri: "http://foo.remote.com/3",
device: "My Phone",
title: "A title",
lastUsed: tabs[3].lastUsed,
}),
makeRemoteTabResult(context, {
uri: "http://foo.remote.com/4",
device: "My Phone",
title: "A title",
lastUsed: tabs[4].lastUsed,
}),
// We don't expect http://foo.remote.com/5, because it is over the limit
// of maxResults / 2.
// We don't expect http://foo.remote.com/6, because it is both over the
// limit of maxResults / 2 and it is stale.
],
});
});
add_task(async function test_restrictionCharacter() {
let url = "http://foo.remote.com/";
let tabs = Array(5)
.fill(0)
.map((e, i) => ({
urlHistory: [`${url}${i}`],
title: "A title",
lastUsed: Math.floor(Date.now() / 1000) - i,
}));
configureEngine({
guid_mobile: {
id: "mobile",
tabs,
},
});
// Also add an open page.
let openTabUrl = url + "openpage/";
let uri = Services.io.newURI(openTabUrl);
await PlacesTestUtils.addVisits([{ uri, title: "An Example" }]);
await addOpenPages(uri, 1);
// We expect the open tab to flex to the bottom.
let query = UrlbarTokenizer.RESTRICT.OPENPAGE;
let context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
}),
makeRemoteTabResult(context, {
uri: "http://foo.remote.com/0",
device: "My Phone",
title: "A title",
lastUsed: tabs[0].lastUsed,
}),
makeRemoteTabResult(context, {
uri: "http://foo.remote.com/1",
device: "My Phone",
title: "A title",
lastUsed: tabs[1].lastUsed,
}),
makeRemoteTabResult(context, {
uri: "http://foo.remote.com/2",
device: "My Phone",
title: "A title",
lastUsed: tabs[2].lastUsed,
}),
makeRemoteTabResult(context, {
uri: "http://foo.remote.com/3",
device: "My Phone",
title: "A title",
lastUsed: tabs[3].lastUsed,
}),
makeRemoteTabResult(context, {
uri: "http://foo.remote.com/4",
device: "My Phone",
title: "A title",
lastUsed: tabs[4].lastUsed,
}),
makeTabSwitchResult(context, {
uri: openTabUrl,
title: "An Example",
}),
],
});
await removeOpenPages(uri, 1);
await cleanupPlaces();
});
add_task(async function test_duplicate_remote_tabs() {
let url = "http://foo.remote.com/";
let tabs = Array(3)
.fill(0)
.map((e, i) => ({
urlHistory: [url],
title: "A title",
lastUsed: Math.floor(Date.now() / 1000),
}));
configureEngine({
guid_mobile: {
id: "mobile",
tabs,
},
});
// We expect the duplicate tabs to be deduped.
let query = UrlbarTokenizer.RESTRICT.OPENPAGE;
let context = createContext(query, { isPrivate: false });
await check_results({
context,
matches: [
makeSearchResult(context, {
engineName: SUGGESTIONS_ENGINE_NAME,
heuristic: true,
}),
makeRemoteTabResult(context, {
uri: "http://foo.remote.com/",
device: "My Phone",
title: "A title",
lastUsed: tabs[0].lastUsed,
}),
],
});
});

View File

@ -36,6 +36,8 @@ skip-if = os == 'linux' # bug 1474616
[test_providerUnifiedComplete_duplicate_entries.js]
[test_query_url.js]
[test_queryScorer.js]
[test_remote_tabs.js]
skip-if = !sync
[test_resultBuckets.js]
[test_search_engine_host.js]
[test_search_suggestions.js]

View File

@ -1,408 +0,0 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
* vim:set ts=2 sw=2 sts=2 et:
*/
"use strict";
const { Weave } = ChromeUtils.import("resource://services-sync/main.js");
Services.prefs.setCharPref("services.sync.username", "someone@somewhere.com");
Services.prefs.setCharPref("services.sync.registerEngines", "");
// 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",
startTracking() {},
getAllClients() {
return this.clients;
},
};
// A clients engine that doesn't need to be a constructor.
let MockClientsEngine = {
getClientType(guid) {
Assert.ok(guid.endsWith("desktop") || guid.endsWith("mobile"));
return guid.endsWith("mobile") ? "phone" : "desktop";
},
remoteClientExists(id) {
return true;
},
getClientName(id) {
return id.endsWith("mobile") ? "My Phone" : "My Desktop";
},
};
// Tell Sync about the mocks.
Weave.Service.engineManager.register(MockTabsEngine);
// 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;
Weave.Service.clientsEngine = MockClientsEngine;
// 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,
};
}
add_task(async function test_minimal() {
// The minimal client and tabs info we can get away with.
configureEngine({
guid_desktop: {
id: "desktop",
tabs: [
{
urlHistory: ["http://example.com/"],
},
],
},
});
await check_autocomplete({
search: "ex",
searchParam: "enable-actions",
matches: [makeRemoteTabMatch("http://example.com/", "My Desktop")],
});
});
add_task(async function test_maximal() {
// Every field that could possibly exist on a remote record.
configureEngine({
guid_mobile: {
id: "mobile",
tabs: [
{
urlHistory: ["http://example.com/"],
title: "An Example",
icon: "http://favicon",
},
],
},
});
await check_autocomplete({
search: "ex",
searchParam: "enable-actions",
matches: [
makeRemoteTabMatch("http://example.com/", "My Phone", {
title: "An Example",
icon: "moz-anno:favicon:http://favicon/",
}),
],
});
});
add_task(async function test_noShowIcons() {
Services.prefs.setBoolPref("services.sync.syncedTabs.showRemoteIcons", false);
configureEngine({
guid_mobile: {
id: "mobile",
tabs: [
{
urlHistory: ["http://example.com/"],
title: "An Example",
icon: "http://favicon",
},
],
},
});
await check_autocomplete({
search: "ex",
searchParam: "enable-actions",
matches: [
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(async function test_dontMatchSyncedTabs() {
Services.prefs.setBoolPref("services.sync.syncedTabs.showRemoteTabs", false);
configureEngine({
guid_mobile: {
id: "mobile",
tabs: [
{
urlHistory: ["http://example.com/"],
title: "An Example",
icon: "http://favicon",
},
],
},
});
await check_autocomplete({
search: "ex",
searchParam: "enable-actions",
matches: [],
});
Services.prefs.clearUserPref("services.sync.syncedTabs.showRemoteTabs");
});
add_task(async function test_matches_title() {
// URL doesn't match search expression, should still match the title.
configureEngine({
guid_mobile: {
id: "mobile",
tabs: [
{
urlHistory: ["http://foo.com/"],
title: "An Example",
},
],
},
});
await check_autocomplete({
search: "ex",
searchParam: "enable-actions",
matches: [
makeRemoteTabMatch("http://foo.com/", "My Phone", {
title: "An Example",
}),
],
});
});
add_task(async 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: {
id: "mobile",
tabs: [
{
urlHistory: ["http://foo.com/"],
title: "An Example",
},
],
},
});
// Setup Places to think the tab is open locally.
let uri = NetUtil.newURI("http://foo.com/");
await PlacesTestUtils.addVisits([{ uri, title: "An Example" }]);
await addOpenPages(uri, 1);
await check_autocomplete({
search: "ex",
searchParam: "enable-actions",
matches: [makeSwitchToTabMatch("http://foo.com/", { title: "An Example" })],
});
await removeOpenPages(uri, 1);
});
add_task(async function test_remotetab_matches_override() {
// If We have an history result to the same page, we should only get the
// remote tab match.
let url = "http://foo.remote.com/";
// First setup Sync to have the page as a remote tab.
configureEngine({
guid_mobile: {
id: "mobile",
tabs: [
{
urlHistory: [url],
title: "An Example",
},
],
},
});
// Setup Places to think the tab is open locally.
await PlacesTestUtils.addVisits(url);
await check_autocomplete({
search: "rem",
searchParam: "enable-actions",
matches: [
makeRemoteTabMatch("http://foo.remote.com/", "My Phone", {
title: "An Example",
}),
],
});
});
add_task(async function test_many_remotetab_matches() {
await PlacesUtils.history.clear();
// In case we have many results, the most recent ones should be added on top,
// while others should be appended.
let url = "http://foo.remote.com/";
// First setup Sync to have the page as a remote tab.
configureEngine({
guid_mobile: {
id: "mobile",
tabs: Array(5)
.fill(0)
.map((e, i) => ({
urlHistory: [`${url}${i}`],
title: "A title",
lastUsed: Date.now() / 1000 - i * 86400, // i days ago.
})),
},
});
// Also add a local history result.
let historyUrl = url + "history/";
await PlacesTestUtils.addVisits(historyUrl);
await check_autocomplete({
search: "rem",
searchParam: "enable-actions",
checkSorting: true,
matches: [
makeRemoteTabMatch("http://foo.remote.com/0", "My Phone", {
title: "A title",
}),
makeRemoteTabMatch("http://foo.remote.com/1", "My Phone", {
title: "A title",
}),
makeRemoteTabMatch("http://foo.remote.com/2", "My Phone", {
title: "A title",
}),
{
uri: Services.io.newURI(historyUrl),
title: "test visit for " + historyUrl,
},
makeRemoteTabMatch("http://foo.remote.com/3", "My Phone", {
title: "A title",
}),
makeRemoteTabMatch("http://foo.remote.com/4", "My Phone", {
title: "A title",
}),
],
});
});
add_task(async function test_maxResults() {
await PlacesUtils.history.clear();
let url = "http://foo.remote.com/";
// Add 10 mock remote tabs. Important: We set `lastUsed` so that these tabs
// are newer than RECENT_REMOTE_TAB_THRESHOLD_MS in UnifiedComplete. That way
// they are added immediately in _matchRemoteTabs rather than being pushed
// onto _extraRemoteTabRows and then added later in execute(). The former
// does not check maxResults, but the latter does, and in this test, we want
// to verify that PlacesRemoteTabsAutocompleteProvider.getMatches returns at
// most ceil(maxResults / 2) tabs.
configureEngine({
guid_mobile: {
id: "mobile",
tabs: Array(10)
.fill(0)
.map((e, i) => ({
urlHistory: [`${url}${i}`],
title: "A title",
lastUsed: Date.now() - i,
})),
},
});
// Set maxResults to 4 in our search.
await check_autocomplete({
search: "rem",
searchParam: "enable-actions max-results:4",
checkSorting: true,
matches: [
makeRemoteTabMatch("http://foo.remote.com/0", "My Phone", {
title: "A title",
}),
makeRemoteTabMatch("http://foo.remote.com/1", "My Phone", {
title: "A title",
}),
makeRemoteTabMatch("http://foo.remote.com/2", "My Phone", {
title: "A title",
}),
makeRemoteTabMatch("http://foo.remote.com/3", "My Phone", {
title: "A title",
}),
],
});
});
add_task(async function test_restrictionCharacter() {
await PlacesUtils.history.clear();
let url = "http://foo.remote.com/";
configureEngine({
guid_mobile: {
id: "mobile",
tabs: Array(10)
.fill(0)
.map((e, i) => ({
urlHistory: [`${url}${i}`],
title: "A title",
lastUsed: Date.now() - i,
})),
},
});
// Also add an open page.
let uri = Services.io.newURI(`${url}openpage/`);
await PlacesTestUtils.addVisits([{ uri, title: "An Example" }]);
await addOpenPages(uri, 1);
// Set maxResults to 7 in our search. 7 results should be returned:
// ceil(maxResults / 2) remote tabs, then the open tab, then 2 more remote tab
// results to get to 7 total.
await check_autocomplete({
search: UrlbarTokenizer.RESTRICT.OPENPAGE,
searchParam: "enable-actions max-results:7",
checkSorting: true,
matches: [
makeRemoteTabMatch("http://foo.remote.com/0", "My Phone", {
title: "A title",
}),
makeRemoteTabMatch("http://foo.remote.com/1", "My Phone", {
title: "A title",
}),
makeRemoteTabMatch("http://foo.remote.com/2", "My Phone", {
title: "A title",
}),
makeRemoteTabMatch("http://foo.remote.com/3", "My Phone", {
title: "A title",
}),
makeSwitchToTabMatch("http://foo.remote.com/openpage/", {
title: "An Example",
}),
makeRemoteTabMatch("http://foo.remote.com/4", "My Phone", {
title: "A title",
}),
makeRemoteTabMatch("http://foo.remote.com/5", "My Phone", {
title: "A title",
}),
],
});
await removeOpenPages(uri, 1);
});

View File

@ -23,8 +23,6 @@ support-files =
[test_keyword_search_actions.js]
[test_multi_word_search.js]
[test_preloaded_sites.js]
[test_remote_tab_matches.js]
skip-if = !sync
[test_search_engine_alias.js]
[test_search_engine_restyle.js]
[test_special_search.js]