Bug 1495380 - Check that addons are displayed and update for network runtimes;r=ladybenko
authorJulian Descottes <jdescottes@mozilla.com>
Fri, 30 Nov 2018 15:55:30 +0000
changeset 508193 1e6a6598ffed79bd9c90870ea153108c7988aba5
parent 508192 77a11b6a13ec51370c1d3bec60d9b77783fb90e0
child 508194 add6ce065c17774c038c6e5762cd2996c28060fe
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersladybenko
bugs1495380
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1495380 - Check that addons are displayed and update for network runtimes;r=ladybenko Depends on D12946 Differential Revision: https://phabricator.services.mozilla.com/D12947
devtools/client/aboutdebugging-new/test/browser/browser.ini
devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_addons_remote_runtime.js
devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_addons_usb_runtime.js
devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_persist_connection.js
devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_routes.js
devtools/client/aboutdebugging-new/test/browser/head-mocks.js
devtools/client/aboutdebugging-new/test/browser/head.js
--- a/devtools/client/aboutdebugging-new/test/browser/browser.ini
+++ b/devtools/client/aboutdebugging-new/test/browser/browser.ini
@@ -13,17 +13,17 @@ support-files =
   mocks/*
   resources/test-adb-extension/*
   resources/test-temporary-extension/*
   test-tab-favicons.html
   !/devtools/client/shared/test/shared-head.js
   !/devtools/client/shared/test/shared-redux-head.js
   !/devtools/client/shared/test/telemetry-test-helpers.js
 
-[browser_aboutdebugging_addons_usb_runtime.js]
+[browser_aboutdebugging_addons_remote_runtime.js]
 [browser_aboutdebugging_connect_networklocations.js]
 [browser_aboutdebugging_connect_toggle_usb_devices.js]
 skip-if = (os == 'linux' && bits == 32) # ADB start() fails on linux 32, see Bug 1499638
 [browser_aboutdebugging_connection_prompt_setting.js]
 [browser_aboutdebugging_debug-target-pane_collapsibilities_interaction.js]
 [browser_aboutdebugging_debug-target-pane_collapsibilities_preference.js]
 [browser_aboutdebugging_debug-target-pane_empty.js]
 [browser_aboutdebugging_debug-target-pane_usb_runtime.js]
rename from devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_addons_usb_runtime.js
rename to devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_addons_remote_runtime.js
--- a/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_addons_usb_runtime.js
+++ b/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_addons_remote_runtime.js
@@ -1,73 +1,93 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-const RUNTIME_ID = "test-runtime-id";
-const RUNTIME_DEVICE_NAME = "test device name";
-const RUNTIME_APP_NAME = "TestApp";
+const NETWORK_RUNTIME_HOST = "localhost:6080";
+const NETWORK_RUNTIME_APP_NAME = "TestNetworkApp";
+const USB_RUNTIME_ID = "test-runtime-id";
+const USB_RUNTIME_DEVICE_NAME = "test device name";
+const USB_RUNTIME_APP_NAME = "TestUsbApp";
 
 /* import-globals-from head-mocks.js */
 Services.scriptloader.loadSubScript(CHROME_URL_ROOT + "head-mocks.js", this);
 
 // Test that addons are displayed and updated for USB runtimes when expected.
 add_task(async function() {
   const mocks = new Mocks();
   mocks.enableMocks();
   registerCleanupFunction(() => mocks.disableMocks());
 
   const { document, tab } = await openAboutDebugging();
 
-  const usbClient = mocks.createUSBRuntime(RUNTIME_ID, {
-    deviceName: RUNTIME_DEVICE_NAME,
-    name: RUNTIME_APP_NAME,
+  info("Prepare USB client mock");
+  const usbClient = mocks.createUSBRuntime(USB_RUNTIME_ID, {
+    deviceName: USB_RUNTIME_DEVICE_NAME,
+    name: USB_RUNTIME_APP_NAME,
   });
   mocks.emitUSBUpdate();
 
-  await connectToRuntime(RUNTIME_DEVICE_NAME, document);
-  await selectRuntime(RUNTIME_DEVICE_NAME, RUNTIME_APP_NAME, document);
+  info("Test addons in runtime page for USB client");
+  await connectToRuntime(USB_RUNTIME_DEVICE_NAME, document);
+  await selectRuntime(USB_RUNTIME_DEVICE_NAME, USB_RUNTIME_APP_NAME, document);
+  await testAddonsOnMockedRemoteClient(usbClient, mocks.thisFirefoxClient, document);
+
+  info("Prepare Network client mock");
+  const networkClient = mocks.createNetworkRuntime(NETWORK_RUNTIME_HOST, {
+    name: NETWORK_RUNTIME_APP_NAME,
+  });
 
+  info("Test addons in runtime page for Network client");
+  await connectToRuntime(NETWORK_RUNTIME_HOST, document);
+  await selectRuntime(NETWORK_RUNTIME_HOST, NETWORK_RUNTIME_APP_NAME, document);
+  await testAddonsOnMockedRemoteClient(networkClient, mocks.thisFirefoxClient, document);
+
+  await removeTab(tab);
+});
+
+/**
+ * Check that addons are visible in the runtime page for a remote client (USB or network).
+ */
+async function testAddonsOnMockedRemoteClient(remoteClient, firefoxClient, document) {
   const extensionPane = getDebugTargetPane("Extensions", document);
   info("Check an empty target pane message is displayed");
   ok(extensionPane.querySelector(".js-debug-target-list-empty"),
     "Extensions list is empty");
 
   info("Add an extension to the remote client");
   const addon = { name: "Test extension name", debuggable: true };
-  usbClient.listAddons = () => [addon];
-  usbClient._eventEmitter.emit("addonListChanged");
+  remoteClient.listAddons = () => [addon];
+  remoteClient._eventEmitter.emit("addonListChanged");
 
   info("Wait until the extension appears");
   await waitUntil(() => !extensionPane.querySelector(".js-debug-target-list-empty"));
 
   const extensionTarget = findDebugTargetByText("Test extension name", document);
-  ok(extensionTarget, "Extension target appeared for the USB runtime");
+  ok(extensionTarget, "Extension target appeared for the remote runtime");
 
-  // The goal here is to check that USB runtimes addons are only updated when the USB
+  // The goal here is to check that runtimes addons are only updated when the remote
   // runtime is sending addonListChanged events. The reason for this test is because the
-  // previous implementation was updating the USB runtime extensions list when the _local_
-  // AddonManager was updated.
+  // previous implementation was updating the remote runtime extensions list when the
+  // _local_ AddonManager was updated.
   info("Remove the extension from the remote client WITHOUT sending an event");
-  usbClient.listAddons = () => [];
+  remoteClient.listAddons = () => [];
 
   info("Simulate an addon update on the ThisFirefox client");
-  mocks.thisFirefoxClient._eventEmitter.emit("addonListChanged");
+  firefoxClient._eventEmitter.emit("addonListChanged");
 
   // To avoid wait for a set period of time we trigger another async update, adding a new
   // tab. We assume that if the addon update mechanism had started, it would also be done
   // when the new tab was processed.
   info("Wait until the tab target for 'http://some.random/url.com' appears");
   const testTab = { outerWindowID: 0, url: "http://some.random/url.com" };
-  usbClient.listTabs = () => ({ tabs: [testTab] });
-  usbClient._eventEmitter.emit("tabListChanged");
+  remoteClient.listTabs = () => ({ tabs: [testTab] });
+  remoteClient._eventEmitter.emit("tabListChanged");
   await waitUntil(() => findDebugTargetByText("http://some.random/url.com", document));
 
   ok(findDebugTargetByText("Test extension name", document),
     "The test extension is still visible");
 
-  info("Emit `addonListChanged` on usbClient and wait for the target list to update");
-  usbClient._eventEmitter.emit("addonListChanged");
+  info("Emit `addonListChanged` on remoteClient and wait for the target list to update");
+  remoteClient._eventEmitter.emit("addonListChanged");
   await waitUntil(() => !findDebugTargetByText("Test extension name", document));
-
-  await removeTab(tab);
-});
+}
--- a/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_persist_connection.js
+++ b/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_persist_connection.js
@@ -2,50 +2,50 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 const RUNTIME_ID = "test-runtime-id";
 const RUNTIME_DEVICE_NAME = "test device name";
 const RUNTIME_APP_NAME = "TestApp";
 
