Bug 1319950 - Only clear properties on resize if device is active. r=gl, a=jcristau
authorJ. Ryan Stinnett <jryans@gmail.com>
Fri, 20 Jan 2017 17:08:48 -0600
changeset 375646 c933e719a5674efc1fb7d33844ee76987c5f1768
parent 375645 b48c0364b756a2dc9fc9fbf1f257fc36bdcbbe96
child 375647 7d4459bdab3d0e46fb982c8ea1f2a4cd1aa8f8a9
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgl, jcristau
bugs1319950
milestone53.0a2
Bug 1319950 - Only clear properties on resize if device is active. r=gl, a=jcristau If a device is active, remove it on resize. If not, leave device properties alone, so that things like touch simulation stay enabled when resizing without a device. MozReview-Commit-ID: Hvo6AdTJRBJ
devtools/client/responsive.html/actions/index.js
devtools/client/responsive.html/actions/viewports.js
devtools/client/responsive.html/app.js
devtools/client/responsive.html/components/resizable-viewport.js
devtools/client/responsive.html/components/viewport-dimension.js
devtools/client/responsive.html/components/viewport.js
devtools/client/responsive.html/components/viewports.js
devtools/client/responsive.html/manager.js
devtools/client/responsive.html/reducers/viewports.js
devtools/client/responsive.html/test/browser/browser.ini
devtools/client/responsive.html/test/browser/browser_device_change.js
devtools/client/responsive.html/test/browser/browser_dpr_change.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/actions/index.js
+++ b/devtools/client/responsive.html/actions/index.js
@@ -48,16 +48,19 @@ createEnum([
   "LOAD_DEVICE_LIST_START",
 
   // Indicates that the device list loading action threw an error
   "LOAD_DEVICE_LIST_ERROR",
 
   // Indicates that the device list has been loaded successfully
   "LOAD_DEVICE_LIST_END",
 
+  // Remove the viewport's device assocation.
+  "REMOVE_DEVICE",
+
   // Resize the viewport.
   "RESIZE_VIEWPORT",
 
   // Rotate the viewport.
   "ROTATE_VIEWPORT",
 
   // Take a screenshot of the viewport.
   "TAKE_SCREENSHOT_START",
--- a/devtools/client/responsive.html/actions/viewports.js
+++ b/devtools/client/responsive.html/actions/viewports.js
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const {
   ADD_VIEWPORT,
   CHANGE_DEVICE,
   CHANGE_PIXEL_RATIO,
+  REMOVE_DEVICE,
   RESIZE_VIEWPORT,
   ROTATE_VIEWPORT
 } = require("./index");
 
 module.exports = {
 
   /**
    * Add an additional viewport to display the document.
@@ -41,16 +42,26 @@ module.exports = {
     return {
       type: CHANGE_PIXEL_RATIO,
       id,
       pixelRatio,
     };
   },
 
   /**
+   * Remove the viewport's device assocation.
+   */
+  removeDevice(id) {
+    return {
+      type: REMOVE_DEVICE,
+      id,
+    };
+  },
+
+  /**
    * Resize the viewport.
    */
   resizeViewport(id, width, height) {
     return {
       type: RESIZE_VIEWPORT,
       id,
       width,
       height,
--- a/devtools/client/responsive.html/app.js
+++ b/devtools/client/responsive.html/app.js
@@ -16,18 +16,19 @@ const {
   updatePreferredDevices,
 } = require("./actions/devices");
 const { changeNetworkThrottling } = require("./actions/network-throttling");
 const { takeScreenshot } = require("./actions/screenshot");
 const { changeTouchSimulation } = require("./actions/touch-simulation");
 const {
   changeDevice,
   changePixelRatio,
+  removeDevice,
   resizeViewport,
-  rotateViewport
+  rotateViewport,
 } = require("./actions/viewports");
 const DeviceModal = createFactory(require("./components/device-modal"));
 const GlobalToolbar = createFactory(require("./components/global-toolbar"));
 const Viewports = createFactory(require("./components/viewports"));
 const Types = require("./types");
 
 let App = createClass({
   displayName: "App",
@@ -93,16 +94,26 @@ let App = createClass({
   onDeviceListUpdate(devices) {
     updatePreferredDevices(devices);
   },
 
   onExit() {
     window.postMessage({ type: "exit" }, "*");
   },
 
+  onRemoveDevice(id) {
+    // TODO: Bug 1332754: Move messaging and logic into the action creator.
+    window.postMessage({
+      type: "remove-device",
+    }, "*");
+    this.props.dispatch(removeDevice(id));
+    this.props.dispatch(changeTouchSimulation(false));
+    this.props.dispatch(changePixelRatio(id, 0));
+  },
+
   onResizeViewport(id, width, height) {
     this.props.dispatch(resizeViewport(id, width, height));
   },
 
   onRotateViewport(id) {
     this.props.dispatch(rotateViewport(id));
   },
 
@@ -133,16 +144,17 @@ let App = createClass({
       onBrowserMounted,
       onChangeDevice,
       onChangeNetworkThrottling,
       onChangePixelRatio,
       onChangeTouchSimulation,
       onContentResize,
       onDeviceListUpdate,
       onExit,
+      onRemoveDevice,
       onResizeViewport,
       onRotateViewport,
       onScreenshot,
       onUpdateDeviceDisplayed,
       onUpdateDeviceModalOpen,
     } = this;
 
     let selectedDevice = "";
@@ -174,16 +186,17 @@ let App = createClass({
       Viewports({
         devices,
         location,
         screenshot,
         viewports,
         onBrowserMounted,
         onChangeDevice,
         onContentResize,
+        onRemoveDevice,
         onRotateViewport,
         onResizeViewport,
         onUpdateDeviceModalOpen,
       }),
       DeviceModal({
         devices,
         onDeviceListUpdate,
         onUpdateDeviceDisplayed,
--- a/devtools/client/responsive.html/components/resizable-viewport.js
+++ b/devtools/client/responsive.html/components/resizable-viewport.js
@@ -25,16 +25,17 @@ module.exports = createClass({
     devices: PropTypes.shape(Types.devices).isRequired,
     location: Types.location.isRequired,
     screenshot: PropTypes.shape(Types.screenshot).isRequired,
     swapAfterMount: PropTypes.bool.isRequired,
     viewport: PropTypes.shape(Types.viewport).isRequired,
     onBrowserMounted: PropTypes.func.isRequired,
     onChangeDevice: PropTypes.func.isRequired,
     onContentResize: PropTypes.func.isRequired,
+    onRemoveDevice: PropTypes.func.isRequired,
     onResizeViewport: PropTypes.func.isRequired,
     onRotateViewport: PropTypes.func.isRequired,
     onUpdateDeviceModalOpen: PropTypes.func.isRequired,
   },
 
   getInitialState() {
     return {
       isResizing: false,
@@ -102,19 +103,24 @@ module.exports = createClass({
       height = VIEWPORT_MIN_HEIGHT;
     } else {
       lastClientY = clientY;
     }
 
     // Update the viewport store with the new width and height.
     this.props.onResizeViewport(width, height);
     // Change the device selector back to an unselected device
-    // TODO: Bug 1313140: We should avoid calling this for every resize event, since it
-    // triggers RDP calls each time.
-    this.props.onChangeDevice({ name: "" });
+    // TODO: Bug 1332754: Logic like this probably belongs in the action creator.
+    if (this.props.viewport.device) {
+      // In bug 1329843 and others, we may eventually stop this approach of removing the
+      // the properties of the device on resize.  However, at the moment, there is no
+      // way to edit dPR when a device is selected, and there is no UI at all for editing
+      // UA, so it's important to keep doing this for now.
+      this.props.onRemoveDevice();
+    }
 
     this.setState({
       lastClientX,
       lastClientY
     });
   },
 
   render() {
--- a/devtools/client/responsive.html/components/viewport-dimension.js
+++ b/devtools/client/responsive.html/components/viewport-dimension.js
@@ -10,17 +10,17 @@ const { DOM: dom, createClass, PropTypes
 const Constants = require("../constants");
 const Types = require("../types");
 
 module.exports = createClass({
   displayName: "ViewportDimension",
 
   propTypes: {
     viewport: PropTypes.shape(Types.viewport).isRequired,
-    onChangeDevice: PropTypes.func.isRequired,
+    onRemoveDevice: PropTypes.func.isRequired,
     onResizeViewport: PropTypes.func.isRequired,
   },
 
   getInitialState() {
     let { width, height } = this.props.viewport;
 
     return {
       width,
@@ -109,17 +109,20 @@ module.exports = createClass({
         height,
         isInvalid: false,
       });
 
       return;
     }
 
     // Change the device selector back to an unselected device
-    this.props.onChangeDevice({ name: "" });
+    // TODO: Bug 1332754: Logic like this probably belongs in the action creator.
+    if (this.props.viewport.device) {
+      this.props.onRemoveDevice();
+    }
     this.props.onResizeViewport(parseInt(this.state.width, 10),
                                 parseInt(this.state.height, 10));
   },
 
   render() {
     let editableClass = "viewport-dimension-editable";
     let inputClass = "viewport-dimension-input";
 
--- a/devtools/client/responsive.html/components/viewport.js
+++ b/devtools/client/responsive.html/components/viewport.js
@@ -19,30 +19,40 @@ module.exports = createClass({
     devices: PropTypes.shape(Types.devices).isRequired,
     location: Types.location.isRequired,
     screenshot: PropTypes.shape(Types.screenshot).isRequired,
     swapAfterMount: PropTypes.bool.isRequired,
     viewport: PropTypes.shape(Types.viewport).isRequired,
     onBrowserMounted: PropTypes.func.isRequired,
     onChangeDevice: PropTypes.func.isRequired,
     onContentResize: PropTypes.func.isRequired,
+    onRemoveDevice: PropTypes.func.isRequired,
     onResizeViewport: PropTypes.func.isRequired,
     onRotateViewport: PropTypes.func.isRequired,
     onUpdateDeviceModalOpen: PropTypes.func.isRequired,
   },
 
   onChangeDevice(device) {
     let {
       viewport,
       onChangeDevice,
     } = this.props;
 
     onChangeDevice(viewport.id, device);
   },
 
+  onRemoveDevice() {
+    let {
+      viewport,
+      onRemoveDevice,
+    } = this.props;
+
+    onRemoveDevice(viewport.id);
+  },
+
   onResizeViewport(width, height) {
     let {
       viewport,
       onResizeViewport,
     } = this.props;
 
     onResizeViewport(viewport.id, width, height);
   },
@@ -65,38 +75,40 @@ module.exports = createClass({
       viewport,
       onBrowserMounted,
       onContentResize,
       onUpdateDeviceModalOpen,
     } = this.props;
 
     let {
       onChangeDevice,
+      onRemoveDevice,
       onRotateViewport,
       onResizeViewport,
     } = this;
 
     return dom.div(
       {
         className: "viewport",
       },
       ViewportDimension({
         viewport,
-        onChangeDevice,
+        onRemoveDevice,
         onResizeViewport,
       }),
       ResizableViewport({
         devices,
         location,
         screenshot,
         swapAfterMount,
         viewport,
         onBrowserMounted,
         onChangeDevice,
         onContentResize,
+        onRemoveDevice,
         onResizeViewport,
         onRotateViewport,
         onUpdateDeviceModalOpen,
       })
     );
   },
 
 });
--- a/devtools/client/responsive.html/components/viewports.js
+++ b/devtools/client/responsive.html/components/viewports.js
@@ -17,30 +17,32 @@ module.exports = createClass({
   propTypes: {
     devices: PropTypes.shape(Types.devices).isRequired,
     location: Types.location.isRequired,
     screenshot: PropTypes.shape(Types.screenshot).isRequired,
     viewports: PropTypes.arrayOf(PropTypes.shape(Types.viewport)).isRequired,
     onBrowserMounted: PropTypes.func.isRequired,
     onChangeDevice: PropTypes.func.isRequired,
     onContentResize: PropTypes.func.isRequired,
+    onRemoveDevice: PropTypes.func.isRequired,
     onResizeViewport: PropTypes.func.isRequired,
     onRotateViewport: PropTypes.func.isRequired,
     onUpdateDeviceModalOpen: PropTypes.func.isRequired,
   },
 
   render() {
     let {
       devices,
       location,
       screenshot,
       viewports,
       onBrowserMounted,
       onChangeDevice,
       onContentResize,
+      onRemoveDevice,
       onResizeViewport,
       onRotateViewport,
       onUpdateDeviceModalOpen,
     } = this.props;
 
     return dom.div(
       {
         id: "viewports",
@@ -51,16 +53,17 @@ module.exports = createClass({
           devices,
           location,
           screenshot,
           swapAfterMount: i == 0,
           viewport,
           onBrowserMounted,
           onChangeDevice,
           onContentResize,
+          onRemoveDevice,
           onResizeViewport,
           onRotateViewport,
           onUpdateDeviceModalOpen,
         });
       })
     );
   },
 
--- a/devtools/client/responsive.html/manager.js
+++ b/devtools/client/responsive.html/manager.js
@@ -462,16 +462,19 @@ ResponsiveUI.prototype = {
         this.onChangeTouchSimulation(event);
         break;
       case "content-resize":
         this.onContentResize(event);
         break;
       case "exit":
         this.onExit();
         break;
+      case "remove-device":
+        this.onRemoveDevice(event);
+        break;
     }
   },
 
   onChangeDevice: Task.async(function* (event) {
     let { userAgent, pixelRatio, touch } = event.data.device;
     yield this.updateUserAgent(userAgent);
     yield this.updateDPPX(pixelRatio);
     yield this.updateTouchSimulation(touch);
@@ -504,16 +507,24 @@ ResponsiveUI.prototype = {
     });
   },
 
   onExit() {
     let { browserWindow, tab } = this;
     ResponsiveUIManager.closeIfNeeded(browserWindow, tab);
   },
 
+  onRemoveDevice: Task.async(function* (event) {
+    yield this.updateUserAgent();
+    yield this.updateDPPX();
+    yield this.updateTouchSimulation();
+    // Used by tests
+    this.emit("device-removed");
+  }),
+
   updateDPPX: Task.async(function* (dppx) {
     if (!dppx) {
       yield this.emulationFront.clearDPPXOverride();
       return;
     }
     yield this.emulationFront.setDPPXOverride(dppx);
   }),
 
--- a/devtools/client/responsive.html/reducers/viewports.js
+++ b/devtools/client/responsive.html/reducers/viewports.js
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const {
   ADD_VIEWPORT,
   CHANGE_DEVICE,
   CHANGE_PIXEL_RATIO,
+  REMOVE_DEVICE,
   RESIZE_VIEWPORT,
   ROTATE_VIEWPORT,
 } = require("../actions/index");
 
 let nextViewportId = 0;
 
 const INITIAL_VIEWPORTS = [];
 const INITIAL_VIEWPORT = {
@@ -56,16 +57,28 @@ let reducers = {
       return Object.assign({}, viewport, {
         pixelRatio: {
           value: pixelRatio
         },
       });
     });
   },
 
+  [REMOVE_DEVICE](viewports, { id }) {
+    return viewports.map(viewport => {
+      if (viewport.id !== id) {
+        return viewport;
+      }
+
+      return Object.assign({}, viewport, {
+        device: "",
+      });
+    });
+  },
+
   [RESIZE_VIEWPORT](viewports, { id, width, height }) {
     return viewports.map(viewport => {
       if (viewport.id !== id) {
         return viewport;
       }
 
       if (!width) {
         width = viewport.width;
--- a/devtools/client/responsive.html/test/browser/browser.ini
+++ b/devtools/client/responsive.html/test/browser/browser.ini
@@ -33,11 +33,12 @@ support-files =
 [browser_permission_doorhanger.js]
 [browser_resize_cmd.js]
 [browser_screenshot_button.js]
 [browser_tab_close.js]
 [browser_tab_remoteness_change.js]
 [browser_toolbox_computed_view.js]
 [browser_toolbox_rule_view.js]
 [browser_toolbox_swap_browsers.js]
+[browser_touch_device.js]
 [browser_touch_simulation.js]
 [browser_viewport_basics.js]
 [browser_window_close.js]
--- a/devtools/client/responsive.html/test/browser/browser_device_change.js
+++ b/devtools/client/responsive.html/test/browser/browser_device_change.js
@@ -35,34 +35,34 @@ addRDMTask(TEST_URL, function* ({ ui, ma
   yield waitUntilState(store, state => state.viewports.length == 1
     && state.devices.listState == Types.deviceListState.LOADED);
 
   // Test defaults
   testViewportDimensions(ui, 320, 480);
   yield testUserAgent(ui, DEFAULT_UA);
   yield testDevicePixelRatio(ui, DEFAULT_DPPX);
   yield testTouchEventsOverride(ui, false);
-  testViewportSelectLabel(ui, "no device selected");
+  testViewportDeviceSelectLabel(ui, "no device selected");
 
   // Test device with custom properties
   yield selectDevice(ui, "Fake Phone RDM Test");
   yield waitForViewportResizeTo(ui, testDevice.width, testDevice.height);
   yield testUserAgent(ui, testDevice.userAgent);
   yield testDevicePixelRatio(ui, testDevice.pixelRatio);
   yield testTouchEventsOverride(ui, true);
 
   // Test resetting device when resizing viewport
-  let deviceChanged = once(ui, "device-changed");
+  let deviceRemoved = once(ui, "device-removed");
   yield testViewportResize(ui, ".viewport-vertical-resize-handle",
     [-10, -10], [testDevice.width, testDevice.height - 10], [0, -10], ui);
-  yield deviceChanged;
+  yield deviceRemoved;
   yield testUserAgent(ui, DEFAULT_UA);
   yield testDevicePixelRatio(ui, DEFAULT_DPPX);
   yield testTouchEventsOverride(ui, false);
-  testViewportSelectLabel(ui, "no device selected");
+  testViewportDeviceSelectLabel(ui, "no device selected");
 
   // Test device with generic properties
   yield selectDevice(ui, "Laptop (1366 x 768)");
   yield waitForViewportResizeTo(ui, 1366, 768);
   yield testUserAgent(ui, DEFAULT_UA);
   yield testDevicePixelRatio(ui, 1);
   yield testTouchEventsOverride(ui, false);
 });
@@ -71,42 +71,25 @@ function testViewportDimensions(ui, w, h
   let viewport = ui.toolWindow.document.querySelector(".viewport-content");
 
   is(ui.toolWindow.getComputedStyle(viewport).getPropertyValue("width"),
      `${w}px`, `Viewport should have width of ${w}px`);
   is(ui.toolWindow.getComputedStyle(viewport).getPropertyValue("height"),
      `${h}px`, `Viewport should have height of ${h}px`);
 }
 
-function testViewportSelectLabel(ui, expected) {
-  let select = ui.toolWindow.document.querySelector(".viewport-device-selector");
-  is(select.selectedOptions[0].textContent, expected,
-     `Select label should be changed to ${expected}`);
-}
-
 function* testUserAgent(ui, expected) {
   let ua = yield ContentTask.spawn(ui.getViewportBrowser(), {}, function* () {
     return content.navigator.userAgent;
   });
   is(ua, expected, `UA should be set to ${expected}`);
 }
 
 function* testDevicePixelRatio(ui, expected) {
   let dppx = yield getViewportDevicePixelRatio(ui);
   is(dppx, expected, `devicePixelRatio should be set to ${expected}`);
 }
 
-function* testTouchEventsOverride(ui, expected) {
-  let { document } = ui.toolWindow;
-  let touchButton = document.querySelector("#global-touch-simulation-button");
-
-  let flag = yield ui.emulationFront.getTouchEventsOverride();
-  is(flag === Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_ENABLED, expected,
-    `Touch events override should be ${expected ? "enabled" : "disabled"}`);
-  is(touchButton.classList.contains("active"), expected,
-    `Touch simulation button should be ${expected ? "" : "not"} active.`);
-}
-
 function* getViewportDevicePixelRatio(ui) {
   return yield ContentTask.spawn(ui.getViewportBrowser(), {}, function* () {
     return content.devicePixelRatio;
   });
 }
--- a/devtools/client/responsive.html/test/browser/browser_dpr_change.js
+++ b/devtools/client/responsive.html/test/browser/browser_dpr_change.js
@@ -1,14 +1,14 @@
 /* Any copyright is dedicated to the Public Domain.
 http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-// Tests changing viewport device
+// Tests changing viewport DPR
 const TEST_URL = "data:text/html;charset=utf-8,DPR list test";
 const DEFAULT_DPPX = window.devicePixelRatio;
 const VIEWPORT_DPPX = DEFAULT_DPPX + 2;
 const Types = require("devtools/client/responsive.html/types");
 
 const testDevice = {
   "name": "Fake Phone RDM Test",
   "width": 320,
@@ -62,18 +62,20 @@ function* testChangingDevice(ui) {
   testViewportDeviceSelectLabel(ui, testDevice.name);
 }
 
 function* testResetWhenResizingViewport(ui) {
   info("Test reset when resizing the viewport");
 
   let waitPixelRatioChange = onceDevicePixelRatioChange(ui);
 
+  let deviceRemoved = once(ui, "device-removed");
   yield testViewportResize(ui, ".viewport-vertical-resize-handle",
     [-10, -10], [testDevice.width, testDevice.height - 10], [0, -10], ui);
+  yield deviceRemoved;
 
   yield waitPixelRatioChange;
   yield testDevicePixelRatio(ui, window.devicePixelRatio);
 
   testViewportDPRSelect(ui, {value: window.devicePixelRatio, disabled: false});
   testViewportDeviceSelectLabel(ui, "no device selected");
 }
 
@@ -94,24 +96,16 @@ function testViewportDPRSelect(ui, expec
 
   let select = ui.toolWindow.document.querySelector("#global-dpr-selector > select");
   is(select.value, expected.value,
      `DPR Select value should be: ${expected.value}`);
   is(select.disabled, expected.disabled,
     `DPR Select should be ${expected.disabled ? "disabled" : "enabled"}.`);
 }
 
-function testViewportDeviceSelectLabel(ui, expected) {
-  info("Test viewport's device select label");
-
-  let select = ui.toolWindow.document.querySelector(".viewport-device-selector");
-  is(select.selectedOptions[0].textContent, expected,
-     `Device Select value should be: ${expected}`);
-}
-
 function* testDevicePixelRatio(ui, expected) {
   info("Test device pixel ratio");
 
   let dppx = yield getViewportDevicePixelRatio(ui);
   is(dppx, expected, `devicePixelRatio should be: ${expected}`);
 }
 
 function* getViewportDevicePixelRatio(ui) {
new file mode 100644
--- /dev/null
+++ b/devtools/client/responsive.html/test/browser/browser_touch_device.js
@@ -0,0 +1,77 @@
+/* Any copyright is dedicated to the Public Domain.
+http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Tests changing viewport touch simulation
+const TEST_URL = "data:text/html;charset=utf-8,touch simulation test";
+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",
+  "touch": true,
+  "firefoxOS": true,
+  "os": "custom",
+  "featured": true,
+};
+
+// Add the new device to the list
+addDeviceForTest(testDevice);
+
+addRDMTask(TEST_URL, function* ({ ui, manager }) {
+  yield waitStartup(ui);
+
+  yield testDefaults(ui);
+  yield testChangingDevice(ui);
+  yield testResizingViewport(ui, true, false);
+  yield testEnableTouchSimulation(ui);
+  yield testResizingViewport(ui, false, true);
+});
+
+function* waitStartup(ui) {
+  let { store } = ui.toolWindow;
+
+  // Wait until the viewport has been added and the device list has been loaded
+  yield waitUntilState(store, state => state.viewports.length == 1
+    && state.devices.listState == Types.deviceListState.LOADED);
+}
+
+function* testDefaults(ui) {
+  info("Test Defaults");
+
+  yield testTouchEventsOverride(ui, false);
+  testViewportDeviceSelectLabel(ui, "no device selected");
+}
+
+function* testChangingDevice(ui) {
+  info("Test Changing Device");
+
+  yield selectDevice(ui, testDevice.name);
+  yield waitForViewportResizeTo(ui, testDevice.width, testDevice.height);
+  yield testTouchEventsOverride(ui, true);
+  testViewportDeviceSelectLabel(ui, testDevice.name);
+}
+
+function* testResizingViewport(ui, device, expected) {
+  info(`Test resizing the viewport, device ${device}, expected ${expected}`);
+
+  let deviceRemoved = once(ui, "device-removed");
+  yield testViewportResize(ui, ".viewport-vertical-resize-handle",
+    [-10, -10], [testDevice.width, testDevice.height - 10], [0, -10], ui);
+  if (device) {
+    yield deviceRemoved;
+  }
+  yield testTouchEventsOverride(ui, expected);
+  testViewportDeviceSelectLabel(ui, "no device selected");
+}
+
+function* testEnableTouchSimulation(ui) {
+  info("Test enabling touch simulation via button");
+
+  yield enableTouchSimulation(ui);
+  yield 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
@@ -166,28 +166,28 @@ function* testWithMetaViewportDisabled(u
       "300ms delay between touch events and mouse events should work");
   });
 }
 
 function testTouchButton(ui) {
   let { document } = ui.toolWindow;
   let touchButton = document.querySelector("#global-touch-simulation-button");
 
+  ok(touchButton.classList.contains("active"),
+    "Touch simulation is active at end of test.");
+
+  touchButton.click();
+
   ok(!touchButton.classList.contains("active"),
-    "Touch simulation is not active by default.");
+    "Touch simulation is stopped on click.");
 
   touchButton.click();
 
   ok(touchButton.classList.contains("active"),
     "Touch simulation is started on click.");
-
-  touchButton.click();
-
-  ok(!touchButton.classList.contains("active"),
-    "Touch simulation is stopped on click.");
 }
 
 function* waitBootstrap(ui) {
   let { store } = ui.toolWindow;
 
   yield waitUntilState(store, state => state.viewports.length == 1);
   yield waitForFrameLoad(ui, TEST_URL);
 }
@@ -221,20 +221,8 @@ function* injectEventUtils(ui) {
       EventUtils.synthesizeMouseAtCenter(element,
         { type: "mouseup", isSynthesized: false }, content);
     });
 
     Services.scriptloader.loadSubScript(
       "chrome://mochikit/content/tests/SimpleTest/EventUtils.js", EventUtils);
   });
 }
-
-const enableTouchSimulation = ui => new Promise(
-  Task.async(function* (resolve) {
-    let browser = ui.getViewportBrowser();
-
-    browser.addEventListener("mozbrowserloadend", function onLoad() {
-      browser.removeEventListener("mozbrowserloadend", onLoad);
-      resolve();
-    });
-
-    yield ui.updateTouchSimulation(true);
-  }));
--- a/devtools/client/responsive.html/test/browser/head.js
+++ b/devtools/client/responsive.html/test/browser/head.js
@@ -207,22 +207,19 @@ function dragElementBy(selector, x, y, w
   EventUtils.synthesizeMouseAtPoint(...endPoint, { type: "mouseup" }, win);
 
   return rect;
 }
 
 function* testViewportResize(ui, selector, moveBy,
                              expectedViewportSize, expectedHandleMove) {
   let win = ui.toolWindow;
-
-  let changed = once(ui, "device-changed");
   let resized = waitForViewportResizeTo(ui, ...expectedViewportSize);
   let startRect = dragElementBy(selector, ...moveBy, win);
   yield resized;
-  yield changed;
 
   let 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`);
 }
 
@@ -324,16 +321,25 @@ function waitForPageShow(browser) {
       }
       mm.removeMessageListener("PageVisibility:Show", onShow);
       resolve();
     };
     mm.addMessageListener("PageVisibility:Show", onShow);
   });
 }
 
+function waitForViewportLoad(ui) {
+  return new Promise(resolve => {
+    let browser = ui.getViewportBrowser();
+    browser.addEventListener("mozbrowserloadend", () => {
+      resolve();
+    }, { once: true });
+  });
+}
+
 function load(browser, url) {
   let loaded = BrowserTestUtils.browserLoaded(browser, false, url);
   browser.loadURI(url, null, null);
   return loaded;
 }
 
 function back(browser) {
   let shown = waitForPageShow(browser);
@@ -358,8 +364,35 @@ function addDeviceForTest(device) {
 }
 
 function waitForClientClose(ui) {
   return new Promise(resolve => {
     info("RDM's debugger client is now closed");
     ui.client.addOneTimeListener("closed", resolve);
   });
 }
+
+function* testTouchEventsOverride(ui, expected) {
+  let { document } = ui.toolWindow;
+  let touchButton = document.querySelector("#global-touch-simulation-button");
+
+  let flag = yield ui.emulationFront.getTouchEventsOverride();
+  is(flag === Ci.nsIDocShell.TOUCHEVENTS_OVERRIDE_ENABLED, expected,
+    `Touch events override should be ${expected ? "enabled" : "disabled"}`);
+  is(touchButton.classList.contains("active"), expected,
+    `Touch simulation button should be ${expected ? "" : "in"}active.`);
+}
+
+function testViewportDeviceSelectLabel(ui, expected) {
+  info("Test viewport's device select label");
+
+  let select = ui.toolWindow.document.querySelector(".viewport-device-selector");
+  is(select.selectedOptions[0].textContent, expected,
+     `Device Select value should be: ${expected}`);
+}
+
+function* enableTouchSimulation(ui) {
+  let { document } = ui.toolWindow;
+  let touchButton = document.querySelector("#global-touch-simulation-button");
+  let loaded = waitForViewportLoad(ui);
+  touchButton.click();
+  yield loaded;
+}