Bug 1527898 - Turn sourceditor `setup` test helper async; r=gl a=lizzard
authorNicolas Chevobbe <nchevobbe@mozilla.com>
Mon, 18 Feb 2019 06:13:29 +0000
changeset 516059 f3b5d5cc711a4d678cc9d481f1ec839a28b1fde7
parent 516058 8b328a01648ca83883c2de044a2e4c7154779260
child 516060 d599140e150247467c8d87912659a832f1f62bd9
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgl, lizzard
bugs1527898
milestone66.0
Bug 1527898 - Turn sourceditor `setup` test helper async; r=gl a=lizzard The function was returning a Promise but was also taking a callback for old-style test. This patch turns the function into an async one, remove the callback param and refactor tests that relied on it. Differential Revision: https://phabricator.services.mozilla.com/D19963
devtools/client/sourceeditor/test/browser_codemirror.js
devtools/client/sourceeditor/test/browser_detectindent.js
devtools/client/sourceeditor/test/browser_editor_addons.js
devtools/client/sourceeditor/test/browser_editor_autocomplete_basic.js
devtools/client/sourceeditor/test/browser_editor_autocomplete_events.js
devtools/client/sourceeditor/test/browser_editor_autocomplete_js.js
devtools/client/sourceeditor/test/browser_editor_basic.js
devtools/client/sourceeditor/test/browser_editor_cursor.js
devtools/client/sourceeditor/test/browser_editor_goto_line.js
devtools/client/sourceeditor/test/browser_editor_history.js
devtools/client/sourceeditor/test/browser_editor_markers.js
devtools/client/sourceeditor/test/browser_editor_movelines.js
devtools/client/sourceeditor/test/browser_editor_prefs.js
devtools/client/sourceeditor/test/browser_editor_script_injection.js
devtools/client/sourceeditor/test/head.js
--- a/devtools/client/sourceeditor/test/browser_codemirror.js
+++ b/devtools/client/sourceeditor/test/browser_codemirror.js
@@ -3,33 +3,30 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
 const URI = "chrome://mochitests/content/browser/devtools/client/" +
             "sourceeditor/test/codemirror/codemirror.html";
 loadHelperScript("helper_codemirror_runner.js");
 
