mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 17:23:59 +00:00
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:
parent
2ae48118ca
commit
8c2a61dafd
@ -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,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -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,
|
||||
})
|
||||
)
|
||||
);
|
||||
|
@ -27,7 +27,7 @@ const REMOTE_TAB = {
|
||||
url: TEST_URL,
|
||||
icon: UrlbarUtils.ICON.DEFAULT,
|
||||
client: "7cqCr77ptzX3",
|
||||
lastUsed: 1452124677,
|
||||
lastUsed: Math.floor(Date.now() / 1000),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
@ -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),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
@ -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),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
@ -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),
|
||||
},
|
||||
],
|
||||
};
|
||||
|
@ -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
|
||||
|
568
browser/components/urlbar/tests/unit/test_remote_tabs.js
Normal file
568
browser/components/urlbar/tests/unit/test_remote_tabs.js
Normal 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,
|
||||
}),
|
||||
],
|
||||
});
|
||||
});
|
@ -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]
|
||||
|
@ -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);
|
||||
});
|
@ -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]
|
||||
|
Loading…
Reference in New Issue
Block a user