Bug 1143742 - part4: add textarea to valid targets when copying;r=gl draft
authorJulian Descottes <jdescottes@mozilla.com>
Wed, 30 Mar 2016 16:39:33 +0200
changeset 346100 0ed4c0139a31bb7cf1a4006418d91571a87271ab
parent 346099 80195d4d45891552c0781208cf737f416828abc9
child 517325 494210f13f28c9ff20105b6121ed414b6ccdb947
push id14240
push userjdescottes@mozilla.com
push dateWed, 30 Mar 2016 23:01:44 +0000
reviewersgl
bugs1143742
milestone48.0a1
Bug 1143742 - part4: add textarea to valid targets when copying;r=gl When opening the context menu (and displaying the "copy" menu entry) or when receiving a copy event, we now check if the current target is a textarea. (multiline inplace editor relies on textarea) Modified existing test to check this new use case. MozReview-Commit-ID: Cgm67JCdN4c
devtools/client/inspector/rules/rules.js
devtools/client/inspector/rules/test/browser_rules_select-and-copy-styles.js
devtools/client/inspector/shared/style-inspector-menu.js
--- a/devtools/client/inspector/rules/rules.js
+++ b/devtools/client/inspector/rules/rules.js
@@ -457,17 +457,18 @@ CssRuleView.prototype = {
    *
    * @param {DOMNode} target
    *        DOMNode target of the copy action
    */
   copySelection: function(target) {
     try {
       let text = "";
 
-      if (target && target.nodeName === "input") {
+      let nodeName = target && target.nodeName;
+      if (nodeName === "input" || nodeName == "textarea") {
         let start = Math.min(target.selectionStart, target.selectionEnd);
         let end = Math.max(target.selectionStart, target.selectionEnd);
         let count = end - start;
         text = target.value.substr(start, count);
       } else {
         text = this.styleWindow.getSelection().toString();
 
         // Remove any double newlines.
--- a/devtools/client/inspector/rules/test/browser_rules_select-and-copy-styles.js
+++ b/devtools/client/inspector/rules/test/browser_rules_select-and-copy-styles.js
@@ -39,16 +39,17 @@ const TEST_URI = `
 `;
 
 add_task(function*() {
   yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
   let {inspector, view} = yield openRuleView();
   yield selectNode("div", inspector);
   yield checkCopySelection(view);
   yield checkSelectAll(view);
+  yield checkCopyEditorValue(view);
 });
 
 function* checkCopySelection(view) {
   info("Testing selection copy");
 
   let contentDoc = view.styleDocument;
   let win = view.styleWindow;
   let prop = contentDoc.querySelector(".ruleview-property");
@@ -70,17 +71,17 @@ function* checkCopySelection(view) {
                         "    color: #000000;[\\r\\n]*";
 
   let onPopup = once(view._contextmenu._menupopup, "popupshown");
   EventUtils.synthesizeMouseAtCenter(prop,
     {button: 2, type: "contextmenu"}, win);
   yield onPopup;
 
   ok(!view._contextmenu.menuitemCopy.hidden,
-    "Copy menu item is not hidden as expected");
+    "Copy menu item is displayed as expected");
 
   try {
     yield waitForClipboard(() => view._contextmenu.menuitemCopy.click(),
       () => checkClipboardData(expectedPattern));
   } catch (e) {
     failedClipboard(expectedPattern);
   }
 
@@ -108,28 +109,66 @@ function* checkSelectAll(view) {
                         "}[\\r\\n]*";
 
   let onPopup = once(view._contextmenu._menupopup, "popupshown");
   EventUtils.synthesizeMouseAtCenter(prop,
     {button: 2, type: "contextmenu"}, win);
   yield onPopup;
 
   ok(!view._contextmenu.menuitemCopy.hidden,
-    "Copy menu item is not hidden as expected");
+    "Copy menu item is displayed as expected");
 
   try {
     yield waitForClipboard(() => view._contextmenu.menuitemCopy.click(),
       () => checkClipboardData(expectedPattern));
   } catch (e) {
     failedClipboard(expectedPattern);
   }
 
   view._contextmenu._menupopup.hidePopup();
 }
 
+function* checkCopyEditorValue(view) {
+  info("Testing CSS property editor value copy");
+
+  let win = view.styleWindow;
+  let ruleEditor = getRuleViewRuleEditor(view, 0);
+  let propEditor = ruleEditor.rule.textProps[0].editor;
+
+  let editor = yield focusEditableField(view, propEditor.valueSpan);
+
+  info("Checking that copying a css property value editor returns the correct" +
+    " clipboard value");
+
+  let expectedPattern = "10em";
+
+  let onPopup = once(view._contextmenu._menupopup, "popupshown");
+  EventUtils.synthesizeMouseAtCenter(editor.input,
+    {button: 2, type: "contextmenu"}, win);
+  yield onPopup;
+
+  ok(!view._contextmenu.menuitemCopy.hidden,
+    "Copy menu item is displayed as expected");
+
+  try {
+    yield waitForClipboard(() => view._contextmenu.menuitemCopy.click(),
+      () => checkClipboardData(expectedPattern));
+  } catch (e) {
+    failedClipboard(expectedPattern);
+  }
+
+  view._contextmenu._menupopup.hidePopup();
+
+  // The value field is still focused. Blur it now and wait for the
+  // ruleview-changed event to avoid pending requests.
+  let onRuleViewChanged = view.once("ruleview-changed");
+  EventUtils.synthesizeKey("VK_ESCAPE", {});
+  yield onRuleViewChanged;
+}
+
 function checkClipboardData(expectedPattern) {
   let actual = SpecialPowers.getClipboardData("text/unicode");
   let expectedRegExp = new RegExp(expectedPattern, "g");
   return expectedRegExp.test(actual);
 }
 
 function failedClipboard(expectedPattern) {
   // Format expected text for comparison
--- a/devtools/client/inspector/shared/style-inspector-menu.js
+++ b/devtools/client/inspector/shared/style-inspector-menu.js
@@ -271,18 +271,17 @@ StyleInspectorMenu.prototype = {
     }
   },
 
   _hasTextSelected: function() {
     let hasTextSelected;
     let selection = this.styleWindow.getSelection();
 
     let node = this._getClickedNode();
-    if (node.nodeName == "input") {
-       // input type="text"
+    if (node.nodeName == "input" || node.nodeName == "textarea") {
       let { selectionStart, selectionEnd } = node;
       hasTextSelected = isFinite(selectionStart) && isFinite(selectionEnd)
         && selectionStart !== selectionEnd;
     } else {
       hasTextSelected = selection.toString() && !selection.isCollapsed;
     }
 
     return hasTextSelected;