-/* import-globals-from mocks/head-usb-mocks.js */
-Services.scriptloader.loadSubScript(CHROME_URL_ROOT + "mocks/head-usb-mocks.js", this);
+/* import-globals-from head-mocks.js */
+Services.scriptloader.loadSubScript(CHROME_URL_ROOT + "head-mocks.js", this);
 
 // Test that remote runtime connections are persisted across about:debugging reloads.
 add_task(async function() {
-  const usbMocks = new UsbMocks();
-  usbMocks.enableMocks();
-  registerCleanupFunction(() => usbMocks.disableMocks());
+  const mocks = new Mocks();
+  mocks.enableMocks();
+  registerCleanupFunction(() => mocks.disableMocks());
 
   let { document, tab } = await openAboutDebugging();
 
-  const usbClient = usbMocks.createRuntime(RUNTIME_ID, {
+  const usbClient = mocks.createUSBRuntime(RUNTIME_ID, {
     name: RUNTIME_APP_NAME,
     deviceName: RUNTIME_DEVICE_NAME,
   });
-  usbMocks.emitUpdate();
+  mocks.emitUSBUpdate();
 
   await connectToRuntime(RUNTIME_DEVICE_NAME, document);
   await selectRuntime(RUNTIME_DEVICE_NAME, RUNTIME_APP_NAME, document);
 
   info("Reload about:debugging");
   document = await reloadAboutDebugging(tab);
-  usbMocks.emitUpdate();
+  mocks.emitUSBUpdate();
 
   info("Wait until the remote runtime appears as connected");
   await waitUntil(() => {
     const sidebarItem = findSidebarItemByText(RUNTIME_DEVICE_NAME, document);
     return sidebarItem && !sidebarItem.querySelector(".js-connect-button");
   });
 
   // Remove the runtime without emitting an update.
   // This is what happens today when we simply close Firefox for Android.
   info("Remove the runtime from the list of USB runtimes");
-  usbMocks.removeRuntime(RUNTIME_ID);
+  mocks.removeUSBRuntime(RUNTIME_ID);
 
   info("Emit 'closed' on the client and wait for the sidebar item to disappear");
   usbClient._eventEmitter.emit("closed");
   await waitUntil(() => !findSidebarItemByText(RUNTIME_DEVICE_NAME, document));
 
   info("Remove the tab");
   await removeTab(tab);
 });
--- a/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_routes.js
+++ b/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_routes.js
@@ -1,15 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-/* import-globals-from mocks/head-usb-mocks.js */
-Services.scriptloader.loadSubScript(CHROME_URL_ROOT + "mocks/head-usb-mocks.js", this);
+/* import-globals-from head-mocks.js */
+Services.scriptloader.loadSubScript(CHROME_URL_ROOT + "head-mocks.js", this);
 
 /**
  * Test that the initial route is /runtime/this-firefox
  */
 add_task(async function() {
   info("Check root route redirects to 'This Firefox'");
   const { document, tab } = await openAboutDebugging();
   is(document.location.hash, "#/runtime/this-firefox");
@@ -17,19 +17,19 @@ add_task(async function() {
   await removeTab(tab);
 });
 
 /**
  * Test that the routes in about:debugging show the proper views
  */
 add_task(async function() {
   // enable USB devices mocks
-  const usbMocks = new UsbMocks();
-  usbMocks.enableMocks();
-  registerCleanupFunction(() => usbMocks.disableMocks());
+  const mocks = new Mocks();
+  mocks.enableMocks();
+  registerCleanupFunction(() => mocks.disableMocks());
 
   const { document, tab } = await openAboutDebugging();
 
   info("Check 'This Firefox' route");
   document.location.hash = "#/runtime/this-firefox";
   await waitUntil(() => document.querySelector(".js-runtime-page"));
   const infoLabel = document.querySelector(".js-runtime-info").textContent;
   // NOTE: when using USB Mocks, we see only "Firefox" as the device name
@@ -38,21 +38,21 @@ add_task(async function() {
 
   info("Check 'Connect' page");
   document.location.hash = "#/connect";
   await waitUntil(() => document.querySelector(".js-connect-page"));
   ok(true, "Connect page has been shown");
 
   info("Check 'USB device runtime' page");
   // connect to a mocked USB runtime
-  usbMocks.createRuntime("1337id", {
+  mocks.createUSBRuntime("1337id", {
     deviceName: "Fancy Phone",
     name: "Lorem ipsum",
   });
-  usbMocks.emitUpdate();
+  mocks.emitUSBUpdate();
   await connectToRuntime("Fancy Phone", document);
   // navigate to it via URL
   document.location.hash = "#/runtime/1337id";
   await waitUntil(() => document.querySelector(".js-runtime-page"));
   const runtimeLabel = document.querySelector(".js-runtime-info").textContent;
   ok(runtimeLabel.includes("Lorem ipsum"), "Runtime is displayed with the mocked name");
 
   await removeTab(tab);
--- a/devtools/client/aboutdebugging-new/test/browser/head-mocks.js
+++ b/devtools/client/aboutdebugging-new/test/browser/head-mocks.js
@@ -11,62 +11,98 @@ const { RUNTIMES } = require("devtools/c
 Services.scriptloader.loadSubScript(MOCKS_ROOT + "head-client-wrapper-mock.js", this);
 /* import-globals-from mocks/head-runtime-client-factory-mock.js */
 Services.scriptloader.loadSubScript(MOCKS_ROOT + "head-runtime-client-factory-mock.js",
   this);
 /* import-globals-from mocks/head-usb-runtimes-mock.js */
 Services.scriptloader.loadSubScript(MOCKS_ROOT + "head-usb-runtimes-mock.js", this);
 
 /**
- * This wrapper around the USB mocks used in about:debugging tests provides helpers to
- * quickly setup mocks for typical USB runtime tests.
+ * This wrapper around the mocks used in about:debugging tests provides helpers to
+ * quickly setup mocks for runtime tests involving USB, network or wifi runtimes that can
+ * are difficult to setup in a test environment.
  */
 class Mocks {
   constructor() {
-    // Setup the usb-runtimes mock to rely on the internal _runtimes array.
+    // Setup the usb-runtimes mock to rely on the internal _usbRuntimes array.
     this.usbRuntimesMock = createUsbRuntimesMock();
-    this._runtimes = [];
+    this._usbRuntimes = [];
     this.usbRuntimesMock.getUSBRuntimes = () => {
-      return this._runtimes;
+      return this._usbRuntimes;
     };
 
     // refreshUSBRuntimes normally starts scan, which should ultimately fire the
     // "runtime-list-updated" event.
     this.usbRuntimesMock.refreshUSBRuntimes = () => {
-      this.emitUpdate();
+      this.emitUSBUpdate();
     };
 
     // Prepare a fake observer to be able to emit events from this mock.
     this._observerMock = addObserverMock(this.usbRuntimesMock);
 
     // Setup the runtime-client-factory mock to rely on the internal _clients map.
     this.runtimeClientFactoryMock = createRuntimeClientFactoryMock();
-    this._clients = {};
+    this._clients = {
+      [RUNTIMES.NETWORK]: {},
+      [RUNTIMES.THIS_FIREFOX]: {},
+      [RUNTIMES.USB]: {},
+    };
     this.runtimeClientFactoryMock.createClientForRuntime = runtime => {
-      return this._clients[runtime.id];
+      return this._clients[runtime.type][runtime.id];
     };
 
     // Add a client for THIS_FIREFOX, since about:debugging will start on the This Firefox
     // page.
     this._thisFirefoxClient = createThisFirefoxClientMock();
-    this._clients[RUNTIMES.THIS_FIREFOX] = this._thisFirefoxClient;
+    this._clients[RUNTIMES.THIS_FIREFOX][RUNTIMES.THIS_FIREFOX] = this._thisFirefoxClient;
   }
 
   get thisFirefoxClient() {
     return this._thisFirefoxClient;
   }
 
   enableMocks() {
     enableUsbRuntimesMock(this.usbRuntimesMock);
     enableRuntimeClientFactoryMock(this.runtimeClientFactoryMock);
   }
 
   disableMocks() {
     disableUsbRuntimesMock();
     disableRuntimeClientFactoryMock();
+
+    for (const host of Object.keys(this._clients[RUNTIMES.NETWORK])) {
+      this.removeNetworkRuntime(host);
+    }
+  }
+
+  createNetworkRuntime(host, runtimeInfo) {
+    const { addNetworkLocation } =
+      require("devtools/client/aboutdebugging-new/src/modules/network-locations");
+    addNetworkLocation(host);
+
+    // Add a valid client that can be returned for this particular runtime id.
+    const mockNetworkClient = createClientMock();
+    mockNetworkClient.getDeviceDescription = () => {
+      return {
+        name: runtimeInfo.name || "TestBrand",
+        channel: runtimeInfo.channel || "release",
+        version: runtimeInfo.version || "1.0",
+      };
+    };
+    this._clients[RUNTIMES.NETWORK][host] = mockNetworkClient;
+
+    return mockNetworkClient;
+  }
+
+  removeNetworkRuntime(host) {
+    const { removeNetworkLocation } =
+      require("devtools/client/aboutdebugging-new/src/modules/network-locations");
+    removeNetworkLocation(host);
+
+    delete this._clients[RUNTIMES.NETWORK][host];
   }
 
   emitUSBUpdate() {
     this._observerMock.emit("runtime-list-updated");
   }
 
   /**
    * Creates a USB runtime for which a client conenction can be established.
@@ -79,34 +115,34 @@ class Mocks {
    *        - channel: {String} Release channel, for instance "release", "nightly"
    *        - version: {String} Version, for instance "63.0a"
    *        - socketPath: {String} (should only be used for connecting, so not here)
    * @return {Object} Returns the mock client created for this runtime so that methods
    * can be overridden on it.
    */
   createUSBRuntime(id, runtimeInfo = {}) {
     // Add a new runtime to the list of scanned runtimes.
-    this._runtimes.push({
+    this._usbRuntimes.push({
       id: id,
       _socketPath: runtimeInfo.socketPath || "test/path",
       deviceName: runtimeInfo.deviceName || "test device name",
       shortName: runtimeInfo.shortName || "testshort",
     });
 
     // Add a valid client that can be returned for this particular runtime id.
     const mockUsbClient = createClientMock();
     mockUsbClient.getDeviceDescription = () => {
       return {
         name: runtimeInfo.name || "TestBrand",
         channel: runtimeInfo.channel || "release",
         version: runtimeInfo.version || "1.0",
       };
     };
-    this._clients[id] = mockUsbClient;
+    this._clients[RUNTIMES.USB][id] = mockUsbClient;
 
     return mockUsbClient;
   }
 
   removeUSBRuntime(id) {
-    this._runtimes = this._runtimes.filter(runtime => runtime.id !== id);
-    delete this._clients[id];
+    this._usbRuntimes = this._usbRuntimes.filter(runtime => runtime.id !== id);
+    delete this._clients[RUNTIMES.USB][id];
   }
 }
--- a/devtools/client/aboutdebugging-new/test/browser/head.js
+++ b/devtools/client/aboutdebugging-new/test/browser/head.js
@@ -178,11 +178,11 @@ async function connectToRuntime(deviceNa
 }
 
 async function selectRuntime(deviceName, name, document) {
   const sidebarItem = findSidebarItemByText(deviceName, document);
   sidebarItem.querySelector(".js-sidebar-link").click();
 
   await waitUntil(() => {
     const runtimeInfo = document.querySelector(".js-runtime-info");
-    return runtimeInfo.textContent.includes(name);
+    return runtimeInfo && runtimeInfo.textContent.includes(name);
   });
 }