Backed out 3 changesets (bug 1479521) for webconsole/autocomplete.js failures CLOSED TREE
authorBogdan Tara <btara@mozilla.com>
Fri, 10 Aug 2018 20:27:45 +0300
changeset 486095 5f7aa22e5ee66a9b4644273066d0d8c02825c3e5
parent 486094 818a07277354cacbf0956fdaed0100771dde3a92
child 486096 39a528147c34c988e990e9b7675f5a21e7756b10
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1479521
milestone63.0a1
backs outce455e421b0b4656a66dca47b004ba61669ba022
618fe87eb9f0f55f7b9e35d2fcb7e69649e9fb4b
67fc7d23d665f175f6f61448a5afbbb9f712395b
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
Backed out 3 changesets (bug 1479521) for webconsole/autocomplete.js failures CLOSED TREE Backed out changeset ce455e421b0b (bug 1479521) Backed out changeset 618fe87eb9f0 (bug 1479521) Backed out changeset 67fc7d23d665 (bug 1479521)
devtools/client/webconsole/components/JSTerm.js
devtools/client/webconsole/test/mochitest/browser.ini
devtools/client/webconsole/test/mochitest/browser_jsterm_accessibility.js
devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete-properties-with-non-alphanumeric-names.js
devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_cached_results.js
devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_extraneous_closing_brackets.js
devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_helpers.js
devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_in_chrome_tab.js
devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_in_debugger_stackframe.js
devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_inside_text.js
devtools/client/webconsole/test/mochitest/browser_jsterm_completion.js
devtools/client/webconsole/test/mochitest/browser_jsterm_content_defined_helpers.js
devtools/client/webconsole/test/mochitest/browser_jsterm_no_autocompletion_on_defined_variables.js
devtools/client/webconsole/test/mochitest/browser_webconsole_closing_after_completion.js
devtools/client/webconsole/test/mochitest/browser_webconsole_split_escape_key.js
devtools/client/webconsole/test/mochitest/head.js
devtools/shared/webconsole/test/test_jsterm_autocomplete.html
--- a/devtools/client/webconsole/components/JSTerm.js
+++ b/devtools/client/webconsole/components/JSTerm.js
@@ -1403,20 +1403,19 @@ class JSTerm extends Component {
   /**
    * Update the node that displays the currently selected autocomplete proposal.
    *
    * @param string suffix
    *        The proposed suffix for the inputNode value.
    */
   updateCompleteNode(suffix) {
     if (this.completeNode) {
-      const lines = this.getInputValueBeforeCursor().split("\n");
-      const lastLine = lines[lines.length - 1];
-      const prefix = ("\n".repeat(lines.length - 1)) + lastLine.replace(/[\S]/g, " ");
-      this.completeNode.value = suffix ? prefix + suffix : "";
+      // completion prefix = input, with non-control chars replaced by spaces
+      const prefix = suffix ? this.getInputValue().replace(/[\S]/g, " ") : "";
+      this.completeNode.value = prefix + suffix;
     }
 
     if (this.editor) {
       this.editor.setAutoCompletionText(suffix);
     }
   }
 
   /**
--- a/devtools/client/webconsole/test/mochitest/browser.ini
+++ b/devtools/client/webconsole/test/mochitest/browser.ini
@@ -219,16 +219,17 @@ skip-if = os != 'mac' # The tested ctrl+
 [browser_jsterm_hide_when_devtools_chrome_enabled_false.js]
 [browser_jsterm_history.js]
 [browser_jsterm_history_arrow_keys.js]
 [browser_jsterm_history_nav.js]
 [browser_jsterm_history_persist.js]
 [browser_jsterm_inspect.js]
 [browser_jsterm_instance_of.js]
 [browser_jsterm_multiline.js]
+[browser_jsterm_no_autocompletion_on_defined_variables.js]
 [browser_jsterm_no_input_and_tab_key_pressed.js]
 [browser_jsterm_null_undefined.js]
 [browser_jsterm_popup_close_on_tab_switch.js]
 [browser_jsterm_screenshot_command_clipboard.js]
 subsuite = clipboard
 [browser_jsterm_screenshot_command_user.js]
 subsuite = clipboard
 [browser_jsterm_screenshot_command_file.js]
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_accessibility.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_accessibility.js
@@ -6,35 +6,31 @@
 // Tests that the autocomplete input is being blurred and focused when selecting a value.
 // This will help screen-readers notify users of the value that was set in the input.
 
 "use strict";
 
 const TEST_URI = "data:text/html;charset=utf8,<p>test code completion";
 
 add_task(async function() {
-  // Only run test with legacy JsTerm
-  await pushPref("devtools.webconsole.jsterm.codeMirror", false);
+  const hud = await openNewTabAndConsole(TEST_URI);
 
-  const {jsterm} = await openNewTabAndConsole(TEST_URI);
+  const jsterm = hud.jsterm;
   const input = jsterm.inputNode;
 
   info("Test that the console input is not treated as a live region");
   ok(!isElementInLiveRegion(input), "Console input is not treated as a live region");
 
   info("Test the console input has no aria-activedescendant attribute");
   ok(!input.hasAttribute("aria-activedescendant"), "no aria-activedescendant");
 
   info("Type 'd' to open the autocomplete popup");
-  const {autocompletePopup} = jsterm;
-  const onPopupOpen = autocompletePopup.once("popup-opened");
-  EventUtils.sendString("d");
+  const onPopupOpen = jsterm.autocompletePopup.once("popup-opened");
+  autocomplete(jsterm, "d");
   await onPopupOpen;
-  ok(autocompletePopup.isOpen && autocompletePopup.itemCount > 0,
-    "Autocomplete popup is open and contains suggestions");
 
   info("Test the console input has an aria-activedescendant attribute");
   ok(input.hasAttribute("aria-activedescendant"), "aria-activedescendant");
 
   // Add listeners for focus and blur events.
   let wasBlurred = false;
   input.addEventListener("blur", () => {
     wasBlurred = true;
@@ -58,16 +54,28 @@ add_task(async function() {
   await onPopupClosed;
 
   ok(wasFocused, "jsterm input received a focus event");
 
   info("Test the console input has no aria-activedescendant attribute no more");
   ok(!input.hasAttribute("aria-activedescendant"), "no aria-activedescendant");
 });
 
+async function autocomplete(jsterm, value) {
+  const popup = jsterm.autocompletePopup;
+
+  await new Promise(resolve => {
+    jsterm.setInputValue(value);
+    jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve);
+  });
+
+  ok(popup.isOpen && popup.itemCount > 0,
+    "Autocomplete popup is open and contains suggestions");
+}
+
 function isElementInLiveRegion(element) {
   if (!element) {
     return false;
   }
 
   if (element.hasAttribute("aria-live")) {
     return element.getAttribute("aria-live") !== "off";
   }
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete-properties-with-non-alphanumeric-names.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete-properties-with-non-alphanumeric-names.js
@@ -35,12 +35,14 @@ async function performTests() {
   await jsterm.execute("let foobar = {a: ''}; const blargh = {a: 1};");
   await testAutocomplete(jsterm, "foobar");
   await testAutocomplete(jsterm, "blargh");
   await testAutocomplete(jsterm, "foobar.a");
   await testAutocomplete(jsterm, "blargh.a");
 }
 
 async function testAutocomplete(jsterm, inputString) {
-  await setInputValueForAutocompletion(jsterm, inputString);
+  jsterm.setInputValue(inputString);
+  await new Promise(resolve => jsterm.complete(jsterm.COMPLETE_HINT_ONLY, resolve));
+
   const popup = jsterm.autocompletePopup;
   ok(popup.itemCount > 0, `There's ${popup.itemCount} suggestions for '${inputString}'`);
 }
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_cached_results.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_cached_results.js
@@ -19,17 +19,17 @@ add_task(async function() {
   await performTests();
 });
 
 async function performTests() {
   const { jsterm } = await openNewTabAndConsole(TEST_URI);
   const { autocompletePopup: popup } = jsterm;
 
   const jstermComplete = (value, caretPosition) =>
-    setInputValueForAutocompletion(jsterm, value, caretPosition);
+    jstermSetValueAndComplete(jsterm, value, caretPosition);
 
   // Test if 'doc' gives 'document'
   await jstermComplete("doc");
   is(jsterm.getInputValue(), "doc", "'docu' completion (input.value)");
   checkJsTermCompletionValue(jsterm, "   ument", "'docu' completion (completeNode)");
 
   // Test typing 'window.'.'
   await jstermComplete("window.");
@@ -71,31 +71,27 @@ async function performTests() {
   ok(getPopupLabels(popup).includes("getComputedStyle"),
     "autocomplete results do contain getComputedStyle");
 
   // Test if 'dump(d' gives non-zero results
   await jstermComplete("dump(d");
   ok(popup.getItems().length > 0, "'dump(d' gives non-zero results");
 
   // Test that 'dump(window.)' works.
-  await jstermComplete("dump(window)", -1);
-  onUpdated = jsterm.once("autocomplete-updated");
-  EventUtils.sendString(".");
-  await onUpdated;
+  await jstermComplete("dump(window.)", -1);
   ok(popup.getItems().length > 0, "'dump(window.' gave a list of suggestions");
 
   info("Add a property on the window object");
   await ContentTask.spawn(gBrowser.selectedBrowser, {}, () => {
     content.wrappedJSObject.window.docfoobar = true;
   });
 
   // Make sure 'dump(window.d)' does not contain 'docfoobar'.
   onUpdated = jsterm.once("autocomplete-updated");
-  EventUtils.sendString("d");
+  EventUtils.synthesizeKey("d");
   await onUpdated;
-
   ok(!getPopupLabels(popup).includes("docfoobar"),
     "autocomplete cached results do not contain docfoobar. list has not been updated");
 }
 
 function getPopupLabels(popup) {
   return popup.getItems().map(item => item.label);
 }
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_extraneous_closing_brackets.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_extraneous_closing_brackets.js
@@ -18,14 +18,14 @@ add_task(async function() {
   await pushPref("devtools.webconsole.jsterm.codeMirror", true);
   await performTests();
 });
 
 async function performTests() {
   const { jsterm } = await openNewTabAndConsole(TEST_URI);
 
   try {
-    await setInputValueForAutocompletion(jsterm, "document.getElementById)");
+    await jstermSetValueAndComplete(jsterm, "document.getElementById)");
     ok(true, "no error was thrown when an extraneous bracket was inserted");
   } catch (ex) {
     ok(false, "an error was thrown when an extraneous bracket was inserted");
   }
 }
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_helpers.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_helpers.js
@@ -23,20 +23,23 @@ async function performTests() {
   const {jsterm} = await openNewTabAndConsole(TEST_URI);
   await testInspectAutoCompletion(jsterm, "i", true);
   await testInspectAutoCompletion(jsterm, "window.", false);
   await testInspectAutoCompletion(jsterm, "dump(i", true);
   await testInspectAutoCompletion(jsterm, "window.dump(i", true);
 }
 
 async function testInspectAutoCompletion(jsterm, inputValue, expectInspect) {
-  jsterm.setInputValue("");
-  jsterm.focus();
-  const updated = jsterm.once("autocomplete-updated");
-  EventUtils.sendString(inputValue);
-  await updated;
+  jsterm.setInputValue(inputValue);
+  await complete(jsterm);
   is(getPopupItemsLabel(jsterm.autocompletePopup).includes("inspect"), expectInspect,
     `autocomplete results${expectInspect ? "" : " does not"} contain helper 'inspect'`);
 }
 
+function complete(jsterm) {
+  const updated = jsterm.once("autocomplete-updated");
+  jsterm.complete(jsterm.COMPLETE_HINT_ONLY);
+  return updated;
+}
+
 function getPopupItemsLabel(popup) {
   return popup.getItems().map(item => item.label);
 }
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_in_chrome_tab.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_in_chrome_tab.js
@@ -21,11 +21,11 @@ async function performTests() {
   ok(hud, "we have a console");
   ok(hud.iframeWindow, "we have the console UI window");
 
   const {jsterm} = hud;
   ok(jsterm, "we have a jsterm");
   ok(hud.outputNode, "we have an output node");
 
   // Test typing 'docu'.
-  await setInputValueForAutocompletion(jsterm, "docu");
+  await jstermSetValueAndComplete(jsterm, "docu");
   checkJsTermCompletionValue(jsterm, "    ment", "'docu' completion");
 }
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_in_debugger_stackframe.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_in_debugger_stackframe.js
@@ -27,17 +27,17 @@ async function performTests() {
   const { jsterm } = await openNewTabAndConsole(TEST_URI);
   const {
     autocompletePopup: popup,
   } = jsterm;
 
   const target = TargetFactory.forTab(gBrowser.selectedTab);
   const toolbox = gDevTools.getToolbox(target);
 
-  const jstermComplete = value => setInputValueForAutocompletion(jsterm, value);
+  const jstermComplete = value => jstermSetValueAndComplete(jsterm, value);
 
   // Test that document.title gives string methods. Native getters must execute.
   await jstermComplete("document.title.");
 
   const newItemsLabels = getPopupLabels(popup);
   ok(newItemsLabels.length > 0, "'document.title.' gave a list of suggestions");
   ok(newItemsLabels.includes("substr"), `results do contain "substr"`);
   ok(newItemsLabels.includes("toLowerCase"), `results do contain "toLowerCase"`);
@@ -45,17 +45,16 @@ async function performTests() {
 
   // Test if 'foo' gives 'foo1' but not 'foo2' or 'foo3'
   await jstermComplete("foo");
   is(getPopupLabels(popup).join("-"), "foo1-foo1Obj",
     `"foo" gave the expected suggestions`);
 
   // Test if 'foo1Obj.' gives 'prop1' and 'prop2'
   await jstermComplete("foo1Obj.");
-  checkJsTermCompletionValue(jsterm, "        prop1", "foo1Obj completion");
   is(getPopupLabels(popup).join("-"), "prop1-prop2",
     `"foo1Obj." gave the expected suggestions`);
 
   // Test if 'foo1Obj.prop2.' gives 'prop21'
   await jstermComplete("foo1Obj.prop2.");
   ok(getPopupLabels(popup).includes("prop21"),
     `"foo1Obj.prop2." gave the expected suggestions`);
 
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_inside_text.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_autocomplete_inside_text.js
@@ -1,28 +1,22 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-// Test that editing text inside parens behave as expected, i.e.
-// - it does not show the autocompletion text
-// - show popup when there's properties to complete
-// - insert the selected item from the popup in the input
-// - right arrow dismiss popup and don't autocomplete
-// - tab key when there is not visible autocomplete suggestion insert a tab
-// See Bug 812618, 1479521 and 1334130.
+// See Bug 812618.
 
 const TEST_URI = `data:text/html;charset=utf-8,
 <head>
   <script>
-    window.testBugAA = "hello world";
-    window.testBugBB = "hello world 2";
+    window.testBugA = "hello world";
+    window.testBugB = "hello world 2";
   </script>
 </head>
 <body>bug 812618 - test completion inside text</body>`;
 
 add_task(async function() {
   // Run test with legacy JsTerm
   await pushPref("devtools.webconsole.jsterm.codeMirror", false);
   await performTests();
@@ -32,83 +26,40 @@ add_task(async function() {
 });
 
 async function performTests() {
   const { jsterm } = await openNewTabAndConsole(TEST_URI);
   info("web console opened");
 
   const { autocompletePopup: popup } = jsterm;
 
-  await setInitialState(jsterm);
+  const onPopUpOpen = popup.once("popup-opened");
+
+  const dumpString = "dump(window.testBu)";
+  jstermSetValueAndComplete(jsterm, dumpString, -1);
+
+  await onPopUpOpen;
 
   ok(popup.isOpen, "popup is open");
   is(popup.itemCount, 2, "popup.itemCount is correct");
   is(popup.selectedIndex, 0, "popup.selectedIndex is correct");
-  ok(!getJsTermCompletionValue(jsterm), "there is no completion text");
 
-  info("Pressing arrow right");
-  let onPopupClose = popup.once("popup-closed");
-  EventUtils.synthesizeKey("KEY_ArrowRight");
-  await onPopupClose;
-  ok(true, "popup was closed");
-  let expectedInput = "dump(window.testB)";
-  is(jsterm.getInputValue(), expectedInput, "input wasn't modified");
-  checkJsTermCursor(jsterm, expectedInput.length, "cursor was moved to the right");
-
-  await setInitialState(jsterm);
   EventUtils.synthesizeKey("KEY_ArrowDown");
   is(popup.selectedIndex, 1, "popup.selectedIndex is correct");
   ok(!getJsTermCompletionValue(jsterm), "completeNode.value is empty");
 
   const items = popup.getItems().map(e => e.label);
-  const expectedItems = ["testBugAA", "testBugBB"];
+  const expectedItems = ["testBugA", "testBugB"];
   is(items.join("-"), expectedItems.join("-"), "getItems returns the items we expect");
 
   info("press Tab and wait for popup to hide");
-  onPopupClose = popup.once("popup-closed");
+  const onPopupClose = popup.once("popup-closed");
   EventUtils.synthesizeKey("KEY_Tab");
+
   await onPopupClose;
 
   // At this point the completion suggestion should be accepted.
   ok(!popup.isOpen, "popup is not open");
-  expectedInput = "dump(window.testBugBB)";
+  const expectedInput = "dump(window.testBugB)";
   is(jsterm.getInputValue(), expectedInput, "completion was successful after VK_TAB");
   checkJsTermCursor(jsterm, expectedInput.length - 1, "cursor location is correct");
-  ok(!getJsTermCompletionValue(jsterm), "there is no completion text");
-
-  info("Test ENTER key when popup is visible with a selected item");
-  await setInitialState(jsterm);
-  info("press Enter and wait for popup to hide");
-  onPopupClose = popup.once("popup-closed");
-  EventUtils.synthesizeKey("KEY_Enter");
-  await onPopupClose;
-
-  ok(!popup.isOpen, "popup is not open");
-  expectedInput = "dump(window.testBugAA)";
-  is(jsterm.getInputValue(), expectedInput, "completion was successful after Enter");
-  checkJsTermCursor(jsterm, expectedInput.length - 1, "cursor location is correct");
-  ok(!getJsTermCompletionValue(jsterm), "there is no completion text");
-
-  info("Test TAB key when there is no autocomplete suggestion");
-  jsterm.setInputValue("dump()");
-  EventUtils.synthesizeKey("KEY_ArrowLeft");
-  const onAutocompleteUpdated = jsterm.once("autocomplete-updated");
-  EventUtils.sendString("window.testBugA");
-  await onAutocompleteUpdated;
-  ok(!popup.isOpen, "popup is not open");
-  ok(!getJsTermCompletionValue(jsterm), "there is no completion text");
-
-  EventUtils.synthesizeKey("KEY_Tab");
-
-  expectedInput = "dump(window.testBugAA)";
-  is(jsterm.getInputValue(), "dump(window.testBugA\t)", "Tab inserted a tab char");
-  checkJsTermCursor(jsterm, expectedInput.length - 1, "cursor location is correct");
+  ok(!getJsTermCompletionValue(jsterm), "completeNode is empty");
 }
-
-function setInitialState(jsterm) {
-  jsterm.focus();
-  jsterm.setInputValue("dump()");
-  EventUtils.synthesizeKey("KEY_ArrowLeft");
-
-  const onPopUpOpen = jsterm.autocompletePopup.once("popup-opened");
-  EventUtils.sendString("window.testB");
-  return onPopUpOpen;
-}
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_completion.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_completion.js
@@ -18,84 +18,67 @@ add_task(async function() {
   await performTests();
 });
 
 async function performTests() {
   const {jsterm, ui} = await openNewTabAndConsole(TEST_URI);
   const {autocompletePopup} = jsterm;
 
   // Test typing 'docu'.
-  await setInputValueForAutocompletion(jsterm, "docu");
+  await jstermSetValueAndComplete(jsterm, "docu");
   is(jsterm.getInputValue(), "docu", "'docu' completion (input.value)");
   checkJsTermCompletionValue(jsterm, "    ment", "'docu' completion (completeNode)");
   is(autocompletePopup.items.length, 1, "autocomplete popup has 1 item");
-  is(autocompletePopup.isOpen, false, "autocomplete popup is not open");
+  ok(autocompletePopup.isOpen, "autocomplete popup is open with 1 item");
 
   // Test typing 'docu' and press tab.
-  EventUtils.synthesizeKey("KEY_Tab");
+  await jstermSetValueAndComplete(jsterm, "docu", undefined, jsterm.COMPLETE_FORWARD);
   is(jsterm.getInputValue(), "document", "'docu' tab completion");
 
   checkJsTermCursor(jsterm, "document".length, "cursor is at the end of 'document'");
   is(getJsTermCompletionValue(jsterm).replace(/ /g, ""), "", "'docu' completed");
 
   // Test typing 'window.Ob' and press tab.  Just 'window.O' is
   // ambiguous: could be window.Object, window.Option, etc.
-  await setInputValueForAutocompletion(jsterm, "window.Ob");
-  EventUtils.synthesizeKey("KEY_Tab");
+  await jstermSetValueAndComplete(jsterm, "window.Ob", undefined,
+                                  jsterm.COMPLETE_FORWARD);
   is(jsterm.getInputValue(), "window.Object", "'window.Ob' tab completion");
 
   // Test typing 'document.getElem'.
-  const onPopupOpened = autocompletePopup.once("popup-opened");
-  await setInputValueForAutocompletion(jsterm, "document.getElem");
+  await jstermSetValueAndComplete(
+    jsterm, "document.getElem", undefined, jsterm.COMPLETE_FORWARD);
   is(jsterm.getInputValue(), "document.getElem", "'document.getElem' completion");
   checkJsTermCompletionValue(jsterm, "                entById",
      "'document.getElem' completion");
 
-  // Test pressing key down.
-  await onPopupOpened;
-  EventUtils.synthesizeKey("KEY_ArrowDown");
+  // Test pressing tab another time.
+  await jsterm.complete(jsterm.COMPLETE_FORWARD);
   is(jsterm.getInputValue(), "document.getElem", "'document.getElem' completion");
   checkJsTermCompletionValue(jsterm, "                entsByClassName",
      "'document.getElem' another tab completion");
 
-  // Test pressing key up.
-  EventUtils.synthesizeKey("KEY_ArrowUp");
-  await waitFor(() => (getJsTermCompletionValue(jsterm) || "").includes("entById"));
+  // Test pressing shift_tab.
+  await jstermComplete(jsterm, jsterm.COMPLETE_BACKWARD);
   is(jsterm.getInputValue(), "document.getElem", "'document.getElem' untab completion");
   checkJsTermCompletionValue(jsterm, "                entById",
      "'document.getElem' completion");
 
   ui.clearOutput();
 
-  await setInputValueForAutocompletion(jsterm, "docu");
+  await jstermSetValueAndComplete(jsterm, "docu");
   checkJsTermCompletionValue(jsterm, "    ment", "'docu' completion");
 
-  let onAutocompletUpdated = jsterm.once("autocomplete-updated");
   await jsterm.execute();
   checkJsTermCompletionValue(jsterm, "", "clear completion on execute()");
 
-  // Test multi-line completion works. We can't use setInputValueForAutocompletion because
-  // it would trigger an evaluation (because of the new line, an Enter keypress is
-  // simulated).
-  onAutocompletUpdated = jsterm.once("autocomplete-updated");
-  jsterm.setInputValue("console.log('one');\n");
-  EventUtils.sendString("consol");
-  await onAutocompletUpdated;
-  checkJsTermCompletionValue(jsterm, "\n      e", "multi-line completion");
-
-  // Test multi-line completion works even if there is text after the cursor
-  onAutocompletUpdated = jsterm.once("autocomplete-updated");
-  jsterm.setInputValue("{\n\n}");
-  EventUtils.synthesizeKey("KEY_ArrowUp");
-  EventUtils.sendString("console.g");
-  await onAutocompletUpdated;
-  checkJsTermValueAndCursor(jsterm, "{\nconsole.g|\n}");
-  checkJsTermCompletionValue(jsterm, "\n         roup", "multi-line completion");
-  is(autocompletePopup.isOpen, true, "popup is opened");
+  // Test multi-line completion works
+  await jstermSetValueAndComplete(jsterm, "console.log('one');\nconsol");
+  checkJsTermCompletionValue(jsterm, "                   \n      e",
+     "multi-line completion");
 
   // Test non-object autocompletion.
-  await setInputValueForAutocompletion(jsterm, "Object.name.sl");
+  await jstermSetValueAndComplete(jsterm, "Object.name.sl");
   checkJsTermCompletionValue(jsterm, "              ice", "non-object completion");
 
   // Test string literal autocompletion.
-  await setInputValueForAutocompletion(jsterm, "'Asimov'.sl");
+  await jstermSetValueAndComplete(jsterm, "'Asimov'.sl");
   checkJsTermCompletionValue(jsterm, "           ice", "string literal completion");
 }
--- a/devtools/client/webconsole/test/mochitest/browser_jsterm_content_defined_helpers.js
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_content_defined_helpers.js
@@ -45,17 +45,17 @@ add_task(async function() {
   await performTests();
 });
 
 async function performTests() {
   const {jsterm} = await openNewTabAndConsole(TEST_URI);
   const {autocompletePopup} = jsterm;
 
   for (const helper of HELPERS) {
-    await setInputValueForAutocompletion(jsterm, helper);
+    await jstermSetValueAndComplete(jsterm, helper);
     const autocompleteItems = getPopupLabels(autocompletePopup).filter(l => l === helper);
     is(autocompleteItems.length, 1,
       `There's no duplicated "${helper}" item in the autocomplete popup`);
     const msg = await jsterm.execute(`${helper}()`);
     ok(msg.textContent.includes(PREFIX + helper), `output is correct for ${helper}()`);
   }
 }
 
new file mode 100644
--- /dev/null
+++ b/devtools/client/webconsole/test/mochitest/browser_jsterm_no_autocompletion_on_defined_variables.js
@@ -0,0 +1,41 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests for bug 704295
+
+"use strict";
+
+const TEST_URI = "http://example.com/browser/devtools/client/webconsole/" +
+                 "test/mochitest/test-console.html";
+
+add_task(async function() {
+  // Run test with legacy JsTerm
+  await pushPref("devtools.webconsole.jsterm.codeMirror", false);
+  await performTests();
+  // And then run it with the CodeMirror-powered one.
+  await pushPref("devtools.webconsole.jsterm.codeMirror", true);
+  await performTests();
+});
+
+async function performTests() {
+  const hud = await openNewTabAndConsole(TEST_URI);
+  const jsterm = hud.jsterm;
+
+  // Test typing 'var d = 5;' and press RETURN
+  jsterm.setInputValue("var d = ");
+  EventUtils.sendString("5;");
+  is(jsterm.getInputValue(), "var d = 5;", "var d = 5;");
+  checkJsTermCompletionValue(jsterm, "", "no completion");
+  EventUtils.synthesizeKey("KEY_Enter");
+  checkJsTermCompletionValue(jsterm, "", "clear completion on execute()");
+
+  // Test typing 'var a = d' and press RETURN
+  jsterm.setInputValue("var a = ");
+  EventUtils.sendString("d");
+  is(jsterm.getInputValue(), "var a = d", "var a = d");
+  checkJsTermCompletionValue(jsterm, "", "no completion");
+  EventUtils.synthesizeKey("KEY_Enter");
+  checkJsTermCompletionValue(jsterm, "", "clear completion on execute()");
+}
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_closing_after_completion.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_closing_after_completion.js
@@ -12,17 +12,17 @@ const TEST_URI = "http://example.com/bro
                  "test/mochitest/test-console.html";
 
 add_task(async function() {
   const tab = await addTab(TEST_URI);
   const browser = tab.linkedBrowser;
   const hud = await openConsole();
 
   // Fire a completion.
-  await setInputValueForAutocompletion(hud.jsterm, "doc");
+  await jstermSetValueAndComplete(hud.jsterm, "doc");
 
   let errorWhileClosing = false;
   function errorListener() {
     errorWhileClosing = true;
   }
 
   browser.addEventListener("error", errorListener);
   const onToolboxDestroyed = gDevTools.once("toolbox-destroyed");
--- a/devtools/client/webconsole/test/mochitest/browser_webconsole_split_escape_key.js
+++ b/devtools/client/webconsole/test/mochitest/browser_webconsole_split_escape_key.js
@@ -22,17 +22,18 @@ add_task(async function() {
   const hud = toolbox.getPanel("webconsole").hud;
   const jsterm = hud.jsterm;
   ok(toolbox.splitConsole, "Split console is created.");
 
   info("Wait for the autocomplete to show suggestions for `document.location.`");
   const popup = jsterm.autocompletePopup;
   const onPopupShown = popup.once("popup-opened");
   jsterm.focus();
-  EventUtils.sendString("document.location.");
+  jsterm.setInputValue("document.location.");
+  EventUtils.sendKey("TAB", hud.iframeWindow);
   await onPopupShown;
 
   info("Send ESCAPE key and check that it only hides the autocomplete suggestions");
 
   const onPopupClosed = popup.once("popup-closed");
   EventUtils.sendKey("ESCAPE", toolbox.win);
   await onPopupClosed;
 
--- a/devtools/client/webconsole/test/mochitest/head.js
+++ b/devtools/client/webconsole/test/mochitest/head.js
@@ -342,53 +342,76 @@ async function checkClickOnNode(hud, too
  * Returns true if the give node is currently focused.
  */
 function hasFocus(node) {
   return node.ownerDocument.activeElement == node
     && node.ownerDocument.hasFocus();
 }
 
 /**
- * Set the value of the JsTerm and its caret position, and wait for the autocompletion
- * to be updated.
+ * Set the value of the JsTerm and its caret position, and fire a completion request.
  *
  * @param {JsTerm} jsterm
  * @param {String} value : The value to set the jsterm to.
  * @param {Integer} caretPosition : The index where to place the cursor. A negative
  *                  number will place the caret at (value.length - offset) position.
  *                  Default to value.length (caret set at the end).
+ * @param {Integer} completionType : One of the following jsterm property
+ *                   - COMPLETE_FORWARD
+ *                   - COMPLETE_BACKWARD
+ *                   - COMPLETE_HINT_ONLY
+ *                   - COMPLETE_PAGEUP
+ *                   - COMPLETE_PAGEDOWN
+ *                  Will default to COMPLETE_HINT_ONLY.
  * @returns {Promise} resolves when the jsterm is completed.
  */
-async function setInputValueForAutocompletion(
+function jstermSetValueAndComplete(
   jsterm,
   value,
   caretPosition = value.length,
+  completionType
 ) {
-  jsterm.setInputValue("");
-  jsterm.focus();
-
-  const updated = jsterm.once("autocomplete-updated");
-  EventUtils.sendString(value);
-  await updated;
+  jsterm.setInputValue(value);
 
   if (caretPosition < 0) {
     caretPosition = value.length + caretPosition;
   }
 
   if (Number.isInteger(caretPosition)) {
     if (jsterm.inputNode) {
       const {inputNode} = jsterm;
       inputNode.value = value;
       inputNode.setSelectionRange(caretPosition, caretPosition);
     }
 
     if (jsterm.editor) {
       jsterm.editor.setCursor(jsterm.editor.getPosition(caretPosition));
     }
   }
+
+  return jstermComplete(jsterm, completionType);
+}
+
+/**
+ * Fires a completion request on the jsterm with the specified completionType
+ *
+ * @param {JsTerm} jsterm
+ * @param {Integer} completionType : One of the following jsterm property
+ *                   - COMPLETE_FORWARD
+ *                   - COMPLETE_BACKWARD
+ *                   - COMPLETE_HINT_ONLY
+ *                   - COMPLETE_PAGEUP
+ *                   - COMPLETE_PAGEDOWN
+ *                  Will default to COMPLETE_HINT_ONLY.
+ * @returns {Promise} resolves when the jsterm is completed.
+ */
+function jstermComplete(jsterm, completionType = jsterm.COMPLETE_HINT_ONLY) {
+  const updated = jsterm.once("autocomplete-updated");
+  jsterm.complete(completionType);
+  return updated;
 }
 
 /**
  * Checks if the jsterm has the expected completion value.
  *
  * @param {JsTerm} jsterm
  * @param {String} expectedValue
  * @param {String} assertionInfo: Description of the assertion passed to `is`.
--- a/devtools/shared/webconsole/test/test_jsterm_autocomplete.html
+++ b/devtools/shared/webconsole/test/test_jsterm_autocomplete.html
@@ -19,17 +19,19 @@ let {MAX_AUTOCOMPLETE_ATTEMPTS,MAX_AUTOC
 
 function evaluateJS(input, options = {}) {
   return new Promise((resolve, reject) => {
     gState.client.evaluateJSAsync(input, resolve, options);
   });
 }
 
 function autocompletePromise(str, cursor = str.length, frameActor) {
-  return gState.client.autocomplete(str, cursor, frameActor);
+  return new Promise(resolve => {
+    gState.client.autocomplete(str, cursor, resolve, frameActor);
+  });
 }
 
 // This test runs all of its assertions twice - once with
 // the tab as a target and once with a worker
 let runningInTab = true;
 function startTest({worker}) {
   if (worker) {
     attachConsoleToWorker(["PageError"], onAttach.bind(null, true));