-function test() {
+async function test() {
   requestLongerTimeout(3);
   waitForExplicitFinish();
 
   /*
    * In devtools/client/sourceeditor/test/codemirror/search_test.js there is a test
    * multilineInsensitiveSlow which assumes an operation takes less than 100ms.
    * With a precision of 100ms, if we get unlikely and begin execution towards the
    * end of one spot (e.g. at 95 ms) we will clamp down, take (e.g.) 10ms to execute
    * and it will appear to take 100ms.
    *
    * To avoid this, we hardcode to 2ms of precision.
    *
    * In theory we don't need to set the pref for all of CodeMirror, in practice
    * it seems very difficult to set a pref for just one of the tests.
    */
-  SpecialPowers.pushPrefEnv(
-    { set: [["privacy.reduceTimerPrecision", true],
-            ["privacy.resistFingerprinting.reduceTimerPrecision.microseconds", 2000]]},
-    function() {
-      addTab(URI).then(function(tab) {
-        runCodeMirrorTest(tab.linkedBrowser);
-      });
-    });
+  await pushPref("privacy.reduceTimerPrecision", true);
+  await pushPref("privacy.resistFingerprinting.reduceTimerPrecision.microseconds", 2000);
+
+  const tab = await addTab(URI);
+  runCodeMirrorTest(tab.linkedBrowser);
 }
--- a/devtools/client/sourceeditor/test/browser_detectindent.js
+++ b/devtools/client/sourceeditor/test/browser_detectindent.js
@@ -59,44 +59,33 @@ const TABS_CODE = [
 const NONE_CODE = [
   "var x = 0;",
   "           // stray thing",
   "var y = 9;",
   "    ",
   "",
 ].join("\n");
 
-function test() {
+async function test() {
   waitForExplicitFinish();
 
-  setup((ed, win) => {
-    is(ed.getOption("indentUnit"), 2,
-       "2 spaces before code added");
-    is(ed.getOption("indentWithTabs"), false,
-       "spaces is default");
+  const {ed, win} = await setup();
+  is(ed.getOption("indentUnit"), 2, "2 spaces before code added");
+  is(ed.getOption("indentWithTabs"), false, "spaces is default");
 
-    ed.setText(NONE_CODE);
-    is(ed.getOption("indentUnit"), 2,
-       "2 spaces after un-detectable code");
-    is(ed.getOption("indentWithTabs"), false,
-       "spaces still set after un-detectable code");
+  ed.setText(NONE_CODE);
+  is(ed.getOption("indentUnit"), 2, "2 spaces after un-detectable code");
+  is(ed.getOption("indentWithTabs"), false, "spaces still set after un-detectable code");
 
-    ed.setText(FOUR_SPACES_CODE);
-    is(ed.getOption("indentUnit"), 4,
-       "4 spaces detected in 4 space code");
-    is(ed.getOption("indentWithTabs"), false,
-       "spaces detected in 4 space code");
+  ed.setText(FOUR_SPACES_CODE);
+  is(ed.getOption("indentUnit"), 4, "4 spaces detected in 4 space code");
+  is(ed.getOption("indentWithTabs"), false, "spaces detected in 4 space code");
 
-    ed.setText(TWO_SPACES_CODE);
-    is(ed.getOption("indentUnit"), 2,
-       "2 spaces detected in 2 space code");
-    is(ed.getOption("indentWithTabs"), false,
-       "spaces detected in 2 space code");
+  ed.setText(TWO_SPACES_CODE);
+  is(ed.getOption("indentUnit"), 2, "2 spaces detected in 2 space code");
+  is(ed.getOption("indentWithTabs"), false, "spaces detected in 2 space code");
 
-    ed.setText(TABS_CODE);
-    is(ed.getOption("indentUnit"), 2,
-       "2 space indentation unit");
-    is(ed.getOption("indentWithTabs"), true,
-       "tabs detected in majority tabs code");
+  ed.setText(TABS_CODE);
+  is(ed.getOption("indentUnit"), 2, "2 space indentation unit");
+  is(ed.getOption("indentWithTabs"), true, "tabs detected in majority tabs code");
 
-    teardown(ed, win);
-  });
+  teardown(ed, win);
 }
--- a/devtools/client/sourceeditor/test/browser_editor_addons.js
+++ b/devtools/client/sourceeditor/test/browser_editor_addons.js
@@ -1,31 +1,30 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-function test() {
+async function test() {
   waitForExplicitFinish();
 
-  setup((ed, win) => {
-    const doc = win.document.querySelector("iframe").contentWindow.document;
+  const {ed, win} = await setup();
+  const doc = win.document.querySelector("iframe").contentWindow.document;
 
-    // trailingspace.js
-    ed.setText("Hello   ");
-    ed.setOption("showTrailingSpace", false);
-    ok(!doc.querySelector(".cm-trailingspace"));
-    ed.setOption("showTrailingSpace", true);
-    ok(doc.querySelector(".cm-trailingspace"));
+  // trailingspace.js
+  ed.setText("Hello   ");
+  ed.setOption("showTrailingSpace", false);
+  ok(!doc.querySelector(".cm-trailingspace"));
+  ed.setOption("showTrailingSpace", true);
+  ok(doc.querySelector(".cm-trailingspace"));
 
-    // foldcode.js and foldgutter.js
-    ed.setMode(Editor.modes.js);
-    ed.setText("function main() {\nreturn 'Hello, World!';\n}");
-    executeSoon(() => testFold(doc, ed, win));
-  });
+  // foldcode.js and foldgutter.js
+  ed.setMode(Editor.modes.js);
+  ed.setText("function main() {\nreturn 'Hello, World!';\n}");
+  executeSoon(() => testFold(doc, ed, win));
 }
 
 function testFold(doc, ed, win) {
   // Wait until folding arrow is there.
   if (!doc.querySelector(".CodeMirror-foldgutter-open")) {
     executeSoon(() => testFold(doc, ed, win));
     return;
   }
--- a/devtools/client/sourceeditor/test/browser_editor_autocomplete_basic.js
+++ b/devtools/client/sourceeditor/test/browser_editor_autocomplete_basic.js
@@ -4,25 +4,24 @@
 
 "use strict";
 
 const AUTOCOMPLETION_PREF = "devtools.editor.autocomplete";
 
 // Test to make sure that different autocompletion modes can be created,
 // switched, and destroyed.  This doesn't test the actual autocompletion
 // popups, only their integration with the editor.
-function test() {
+async function test() {
   waitForExplicitFinish();
-  setup((ed, win) => {
-    const edWin = ed.container.contentWindow.wrappedJSObject;
-    testJS(ed, edWin);
-    testCSS(ed, edWin);
-    testPref(ed, edWin);
-    teardown(ed, win);
-  });
+  const {ed, win} = await setup();
+  const edWin = ed.container.contentWindow.wrappedJSObject;
+  testJS(ed, edWin);
+  testCSS(ed, edWin);
+  testPref(ed, edWin);
+  teardown(ed, win);
 }
 
 function testJS(ed, win) {
   ok(!ed.getOption("autocomplete"), "Autocompletion is not set");
   ok(!win.tern, "Tern is not defined on the window");
 
   ed.setMode(Editor.modes.js);
   ed.setOption("autocomplete", true);
--- a/devtools/client/sourceeditor/test/browser_editor_autocomplete_events.js
+++ b/devtools/client/sourceeditor/test/browser_editor_autocomplete_events.js
@@ -12,17 +12,17 @@ add_task(async function() {
   await runTests();
 });
 
 async function runTests() {
   const target = await TargetFactory.forTab(gBrowser.selectedTab);
   await target.attach();
   const inspector = await target.getInspector();
   const walker = inspector.walker;
-  const {ed, win, edWin} = await setup(null, {
+  const {ed, win, edWin} = await setup({
     autocomplete: true,
     mode: Editor.modes.css,
     autocompleteOpts: {walker: walker, cssProperties: getClientCssProperties()},
   });
   await testMouse(ed, edWin);
   await testKeyboard(ed, edWin);
   await testKeyboardCycle(ed, edWin);
   await testKeyboardCycleForPrefixedString(ed, edWin);
--- a/devtools/client/sourceeditor/test/browser_editor_autocomplete_js.js
+++ b/devtools/client/sourceeditor/test/browser_editor_autocomplete_js.js
@@ -1,23 +1,21 @@
 /* vim: set 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 to make sure that JS autocompletion is opening popups.
-function test() {
+async function test() {
   waitForExplicitFinish();
-  setup((ed, win) => {
-    const edWin = ed.container.contentWindow.wrappedJSObject;
-    testJS(ed, edWin).then(() => {
-      teardown(ed, win);
-    });
-  });
+  const {ed, win} = await setup();
+  const edWin = ed.container.contentWindow.wrappedJSObject;
+  await testJS(ed, edWin);
+  teardown(ed, win);
 }
 
 function testJS(ed, win) {
   ok(!ed.getOption("autocomplete"), "Autocompletion is not set");
   ok(!win.tern, "Tern is not defined on the window");
 
   ed.setMode(Editor.modes.js);
   ed.setOption("autocomplete", true);
--- a/devtools/client/sourceeditor/test/browser_editor_basic.js
+++ b/devtools/client/sourceeditor/test/browser_editor_basic.js
@@ -1,63 +1,62 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-function test() {
+async function test() {
   waitForExplicitFinish();
-  setup((ed, win) => {
-    // appendTo
-    const cmFrame = win.document.querySelector("iframe");
-    const cmStyle = cmFrame.contentDocument.getElementById("cmBaseStyle");
-    ok(~cmStyle.innerHTML.indexOf(".CodeMirror"), "correct iframe is there");
+  const {ed, win} = await setup();
+  // appendTo
+  const cmFrame = win.document.querySelector("iframe");
+  const cmStyle = cmFrame.contentDocument.getElementById("cmBaseStyle");
+  ok(~cmStyle.innerHTML.indexOf(".CodeMirror"), "correct iframe is there");
 
-    // getOption/setOption
-    ok(ed.getOption("styleActiveLine"), "getOption works");
-    ed.setOption("styleActiveLine", false);
-    ok(!ed.getOption("styleActiveLine"), "setOption works");
+  // getOption/setOption
+  ok(ed.getOption("styleActiveLine"), "getOption works");
+  ed.setOption("styleActiveLine", false);
+  ok(!ed.getOption("styleActiveLine"), "setOption works");
 
-    // Language modes
-    is(ed.getMode(), Editor.modes.text, "getMode");
-    ed.setMode(Editor.modes.js);
-    is(ed.getMode(), Editor.modes.js, "setMode");
+  // Language modes
+  is(ed.getMode(), Editor.modes.text, "getMode");
+  ed.setMode(Editor.modes.js);
+  is(ed.getMode(), Editor.modes.js, "setMode");
 
-    // Content
-    is(ed.getText(), "Hello.", "getText");
-    ed.setText("Hi.\nHow are you?");
-    is(ed.getText(), "Hi.\nHow are you?", "setText");
-    is(ed.getText(1), "How are you?", "getText(num)");
-    is(ed.getText(5), "", "getText(num) when num is out of scope");
+  // Content
+  is(ed.getText(), "Hello.", "getText");
+  ed.setText("Hi.\nHow are you?");
+  is(ed.getText(), "Hi.\nHow are you?", "setText");
+  is(ed.getText(1), "How are you?", "getText(num)");
+  is(ed.getText(5), "", "getText(num) when num is out of scope");
 
-    ed.replaceText("YOU", { line: 1, ch: 8 }, { line: 1, ch: 11 });
-    is(ed.getText(1), "How are YOU?", "replaceText(str, from, to)");
-    ed.replaceText("you?", { line: 1, ch: 8 });
-    is(ed.getText(1), "How are you?", "replaceText(str, from)");
-    ed.replaceText("Hello.");
-    is(ed.getText(), "Hello.", "replaceText(str)");
+  ed.replaceText("YOU", { line: 1, ch: 8 }, { line: 1, ch: 11 });
+  is(ed.getText(1), "How are YOU?", "replaceText(str, from, to)");
+  ed.replaceText("you?", { line: 1, ch: 8 });
+  is(ed.getText(1), "How are you?", "replaceText(str, from)");
+  ed.replaceText("Hello.");
+  is(ed.getText(), "Hello.", "replaceText(str)");
 
-    ed.insertText(", sir/madam", { line: 0, ch: 5});
-    is(ed.getText(), "Hello, sir/madam.", "insertText");
+  ed.insertText(", sir/madam", { line: 0, ch: 5});
+  is(ed.getText(), "Hello, sir/madam.", "insertText");
 
-    // Add-ons
-    ed.extend({ whoami: () => "Anton", whereami: () => "Mozilla" });
-    is(ed.whoami(), "Anton", "extend/1");
-    is(ed.whereami(), "Mozilla", "extend/2");
+  // Add-ons
+  ed.extend({ whoami: () => "Anton", whereami: () => "Mozilla" });
+  is(ed.whoami(), "Anton", "extend/1");
+  is(ed.whereami(), "Mozilla", "extend/2");
 
-    // Line classes
-    ed.setText("Hello!\nHow are you?");
-    ok(!ed.hasLineClass(0, "test"), "no test line class");
-    ed.addLineClass(0, "test");
-    ok(ed.hasLineClass(0, "test"), "test line class is there");
-    ed.removeLineClass(0, "test");
-    ok(!ed.hasLineClass(0, "test"), "test line class is gone");
+  // Line classes
+  ed.setText("Hello!\nHow are you?");
+  ok(!ed.hasLineClass(0, "test"), "no test line class");
+  ed.addLineClass(0, "test");
+  ok(ed.hasLineClass(0, "test"), "test line class is there");
+  ed.removeLineClass(0, "test");
+  ok(!ed.hasLineClass(0, "test"), "test line class is gone");
 
-    // Font size
-    const size = ed.getFontSize();
-    is("number", typeof size, "we have the default font size");
-    ed.setFontSize(ed.getFontSize() + 1);
-    is(ed.getFontSize(), size + 1, "new font size was set");
+  // Font size
+  const size = ed.getFontSize();
+  is("number", typeof size, "we have the default font size");
+  ed.setFontSize(ed.getFontSize() + 1);
+  is(ed.getFontSize(), size + 1, "new font size was set");
 
-    teardown(ed, win);
-  });
+  teardown(ed, win);
 }
--- a/devtools/client/sourceeditor/test/browser_editor_cursor.js
+++ b/devtools/client/sourceeditor/test/browser_editor_cursor.js
@@ -1,44 +1,42 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-function test() {
+async function test() {
   waitForExplicitFinish();
-  setup((ed, win) => {
-    ch(ed.getCursor(), { line: 0, ch: 0 }, "default cursor position is ok");
-    ed.setText("Hello.\nHow are you?");
-
-    ed.setCursor({ line: 1, ch: 5 });
-    ch(ed.getCursor(), { line: 1, ch: 5 }, "setCursor({ line, ch })");
+  const {ed, win} = await setup();
+  ch(ed.getCursor(), { line: 0, ch: 0 }, "default cursor position is ok");
+  ed.setText("Hello.\nHow are you?");
 
-    ch(ed.getPosition(7), { line: 1, ch: 0}, "getPosition(num)");
-    ch(ed.getPosition(7, 1)[0], { line: 1, ch: 0}, "getPosition(num, num)[0]");
-    ch(ed.getPosition(7, 1)[1], { line: 0, ch: 1}, "getPosition(num, num)[1]");
+  ed.setCursor({ line: 1, ch: 5 });
+  ch(ed.getCursor(), { line: 1, ch: 5 }, "setCursor({ line, ch })");
 
-    ch(ed.getOffset({ line: 1, ch: 0 }), 7, "getOffset(num)");
-    ch(ed.getOffset({ line: 1, ch: 0 }, { line: 0, ch: 1 })[0], 7,
-      "getOffset(num, num)[0]");
-    ch(ed.getOffset({ line: 1, ch: 0 }, { line: 0, ch: 1 })[0], 2,
-      "getOffset(num, num)[1]");
+  ch(ed.getPosition(7), { line: 1, ch: 0}, "getPosition(num)");
+  ch(ed.getPosition(7, 1)[0], { line: 1, ch: 0}, "getPosition(num, num)[0]");
+  ch(ed.getPosition(7, 1)[1], { line: 0, ch: 1}, "getPosition(num, num)[1]");
 
-    is(ed.getSelection(), "", "nothing is selected");
-    ed.setSelection({ line: 0, ch: 0 }, { line: 0, ch: 5 });
-    is(ed.getSelection(), "Hello", "setSelection");
+  ch(ed.getOffset({ line: 1, ch: 0 }), 7, "getOffset(num)");
+  ch(ed.getOffset({ line: 1, ch: 0 }, { line: 0, ch: 1 })[0], 7,
+    "getOffset(num, num)[0]");
+  ch(ed.getOffset({ line: 1, ch: 0 }, { line: 0, ch: 1 })[0], 2,
+    "getOffset(num, num)[1]");
 
-    ed.dropSelection();
-    is(ed.getSelection(), "", "dropSelection");
+  is(ed.getSelection(), "", "nothing is selected");
+  ed.setSelection({ line: 0, ch: 0 }, { line: 0, ch: 5 });
+  is(ed.getSelection(), "Hello", "setSelection");
 
-    // Check that shift-click on a gutter selects the whole line (bug 919707)
-    const iframe = win.document.querySelector("iframe");
-    const gutter =
-      iframe.contentWindow.document.querySelector(".CodeMirror-gutters");
+  ed.dropSelection();
+  is(ed.getSelection(), "", "dropSelection");
+
+  // Check that shift-click on a gutter selects the whole line (bug 919707)
+  const iframe = win.document.querySelector("iframe");
+  const gutter = iframe.contentWindow.document.querySelector(".CodeMirror-gutters");
 
-    EventUtils.sendMouseEvent({ type: "mousedown", shiftKey: true }, gutter,
-      iframe.contentWindow);
-    is(ed.getSelection(), "", "shift-click");
+  EventUtils.sendMouseEvent({ type: "mousedown", shiftKey: true }, gutter,
+    iframe.contentWindow);
+  is(ed.getSelection(), "", "shift-click");
 
-    teardown(ed, win);
-  });
+  teardown(ed, win);
 }
--- a/devtools/client/sourceeditor/test/browser_editor_goto_line.js
+++ b/devtools/client/sourceeditor/test/browser_editor_goto_line.js
@@ -11,121 +11,120 @@ function testJumpToLine(ed, inputLine, e
   const lineInput = editorDoc.querySelector("input");
   lineInput.value = inputLine;
   EventUtils.synthesizeKey("VK_RETURN", { }, editorDoc.defaultView);
   // CodeMirror lines and columns are 0-based, Scratchpad UI is 1-based.
   ch(ed.getCursor(), expectCursor,
     "jumpToLine " + inputLine + " expects cursor " + expectCursor.toSource());
 }
 
-function test() {
+async function test() {
   waitForExplicitFinish();
-  setup((ed, win) => {
-    const textLines = [
-      "// line 1",
-      "//  line 2",
-      "//   line 3",
-      "//    line 4",
-      "//     line 5",
-      ""];
-    ed.setText(textLines.join("\n"));
-    waitForFocus(function() {
-      const testVectors = [
-        // Various useless inputs go to line 0, column 0 or do nothing.
-        ["",
-         {line: 0, ch: 0}],
-        [":",
-         {line: 0, ch: 0}],
-        [" ",
-         {line: 0, ch: 0}],
-        [" : ",
-         {line: 0, ch: 0}],
-        ["a:b",
-         {line: 0, ch: 0}],
-        ["LINE: COLUMN ",
-         {line: 0, ch: 0}],
-        ["-1",
-         {line: 0, ch: 0}],
-        [":-1",
-         {line: 0, ch: 0}],
-        ["-1:-1",
-         {line: 0, ch: 0}],
-        ["0",
-         {line: 0, ch: 0}],
-        [":0",
-         {line: 0, ch: 0}],
-        ["0:0",
-         {line: 0, ch: 0}],
-        // Starting here expect data needs to get updated for length changes to
-        // "textLines" above.
-        // Just jump to line
-        ["1",
-         {line: 0, ch: 0}],
-        // Jump to second character in line
-        ["1:2",
-         {line: 0, ch: 1}],
-        // Jump to last character on line
-        ["1:9",
-         {line: 0, ch: 8}],
-        // Jump just after last character on line (end of line)
-        ["1:10",
-         {line: 0, ch: 9}],
-        // Jump one character past end of line (gets clamped to end of line)
-        ["1:11",
-         {line: 0, ch: 9}],
-        ["2",
-         {line: 1, ch: 0}],
-        ["2:2",
-         {line: 1, ch: 1}],
-        ["2:10",
-         {line: 1, ch: 9}],
-        ["2:11",
-         {line: 1, ch: 10}],
-        ["2:12",
-         {line: 1, ch: 10}],
-        ["3",
-         {line: 2, ch: 0}],
-        ["3:2",
-         {line: 2, ch: 1}],
-        ["3:11",
-         {line: 2, ch: 10}],
-        ["3:12",
-         {line: 2, ch: 11}],
-        ["3:13",
-         {line: 2, ch: 11}],
-        ["4",
-         {line: 3, ch: 0}],
-        ["4:2",
-         {line: 3, ch: 1}],
-        ["4:12",
-         {line: 3, ch: 11}],
-        ["4:13",
-         {line: 3, ch: 12}],
-        ["4:14",
-         {line: 3, ch: 12}],
-        ["5",
-         {line: 4, ch: 0}],
-        ["5:2",
-         {line: 4, ch: 1}],
-        ["5:13",
-         {line: 4, ch: 12}],
-        ["5:14",
-         {line: 4, ch: 13}],
-        ["5:15",
-         {line: 4, ch: 13}],
-        // One line beyond last newline in editor text:
-        ["6",
-         {line: 5, ch: 0}],
-        ["6:2",
-         {line: 5, ch: 0}],
-        // Two line beyond last newline in editor text (gets clamped):
-        ["7",
-         {line: 5, ch: 0}],
-        ["7:2",
-         {line: 5, ch: 0}],
-      ];
-      testVectors.forEach(vector => {
-        testJumpToLine(ed, vector[0], vector[1]);
-      });
-      teardown(ed, win);
-    });
+  const {ed, win} = await setup();
+  const textLines = [
+    "// line 1",
+    "//  line 2",
+    "//   line 3",
+    "//    line 4",
+    "//     line 5",
+    ""];
+  ed.setText(textLines.join("\n"));
+  await promiseWaitForFocus();
+
+  const testVectors = [
+    // Various useless inputs go to line 0, column 0 or do nothing.
+    ["",
+      {line: 0, ch: 0}],
+    [":",
+      {line: 0, ch: 0}],
+    [" ",
+      {line: 0, ch: 0}],
+    [" : ",
+      {line: 0, ch: 0}],
+    ["a:b",
+      {line: 0, ch: 0}],
+    ["LINE: COLUMN ",
+      {line: 0, ch: 0}],
+    ["-1",
+      {line: 0, ch: 0}],
+    [":-1",
+      {line: 0, ch: 0}],
+    ["-1:-1",
+      {line: 0, ch: 0}],
+    ["0",
+      {line: 0, ch: 0}],
+    [":0",
+      {line: 0, ch: 0}],
+    ["0:0",
+      {line: 0, ch: 0}],
+    // Starting here expect data needs to get updated for length changes to
+    // "textLines" above.
+    // Just jump to line
+    ["1",
+      {line: 0, ch: 0}],
+    // Jump to second character in line
+    ["1:2",
+      {line: 0, ch: 1}],
+    // Jump to last character on line
+    ["1:9",
+      {line: 0, ch: 8}],
+    // Jump just after last character on line (end of line)
+    ["1:10",
+      {line: 0, ch: 9}],
+    // Jump one character past end of line (gets clamped to end of line)
+    ["1:11",
+      {line: 0, ch: 9}],
+    ["2",
+      {line: 1, ch: 0}],
+    ["2:2",
+      {line: 1, ch: 1}],
+    ["2:10",
+      {line: 1, ch: 9}],
+    ["2:11",
+      {line: 1, ch: 10}],
+    ["2:12",
+      {line: 1, ch: 10}],
+    ["3",
+      {line: 2, ch: 0}],
+    ["3:2",
+      {line: 2, ch: 1}],
+    ["3:11",
+      {line: 2, ch: 10}],
+    ["3:12",
+      {line: 2, ch: 11}],
+    ["3:13",
+      {line: 2, ch: 11}],
+    ["4",
+      {line: 3, ch: 0}],
+    ["4:2",
+      {line: 3, ch: 1}],
+    ["4:12",
+      {line: 3, ch: 11}],
+    ["4:13",
+      {line: 3, ch: 12}],
+    ["4:14",
+      {line: 3, ch: 12}],
+    ["5",
+      {line: 4, ch: 0}],
+    ["5:2",
+      {line: 4, ch: 1}],
+    ["5:13",
+      {line: 4, ch: 12}],
+    ["5:14",
+      {line: 4, ch: 13}],
+    ["5:15",
+      {line: 4, ch: 13}],
+    // One line beyond last newline in editor text:
+    ["6",
+      {line: 5, ch: 0}],
+    ["6:2",
+      {line: 5, ch: 0}],
+    // Two line beyond last newline in editor text (gets clamped):
+    ["7",
+      {line: 5, ch: 0}],
+    ["7:2",
+      {line: 5, ch: 0}],
+  ];
+  testVectors.forEach(vector => {
+    testJumpToLine(ed, vector[0], vector[1]);
   });
+  teardown(ed, win);
 }
--- a/devtools/client/sourceeditor/test/browser_editor_history.js
+++ b/devtools/client/sourceeditor/test/browser_editor_history.js
@@ -1,32 +1,31 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-function test() {
+async function test() {
   waitForExplicitFinish();
-  setup((ed, win) => {
-    ok(ed.isClean(), "default isClean");
-    ok(!ed.canUndo(), "default canUndo");
-    ok(!ed.canRedo(), "default canRedo");
+  const {ed, win} = await setup();
+  ok(ed.isClean(), "default isClean");
+  ok(!ed.canUndo(), "default canUndo");
+  ok(!ed.canRedo(), "default canRedo");
 
-    ed.setText("Hello, World!");
-    ok(!ed.isClean(), "isClean");
-    ok(ed.canUndo(), "canUndo");
-    ok(!ed.canRedo(), "canRedo");
+  ed.setText("Hello, World!");
+  ok(!ed.isClean(), "isClean");
+  ok(ed.canUndo(), "canUndo");
+  ok(!ed.canRedo(), "canRedo");
 
-    ed.undo();
-    ok(ed.isClean(), "isClean after undo");
-    ok(!ed.canUndo(), "canUndo after undo");
-    ok(ed.canRedo(), "canRedo after undo");
+  ed.undo();
+  ok(ed.isClean(), "isClean after undo");
+  ok(!ed.canUndo(), "canUndo after undo");
+  ok(ed.canRedo(), "canRedo after undo");
 
-    ed.setText("What's up?");
-    ed.setClean();
-    ok(ed.isClean(), "isClean after setClean");
-    ok(ed.canUndo(), "canUndo after setClean");
-    ok(!ed.canRedo(), "canRedo after setClean");
+  ed.setText("What's up?");
+  ed.setClean();
+  ok(ed.isClean(), "isClean after setClean");
+  ok(ed.canUndo(), "canUndo after setClean");
+  ok(!ed.canRedo(), "canRedo after setClean");
 
-    teardown(ed, win);
-  });
+  teardown(ed, win);
 }
--- a/devtools/client/sourceeditor/test/browser_editor_markers.js
+++ b/devtools/client/sourceeditor/test/browser_editor_markers.js
@@ -1,39 +1,38 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-function test() {
+async function test() {
   waitForExplicitFinish();
-  setup((ed, win) => {
-    ok(!ed.hasMarker(0, "breakpoints", "test"), "default is ok");
-    ed.addMarker(0, "breakpoints", "test");
-    ed.addMarker(0, "breakpoints", "test2");
-    ok(ed.hasMarker(0, "breakpoints", "test"), "addMarker/1");
-    ok(ed.hasMarker(0, "breakpoints", "test2"), "addMarker/2");
+  const {ed, win} = await setup();
+  ok(!ed.hasMarker(0, "breakpoints", "test"), "default is ok");
+  ed.addMarker(0, "breakpoints", "test");
+  ed.addMarker(0, "breakpoints", "test2");
+  ok(ed.hasMarker(0, "breakpoints", "test"), "addMarker/1");
+  ok(ed.hasMarker(0, "breakpoints", "test2"), "addMarker/2");
 
-    ed.removeMarker(0, "breakpoints", "test");
-    ok(!ed.hasMarker(0, "breakpoints", "test"), "removeMarker/1");
-    ok(ed.hasMarker(0, "breakpoints", "test2"), "removeMarker/2");
-
-    ed.removeAllMarkers("breakpoints");
-    ok(!ed.hasMarker(0, "breakpoints", "test"), "removeAllMarkers/1");
-    ok(!ed.hasMarker(0, "breakpoints", "test2"), "removeAllMarkers/2");
+  ed.removeMarker(0, "breakpoints", "test");
+  ok(!ed.hasMarker(0, "breakpoints", "test"), "removeMarker/1");
+  ok(ed.hasMarker(0, "breakpoints", "test2"), "removeMarker/2");
 
-    ed.addMarker(0, "breakpoints", "breakpoint");
-    ed.setMarkerListeners(0, "breakpoints", "breakpoint", {
-      "click": (line, marker, param) => {
-        is(line, 0, "line is ok");
-        is(marker.className, "breakpoint", "marker is ok");
-        ok(param, "click is ok");
+  ed.removeAllMarkers("breakpoints");
+  ok(!ed.hasMarker(0, "breakpoints", "test"), "removeAllMarkers/1");
+  ok(!ed.hasMarker(0, "breakpoints", "test2"), "removeAllMarkers/2");
 
-        teardown(ed, win);
-      },
-    }, [ true ]);
+  ed.addMarker(0, "breakpoints", "breakpoint");
+  ed.setMarkerListeners(0, "breakpoints", "breakpoint", {
+    "click": (line, marker, param) => {
+      is(line, 0, "line is ok");
+      is(marker.className, "breakpoint", "marker is ok");
+      ok(param, "click is ok");
 
-    const env = win.document.querySelector("iframe").contentWindow;
-    const div = env.document.querySelector("div.breakpoint");
-    div.click();
-  });
+      teardown(ed, win);
+    },
+  }, [ true ]);
+
+  const env = win.document.querySelector("iframe").contentWindow;
+  const div = env.document.querySelector("div.breakpoint");
+  div.click();
 }
--- a/devtools/client/sourceeditor/test/browser_editor_movelines.js
+++ b/devtools/client/sourceeditor/test/browser_editor_movelines.js
@@ -1,63 +1,62 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-function test() {
+async function test() {
   waitForExplicitFinish();
-  setup((ed, win) => {
-    const simpleProg = "function foo() {\n  let i = 1;\n  let j = 2;\n  " +
-                     "return bar;\n}";
-    ed.setText(simpleProg);
+  const {ed, win} = await setup();
+  const simpleProg = "function foo() {\n  let i = 1;\n  let j = 2;\n  " +
+                    "return bar;\n}";
+  ed.setText(simpleProg);
 
-    // Move first line up
-    ed.setCursor({ line: 0, ch: 0 });
-    ed.moveLineUp();
-    is(ed.getText(0), "function foo() {", "getText(num)");
-    ch(ed.getCursor(), { line: 0, ch: 0 }, "getCursor");
+  // Move first line up
+  ed.setCursor({ line: 0, ch: 0 });
+  ed.moveLineUp();
+  is(ed.getText(0), "function foo() {", "getText(num)");
+  ch(ed.getCursor(), { line: 0, ch: 0 }, "getCursor");
 
-    // Move last line down
-    ed.setCursor({ line: 4, ch: 0 });
-    ed.moveLineDown();
-    is(ed.getText(4), "}", "getText(num)");
-    ch(ed.getCursor(), { line: 4, ch: 0 }, "getCursor");
+  // Move last line down
+  ed.setCursor({ line: 4, ch: 0 });
+  ed.moveLineDown();
+  is(ed.getText(4), "}", "getText(num)");
+  ch(ed.getCursor(), { line: 4, ch: 0 }, "getCursor");
 
-    // Move line 2 up
-    ed.setCursor({ line: 1, ch: 5});
-    ed.moveLineUp();
-    is(ed.getText(0), "  let i = 1;", "getText(num)");
-    is(ed.getText(1), "function foo() {", "getText(num)");
-    ch(ed.getCursor(), { line: 0, ch: 5 }, "getCursor");
+  // Move line 2 up
+  ed.setCursor({ line: 1, ch: 5});
+  ed.moveLineUp();
+  is(ed.getText(0), "  let i = 1;", "getText(num)");
+  is(ed.getText(1), "function foo() {", "getText(num)");
+  ch(ed.getCursor(), { line: 0, ch: 5 }, "getCursor");
 
-    // Undo previous move by moving line 1 down
-    ed.moveLineDown();
-    is(ed.getText(0), "function foo() {", "getText(num)");
-    is(ed.getText(1), "  let i = 1;", "getText(num)");
-    ch(ed.getCursor(), { line: 1, ch: 5 }, "getCursor");
+  // Undo previous move by moving line 1 down
+  ed.moveLineDown();
+  is(ed.getText(0), "function foo() {", "getText(num)");
+  is(ed.getText(1), "  let i = 1;", "getText(num)");
+  ch(ed.getCursor(), { line: 1, ch: 5 }, "getCursor");
 
-    // Move line 2 and 3 up
-    ed.setSelection({ line: 1, ch: 0 }, { line: 2, ch: 0 });
-    ed.moveLineUp();
-    is(ed.getText(0), "  let i = 1;", "getText(num)");
-    is(ed.getText(1), "  let j = 2;", "getText(num)");
-    is(ed.getText(2), "function foo() {", "getText(num)");
-    ch(ed.getCursor("start"), { line: 0, ch: 0 }, "getCursor(string)");
-    ch(ed.getCursor("end"), { line: 1, ch: 0 }, "getCursor(string)");
+  // Move line 2 and 3 up
+  ed.setSelection({ line: 1, ch: 0 }, { line: 2, ch: 0 });
+  ed.moveLineUp();
+  is(ed.getText(0), "  let i = 1;", "getText(num)");
+  is(ed.getText(1), "  let j = 2;", "getText(num)");
+  is(ed.getText(2), "function foo() {", "getText(num)");
+  ch(ed.getCursor("start"), { line: 0, ch: 0 }, "getCursor(string)");
+  ch(ed.getCursor("end"), { line: 1, ch: 0 }, "getCursor(string)");
 
-    // Move line 1 to 3 down twice
-    ed.dropSelection();
-    ed.setSelection({ line: 0, ch: 7 }, { line: 2, ch: 5 });
-    ed.moveLineDown();
-    ed.moveLineDown();
-    is(ed.getText(0), "  return bar;", "getText(num)");
-    is(ed.getText(1), "}", "getText(num)");
-    is(ed.getText(2), "  let i = 1;", "getText(num)");
-    is(ed.getText(3), "  let j = 2;", "getText(num)");
-    is(ed.getText(4), "function foo() {", "getText(num)");
-    ch(ed.getCursor("start"), { line: 2, ch: 7 }, "getCursor(string)");
-    ch(ed.getCursor("end"), { line: 4, ch: 5 }, "getCursor(string)");
+  // Move line 1 to 3 down twice
+  ed.dropSelection();
+  ed.setSelection({ line: 0, ch: 7 }, { line: 2, ch: 5 });
+  ed.moveLineDown();
+  ed.moveLineDown();
+  is(ed.getText(0), "  return bar;", "getText(num)");
+  is(ed.getText(1), "}", "getText(num)");
+  is(ed.getText(2), "  let i = 1;", "getText(num)");
+  is(ed.getText(3), "  let j = 2;", "getText(num)");
+  is(ed.getText(4), "function foo() {", "getText(num)");
+  ch(ed.getCursor("start"), { line: 2, ch: 7 }, "getCursor(string)");
+  ch(ed.getCursor("end"), { line: 4, ch: 5 }, "getCursor(string)");
 
-    teardown(ed, win);
-  });
+  teardown(ed, win);
 }
--- a/devtools/client/sourceeditor/test/browser_editor_prefs.js
+++ b/devtools/client/sourceeditor/test/browser_editor_prefs.js
@@ -9,113 +9,112 @@
 const TAB_SIZE = "devtools.editor.tabsize";
 const ENABLE_CODE_FOLDING = "devtools.editor.enableCodeFolding";
 const EXPAND_TAB = "devtools.editor.expandtab";
 const KEYMAP = "devtools.editor.keymap";
 const AUTO_CLOSE = "devtools.editor.autoclosebrackets";
 const AUTOCOMPLETE = "devtools.editor.autocomplete";
 const DETECT_INDENT = "devtools.editor.detectindentation";
 
-function test() {
+async function test() {
   waitForExplicitFinish();
-  setup((ed, win) => {
-    Assert.deepEqual(ed.getOption("gutters"), [
-      "CodeMirror-linenumbers",
-      "breakpoints",
-      "CodeMirror-foldgutter"], "gutters is correct");
+  const {ed, win} = await setup();
+  Assert.deepEqual(ed.getOption("gutters"), [
+    "CodeMirror-linenumbers",
+    "breakpoints",
+    "CodeMirror-foldgutter"], "gutters is correct");
 
-    ed.setText("Checking preferences.");
+  ed.setText("Checking preferences.");
 
-    info("Turning prefs off");
+  info("Turning prefs off");
 
-    ed.setOption("autocomplete", true);
+  ed.setOption("autocomplete", true);
 
-    Services.prefs.setIntPref(TAB_SIZE, 2);
-    Services.prefs.setBoolPref(ENABLE_CODE_FOLDING, false);
-    Services.prefs.setBoolPref(EXPAND_TAB, false);
-    Services.prefs.setCharPref(KEYMAP, "default");
-    Services.prefs.setBoolPref(AUTO_CLOSE, false);
-    Services.prefs.setBoolPref(AUTOCOMPLETE, false);
-    Services.prefs.setBoolPref(DETECT_INDENT, false);
+  Services.prefs.setIntPref(TAB_SIZE, 2);
+  Services.prefs.setBoolPref(ENABLE_CODE_FOLDING, false);
+  Services.prefs.setBoolPref(EXPAND_TAB, false);
+  Services.prefs.setCharPref(KEYMAP, "default");
+  Services.prefs.setBoolPref(AUTO_CLOSE, false);
+  Services.prefs.setBoolPref(AUTOCOMPLETE, false);
+  Services.prefs.setBoolPref(DETECT_INDENT, false);
 
-    Assert.deepEqual(ed.getOption("gutters"), [
-      "CodeMirror-linenumbers",
-      "breakpoints"], "gutters is correct");
+  Assert.deepEqual(ed.getOption("gutters"), [
+    "CodeMirror-linenumbers",
+    "breakpoints"], "gutters is correct");
 
-    is(ed.getOption("tabSize"), 2, "tabSize is correct");
-    is(ed.getOption("indentUnit"), 2, "indentUnit is correct");
-    is(ed.getOption("foldGutter"), false, "foldGutter is correct");
-    is(ed.getOption("enableCodeFolding"), undefined,
-      "enableCodeFolding is correct");
-    is(ed.getOption("indentWithTabs"), true, "indentWithTabs is correct");
-    is(ed.getOption("keyMap"), "default", "keyMap is correct");
-    is(ed.getOption("autoCloseBrackets"), "", "autoCloseBrackets is correct");
-    is(ed.getOption("autocomplete"), true, "autocomplete is correct");
-    ok(!ed.isAutocompletionEnabled(), "Autocompletion is not enabled");
+  is(ed.getOption("tabSize"), 2, "tabSize is correct");
+  is(ed.getOption("indentUnit"), 2, "indentUnit is correct");
+  is(ed.getOption("foldGutter"), false, "foldGutter is correct");
+  is(ed.getOption("enableCodeFolding"), undefined,
+    "enableCodeFolding is correct");
+  is(ed.getOption("indentWithTabs"), true, "indentWithTabs is correct");
+  is(ed.getOption("keyMap"), "default", "keyMap is correct");
+  is(ed.getOption("autoCloseBrackets"), "", "autoCloseBrackets is correct");
+  is(ed.getOption("autocomplete"), true, "autocomplete is correct");
+  ok(!ed.isAutocompletionEnabled(), "Autocompletion is not enabled");
 
-    info("Turning prefs on");
+  info("Turning prefs on");
 
-    Services.prefs.setIntPref(TAB_SIZE, 4);
-    Services.prefs.setBoolPref(ENABLE_CODE_FOLDING, true);
-    Services.prefs.setBoolPref(EXPAND_TAB, true);
-    Services.prefs.setCharPref(KEYMAP, "sublime");
-    Services.prefs.setBoolPref(AUTO_CLOSE, true);
-    Services.prefs.setBoolPref(AUTOCOMPLETE, true);
+  Services.prefs.setIntPref(TAB_SIZE, 4);
+  Services.prefs.setBoolPref(ENABLE_CODE_FOLDING, true);
+  Services.prefs.setBoolPref(EXPAND_TAB, true);
+  Services.prefs.setCharPref(KEYMAP, "sublime");
+  Services.prefs.setBoolPref(AUTO_CLOSE, true);
+  Services.prefs.setBoolPref(AUTOCOMPLETE, true);
 
-    Assert.deepEqual(ed.getOption("gutters"), [
-      "CodeMirror-linenumbers",
-      "breakpoints",
-      "CodeMirror-foldgutter"], "gutters is correct");
+  Assert.deepEqual(ed.getOption("gutters"), [
+    "CodeMirror-linenumbers",
+    "breakpoints",
+    "CodeMirror-foldgutter"], "gutters is correct");
 
-    is(ed.getOption("tabSize"), 4, "tabSize is correct");
-    is(ed.getOption("indentUnit"), 4, "indentUnit is correct");
-    is(ed.getOption("foldGutter"), true, "foldGutter is correct");
-    is(ed.getOption("enableCodeFolding"), undefined,
-      "enableCodeFolding is correct");
-    is(ed.getOption("indentWithTabs"), false, "indentWithTabs is correct");
-    is(ed.getOption("keyMap"), "sublime", "keyMap is correct");
-    is(ed.getOption("autoCloseBrackets"), "()[]{}''\"\"``",
-      "autoCloseBrackets is correct");
-    is(ed.getOption("autocomplete"), true, "autocomplete is correct");
-    ok(ed.isAutocompletionEnabled(), "Autocompletion is enabled");
+  is(ed.getOption("tabSize"), 4, "tabSize is correct");
+  is(ed.getOption("indentUnit"), 4, "indentUnit is correct");
+  is(ed.getOption("foldGutter"), true, "foldGutter is correct");
+  is(ed.getOption("enableCodeFolding"), undefined,
+    "enableCodeFolding is correct");
+  is(ed.getOption("indentWithTabs"), false, "indentWithTabs is correct");
+  is(ed.getOption("keyMap"), "sublime", "keyMap is correct");
+  is(ed.getOption("autoCloseBrackets"), "()[]{}''\"\"``",
+    "autoCloseBrackets is correct");
+  is(ed.getOption("autocomplete"), true, "autocomplete is correct");
+  ok(ed.isAutocompletionEnabled(), "Autocompletion is enabled");
 
-    info("Forcing foldGutter off using enableCodeFolding");
-    ed.setOption("enableCodeFolding", false);
+  info("Forcing foldGutter off using enableCodeFolding");
+  ed.setOption("enableCodeFolding", false);
 
-    is(ed.getOption("foldGutter"), false, "foldGutter is correct");
-    is(ed.getOption("enableCodeFolding"), false,
-      "enableCodeFolding is correct");
-    Assert.deepEqual(ed.getOption("gutters"), [
-      "CodeMirror-linenumbers",
-      "breakpoints"], "gutters is correct");
+  is(ed.getOption("foldGutter"), false, "foldGutter is correct");
+  is(ed.getOption("enableCodeFolding"), false,
+    "enableCodeFolding is correct");
+  Assert.deepEqual(ed.getOption("gutters"), [
+    "CodeMirror-linenumbers",
+    "breakpoints"], "gutters is correct");
 
-    info("Forcing foldGutter on using enableCodeFolding");
-    ed.setOption("enableCodeFolding", true);
+  info("Forcing foldGutter on using enableCodeFolding");
+  ed.setOption("enableCodeFolding", true);
 
-    is(ed.getOption("foldGutter"), true, "foldGutter is correct");
-    is(ed.getOption("enableCodeFolding"), true, "enableCodeFolding is correct");
-    Assert.deepEqual(ed.getOption("gutters"), [
-      "CodeMirror-linenumbers",
-      "breakpoints",
-      "CodeMirror-foldgutter"], "gutters is correct");
+  is(ed.getOption("foldGutter"), true, "foldGutter is correct");
+  is(ed.getOption("enableCodeFolding"), true, "enableCodeFolding is correct");
+  Assert.deepEqual(ed.getOption("gutters"), [
+    "CodeMirror-linenumbers",
+    "breakpoints",
+    "CodeMirror-foldgutter"], "gutters is correct");
 
-    info("Checking indentation detection");
-
-    Services.prefs.setBoolPref(DETECT_INDENT, true);
+  info("Checking indentation detection");
 
-    ed.setText("Detecting\n\tTabs");
-    is(ed.getOption("indentWithTabs"), true, "indentWithTabs is correct");
-    is(ed.getOption("indentUnit"), 4, "indentUnit is correct");
+  Services.prefs.setBoolPref(DETECT_INDENT, true);
 
-    ed.setText("body {\n  color:red;\n  a:b;\n}");
-    is(ed.getOption("indentWithTabs"), false, "indentWithTabs is correct");
-    is(ed.getOption("indentUnit"), 2, "indentUnit is correct");
+  ed.setText("Detecting\n\tTabs");
+  is(ed.getOption("indentWithTabs"), true, "indentWithTabs is correct");
+  is(ed.getOption("indentUnit"), 4, "indentUnit is correct");
+
+  ed.setText("body {\n  color:red;\n  a:b;\n}");
+  is(ed.getOption("indentWithTabs"), false, "indentWithTabs is correct");
+  is(ed.getOption("indentUnit"), 2, "indentUnit is correct");
 
-    Services.prefs.clearUserPref(TAB_SIZE);
-    Services.prefs.clearUserPref(EXPAND_TAB);
-    Services.prefs.clearUserPref(KEYMAP);
-    Services.prefs.clearUserPref(AUTO_CLOSE);
-    Services.prefs.clearUserPref(AUTOCOMPLETE);
-    Services.prefs.clearUserPref(DETECT_INDENT);
+  Services.prefs.clearUserPref(TAB_SIZE);
+  Services.prefs.clearUserPref(EXPAND_TAB);
+  Services.prefs.clearUserPref(KEYMAP);
+  Services.prefs.clearUserPref(AUTO_CLOSE);
+  Services.prefs.clearUserPref(AUTOCOMPLETE);
+  Services.prefs.clearUserPref(DETECT_INDENT);
 
-    teardown(ed, win);
-  });
+  teardown(ed, win);
 }
--- a/devtools/client/sourceeditor/test/browser_editor_script_injection.js
+++ b/devtools/client/sourceeditor/test/browser_editor_script_injection.js
@@ -10,17 +10,17 @@ add_task(async function() {
   await runTest();
 });
 
 async function runTest() {
   const baseURL =
     "chrome://mochitests/content/browser/devtools/client/sourceeditor/test";
   const injectedText = "Script successfully injected!";
 
-  const {ed, win} = await setup(null, {
+  const {ed, win} = await setup({
     mode: "ruby",
     externalScripts: [`${baseURL}/cm_script_injection_test.js`,
                       `${baseURL}/cm_mode_ruby.js`],
   });
 
   is(ed.getText(), injectedText, "The text has been injected");
   is(ed.getOption("mode"), "ruby", "The ruby mode is correctly set");
   teardown(ed, win);
--- a/devtools/client/sourceeditor/test/head.js
+++ b/devtools/client/sourceeditor/test/head.js
@@ -11,57 +11,50 @@
 Services.scriptloader.loadSubScript(
   "chrome://mochitests/content/browser/devtools/client/shared/test/shared-head.js",
   this);
 
 const { NetUtil } = require("resource://gre/modules/NetUtil.jsm");
 const Editor = require("devtools/client/sourceeditor/editor");
 const {getClientCssProperties} = require("devtools/shared/fronts/css-properties");
 
-function promiseWaitForFocus() {
-  return new Promise(resolve =>
-    waitForFocus(resolve));
+function promiseWaitForFocus(el) {
+  return new Promise(resolve => waitForFocus(resolve, el));
 }
 
-function setup(cb, additionalOpts = {}) {
-  cb = cb || function() {};
-  return new Promise(resolve => {
+async function setup(additionalOpts = {}) {
+  try {
     const opt = "chrome,titlebar,toolbar,centerscreen,resizable,dialog=no";
-
     const win = Services.ww.openWindow(null, CHROME_URL_ROOT + "head.xul", "_blank", opt,
-                                     null);
+                                      null);
     const opts = {
       value: "Hello.",
       lineNumbers: true,
       foldGutter: true,
       gutters: ["CodeMirror-linenumbers", "breakpoints", "CodeMirror-foldgutter"],
       cssProperties: getClientCssProperties(),
+      ...additionalOpts,
     };
 
-    for (const o in additionalOpts) {
-      opts[o] = additionalOpts[o];
-    }
+    await once(win, "load");
+    await promiseWaitForFocus(win);
 
-    win.addEventListener("load", function() {
-      waitForFocus(function() {
-        const box = win.document.querySelector("box");
-        const editor = new Editor(opts);
+    const box = win.document.querySelector("box");
+    const editor = new Editor(opts);
+    await editor.appendTo(box);
 
-        editor.appendTo(box)
-          .then(() => {
-            resolve({
-              ed: editor,
-              win: win,
-              edWin: editor.container.contentWindow.wrappedJSObject,
-            });
-            cb(editor, win);
-          }, err => ok(false, err.message));
-      }, win);
-    }, {once: true});
-  });
+    return {
+      ed: editor,
+      win: win,
+      edWin: editor.container.contentWindow.wrappedJSObject,
+    };
+  } catch (o_O) {
+    ok(false, o_O.message);
+    return null;
+  }
 }
 
 function ch(exp, act, label) {
   is(exp.line, act.line, label + " (line)");
   is(exp.ch, act.ch, label + " (ch)");
 }
 
 function teardown(ed, win) {