Bug 1467572 - Part 15: Fix unit tests for RDM to work with the new RDM design. r=Honza
authorGabriel Luong <gabriel.luong@gmail.com>
Wed, 15 Aug 2018 17:27:51 -0400
changeset 431862 e1e8061780fdf074a510b94240ab303f89950a4d
parent 431861 8f34ca109aacc66918bb4e17a44cab8fd1acbbdf
child 431863 3199491bd055a6ac07632efeb7b3592f417f520c
push id34451
push userebalazs@mozilla.com
push dateThu, 16 Aug 2018 09:25:15 +0000
treeherdermozilla-central@161817e6d127 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersHonza
bugs1467572
milestone63.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 1467572 - Part 15: Fix unit tests for RDM to work with the new RDM design. r=Honza - Various element IDs and strings were renamed in the preceeding patches before this. This fixes the strings and element ID reference in the RDM unit tests. - Fixed RDM unit tests to work with new native context menu which used to be <select> elements.
devtools/client/responsive.html/test/browser/browser_device_change.js
devtools/client/responsive.html/test/browser/browser_device_custom.js
devtools/client/responsive.html/test/browser/browser_device_custom_remove.js
devtools/client/responsive.html/test/browser/browser_device_modal_error.js
devtools/client/responsive.html/test/browser/browser_device_modal_exit.js
devtools/client/responsive.html/test/browser/browser_device_modal_submit.js
devtools/client/responsive.html/test/browser/browser_device_pixel_ratio_change.js
devtools/client/responsive.html/test/browser/browser_exit_button.js
devtools/client/responsive.html/test/browser/browser_network_throttling.js
devtools/client/responsive.html/test/browser/browser_screenshot_button.js
devtools/client/responsive.html/test/browser/browser_touch_device.js
devtools/client/responsive.html/test/browser/browser_touch_simulation.js
devtools/client/responsive.html/test/browser/head.js
--- a/devtools/client/responsive.html/test/browser/browser_device_change.js
+++ b/devtools/client/responsive.html/test/browser/browser_device_change.js
@@ -38,17 +38,17 @@ addRDMTask(TEST_URL, async function({ ui
     && state.devices.listState == Types.loadableState.LOADED);
 
   // Test defaults
   testViewportDimensions(ui, 320, 480);
   info("Should have default UA at the start of the test");
   await testUserAgent(ui, DEFAULT_UA);
   await testDevicePixelRatio(ui, DEFAULT_DPPX);
   await testTouchEventsOverride(ui, false);
-  testViewportDeviceSelectLabel(ui, "no device selected");
+  testViewportDeviceMenuLabel(ui, "Responsive");
 
   // Test device with custom properties
   let reloaded = waitForViewportLoad(ui);
   await selectDevice(ui, "Fake Phone RDM Test");
   await reloaded;
   await waitForViewportResizeTo(ui, testDevice.width, testDevice.height);
   info("Should have device UA now that device is applied");
   await testUserAgent(ui, testDevice.userAgent);
@@ -60,17 +60,17 @@ addRDMTask(TEST_URL, async function({ ui
   reloaded = waitForViewportLoad(ui);
   await testViewportResize(ui, ".viewport-vertical-resize-handle",
     [-10, -10], [testDevice.width, testDevice.height - 10], [0, -10], ui);
   await Promise.all([ deviceRemoved, reloaded ]);
   info("Should have default UA after resizing viewport");
   await testUserAgent(ui, DEFAULT_UA);
   await testDevicePixelRatio(ui, DEFAULT_DPPX);
   await testTouchEventsOverride(ui, false);
-  testViewportDeviceSelectLabel(ui, "no device selected");
+  testViewportDeviceMenuLabel(ui, "Responsive");
 
   // Test device with generic properties
   await selectDevice(ui, "Laptop (1366 x 768)");
   await waitForViewportResizeTo(ui, 1366, 768);
   info("Should have default UA when using device without specific UA");
   await testUserAgent(ui, DEFAULT_UA);
   await testDevicePixelRatio(ui, 1);
   await testTouchEventsOverride(ui, false);
--- a/devtools/client/responsive.html/test/browser/browser_device_custom.js
+++ b/devtools/client/responsive.html/test/browser/browser_device_custom.js
@@ -29,23 +29,20 @@ const Types = require("devtools/client/r
 addRDMTask(TEST_URL, async function({ ui }) {
   const { toolWindow } = ui;
   const { store, document } = toolWindow;
 
   // Wait until the viewport has been added and the device list has been loaded
   await waitUntilState(store, state => state.viewports.length == 1
     && state.devices.listState == Types.loadableState.LOADED);
 
-  const deviceSelector = document.querySelector(".viewport-device-selector");
-  const submitButton = document.querySelector("#device-submit-button");
-
-  openDeviceModal(ui);
+  await openDeviceModal(ui);
 
   info("Reveal device adder form, check that defaults match the viewport");
-  const adderShow = document.querySelector("#device-adder-show");
+  const adderShow = document.getElementById("device-adder-show");
   adderShow.click();
   testDeviceAdder(ui, {
     name: "Custom Device",
     width: 320,
     height: 480,
     pixelRatio: window.devicePixelRatio,
     userAgent: navigator.userAgent,
     touch: false,
@@ -53,121 +50,127 @@ addRDMTask(TEST_URL, async function({ ui
 
   info("Fill out device adder form and save");
   await addDeviceInModal(ui, device);
 
   info("Verify device defaults to enabled in modal");
   const deviceCb = [...document.querySelectorAll(".device-input-checkbox")].find(cb => {
     return cb.value == device.name;
   });
+  const submitButton = document.getElementById("device-submit-button");
   ok(deviceCb, "Custom device checkbox added to modal");
   ok(deviceCb.checked, "Custom device enabled");
   submitButton.click();
 
   info("Look for custom device in device selector");
-  const selectorOption =
-    [...deviceSelector.options].find(opt => opt.value == device.name);
-  ok(selectorOption, "Custom device option added to device selector");
+  const deviceSelector = document.getElementById("device-selector");
+  await testMenuItems(toolWindow, deviceSelector, items => {
+    const menuItem = items.find(item => item.getAttribute("label") === device.name);
+    ok(menuItem, "Custom device menu item added to device selector");
+  });
 });
 
 addRDMTask(TEST_URL, async function({ ui }) {
   const { toolWindow } = ui;
   const { store, document } = toolWindow;
 
   // Wait until the viewport has been added and the device list has been loaded
   await waitUntilState(store, state => state.viewports.length == 1
     && state.devices.listState == Types.loadableState.LOADED);
 
-  const deviceSelector = document.querySelector(".viewport-device-selector");
-  const submitButton = document.querySelector("#device-submit-button");
-
   info("Select existing device from the selector");
   await selectDevice(ui, "Test Device");
 
-  openDeviceModal(ui);
+  await openDeviceModal(ui);
 
   info("Reveal device adder form, check that defaults are based on selected device");
-  const adderShow = document.querySelector("#device-adder-show");
+  const adderShow = document.getElementById("device-adder-show");
   adderShow.click();
   testDeviceAdder(ui, Object.assign({}, device, {
     name: "Test Device (Custom)",
   }));
 
   info("Remove previously added custom device");
   const deviceRemoveButton = document.querySelector(".device-remove-button");
+  const submitButton = document.getElementById("device-submit-button");
   const removed = Promise.all([
     waitUntilState(store, state => state.devices.custom.length == 0),
     once(ui, "device-association-removed")
   ]);
   deviceRemoveButton.click();
   await removed;
   submitButton.click();
 
   info("Ensure custom device was removed from device selector");
   await waitUntilState(store, state => state.viewports[0].device == "");
-  is(deviceSelector.value, "", "Device selector reset to no device");
-  const selectorOption =
-    [...deviceSelector.options].find(opt => opt.value == device.name);
-  ok(!selectorOption, "Custom device option removed from device selector");
+  const deviceSelectorTitle = document.querySelector("#device-selector .title");
+  is(deviceSelectorTitle.textContent, "Responsive", "Device selector reset to no device");
+
+  info("Look for custom device in device selector");
+  const deviceSelector = document.getElementById("device-selector");
+  await testMenuItems(toolWindow, deviceSelector, menuItems => {
+    const menuItem = menuItems.find(item => item.getAttribute("label") === device.name);
+    ok(!menuItem, "Custom device option removed from device selector");
+  });
 
   info("Ensure device properties like UA have been reset");
   await testUserAgent(ui, navigator.userAgent);
 });
 
 addRDMTask(TEST_URL, async function({ ui }) {
   const { toolWindow } = ui;
   const { store, document } = toolWindow;
 
   // Wait until the viewport has been added and the device list has been loaded
   await waitUntilState(store, state => state.viewports.length == 1
     && state.devices.listState == Types.loadableState.LOADED);
 
-  const deviceSelector = document.querySelector(".viewport-device-selector");
-  const submitButton = document.querySelector("#device-submit-button");
-
-  openDeviceModal(ui);
+  await openDeviceModal(ui);
 
   info("Reveal device adder form");
   const adderShow = document.querySelector("#device-adder-show");
   adderShow.click();
 
   info("Fill out device adder form by setting details to unicode device and save");
   await addDeviceInModal(ui, unicodeDevice);
 
   info("Verify unicode device defaults to enabled in modal");
   const deviceCb = [...document.querySelectorAll(".device-input-checkbox")].find(cb => {
     return cb.value == unicodeDevice.name;
   });
+  const submitButton = document.getElementById("device-submit-button");
   ok(deviceCb, "Custom unicode device checkbox added to modal");
   ok(deviceCb.checked, "Custom unicode device enabled");
   submitButton.click();
 
   info("Look for custom unicode device in device selector");
-  const selectorOption = [...deviceSelector.options].find(opt =>
-    opt.value == unicodeDevice.name);
-  ok(selectorOption, "Custom unicode device option added to device selector");
+  const deviceSelector = document.getElementById("device-selector");
+  await testMenuItems(toolWindow, deviceSelector, items => {
+    const menuItem = items.find(i => i.getAttribute("label") === unicodeDevice.name);
+    ok(menuItem, "Custom unicode device option added to device selector");
+  });
 });
 
 addRDMTask(TEST_URL, async function({ ui }) {
   const { toolWindow } = ui;
   const { store, document } = toolWindow;
 
   // Wait until the viewport has been added and the device list has been loaded
   await waitUntilState(store, state => state.viewports.length == 1
     && state.devices.listState == Types.loadableState.LOADED);
 
-  const deviceSelector = document.querySelector(".viewport-device-selector");
-
   // Check if the unicode custom device is present in the list of device options since
   // we want to ensure that unicode device names are not forgotten after restarting RDM
   // see bug 1379687
   info("Look for custom unicode device in device selector");
-  const selectorOption = [...deviceSelector.options].find(opt =>
-    opt.value == unicodeDevice.name);
-  ok(selectorOption, "Custom unicode device option present in device selector");
+  const deviceSelector = document.getElementById("device-selector");
+  await testMenuItems(toolWindow, deviceSelector, items => {
+    const menuItem = items.find(i => i.getAttribute("label") === unicodeDevice.name);
+    ok(menuItem, "Custom unicode device option present in device selector");
+  });
 });
 
 function testDeviceAdder(ui, expected) {
   const { document } = ui.toolWindow;
 
   const nameInput = document.querySelector("#device-adder-name input");
   const [ widthInput, heightInput ] =
     document.querySelectorAll("#device-adder-size input");
--- a/devtools/client/responsive.html/test/browser/browser_device_custom_remove.js
+++ b/devtools/client/responsive.html/test/browser/browser_device_custom_remove.js
@@ -29,92 +29,91 @@ addRDMTask(TEST_URL, async function({ ui
   const { store, document } = toolWindow;
 
   info("Verify that remove buttons affect the correct device");
 
   // Wait until the viewport has been added and the device list has been loaded
   await waitUntilState(store, state => state.viewports.length == 1
     && state.devices.listState == Types.loadableState.LOADED);
 
-  const deviceSelector = document.querySelector(".viewport-device-selector");
-  const submitButton = document.querySelector("#device-submit-button");
+  const deviceSelector = document.getElementById("device-selector");
 
-  openDeviceModal(ui);
+  await openDeviceModal(ui);
 
   info("Reveal device adder form");
   let adderShow = document.querySelector("#device-adder-show");
   adderShow.click();
 
   info("Add test device 1");
   await addDeviceInModal(ui, device1);
 
   info("Reveal device adder form");
   adderShow = document.querySelector("#device-adder-show");
   adderShow.click();
 
   info("Add test device 2");
   await addDeviceInModal(ui, device2);
 
   info("Verify all custom devices default to enabled in modal");
+  const submitButton = document.getElementById("device-submit-button");
   const deviceCbs =
     [...document.querySelectorAll(".device-type-custom .device-input-checkbox")];
   is(deviceCbs.length, 2, "Both devices have a checkbox in modal");
   for (const cb of deviceCbs) {
     ok(cb.checked, "Custom device enabled");
   }
   submitButton.click();
 
-  info("Look for device 1 in device selector");
-  let deviceOption1 = [...deviceSelector.options].find(opt => opt.value == device1.name);
-  ok(deviceOption1, "Test device 1 option added to device selector");
+  info("Look for device 1 and 2 in device selector");
 
-  info("Look for device 2 in device selector");
-  let deviceOption2 = [...deviceSelector.options].find(opt => opt.value == device2.name);
-  ok(deviceOption2, "Test device 2 option added to device selector");
+  await testMenuItems(toolWindow, deviceSelector, menuItems => {
+    const deviceItem1 = menuItems.find(i => i.getAttribute("label") === device1.name);
+    const deviceItem2 = menuItems.find(i => i.getAttribute("label") === device2.name);
+    ok(deviceItem1, "Test device 1 menu item added to device selector");
+    ok(deviceItem2, "Test device 2 menu item added to device selector");
+  });
 
-  openDeviceModal(ui);
+  await openDeviceModal(ui);
 
   info("Remove device 2");
   const deviceRemoveButtons = [...document.querySelectorAll(".device-remove-button")];
   is(deviceRemoveButtons.length, 2, "Both devices have a remove button in modal");
   const removed = waitUntilState(store, state => state.devices.custom.length == 1);
   deviceRemoveButtons[1].click();
   await removed;
   submitButton.click();
 
-  info("Ensure device 1 is still in device selector");
-  deviceOption1 = [...deviceSelector.options].find(opt => opt.value == device1.name);
-  ok(deviceOption1, "Test device 1 option exists");
-
   info("Ensure device 2 is no longer in device selector");
-  deviceOption2 = [...deviceSelector.options].find(opt => opt.value == device2.name);
-  ok(!deviceOption2, "Test device 2 option removed");
+  await testMenuItems(toolWindow, deviceSelector, menuItems => {
+    const deviceItem1 = menuItems.find(i => i.getAttribute("label") === device1.name);
+    const deviceItem2 = menuItems.find(i => i.getAttribute("label") === device2.name);
+    ok(deviceItem1, "Test device 1 menu item exists");
+    ok(!deviceItem2, "Test device 2 menu item removed");
+  });
 });
 
 addRDMTask(TEST_URL, async function({ ui }) {
   const { toolWindow } = ui;
   const { store, document } = toolWindow;
 
   // Wait until the viewport has been added and the device list has been loaded
   await waitUntilState(store, state => state.viewports.length == 1
     && state.devices.listState == Types.loadableState.LOADED);
 
-  const deviceSelector = document.querySelector(".viewport-device-selector");
+  const deviceSelector = document.getElementById("device-selector");
 
   info("Ensure device 1 is still in device selector");
-  const deviceOption1 =
-    [...deviceSelector.options].find(opt => opt.value == device1.name);
-  ok(deviceOption1, "Test device 1 option exists");
+  await testMenuItems(toolWindow, deviceSelector, menuItems => {
+    const deviceItem1 = menuItems.find(i => i.getAttribute("label") === device1.name);
+    const deviceItem2 = menuItems.find(i => i.getAttribute("label") === device2.name);
+    ok(deviceItem1, "Test device 1 menu item exists");
+    ok(!deviceItem2, "Test device 2 option removed");
+  });
 
-  info("Ensure device 2 is no longer in device selector");
-  const deviceOption2 =
-    [...deviceSelector.options].find(opt => opt.value == device2.name);
-  ok(!deviceOption2, "Test device 2 option removed");
-
-  openDeviceModal(ui);
+  await openDeviceModal(ui);
 
   info("Ensure device 1 is still in device modal");
   const deviceCbs =
     [...document.querySelectorAll(".device-type-custom .device-input-checkbox")];
   is(deviceCbs.length, 1, "Only 1 custom present in modal");
   const deviceCb1 = deviceCbs.find(cb => cb.value == device1.name);
   ok(deviceCb1 && deviceCb1.checked, "Test device 1 checkbox exists and enabled");
 
--- a/devtools/client/responsive.html/test/browser/browser_device_modal_error.js
+++ b/devtools/client/responsive.html/test/browser/browser_device_modal_error.js
@@ -2,34 +2,28 @@
 http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Test to check that RDM can handle properly an error in the device list
 
 const TEST_URL = "data:text/html;charset=utf-8,";
 const Types = require("devtools/client/responsive.html/types");
-const { getStr } = require("devtools/client/responsive.html/utils/l10n");
 
 // Set a wrong URL for the device list file
 add_task(async function() {
   await SpecialPowers.pushPrefEnv({
     set: [["devtools.devices.url", TEST_URI_ROOT + "wrong_devices_file.json"]],
   });
 });
 
 addRDMTask(TEST_URL, async function({ ui }) {
   const { store, document } = ui.toolWindow;
-  const select = document.querySelector(".viewport-device-selector");
+  const button = document.getElementById("device-selector");
 
   // Wait until the viewport has been added and the device list state indicates
   // an error
   await waitUntilState(store, state => state.viewports.length == 1
     && state.devices.listState == Types.loadableState.ERROR);
 
-  // The device selector placeholder should be set accordingly
-  const placeholder = select.options[select.selectedIndex].innerHTML;
-  ok(placeholder == getStr("responsive.deviceListError"),
-    "Device selector indicates an error");
-
   // The device selector should be disabled
-  ok(select.disabled, "Device selector is disabled");
+  ok(button.disabled, "Device selector is disabled");
 });
--- a/devtools/client/responsive.html/test/browser/browser_device_modal_exit.js
+++ b/devtools/client/responsive.html/test/browser/browser_device_modal_exit.js
@@ -12,17 +12,17 @@ addRDMTask(TEST_URL, async function({ ui
   const { store, document } = ui.toolWindow;
   const modal = document.querySelector("#device-modal-wrapper");
   const closeButton = document.querySelector("#device-close-button");
 
   // Wait until the viewport has been added and the device list has been loaded
   await waitUntilState(store, state => state.viewports.length == 1
     && state.devices.listState == Types.loadableState.LOADED);
 
-  openDeviceModal(ui);
+  await openDeviceModal(ui);
 
   const preferredDevicesBefore = _loadPreferredDevices();
 
   info("Check the first unchecked device and exit the modal.");
   const uncheckedCb = [...document.querySelectorAll(".device-input-checkbox")]
     .filter(cb => !cb.checked)[0];
   const value = uncheckedCb.value;
   uncheckedCb.click();
--- a/devtools/client/responsive.html/test/browser/browser_device_modal_submit.js
+++ b/devtools/client/responsive.html/test/browser/browser_device_modal_submit.js
@@ -17,26 +17,27 @@ const addedDevice = {
   "os": "custom",
   "featured": true,
 };
 
 const TEST_URL = "data:text/html;charset=utf-8,";
 const Types = require("devtools/client/responsive.html/types");
 
 addRDMTask(TEST_URL, async function({ ui }) {
-  const { store, document } = ui.toolWindow;
-  const modal = document.querySelector("#device-modal-wrapper");
-  const select = document.querySelector(".viewport-device-selector");
-  const submitButton = document.querySelector("#device-submit-button");
+  const { toolWindow } = ui;
+  const { store, document } = toolWindow;
+  const deviceSelector = document.getElementById("device-selector");
+  const modal = document.getElementById("device-modal-wrapper");
+  const submitButton = document.getElementById("device-submit-button");
 
   // Wait until the viewport has been added and the device list has been loaded
   await waitUntilState(store, state => state.viewports.length == 1
     && state.devices.listState == Types.loadableState.LOADED);
 
-  openDeviceModal(ui);
+  await openDeviceModal(ui);
 
   info("Checking displayed device checkboxes are checked in the device modal.");
   const checkedCbs = [...document.querySelectorAll(".device-input-checkbox")]
     .filter(cb => cb.checked);
 
   const remoteList = await getDevices();
 
   const featuredCount = remoteList.TYPES.reduce((total, type) => {
@@ -64,24 +65,26 @@ addRDMTask(TEST_URL, async function({ ui
   ok(modal.classList.contains("closed") && !modal.classList.contains("opened"),
     "The device modal is closed on submit.");
 
   info("Checking that the new device is added to the user preference list.");
   let preferredDevices = _loadPreferredDevices();
   ok(preferredDevices.added.has(value), value + " in user added list.");
 
   info("Checking new device is added to the device selector.");
-  let options = [...select.options];
-  is(options.length - 2, featuredCount + 1,
-    "Got expected number of devices in device selector.");
-  ok(options.filter(o => o.value === value)[0],
-    value + " added to the device selector.");
+  await testMenuItems(toolWindow, deviceSelector, menuItems => {
+    is(menuItems.length - 2, featuredCount + 1,
+      "Got expected number of devices in device selector.");
+
+    const menuItem = menuItems.find(item => item.getAttribute("label") === name);
+    ok(menuItem, value + " added to the device selector.");
+  });
 
   info("Reopen device modal and check new device is correctly checked");
-  openDeviceModal(ui);
+  await openDeviceModal(ui);
   ok([...document.querySelectorAll(".device-input-checkbox")]
     .filter(cb => cb.checked && cb.value === value)[0],
     value + " is checked in the device modal.");
 
   // Tests where the user removes a featured device
   info("Uncheck the first checked device different than the previous one");
   const checkedCb = [...document.querySelectorAll(".device-input-checkbox")]
     .filter(cb => cb.checked && cb.value != value)[0];
@@ -89,58 +92,66 @@ addRDMTask(TEST_URL, async function({ ui
   checkedCb.click();
   submitButton.click();
 
   info("Checking that the device is removed from the user preference list.");
   preferredDevices = _loadPreferredDevices();
   ok(preferredDevices.removed.has(checkedVal), checkedVal + " in removed list");
 
   info("Checking that the device is not in the device selector.");
-  options = [...select.options];
-  is(options.length - 2, featuredCount,
-    "Got expected number of devices in device selector.");
-  ok(!options.filter(o => o.value === checkedVal)[0],
-    checkedVal + " removed from the device selector.");
+  await testMenuItems(toolWindow, deviceSelector, menuItems => {
+    is(menuItems.length - 2, featuredCount,
+      "Got expected number of devices in device selector.");
+
+    const menuItem = menuItems.find(item => item.getAttribute("label") === checkedVal);
+    ok(!menuItem, checkedVal + " removed from the device selector.");
+  });
 
   info("Reopen device modal and check device is correctly unchecked");
-  openDeviceModal(ui);
+  await openDeviceModal(ui);
   ok([...document.querySelectorAll(".device-input-checkbox")]
     .filter(cb => !cb.checked && cb.value === checkedVal)[0],
     checkedVal + " is unchecked in the device modal.");
 
   // Let's add a dummy device to simulate featured flag changes for next test
   addDeviceForTest(addedDevice);
 });
 
 addRDMTask(TEST_URL, async function({ ui }) {
-  const { store, document } = ui.toolWindow;
-  const select = document.querySelector(".viewport-device-selector");
+  const { toolWindow } = ui;
+  const { store, document } = toolWindow;
 
   // Wait until the viewport has been added and the device list has been loaded
   await waitUntilState(store, state => state.viewports.length == 1
     && state.devices.listState == Types.loadableState.LOADED);
 
-  openDeviceModal(ui);
+  await openDeviceModal(ui);
 
   const remoteList = await getDevices();
   const featuredCount = remoteList.TYPES.reduce((total, type) => {
     return total + remoteList[type].reduce((subtotal, device) => {
       return subtotal + ((device.os != "fxos" && device.featured) ? 1 : 0);
     }, 0);
   }, 0);
   const preferredDevices = _loadPreferredDevices();
 
   // Tests to prove that reloading the RDM didn't break our device list
   info("Checking new featured device appears in the device selector.");
-  const options = [...select.options];
-  is(options.length - 2, featuredCount
-    - preferredDevices.removed.size + preferredDevices.added.size,
-    "Got expected number of devices in device selector.");
+  const deviceSelector = document.getElementById("device-selector");
+  await testMenuItems(toolWindow, deviceSelector, items => {
+    is(items.length - 2, featuredCount
+      - preferredDevices.removed.size + preferredDevices.added.size,
+      "Got expected number of devices in device selector.");
+
+    const added = items.find(i => i.getAttribute("label") === addedDevice.name);
+    ok(added, "Dummy device added to the device selector.");
 
-  ok(options.filter(o => o.value === addedDevice.name)[0],
-    "dummy device added to the device selector.");
+    for (const name of preferredDevices.added.keys()) {
+      const menuItem = items.find(item => item.getAttribute("label") === name);
+      ok(menuItem, "Device added by user still in the device selector.");
+    }
 
-  ok(options.filter(o => preferredDevices.added.has(o.value))[0],
-    "device added by user still in the device selector.");
-
-  ok(!options.filter(o => preferredDevices.removed.has(o.value))[0],
-    "device removed by user not in the device selector.");
+    for (const name of preferredDevices.removed.keys()) {
+      const menuItem = items.find(item => item.getAttribute("label") === name);
+      ok(!menuItem, "Device removed by user not in the device selector.");
+    }
+  });
 });
--- a/devtools/client/responsive.html/test/browser/browser_device_pixel_ratio_change.js
+++ b/devtools/client/responsive.html/test/browser/browser_device_pixel_ratio_change.js
@@ -1,17 +1,18 @@
 /* Any copyright is dedicated to the Public Domain.
 http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 // Tests changing viewport device pixel ratio
+
 const TEST_URL = "data:text/html;charset=utf-8,DevicePixelRatio list test";
 const DEFAULT_DPPX = window.devicePixelRatio;
-const VIEWPORT_DPPX = DEFAULT_DPPX + 2;
+const VIEWPORT_DPPX = DEFAULT_DPPX + 1;
 const Types = require("devtools/client/responsive.html/types");
 
 const testDevice = {
   "name": "Fake Phone RDM Test",
   "width": 320,
   "height": 470,
   "pixelRatio": 5.5,
   "userAgent": "Mozilla/5.0 (Mobile; rv:39.0) Gecko/39.0 Firefox/39.0",
@@ -45,31 +46,31 @@ async function testDefaults(ui) {
   info("Test Defaults");
 
   const dppx = await getViewportDevicePixelRatio(ui);
   is(dppx, DEFAULT_DPPX, "Content has expected devicePixelRatio");
   testViewportDevicePixelRatioSelect(ui, {
     value: DEFAULT_DPPX,
     disabled: false,
   });
-  testViewportDeviceSelectLabel(ui, "no device selected");
+  testViewportDeviceMenuLabel(ui, "Responsive");
 }
 
 async function testChangingDevice(ui) {
   info("Test Changing Device");
 
   await selectDevice(ui, testDevice.name);
   await waitForViewportResizeTo(ui, testDevice.width, testDevice.height);
   const dppx = await waitForDevicePixelRatio(ui, testDevice.pixelRatio);
   is(dppx, testDevice.pixelRatio, "Content has expected devicePixelRatio");
   testViewportDevicePixelRatioSelect(ui, {
     value: testDevice.pixelRatio,
     disabled: true,
   });
-  testViewportDeviceSelectLabel(ui, testDevice.name);
+  testViewportDeviceMenuLabel(ui, testDevice.name);
 }
 
 async function testResetWhenResizingViewport(ui) {
   info("Test reset when resizing the viewport");
 
   const deviceRemoved = once(ui, "device-association-removed");
   await testViewportResize(ui, ".viewport-vertical-resize-handle",
     [-10, -10], [testDevice.width, testDevice.height - 10], [0, -10], ui);
@@ -77,40 +78,40 @@ async function testResetWhenResizingView
 
   const dppx = await waitForDevicePixelRatio(ui, DEFAULT_DPPX);
   is(dppx, DEFAULT_DPPX, "Content has expected devicePixelRatio");
 
   testViewportDevicePixelRatioSelect(ui, {
     value: DEFAULT_DPPX,
     disabled: false,
   });
-  testViewportDeviceSelectLabel(ui, "no device selected");
+  testViewportDeviceMenuLabel(ui, "Responsive");
 }
 
 async function testChangingDevicePixelRatio(ui) {
   info("Test changing device pixel ratio");
 
   await selectDevicePixelRatio(ui, VIEWPORT_DPPX);
   const dppx = await waitForDevicePixelRatio(ui, VIEWPORT_DPPX);
   is(dppx, VIEWPORT_DPPX, "Content has expected devicePixelRatio");
   testViewportDevicePixelRatioSelect(ui, {
     value: VIEWPORT_DPPX,
     disabled: false,
   });
-  testViewportDeviceSelectLabel(ui, "no device selected");
+  testViewportDeviceMenuLabel(ui, "Responsive");
 }
 
 function testViewportDevicePixelRatioSelect(ui, expected) {
   info("Test viewport's DevicePixelRatio Select");
 
-  const select =
-    ui.toolWindow.document.querySelector("#global-device-pixel-ratio-selector");
-  is(select.value, expected.value,
+  const button = ui.toolWindow.document.getElementById("device-pixel-ratio-menu");
+  const title = ui.toolWindow.document.querySelector("#device-pixel-ratio-menu .title");
+  is(title.textContent, `DPR: ${expected.value}`,
      `DevicePixelRatio Select value should be: ${expected.value}`);
-  is(select.disabled, expected.disabled,
+  is(button.disabled, expected.disabled,
     `DevicePixelRatio Select should be ${expected.disabled ? "disabled" : "enabled"}.`);
 }
 
 function waitForDevicePixelRatio(ui, expected) {
   return ContentTask.spawn(ui.getViewportBrowser(), { expected }, function(args) {
     const initial = content.devicePixelRatio;
     info(`Listening for pixel ratio change ` +
          `(current: ${initial}, expected: ${args.expected})`);
--- a/devtools/client/responsive.html/test/browser/browser_exit_button.js
+++ b/devtools/client/responsive.html/test/browser/browser_exit_button.js
@@ -52,17 +52,17 @@ async function waitBootstrap(ui) {
 
   // Wait until the document has been loaded.
   await waitForFrameLoad(ui, url);
 }
 
 async function testExitButton({ui, manager}) {
   await waitBootstrap(ui);
 
-  const exitButton = ui.toolWindow.document.getElementById("global-exit-button");
+  const exitButton = ui.toolWindow.document.getElementById("exit-button");
 
   ok(manager.isActiveForTab(ui.tab),
     "Responsive Design Mode active for the tab");
 
   exitButton.click();
 
   await once(manager, "off");
 
--- a/devtools/client/responsive.html/test/browser/browser_network_throttling.js
+++ b/devtools/client/responsive.html/test/browser/browser_network_throttling.js
@@ -26,20 +26,18 @@ addRDMTask(TEST_URL, async function({ ui
 
   // Test switching back to no throttling
   await selectNetworkThrottling(ui, "No throttling");
   testNetworkThrottlingSelectorLabel(ui, "No throttling");
   await testNetworkThrottlingState(ui, null);
 });
 
 function testNetworkThrottlingSelectorLabel(ui, expected) {
-  const selector = "#network-throttling-selector";
-  const select = ui.toolWindow.document.querySelector(selector);
-  is(select.selectedOptions[0].textContent, expected,
-    `Select label should be changed to ${expected}`);
+  const title = ui.toolWindow.document.querySelector("#network-throttling-menu .title");
+  is(title.textContent, expected, `Button title should be changed to ${expected}`);
 }
 
 var testNetworkThrottlingState = async function(ui, expected) {
   const state = await ui.emulationFront.getNetworkThrottling();
   Assert.deepEqual(state, expected, "Network throttling state should be " +
                                     JSON.stringify(expected, null, 2));
 };
 
--- a/devtools/client/responsive.html/test/browser/browser_screenshot_button.js
+++ b/devtools/client/responsive.html/test/browser/browser_screenshot_button.js
@@ -29,17 +29,17 @@ function waitUntilScreenshot() {
 
 addRDMTask(TEST_URL, async function({ ui: {toolWindow} }) {
   const { store, document } = toolWindow;
 
   // Wait until the viewport has been added
   await waitUntilState(store, state => state.viewports.length == 1);
 
   info("Click the screenshot button");
-  const screenshotButton = document.getElementById("global-screenshot-button");
+  const screenshotButton = document.getElementById("screenshot-button");
   screenshotButton.click();
 
   const whenScreenshotSucceeded = waitUntilScreenshot();
 
   const filePath = await whenScreenshotSucceeded;
   const image = new Image();
   image.src = OS.Path.toFileURI(filePath);
 
--- a/devtools/client/responsive.html/test/browser/browser_touch_device.js
+++ b/devtools/client/responsive.html/test/browser/browser_touch_device.js
@@ -44,42 +44,42 @@ async function waitStartup(ui) {
   await waitUntilState(store, state => state.viewports.length == 1
     && state.devices.listState == Types.loadableState.LOADED);
 }
 
 async function testDefaults(ui) {
   info("Test Defaults");
 
   await testTouchEventsOverride(ui, false);
-  testViewportDeviceSelectLabel(ui, "no device selected");
+  testViewportDeviceMenuLabel(ui, "Responsive");
 }
 
 async function testChangingDevice(ui) {
   info("Test Changing Device");
 
   await selectDevice(ui, testDevice.name);
   await waitForViewportResizeTo(ui, testDevice.width, testDevice.height);
   await testTouchEventsOverride(ui, true);
-  testViewportDeviceSelectLabel(ui, testDevice.name);
+  testViewportDeviceMenuLabel(ui, testDevice.name);
 }
 
 async function testResizingViewport(ui, device, touch) {
   info(`Test resizing the viewport, device ${device}, touch ${touch}`);
 
   let deviceRemoved;
   if (device) {
     deviceRemoved = once(ui, "device-association-removed");
   }
   await testViewportResize(ui, ".viewport-vertical-resize-handle",
     [-10, -10], [testDevice.width, testDevice.height - 10], [0, -10], ui);
   if (device) {
     await deviceRemoved;
   }
   await testTouchEventsOverride(ui, touch);
-  testViewportDeviceSelectLabel(ui, "no device selected");
+  testViewportDeviceMenuLabel(ui, "Responsive");
 }
 
 async function testEnableTouchSimulation(ui) {
   info("Test enabling touch simulation via button");
 
   await toggleTouchSimulation(ui);
   await testTouchEventsOverride(ui, true);
 }
--- a/devtools/client/responsive.html/test/browser/browser_touch_simulation.js
+++ b/devtools/client/responsive.html/test/browser/browser_touch_simulation.js
@@ -159,17 +159,17 @@ async function testWithMetaViewportDisab
     await synthesizeClick(div);
     is(div.dataset.isDelay, "true",
       "300ms delay between touch events and mouse events should work");
   });
 }
 
 function testTouchButton(ui) {
   const { document } = ui.toolWindow;
-  const touchButton = document.querySelector("#global-touch-simulation-button");
+  const touchButton = document.getElementById("touch-simulation-button");
 
   ok(touchButton.classList.contains("checked"),
     "Touch simulation is active at end of test.");
 
   touchButton.click();
 
   ok(!touchButton.classList.contains("checked"),
     "Touch simulation is stopped on click.");
--- a/devtools/client/responsive.html/test/browser/head.js
+++ b/devtools/client/responsive.html/test/browser/head.js
@@ -26,25 +26,28 @@ Services.scriptloader.loadSubScript(
   "chrome://mochitests/content/browser/devtools/client/shared/test/test-actor-registry.js",
   this);
 
 // Import helpers for the inspector that are also shared with others
 Services.scriptloader.loadSubScript(
   "chrome://mochitests/content/browser/devtools/client/inspector/test/shared-head.js",
   this);
 
+const { _loadPreferredDevices } = require("devtools/client/responsive.html/actions/devices");
+const { getStr } = require("devtools/client/responsive.html/utils/l10n");
+const { getTopLevelWindow } = require("devtools/client/responsive.html/utils/window");
+const { addDevice, removeDevice, removeLocalDevices } = require("devtools/client/shared/devices");
+const asyncStorage = require("devtools/shared/async-storage");
+
+loader.lazyRequireGetter(this, "ResponsiveUIManager", "devtools/client/responsive.html/manager", true);
+
 const E10S_MULTI_ENABLED = Services.prefs.getIntPref("dom.ipc.processCount") > 1;
 const TEST_URI_ROOT = "http://example.com/browser/devtools/client/responsive.html/test/browser/";
-const OPEN_DEVICE_MODAL_VALUE = "OPEN_DEVICE_MODAL";
 const RELOAD_CONDITION_PREF_PREFIX = "devtools.responsive.reloadConditions.";
 
-const { _loadPreferredDevices } = require("devtools/client/responsive.html/actions/devices");
-const asyncStorage = require("devtools/shared/async-storage");
-const { addDevice, removeDevice, removeLocalDevices } = require("devtools/client/shared/devices");
-
 SimpleTest.requestCompleteLog();
 SimpleTest.waitForExplicitFinish();
 
 // Toggling the RDM UI involves several docShell swap operations, which are somewhat slow
 // on debug builds. Usually we are just barely over the limit, so a blanket factor of 2
 // should be enough.
 requestLongerTimeout(2);
 
@@ -58,18 +61,16 @@ registerCleanupFunction(async () => {
   Services.prefs.clearUserPref("devtools.responsive.reloadNotification.enabled");
   Services.prefs.clearUserPref("devtools.responsive.html.displayedDeviceList");
   Services.prefs.clearUserPref("devtools.responsive.reloadConditions.touchSimulation");
   Services.prefs.clearUserPref("devtools.responsive.reloadConditions.userAgent");
   await asyncStorage.removeItem("devtools.devices.url_cache");
   await removeLocalDevices();
 });
 
-loader.lazyRequireGetter(this, "ResponsiveUIManager", "devtools/client/responsive.html/manager", true);
-
 /**
  * Open responsive design mode for the given tab.
  */
 var openRDM = async function(tab) {
   info("Opening responsive design mode");
   const manager = ResponsiveUIManager;
   const ui = await manager.openIfNeeded(tab.ownerGlobal, tab, { trigger: "test" });
   info("Responsive design mode opened");
@@ -224,61 +225,88 @@ async function testViewportResize(ui, se
 
   const endRect = getElRect(selector, win);
   is(endRect.left - startRect.left, expectedHandleMove[0],
     `The x move of ${selector} is as expected`);
   is(endRect.top - startRect.top, expectedHandleMove[1],
     `The y move of ${selector} is as expected`);
 }
 
-function openDeviceModal({ toolWindow }) {
-  const { document } = toolWindow;
-  const { Simulate } = toolWindow.require("devtools/client/shared/vendor/react-dom-test-utils");
-  const select = document.querySelector(".viewport-device-selector");
-  const modal = document.querySelector("#device-modal-wrapper");
+async function openDeviceModal(ui) {
+  const { document } = ui.toolWindow;
+  const modal = document.getElementById("device-modal-wrapper");
 
   info("Checking initial device modal state");
   ok(modal.classList.contains("closed") && !modal.classList.contains("opened"),
     "The device modal is closed by default.");
 
   info("Opening device modal through device selector.");
-  select.value = OPEN_DEVICE_MODAL_VALUE;
-  Simulate.change(select);
+  await selectMenuItem(ui, "#device-selector", getStr("responsive.editDeviceList2"));
+
   ok(modal.classList.contains("opened") && !modal.classList.contains("closed"),
     "The device modal is displayed.");
 }
 
-function changeSelectValue({ toolWindow }, selector, value) {
+async function selectMenuItem({ toolWindow }, selector, value) {
   const { document } = toolWindow;
-  const { Simulate } =
-    toolWindow.require("devtools/client/shared/vendor/react-dom-test-utils");
+
+  const button = document.querySelector(selector);
+  isnot(button, null, `Selector "${selector}" should match an existing element.`);
 
   info(`Selecting ${value} in ${selector}.`);
 
-  const select = document.querySelector(selector);
-  isnot(select, null, `selector "${selector}" should match an existing element.`);
+  await testMenuItems(toolWindow, button, items => {
+    const menuItem = items.find(item => item.getAttribute("label") === value);
+    isnot(menuItem, undefined, `Value "${value}" should match an existing menu item.`);
+    menuItem.click();
+  });
+}
 
-  const option = [...select.options].find(o => o.value === String(value));
-  isnot(option, undefined, `value "${value}" should match an existing option.`);
+/**
+ * Runs the menu items from the button's context menu against a test function.
+ *
+ * @param  {Window} toolWindow
+ *         A window reference.
+ * @param  {Element} button
+ *         The button that will show a context menu when clicked.
+ * @param  {Function} testFn
+ *         A test function that will be ran with the found menu item in the context menu
+ *         as an argument.
+ */
+function testMenuItems(toolWindow, button, testFn) {
+  // The context menu appears only in the top level window, which is different from
+  // the inner toolWindow.
+  const win = getTopLevelWindow(toolWindow);
 
-  select.value = value;
-  Simulate.change(select);
+  return new Promise(resolve => {
+    win.document.addEventListener("popupshown", () => {
+      const popup = win.document.querySelector("menupopup[menu-api=\"true\"]");
+      const menuItems = [...popup.children];
+
+      testFn(menuItems);
+
+      popup.hidePopup();
+      resolve();
+    }, { once: true });
+
+    button.click();
+  });
 }
 
 const selectDevice = (ui, value) => Promise.all([
   once(ui, "device-changed"),
-  changeSelectValue(ui, ".viewport-device-selector", value)
+  selectMenuItem(ui, "#device-selector", value)
 ]);
 
 const selectDevicePixelRatio = (ui, value) =>
-  changeSelectValue(ui, "#global-device-pixel-ratio-selector", value);
+  selectMenuItem(ui, "#device-pixel-ratio-menu", `DPR: ${value}`);
 
 const selectNetworkThrottling = (ui, value) => Promise.all([
   once(ui, "network-throttling-changed"),
-  changeSelectValue(ui, "#network-throttling-selector", value)
+  selectMenuItem(ui, "#network-throttling-menu", value)
 ]);
 
 function getSessionHistory(browser) {
   return ContentTask.spawn(browser, {}, async function() {
     /* eslint-disable no-undef */
     const { SessionHistory } =
       ChromeUtils.import("resource://gre/modules/sessionstore/SessionHistory.jsm", {});
     return SessionHistory.collect(docShell);
@@ -341,36 +369,35 @@ function addDeviceForTest(device) {
 async function waitForClientClose(ui) {
   info("Waiting for RDM debugger client to close");
   await ui.client.addOneTimeListener("closed");
   info("RDM's debugger client is now closed");
 }
 
 async function testTouchEventsOverride(ui, expected) {
   const { document } = ui.toolWindow;
-  const touchButton = document.querySelector("#global-touch-simulation-button");
+  const touchButton = document.getElementById("touch-simulation-button");
 
   const flag = await ui.emulationFront.getTouchEventsOverride();
   is(flag === Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_ENABLED, expected,
     `Touch events override should be ${expected ? "enabled" : "disabled"}`);
   is(touchButton.classList.contains("checked"), expected,
     `Touch simulation button should be ${expected ? "" : "in"}active.`);
 }
 
-function testViewportDeviceSelectLabel(ui, expected) {
+function testViewportDeviceMenuLabel(ui, expected) {
   info("Test viewport's device select label");
 
-  const select = ui.toolWindow.document.querySelector(".viewport-device-selector");
-  is(select.selectedOptions[0].textContent, expected,
-     `Device Select value should be: ${expected}`);
+  const label = ui.toolWindow.document.querySelector("#device-selector .title");
+  is(label.textContent, expected, `Device Select value should be: ${expected}`);
 }
 
 async function toggleTouchSimulation(ui) {
   const { document } = ui.toolWindow;
-  const touchButton = document.querySelector("#global-touch-simulation-button");
+  const touchButton = document.getElementById("touch-simulation-button");
   const changed = once(ui, "touch-simulation-changed");
   const loaded = waitForViewportLoad(ui);
   touchButton.click();
   await Promise.all([ changed, loaded ]);
 }
 
 function testUserAgent(ui, expected) {
   testUserAgentFromBrowser(ui.getViewportBrowser(), expected);