Bug 1270494 - fix autocomplete popup offset for multiple values input;r=pbro
authorJulian Descottes <jdescottes@mozilla.com>
Mon, 06 Jun 2016 12:10:13 +0200
changeset 376743 daadc8567a11c6165986c05719fa44a7ed8af839
parent 376742 5753eb3ec41884030a12d9df006ee8fced481ca5
child 376744 023f2190e75d248bb5631729a3f837911b6e22c3
child 376752 fcd8a5d33cb63d088911f02c601145f2829106ec
child 376788 228f8a4aee5948e49623e4b4ef23d18cf206f0e9
child 376792 2c144b2500080730c8a9d003d4f49f5612d044c2
child 376828 e344323830ed02563fdd99f86cd9919d4aca3091
child 376838 58275e2be1c182d3438e7897235675d5dcff1355
child 376928 77bfa81d1891eff2fef44bf3205e7220f29f4c1f
child 376947 fe9a1e49732526d331f1039878959610913ade22
child 376948 88c595861c0d97b147a5ae26844f59cb9dc59129
child 376949 de658b500f72f907847982af38ec72f60e9f6c5f
child 377015 350806825763ca69895a32a0ad6c2fc14b89aa3c
child 377087 414bd08dd970dc720ae929e03f7f4cc8315e49db
child 377887 c5f40b735bc04d98c21f9a9ed288ed5d27995272
child 378024 096773978afdeab6be5f6b0cdef1aa8736601020
push id20653
push userchevobbe.nicolas@gmail.com
push dateWed, 08 Jun 2016 15:36:47 +0000
reviewerspbro
bugs1270494, 1168246
milestone50.0a1
Bug 1270494 - fix autocomplete popup offset for multiple values input;r=pbro Fixed regression from Bug 1168246 and added a unit test to loosely check that the autocomplete popup moves along with autocompleted query. MozReview-Commit-ID: H7t5WjkwBE4
devtools/client/shared/inplace-editor.js
devtools/client/shared/test/browser.ini
devtools/client/shared/test/browser_inplace-editor_autocomplete_01.js
devtools/client/shared/test/browser_inplace-editor_autocomplete_02.js
devtools/client/shared/test/browser_inplace-editor_autocomplete_offset.js
--- a/devtools/client/shared/inplace-editor.js
+++ b/devtools/client/shared/inplace-editor.js
@@ -1426,17 +1426,17 @@ InplaceEditor.prototype = {
         input.setSelectionRange(query.length, query.length + item.length -
                                               startCheckQuery.length);
         this._updateSize();
       }
 
       // Display the list of suggestions if there are more than one.
       if (finalList.length > 1) {
         // Calculate the popup horizontal offset.
-        let indent = this.input.selectionStart - query.length;
+        let indent = this.input.selectionStart - startCheckQuery.length;
         let offset = indent * this.inputCharDimensions.width;
         offset = this._isSingleLine() ? offset : 0;
 
         // Select the most relevantItem if autoInsert is allowed
         let selectedIndex = autoInsert ? index : -1;
 
         // Open the suggestions popup.
         this.popup.setItems(finalList);
--- a/devtools/client/shared/test/browser.ini
+++ b/devtools/client/shared/test/browser.ini
@@ -119,16 +119,17 @@ skip-if = e10s # Bug 1221911, bug 122228
 [browser_html_tooltip-04.js]
 [browser_html_tooltip-05.js]
 [browser_html_tooltip_arrow-01.js]
 [browser_html_tooltip_arrow-02.js]
 [browser_inplace-editor-01.js]
 [browser_inplace-editor-02.js]
 [browser_inplace-editor_autocomplete_01.js]
 [browser_inplace-editor_autocomplete_02.js]
+[browser_inplace-editor_autocomplete_offset.js]
 [browser_inplace-editor_maxwidth.js]
 [browser_key_shortcuts.js]
 [browser_layoutHelpers.js]
 skip-if = e10s # Layouthelpers test should not run in a content page.
 [browser_layoutHelpers-getBoxQuads.js]
 skip-if = e10s # Layouthelpers test should not run in a content page.
 [browser_mdn-docs-01.js]
 [browser_mdn-docs-02.js]
--- a/devtools/client/shared/test/browser_inplace-editor_autocomplete_01.js
+++ b/devtools/client/shared/test/browser_inplace-editor_autocomplete_01.js
@@ -8,16 +8,23 @@
 const { InplaceEditor } = require("devtools/client/shared/inplace-editor");
 const { AutocompletePopup } = require("devtools/client/shared/autocomplete-popup");
 loadHelperScript("helper_inplace_editor.js");
 
 // Test the inplace-editor autocomplete popup for CSS properties suggestions.
 // Using a mocked list of CSS properties to avoid test failures linked to
 // engine changes (new property, removed property, ...).
 
+// format :
+//  [
+//    what key to press,
+//    expected input box value after keypress,
+//    selected suggestion index (-1 if popup is hidden),
+//    number of suggestions in the popup (0 if popup is hidden),
+//  ]
 const testData = [
   ["b", "border", 1, 3],
   ["VK_DOWN", "box-sizing", 2, 3],
   ["VK_DOWN", "background", 0, 3],
   ["VK_DOWN", "border", 1, 3],
   ["VK_BACK_SPACE", "b", -1, 0],
   ["VK_BACK_SPACE", "", -1, 0],
   ["VK_DOWN", "background", 0, 6],
--- a/devtools/client/shared/test/browser_inplace-editor_autocomplete_02.js
+++ b/devtools/client/shared/test/browser_inplace-editor_autocomplete_02.js
@@ -8,16 +8,23 @@
 const { InplaceEditor } = require("devtools/client/shared/inplace-editor");
 const { AutocompletePopup } = require("devtools/client/shared/autocomplete-popup");
 loadHelperScript("helper_inplace_editor.js");
 
 // Test the inplace-editor autocomplete popup for CSS values suggestions.
 // Using a mocked list of CSS properties to avoid test failures linked to
 // engine changes (new property, removed property, ...).
 
+// format :
+//  [
+//    what key to press,
+//    expected input box value after keypress,
+//    selected suggestion index (-1 if popup is hidden),
+//    number of suggestions in the popup (0 if popup is hidden),
+//  ]
 const testData = [
   ["b", "block", -1, 0],
   ["VK_BACK_SPACE", "b", -1, 0],
   ["VK_BACK_SPACE", "", -1, 0],
   ["i", "inline", 0, 2],
   ["VK_DOWN", "inline-block", 1, 2],
   ["VK_DOWN", "inline", 0, 2],
   ["VK_LEFT", "inline", -1, 0],
new file mode 100644
--- /dev/null
+++ b/devtools/client/shared/test/browser_inplace-editor_autocomplete_offset.js
@@ -0,0 +1,111 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+/* import-globals-from helper_inplace_editor.js */
+
+"use strict";
+
+const { InplaceEditor } = require("devtools/client/shared/inplace-editor");
+const { AutocompletePopup } = require("devtools/client/shared/autocomplete-popup");
+loadHelperScript("helper_inplace_editor.js");
+
+// Test the inplace-editor autocomplete popup is aligned with the completed query.
+// Which means when completing "style=display:flex; color:" the popup will aim to be
+// aligned with the ":" next to "color".
+
+// format :
+//  [
+//    what key to press,
+//    expected input box value after keypress,
+//    selected suggestion index (-1 if popup is hidden),
+//    number of suggestions in the popup (0 if popup is hidden),
+//  ]
+// or
+//  ["checkPopupOffset"]
+// to measure and test the autocomplete popup left offset.
+const testData = [
+  ["VK_RIGHT", "style=", -1, 0],
+  ["d", "style=display", 1, 2],
+  ["checkPopupOffset"],
+  ["VK_RIGHT", "style=display", -1, 0],
+  [":", "style=display:block", 0, 3],
+  ["checkPopupOffset"],
+  ["f", "style=display:flex", -1, 0],
+  ["VK_RIGHT", "style=display:flex", -1, 0],
+  [";", "style=display:flex;", -1, 0],
+  ["c", "style=display:flex;color", 1, 2],
+  ["checkPopupOffset"],
+  ["VK_RIGHT", "style=display:flex;color", -1, 0],
+  [":", "style=display:flex;color:blue", 0, 2],
+  ["checkPopupOffset"],
+];
+
+const mockGetCSSPropertyList = function () {
+  return [
+    "clear",
+    "color",
+    "direction",
+    "display",
+  ];
+};
+
+const mockGetCSSValuesForPropertyName = function (propertyName) {
+  let values = {
+    "color": ["blue", "red"],
+    "display": ["block", "flex", "none"]
+  };
+  return values[propertyName] || [];
+};
+
+add_task(function* () {
+  yield addTab("data:text/html;charset=utf-8,inplace editor CSS value autocomplete");
+  let [host, win, doc] = yield createHost();
+
+  let xulDocument = win.top.document;
+  let popup = new AutocompletePopup(xulDocument, { autoSelect: true });
+
+  info("Create a CSS_MIXED type autocomplete");
+  yield new Promise(resolve => {
+    createInplaceEditorAndClick({
+      initial: "style=",
+      start: runAutocompletionTest,
+      contentType: InplaceEditor.CONTENT_TYPES.CSS_MIXED,
+      done: resolve,
+      popup: popup
+    }, doc);
+  });
+
+  host.destroy();
+  gBrowser.removeCurrentTab();
+});
+
+let runAutocompletionTest = Task.async(function* (editor) {
+  info("Starting autocomplete test for inplace-editor popup offset");
+  editor._getCSSPropertyList = mockGetCSSPropertyList;
+  editor._getCSSValuesForPropertyName = mockGetCSSValuesForPropertyName;
+
+  let previousOffset = -1;
+  for (let data of testData) {
+    if (data[0] === "checkPopupOffset") {
+      info("Check the popup offset has been modified");
+      // We are not testing hard coded offset values here, which could be fragile. We only
+      // want to ensure the popup tries to match the position of the query in the editor
+      // input.
+      let offset = getPopupOffset(editor);
+      ok(offset > previousOffset, "New popup offset is greater than the previous one");
+      previousOffset = offset;
+    } else {
+      yield testCompletion(data, editor);
+    }
+  }
+
+  EventUtils.synthesizeKey("VK_RETURN", {}, editor.input.defaultView);
+});
+
+/**
+ * Get the autocomplete panel left offset, relative to the provided input's left offset.
+ */
+function getPopupOffset({popup, input}) {
+  let popupQuads = popup._panel.getBoxQuads({relativeTo: input});
+  return popupQuads[0].bounds.left;
+}