Bug 1100200 - Part 1: Migrate to promise version. r=hsinyi
authorSzu-Yu Chen [:aknow] <szchen@mozilla.com>
Wed, 17 Dec 2014 23:47:54 +0800
changeset 220157 7ea0cf5b6bc644d587b01bdfdb9c669815db14de
parent 220156 d16461a97b4f90b42c3249637916f5be741f501f
child 220158 b5572f21d6ab744f9e155dcf68541aacd7389dce
push id10457
push userryanvm@gmail.com
push dateThu, 18 Dec 2014 01:54:25 +0000
treeherderfx-team@0e441ff66c5e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershsinyi
bugs1100200
milestone37.0a1
Bug 1100200 - Part 1: Migrate to promise version. r=hsinyi
dom/telephony/test/marionette/head.js
dom/telephony/test/marionette/manifest.ini
dom/telephony/test/marionette/test_crash_emulator.js
dom/telephony/test/marionette/test_emergency.js
dom/telephony/test/marionette/test_emergency_badNumber.js
dom/telephony/test/marionette/test_emergency_label.js
dom/telephony/test/marionette/test_incoming_already_connected.js
dom/telephony/test/marionette/test_incoming_already_held.js
dom/telephony/test/marionette/test_incoming_answer_hangup.js
dom/telephony/test/marionette/test_incoming_answer_hangup_oncallschanged.js
dom/telephony/test/marionette/test_incoming_answer_remote_hangup.js
dom/telephony/test/marionette/test_incoming_connecting_hangup.js
dom/telephony/test/marionette/test_incoming_connecting_remote_hangup.js
dom/telephony/test/marionette/test_incoming_hangup_held.js
dom/telephony/test/marionette/test_incoming_hold_resume.js
dom/telephony/test/marionette/test_incoming_onstatechange.js
dom/telephony/test/marionette/test_incoming_reject.js
dom/telephony/test/marionette/test_incoming_remote_cancel.js
dom/telephony/test/marionette/test_incoming_remote_hangup_held.js
dom/telephony/test/marionette/test_multiple_hold.js
dom/telephony/test/marionette/test_outgoing_already_held.js
dom/telephony/test/marionette/test_outgoing_answer_hangup.js
dom/telephony/test/marionette/test_outgoing_answer_hangup_oncallschanged.js
dom/telephony/test/marionette/test_outgoing_answer_local_hangup.js
dom/telephony/test/marionette/test_outgoing_answer_radio_off.js
dom/telephony/test/marionette/test_outgoing_badNumber.js
dom/telephony/test/marionette/test_outgoing_busy.js
dom/telephony/test/marionette/test_outgoing_emergency_in_airplane_mode.js
dom/telephony/test/marionette/test_outgoing_error_state.js
dom/telephony/test/marionette/test_outgoing_hangup_alerting.js
dom/telephony/test/marionette/test_outgoing_hangup_held.js
dom/telephony/test/marionette/test_outgoing_hold_resume.js
dom/telephony/test/marionette/test_outgoing_onstatechange.js
dom/telephony/test/marionette/test_outgoing_radio_off.js
dom/telephony/test/marionette/test_outgoing_reject.js
dom/telephony/test/marionette/test_outgoing_remote_hangup_held.js
dom/telephony/test/marionette/test_redundant_operations.js
dom/telephony/test/marionette/test_swap_held_and_active.js
dom/telephony/test/marionette/test_temporary_clir.js
--- a/dom/telephony/test/marionette/head.js
+++ b/dom/telephony/test/marionette/head.js
@@ -28,17 +28,17 @@ let emulator = (function() {
 
   // Overwritten it so people could not call this function directly.
   runEmulatorCmd = function() {
     throw "Use emulator.runCmdWithCallback(cmd, callback) instead of runEmulatorCmd";
   };
 
   // Overwritten it so people could not call this function directly.
   runEmulatorShell = function() {
-    throw "Use emulator.runShellCmd(cmd, callback) instead of runEmulatorShell";
+    throw "Use emulator.runShellCmd(cmd) instead of runEmulatorShell";
   };
 
   /**
    * @return Promise
    */
   function runCmd(cmd) {
     return new Promise(function(resolve, reject) {
       pendingCmdCount++;
@@ -152,23 +152,28 @@ let emulator = (function() {
     });
   }
 
   /**
    * Wait for callschanged event with event.call == aExpectedCall
    *
    * @param aTarget
    *        A event target.
-   * @param aExpectedCall
+   * @param aExpectedCall [optional]
    *        Expected call for event.call
-   * @return Promise<DOMEvent>
+   * @return Promise<TelephonyCall>
    */
   function waitForCallsChangedEvent(aTarget, aExpectedCall) {
-    return waitForEvent(aTarget, "callschanged",
-                        event => event.call == aExpectedCall);
+    if (aExpectedCall === undefined) {
+      return waitForEvent(aTarget, "callschanged").then(event => event.call);
+    } else {
+      return waitForEvent(aTarget, "callschanged",
+                          event => event.call == aExpectedCall)
+               .then(event => event.call)
+    }
   }
 
   /**
    * Wait for call state event, e.g., "connected", "disconnected", ...
    *
    * @param aTarget
    *        A event target.
    * @param aState
@@ -436,44 +441,53 @@ let emulator = (function() {
    * @param serviceId [optional]
    *        Identification of a service. 0 is set as default.
    * @return Promise<TelephonyCall>
    */
   function dial(number, serviceId) {
     serviceId = typeof serviceId !== "undefined" ? serviceId : 0;
     log("Make an outgoing call: " + number + ", serviceId: " + serviceId);
 
+    let outCall;
+
     return telephony.dial(number, serviceId)
-      .then(call => {
-        ok(call);
-        is(call.id.number, number);
-        is(call.state, "dialing");
-        is(call.serviceId, serviceId);
-
-        return waitForNamedStateEvent(call, "alerting");
-      });
+      .then(call => outCall = call)
+      .then(() => {
+        ok(outCall instanceof TelephonyCall, "check instance");
+        is(outCall.id.number, number);
+        is(outCall.state, "dialing");
+        is(outCall.serviceId, serviceId);
+      })
+      .then(() => waitForNamedStateEvent(outCall, "alerting"));
   }
 
   /**
    * Make an outgoing emergency call.
    *
    * @param number
    *        A string.
    * @return Promise<TelephonyCall>
    */
   function dialEmergency(number) {
     log("Make an outgoing emergency call: " + number);
 
+    let outCall;
+
     return telephony.dialEmergency(number)
-      .then(call => {
-        ok(call);
-        is(call.id.number, number);
-        is(call.state, "dialing");
-
-        return waitForNamedStateEvent(call, "alerting");
+      .then(call => outCall = call)
+      .then(() => {
+        ok(outCall instanceof TelephonyCall, "check instance");
+        ok(outCall);
+        is(outCall.id.number, number);
+        is(outCall.state, "dialing");
+      })
+      .then(() => waitForNamedStateEvent(outCall, "alerting"))
+      .then(() => {
+        is(outCall.emergency, true, "check emergency");
+        return outCall;
       });
   }
 
   /**
    * Answer an incoming call.
    *
    * @param call
    *        An incoming TelephonyCall object.
@@ -1015,16 +1029,43 @@ let emulator = (function() {
     return telephony.dial(mmi).then(mmiCall => {
       ok(mmiCall instanceof MMICall, "mmiCall is instance of MMICall");
       ok(mmiCall.result instanceof Promise, "result is Promise");
       return mmiCall.result;
     });
   }
 
   /**
+   * Config radio.
+   *
+   * @param connection
+   *        MobileConnection object.
+   * @param enabled
+   *        True to enable the radio.
+   * @return Promise
+   */
+  function setRadioEnabled(connection, enabled) {
+    let desiredRadioState = enabled ? 'enabled' : 'disabled';
+    log("Set radio: " + desiredRadioState);
+
+    let promises = [];
+
+    let promise = gWaitForEvent(connection, "radiostatechange", event => {
+      let state = connection.radioState;
+      log("current radioState: " + state);
+      return state == desiredRadioState;
+    });
+    promises.push(promise);
+
+    promises.push(connection.setRadioEnabled(enabled));
+
+    return Promise.all(promises);
+  }
+
+  /**
    * Public members.
    */
 
   this.gDelay = delay;
   this.gWaitForEvent = waitForEvent;
   this.gWaitForCallsChangedEvent = waitForCallsChangedEvent;
   this.gWaitForNamedStateEvent = waitForNamedStateEvent;
   this.gWaitForStateChangeEvent = waitForStateChangeEvent;
@@ -1047,16 +1088,17 @@ let emulator = (function() {
   this.gRemoteHangUpCalls = remoteHangUpCalls;
   this.gAddCallsToConference = addCallsToConference;
   this.gHoldConference = holdConference;
   this.gResumeConference = resumeConference;
   this.gRemoveCallInConference = removeCallInConference;
   this.gHangUpCallInConference = hangUpCallInConference;
   this.gHangUpConference = hangUpConference;
   this.gSetupConference = setupConference;
+  this.gSetRadioEnabled = setRadioEnabled;
 }());
 
 function _startTest(permissions, test) {
   function permissionSetUp() {
     SpecialPowers.setBoolPref("dom.mozSettings.enabled", true);
     for (let per of permissions) {
       SpecialPowers.addPermission(per, true, document);
     }
--- a/dom/telephony/test/marionette/manifest.ini
+++ b/dom/telephony/test/marionette/manifest.ini
@@ -1,73 +1,68 @@
 [DEFAULT]
 b2g = true
 browser = false
 qemu = true
 
+[test_audiomanager_phonestate.js]
+[test_call_mute.js]
+[test_call_presentation.js]
+[test_conference_add_error.js]
+[test_conference_add_twice_error.js]
+[test_conference_remove_error.js]
+[test_conference_three_hangup_one.js]
+[test_conference_three_remove_one.js]
+[test_conference_two_calls.js]
+[test_conference_two_hangup_all.js]
+[test_conference_two_hangup_one.js]
+[test_conference_two_hold_resume.js]
+[test_conference_two_remove_one.js]
 [test_crash_emulator.js]
-[test_ready.js]
+[test_dsds_connection_conflict.js]
+[test_dsds_default_service_id.js]
+[test_dsds_normal_call.js]
+[test_emergency.js]
+[test_emergency_badNumber.js]
+[test_emergency_label.js]
+[test_incall_mmi_call_hold.js]
+[test_incall_mmi_call_waiting.js]
+[test_incall_mmi_conference.js]
+[test_incoming_already_connected.js]
+[test_incoming_already_held.js]
 [test_incoming_answer_hangup.js]
-[test_incoming_reject.js]
-[test_outgoing_answer_hangup.js]
 [test_incoming_answer_hangup_oncallschanged.js]
-[test_outgoing_answer_hangup_oncallschanged.js]
-[test_outgoing_hangup_alerting.js]
-[test_outgoing_hangup_held.js]
-[test_outgoing_radio_off.js]
-[test_outgoing_badNumber.js]
-[test_outgoing_busy.js]
-[test_outgoing_reject.js]
-[test_incoming_hold_resume.js]
-[test_outgoing_hold_resume.js]
-[test_incoming_already_connected.js]
 [test_incoming_answer_remote_hangup.js]
 [test_incoming_connecting_hangup.js]
 [test_incoming_connecting_remote_hangup.js]
 [test_incoming_hangup_held.js]
+[test_incoming_hold_resume.js]
+[test_incoming_onstatechange.js]
+[test_incoming_reject.js]
 [test_incoming_remote_cancel.js]
 [test_incoming_remote_hangup_held.js]
+[test_mmi.js]
+[test_mmi_call_forwarding.js]
+[test_mmi_change_pin.js]
+[test_mmi_unlock_puk.js]
+[test_multiple_hold.js]
 [test_outgoing_already_held.js]
+[test_outgoing_answer_hangup.js]
+[test_outgoing_answer_hangup_oncallschanged.js]
 [test_outgoing_answer_local_hangup.js]
-[test_outgoing_remote_hangup_held.js]
-disabled = Bug 820802
-[test_incoming_already_held.js]
-disabled = Bug 820802
-[test_swap_held_and_active.js]
-disabled = Bug 820802
-[test_incoming_onstatechange.js]
-disabled = Bug 820802
-[test_outgoing_onstatechange.js]
-disabled = Bug 821966
-[test_redundant_operations.js]
-disabled = Bug 821927
-[test_multiple_hold.js]
-disabled = Bug 821958
+[test_outgoing_answer_radio_off.js]
+[test_outgoing_auto_hold.js]
+[test_outgoing_badNumber.js]
+[test_outgoing_busy.js]
 [test_outgoing_emergency_in_airplane_mode.js]
-[test_emergency_label.js]
-[test_dsds_default_service_id.js]
-[test_call_mute.js]
-[test_dsds_normal_call.js]
-[test_dsds_connection_conflict.js]
-[test_audiomanager_phonestate.js]
-[test_outgoing_answer_radio_off.js]
-[test_conference_two_calls.js]
-[test_conference_add_error.js]
-[test_conference_remove_error.js]
-[test_conference_two_hangup_all.js]
-[test_conference_two_hangup_one.js]
-[test_conference_two_hold_resume.js]
-[test_conference_two_remove_one.js]
-[test_conference_three_hangup_one.js]
-[test_conference_three_remove_one.js]
-[test_conference_add_twice_error.js]
+[test_outgoing_error_state.js]
+[test_outgoing_hangup_alerting.js]
+[test_outgoing_hangup_held.js]
+[test_outgoing_hold_resume.js]
+[test_outgoing_onstatechange.js]
+[test_outgoing_radio_off.js]
+[test_outgoing_reject.js]
+[test_outgoing_remote_hangup_held.js]
 [test_outgoing_when_two_calls_on_line.js]
-[test_call_presentation.js]
+[test_ready.js]
+[test_redundant_operations.js]
+[test_swap_held_and_active.js]
 [test_temporary_clir.js]
-[test_outgoing_error_state.js]
-[test_outgoing_auto_hold.js]
-[test_mmi.js]
-[test_mmi_change_pin.js]
-[test_mmi_call_forwarding.js]
-[test_mmi_unlock_puk.js]
-[test_incall_mmi_call_waiting.js]
-[test_incall_mmi_call_hold.js]
-[test_incall_mmi_conference.js]
--- a/dom/telephony/test/marionette/test_crash_emulator.js
+++ b/dom/telephony/test/marionette/test_crash_emulator.js
@@ -1,45 +1,26 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let outNumber = "5555551111";
-let outgoingCall;
-
-function dial() {
-  log("Make an outgoing call.");
-  telephony.dial(outNumber).then(call => {
-    outgoingCall = call;
-    outgoingCall.onalerting = function onalerting(event) {
-      log("Received 'alerting' call event.");
-      answer();
-    };
-  });
-}
-
-function answer() {
-  log("Answering the outgoing call.");
+startTest(function() {
+  let outCall;
 
-  outgoingCall.onconnected = function onconnectedOut(event) {
-    log("Received 'connected' call event for the original outgoing call.");
-    // just some code to keep call active for awhile
-    callStartTime = Date.now();
-    waitFor(cleanUp,function() {
-      callDuration = Date.now() - callStartTime;
-      log("Waiting while call is active, call duration (ms): " + callDuration);
-      return(callDuration >= 2000);
-    });
-  };
-  emulator.runCmdWithCallback("gsm accept " + outNumber);
-}
-
-function cleanUp(){
-  outgoingCall.hangUp();
-  ok("passed");
-  finish();
-}
-
-startTest(function() {
-  dial();
+  gDial("5555551111")
+    .then(call => outCall = call)
+    .then(() => gRemoteAnswer(outCall))
+    .then(() => {
+      return new Promise(function(resolve, reject) {
+        callStartTime = Date.now();
+        waitFor(resolve,function() {
+          callDuration = Date.now() - callStartTime;
+          log("Waiting while call is active, call duration (ms): " + callDuration);
+          return(callDuration >= 2000);
+        });
+      });
+    })
+    .then(() => gHangUp(outCall))
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_emergency.js
+++ b/dom/telephony/test/marionette/test_emergency.js
@@ -1,88 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let number = "911";
-let outgoing;
-let calls;
-
-function dial() {
-  log("Make an emergency call.");
-
-  telephony.dialEmergency(number).then(call => {
-    outgoing = call;
-    ok(outgoing);
-    is(outgoing.id.number, number);
-    is(outgoing.state, "dialing");
-
-    is(outgoing, telephony.active);
-    //ok(telephony.calls === calls); // bug 717414
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoing);
-
-    outgoing.onalerting = function onalerting(event) {
-      log("Received 'onalerting' call event.");
-      is(outgoing, event.call);
-      is(outgoing.state, "alerting");
-      is(outgoing.emergency, true);
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "outbound to  " + number + "        : ringing");
-        answer();
-      });
-    };
-  });
-}
-
-function answer() {
-  log("Answering the emergency call.");
-
-  // We get no "connecting" event when the remote party answers the call.
+startTest(function() {
+  let outCall;
 
-  outgoing.onconnected = function onconnected(event) {
-    log("Received 'connected' call event.");
-    is(outgoing, event.call);
-    is(outgoing.state, "connected");
-
-    is(outgoing, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + number + "        : active");
-      hangUp();
-    });
-  };
-  emulator.runCmdWithCallback("gsm accept " + number);
-}
-
-function hangUp() {
-  log("Hanging up the emergency call.");
-
-  // We get no "disconnecting" event when the remote party terminates the call.
-
-  outgoing.ondisconnected = function ondisconnected(event) {
-    log("Received 'disconnected' call event.");
-    is(outgoing, event.call);
-    is(outgoing.state, "disconnected");
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  emulator.runCmdWithCallback("gsm cancel " + number);
-}
-
-function cleanUp() {
-  finish();
-}
-
-startTest(function() {
-  dial();
+  gDialEmergency("911")
+    .then(call => outCall = call)
+    .then(() => gRemoteAnswer(outCall))
+    .then(() => gHangUp(outCall))
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_emergency_badNumber.js
+++ b/dom/telephony/test/marionette/test_emergency_badNumber.js
@@ -1,32 +1,15 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let number = "not a valid emergency number";
-
-function dial() {
-  log("Make an outgoing call to an invalid number.");
-
-  telephony.dialEmergency(number).then(null, cause => {
-    log("Received promise 'reject'");
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-    is(cause, "BadNumberError");
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Initial call list: " + result);
-      cleanUp();
-    });
-  });
-}
-
-function cleanUp() {
-  finish();
-}
-
 startTest(function() {
-  dial();
+  gDialEmergency("not a valid emergency number")
+    .catch(cause => {
+      is(cause, "BadNumberError");
+      return gCheckAll(null, [], "", [], []);
+    })
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_emergency_label.js
+++ b/dom/telephony/test/marionette/test_emergency_label.js
@@ -10,62 +10,45 @@ function setEccListProperty(list) {
   log("Set property ril.ecclist: " + list);
 
   // We should wrap empty |list| by ''. Otherwise, the entire command will be
   // "setprop ril.ecclist" which causus the command error.
   if (!list) {
     list = "''";
   }
 
-  let deferred = Promise.defer();
-  try {
-    emulator.runShellCmd(["setprop","ril.ecclist", list]).then(function() {
-      deferred.resolve(list);
-    });
-  } catch (e) {
-    deferred.reject(e);
-  }
-  return deferred.promise;
+  return emulator.runShellCmd(["setprop","ril.ecclist", list])
+    .then(list => list);
 }
 
 function getEccListProperty() {
   log("Get property ril.ecclist.");
 
-  let deferred = Promise.defer();
-  try {
-    emulator.runShellCmd(["getprop","ril.ecclist"]).then(function(aResult) {
-      let list = !aResult.length ? "" : aResult[0];
-      deferred.resolve(list);
+  return emulator.runShellCmd(["getprop","ril.ecclist"])
+    .then(aResult => {
+      return !aResult.length ? "" : aResult[0];
     });
-  } catch (e) {
-    deferred.reject(e);
-  }
-  return deferred.promise;
 }
 
 function testEmergencyLabel(number, list) {
   if (!list) {
     list = DEFAULT_ECC_LIST;
   }
   let index = list.split(",").indexOf(number);
   let emergency = index != -1;
   log("= testEmergencyLabel = " + number + " should be " +
       (emergency ? "emergency" : "normal") + " call");
 
   let outCall;
 
   return gDial(number)
-    .then(call => { outCall = call; })
-    .then(() => {
-      is(outCall.emergency, emergency, "emergency result should be correct");
-    })
+    .then(call => outCall = call)
+    .then(() => is(outCall.emergency, emergency, "check emergency"))
     .then(() => gRemoteAnswer(outCall))
-    .then(() => {
-      is(outCall.emergency, emergency, "emergency result should be correct");
-    })
+    .then(() => is(outCall.emergency, emergency, "check emergency"))
     .then(() => gRemoteHangUp(outCall));
 }
 
 startTest(function() {
   let origEccList;
   let eccList;
 
   getEccListProperty()
--- a/dom/telephony/test/marionette/test_incoming_already_connected.js
+++ b/dom/telephony/test/marionette/test_incoming_already_connected.js
@@ -1,192 +1,47 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let outNumber = "5555551111";
-let inNumber = "5555552222";
-let outgoingCall;
-let incomingCall;
-let gotOriginalConnected = false;
-
-function dial() {
-  log("Make an outgoing call.");
-  telephony.dial(outNumber).then(call => {
-    outgoingCall = call;
-    ok(outgoingCall);
-    is(outgoingCall.id.number, outNumber);
-    is(outgoingCall.state, "dialing");
-
-    is(outgoingCall, telephony.active);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoingCall);
-
-    outgoingCall.onalerting = function onalerting(event) {
-      log("Received 'onalerting' call event.");
-      is(outgoingCall, event.call);
-      is(outgoingCall.state, "alerting");
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "outbound to  " + outNumber + " : ringing");
-        answer();
-      });
-    };
-  });
-}
-
-function answer() {
-  log("Answering the outgoing call.");
-
-  // We get no "connecting" event when the remote party answers the call.
-  outgoingCall.onconnected = function onconnectedOut(event) {
-    log("Received 'connected' call event for the original outgoing call.");
-
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "connected");
-    is(outgoingCall, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + outNumber + " : active");
-
-      if(!gotOriginalConnected){
-        gotOriginalConnected = true;
-        simulateIncoming();
-      } else {
-        // Received connected event for original call multiple times (fail)
-        ok(false,
-           "Received 'connected' event for original call multiple times");
-      }
-    });
-  };
-  emulator.runCmdWithCallback("gsm accept " + outNumber);
-}
-
-// With one connected call already, simulate an incoming call
-function simulateIncoming() {
-  log("Simulating an incoming call (with one call already connected).");
-
-  telephony.onincoming = function onincoming(event) {
-    log("Received 'incoming' call event.");
-    incomingCall = event.call;
-    ok(incomingCall);
-    is(incomingCall.id.number, inNumber);
-    is(incomingCall.state, "incoming");
-
-    // Should be two calls now
-    is(telephony.calls.length, 2);
-    is(telephony.calls[0], outgoingCall);
-    is(telephony.calls[1], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + outNumber + " : active");
-      is(result[1], "inbound from " + inNumber + " : waiting");
-      answerIncoming();
-    });
-  };
-  emulator.runCmdWithCallback("gsm call " + inNumber);
-}
-
-// Answer incoming call; original outgoing call should be held
-function answerIncoming() {
-  log("Answering the incoming call.");
+const outNumber = "5555551111";
+const outInfo = gOutCallStrPool(outNumber);
+let outCall;
 
-  let gotConnecting = false;
-  incomingCall.onconnecting = function onconnectingIn(event) {
-    log("Received 'connecting' call event for incoming/2nd call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connecting");
-    gotConnecting = true;
-  };
-
-  incomingCall.onconnected = function onconnectedIn(event) {
-    log("Received 'connected' call event for incoming/2nd call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connected");
-    ok(gotConnecting);
-
-    is(incomingCall, telephony.active);
-    is(outgoingCall.state, "held");
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + outNumber + " : held");
-      is(result[1], "inbound from " + inNumber + " : active");
-      hangUpOutgoing();
-    });
-  };
-  incomingCall.answer();
-}
-
-// Hang-up original outgoing (now held) call
-function hangUpOutgoing() {
-  log("Hanging up the original outgoing (now held) call.");
-
-  let gotDisconnecting = false;
-  outgoingCall.ondisconnecting = function ondisconnectingOut(event) {
-    log("Received 'disconnecting' call event for original outgoing call.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  outgoingCall.ondisconnected = function ondisconnectedOut(event) {
-    log("Received 'disconnected' call event for original outgoing call.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "disconnected");
-    ok(gotDisconnecting);
-
-    // Back to one call now
-    is(telephony.calls.length, 1);
-    is(incomingCall.state, "connected");
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : active");
-      hangUpIncoming();
-    });
-  };
-  outgoingCall.hangUp();
-}
-
-// Hang-up remaining (incoming) call
-function hangUpIncoming() {
-  log("Hanging up the remaining (incoming) call.");
-
-  let gotDisconnecting = false;
-  incomingCall.ondisconnecting = function ondisconnectingIn(event) {
-    log("Received 'disconnecting' call event for remaining (incoming) call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  incomingCall.ondisconnected = function ondisconnectedIn(event) {
-    log("Received 'disconnected' call event for remaining (incoming) call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnected");
-    ok(gotDisconnecting);
-
-    // Zero calls left
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  incomingCall.hangUp();
-}
-
-function cleanUp() {
-  telephony.onincoming = null;
-  finish();
-}
+const inNumber = "5555552222";
+const inInfo = gInCallStrPool(inNumber);
+let inCall;
 
 startTest(function() {
-  dial();
+  gDial(outNumber)
+    .then(call => outCall = call)
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing]))
+    .then(() => gRemoteAnswer(outCall))
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active]))
+
+    // With one connected call already, simulate an incoming call
+    .then(() => gRemoteDial(inNumber))
+    .then(call => inCall = call)
+    .then(() => gCheckAll(outCall, [outCall, inCall], "", [],
+                          [outInfo.active, inInfo.waiting]))
+
+    // Answer incoming call; original outgoing call should be held
+    .then(() => {
+      let p1 = gWaitForNamedStateEvent(outCall, "held");
+      let p2 = gAnswer(inCall);
+      return Promise.all([p1, p2]);
+    })
+    .then(() => gCheckAll(inCall, [outCall, inCall], "", [],
+                          [outInfo.held, inInfo.active]))
+
+    // Hang-up original outgoing (now held) call
+    .then(() => gHangUp(outCall))
+    .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
+
+    // Hang-up remaining (incoming) call
+    .then(() => gHangUp(inCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_incoming_already_held.js
+++ b/dom/telephony/test/marionette/test_incoming_already_held.js
@@ -1,222 +1,45 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let outNumber = "5555551111";
-let inNumber = "5555552222";
-let outgoingCall;
-let incomingCall;
-let gotOriginalConnected = false;
-
-function dial() {
-  log("Make an outgoing call.");
-  telephony.dial(outNumber).then(call => {
-    outgoingCall = call;
-    ok(outgoingCall);
-    is(outgoingCall.id.number, outNumber);
-    is(outgoingCall.state, "dialing");
-
-    is(outgoingCall, telephony.active);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoingCall);
-
-    outgoingCall.onalerting = function onalerting(event) {
-      log("Received 'onalerting' call event.");
-      is(outgoingCall, event.call);
-      is(outgoingCall.state, "alerting");
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "outbound to  " + outNumber + " : ringing");
-        answer();
-      });
-    };
-  });
-}
-
-function answer() {
-  log("Answering the outgoing call.");
-
-  // We get no "connecting" event when the remote party answers the call.
-  outgoingCall.onconnected = function onconnectedOut(event) {
-    log("Received 'connected' call event for the original outgoing call.");
-
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "connected");
-    is(outgoingCall, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + outNumber + " : active");
-
-      if(!gotOriginalConnected){
-        gotOriginalConnected = true;
-        holdCall();
-      } else {
-        // Received connected event for original call multiple times (fail)
-        ok(false,
-           "Received 'connected' event for original call multiple times");
-      }
-    });
-  };
-  emulator.runCmdWithCallback("gsm accept " + outNumber);
-}
-
-function holdCall() {
-  log("Putting the original (outgoing) call on hold.");
-
-  let gotHolding = false;
-  outgoingCall.onholding = function onholding(event) {
-    log("Received 'holding' call event");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "holding");
-    gotHolding = true;
-  };
-
-  outgoingCall.onheld = function onheld(event) {
-    log("Received 'held' call event");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "held");
-    ok(gotHolding);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + outNumber + " : held");
-      simulateIncoming();
-    });
-  };
-  outgoingCall.hold();
-}
-
-// With one call on hold, simulate an incoming call
-function simulateIncoming() {
-  log("Simulating an incoming call (with one call already held).");
-
-  telephony.onincoming = function onincoming(event) {
-    log("Received 'incoming' call event.");
-    incomingCall = event.call;
-    ok(incomingCall);
-    is(incomingCall.id.number, inNumber);
-    is(incomingCall.state, "incoming");
-
-    // Should be two calls now
-    is(telephony.calls.length, 2);
-    is(telephony.calls[0], outgoingCall);
-    is(telephony.calls[1], incomingCall);
+const outNumber = "5555551111";
+const outInfo = gOutCallStrPool(outNumber);
+let outCall;
 
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + outNumber + " : held");
-      is(result[1], "inbound from " + inNumber + " : incoming");
-      answerIncoming();
-    });
-  };
-  emulator.runCmdWithCallback("gsm call " + inNumber);
-}
-
-// Answer incoming call; original outgoing call should be held
-function answerIncoming() {
-  log("Answering the incoming call.");
-
-  let gotConnecting = false;
-  incomingCall.onconnecting = function onconnectingIn(event) {
-    log("Received 'connecting' call event for incoming/2nd call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connecting");
-    gotConnecting = true;
-  };
-
-  incomingCall.onconnected = function onconnectedIn(event) {
-    log("Received 'connected' call event for incoming/2nd call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connected");
-    ok(gotConnecting);
-
-    is(incomingCall, telephony.active);
-    is(outgoingCall.state, "held");
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + outNumber + " : held");
-      is(result[1], "inbound from " + inNumber + " : active");
-      hangUpOutgoing();
-    });
-  };
-  incomingCall.answer();
-}
-
-// Hang-up original outgoing (now held) call
-function hangUpOutgoing() {
-  log("Hanging up the original outgoing (now held) call.");
-
-  let gotDisconnecting = false;
-  outgoingCall.ondisconnecting = function ondisconnectingOut(event) {
-    log("Received 'disconnecting' call event for original outgoing call.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  outgoingCall.ondisconnected = function ondisconnectedOut(event) {
-    log("Received 'disconnected' call event for original outgoing call.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "disconnected");
-    ok(gotDisconnecting);
-
-    // Back to one call now
-    is(telephony.calls.length, 1);
-    is(incomingCall.state, "connected");
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : active");
-      hangUpIncoming();
-    });
-  };
-  outgoingCall.hangUp();
-}
-
-// Hang-up remaining (incoming) call
-function hangUpIncoming() {
-  log("Hanging up the remaining (incoming) call.");
-
-  let gotDisconnecting = false;
-  incomingCall.ondisconnecting = function ondisconnectingIn(event) {
-    log("Received 'disconnecting' call event for remaining (incoming) call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  incomingCall.ondisconnected = function ondisconnectedIn(event) {
-    log("Received 'disconnected' call event for remaining (incoming) call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnected");
-    ok(gotDisconnecting);
-
-    // Zero calls left
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  incomingCall.hangUp();
-}
-
-function cleanUp() {
-  telephony.onincoming = null;
-  finish();
-}
+const inNumber = "5555552222";
+const inInfo = gInCallStrPool(inNumber);
+let inCall;
 
 startTest(function() {
-  dial();
+  gDial(outNumber)
+    .then(call => outCall = call)
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing]))
+    .then(() => gRemoteAnswer(outCall))
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active]))
+    .then(() => gHold(outCall))
+    .then(() => gCheckAll(null, [outCall], "", [], [outInfo.held]))
+
+    // With one call on hold, simulate an incoming call
+    .then(() => gRemoteDial(inNumber))
+    .then(call => inCall = call)
+    .then(() => gCheckAll(null, [outCall, inCall], "", [],
+                          [outInfo.held, inInfo.waiting]))
+
+    // Answer incoming call; original outgoing call should be held
+    .then(() => gAnswer(inCall))
+    .then(() => gCheckAll(inCall, [outCall, inCall], "", [],
+                          [outInfo.held, inInfo.active]))
+
+    // Hang-up original outgoing (now held) call
+    .then(() => gHangUp(outCall))
+    .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
+
+    // Hang-up remaining (incoming) call
+    .then(() => gHangUp(inCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_incoming_answer_hangup.js
+++ b/dom/telephony/test/marionette/test_incoming_answer_hangup.js
@@ -1,97 +1,26 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let number = "5555552368";
-let incoming;
-let calls;
-
-function simulateIncoming() {
-  log("Simulating an incoming call.");
-
-  telephony.onincoming = function onincoming(event) {
-    log("Received 'incoming' call event.");
-    incoming = event.call;
-    ok(incoming);
-    is(incoming.id.number, number);
-    is(incoming.state, "incoming");
-
-    //ok(telephony.calls === calls); // bug 717414
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incoming);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + number + " : incoming");
-      answer();
-    });
-  };
-  emulator.runCmdWithCallback("gsm call " + number);
-}
-
-function answer() {
-  log("Answering the incoming call.");
-
-  let gotConnecting = false;
-  incoming.onconnecting = function onconnecting(event) {
-    log("Received 'connecting' call event.");
-    is(incoming, event.call);
-    is(incoming.state, "connecting");
-    gotConnecting = true;
-  };
-
-  incoming.onconnected = function onconnected(event) {
-    log("Received 'connected' call event.");
-    is(incoming, event.call);
-    is(incoming.state, "connected");
-    ok(gotConnecting);
-
-    is(incoming, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + number + " : active");
-      hangUp();
-    });
-  };
-  incoming.answer();
-}
-
-function hangUp() {
-  log("Hanging up the incoming call.");
-
-  let gotDisconnecting = false;
-  incoming.ondisconnecting = function ondisconnecting(event) {
-    log("Received 'disconnecting' call event.");
-    is(incoming, event.call);
-    is(incoming.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  incoming.ondisconnected = function ondisconnected(event) {
-    log("Received 'disconnected' call event.");
-    is(incoming, event.call);
-    is(incoming.state, "disconnected");
-    ok(gotDisconnecting);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  incoming.hangUp();
-}
-
-function cleanUp() {
-  telephony.onincoming = null;
-  finish();
-}
+const inNumber = "5555552222";
+const inInfo = gInCallStrPool(inNumber);
+let inCall;
 
 startTest(function() {
-  simulateIncoming();
+  gRemoteDial(inNumber)
+    .then(call => inCall = call)
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming]))
+
+    // Answer incoming call
+    .then(() => gAnswer(inCall))
+    .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
+
+    // Hang-up call
+    .then(() => gHangUp(inCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_incoming_answer_hangup_oncallschanged.js
+++ b/dom/telephony/test/marionette/test_incoming_answer_hangup_oncallschanged.js
@@ -1,124 +1,30 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let number = "5555552368";
-let incoming;
-
-function simulateIncoming() {
-  log("Simulating an incoming call.");
-
-  telephony.oncallschanged = function oncallschanged(event) {
-    log("Received 'callschanged' event.");
-
-    // Check whether the 'calls' array has changed
-    ok(event.call, "undesired callschanged event");
-
-    telephony.oncallschanged = null;
-
-    incoming = event.call;
-    ok(incoming);
-    is(incoming.id.number, number);
-    is(incoming.state, "incoming");
-
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incoming);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + number + " : incoming");
-      answer();
-    });
-  };
-
-  emulator.runCmdWithCallback("gsm call " + number);
-}
-
-function answer() {
-  log("Answering the incoming call.");
-
-  let gotConnecting = false;
-  incoming.onconnecting = function onconnecting(event) {
-    log("Received 'connecting' call event.");
-    is(incoming, event.call);
-    is(incoming.state, "connecting");
-
-    // Incoming call is not 'active' until its state becomes 'connected'.
-    isnot(incoming, telephony.active);
-    gotConnecting = true;
-  };
-
-  incoming.onconnected = function onconnected(event) {
-    log("Received 'connected' call event.");
-    is(incoming, event.call);
-    is(incoming.state, "connected");
-    ok(gotConnecting);
-
-    is(incoming, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + number + " : active");
-      hangUp();
-    });
-  };
-  incoming.answer();
-}
-
-function hangUp() {
-  log("Hanging up the incoming call.");
-
-  // Should received 'diconnecting', 'callschanged', 'disconnected' events in
-  // order.
-  let gotDisconnecting = false;
-  let gotCallschanged = false;
-
-  incoming.ondisconnecting = function ondisconnecting(event) {
-    log("Received 'disconnecting' call event.");
-    is(incoming, event.call);
-    is(incoming.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  telephony.oncallschanged = function oncallschanged(event) {
-    log("Received 'callschanged' event.");
-
-    // Check whether the 'calls' array has changed
-    ok(event.call, "undesired callschanged event");
-
-    is(incoming, event.call);
-    is(incoming.state, "disconnected");
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-    gotCallschanged = true;
-  };
-
-  incoming.ondisconnected = function ondisconnected(event) {
-    log("Received 'disconnected' call event.");
-    is(incoming, event.call);
-    is(incoming.state, "disconnected");
-    ok(gotDisconnecting);
-    ok(gotCallschanged);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-
-  incoming.hangUp();
-}
-
-function cleanUp() {
-  telephony.oncallschanged = null;
-  finish();
-}
+const inNumber = "5555552222";
+const inInfo = gInCallStrPool(inNumber);
+let inCall;
 
 startTest(function() {
-  simulateIncoming();
+  gRemoteDial(inNumber)
+    .then(call => inCall = call)
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming]))
+
+    // Answer incoming call
+    .then(() => gAnswer(inCall))
+    .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
+
+    // Hang-up call
+    .then(() => {
+      let p1 = gHangUp(inCall);
+      let p2 = gWaitForCallsChangedEvent(telephony, inCall);
+      return Promise.all([p1, p2]);
+    })
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_incoming_answer_remote_hangup.js
+++ b/dom/telephony/test/marionette/test_incoming_answer_remote_hangup.js
@@ -1,88 +1,26 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let inNumber = "5555551111";
-let incomingCall;
-
-function simulateIncoming() {
-  log("Simulating an incoming call.");
-
-  telephony.onincoming = function onincoming(event) {
-    log("Received 'incoming' call event.");
-    incomingCall = event.call;
-    ok(incomingCall);
-    is(incomingCall.id.number, inNumber);
-    is(incomingCall.state, "incoming");
-
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : incoming");
-      answerIncoming();
-    });
-  };
-  emulator.runCmdWithCallback("gsm call " + inNumber);
-}
-
-function answerIncoming() {
-  log("Answering the incoming call.");
-
-  let gotConnecting = false;
-  incomingCall.onconnecting = function onconnectingIn(event) {
-    log("Received 'connecting' call event for incoming call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connecting");
-    gotConnecting = true;
-  };
-
-  incomingCall.onconnected = function onconnectedIn(event) {
-    log("Received 'connected' call event for incoming call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connected");
-    ok(gotConnecting);
-
-    is(incomingCall, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : active");
-      remoteHangUp();
-    });
-  };
-  incomingCall.answer();
-}
-
-function remoteHangUp() {
-  log("Hanging up the call (remotely)");
-
-  // We get no 'disconnecting' event when remote party hangs-up the call
-
-  incomingCall.ondisconnected = function ondisconnected(event) {
-    log("Received 'disconnected' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnected");
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  emulator.runCmdWithCallback("gsm cancel " + inNumber);
-}
-
-function cleanUp() {
-  telephony.onincoming = null;
-  finish();
-}
+const inNumber = "5555552222";
+const inInfo = gInCallStrPool(inNumber);
+let inCall;
 
 startTest(function() {
-  simulateIncoming();
+  gRemoteDial(inNumber)
+    .then(call => inCall = call)
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming]))
+
+    // Answer incoming call
+    .then(() => gAnswer(inCall))
+    .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
+
+    // Remote hang-up call
+    .then(() => gRemoteHangUp(inCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_incoming_connecting_hangup.js
+++ b/dom/telephony/test/marionette/test_incoming_connecting_hangup.js
@@ -1,95 +1,29 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let inNumber = "5555551111";
-let incomingCall;
-
-function simulateIncoming() {
-  log("Simulating an incoming call.");
-
-  telephony.onincoming = function onincoming(event) {
-    log("Received 'incoming' call event.");
-    incomingCall = event.call;
-    ok(incomingCall);
-    is(incomingCall.id.number, inNumber);
-    is(incomingCall.state, "incoming");
-
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : incoming");
-      answerIncoming();
-    });
-  };
-  emulator.runCmdWithCallback("gsm call " + inNumber);
-}
-
-function answerIncoming() {
-  log("Answering the incoming call.");
-
-  incomingCall.onconnecting = function onconnecting(event) {
-    log("Received 'connecting' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connecting");
-    // Now hang-up the call before it is fully connected
-
-    // Bug 784429: Hang-up while connecting, call is not terminated
-    // If hang-up between 'connecting' and 'connected' states, receive the
-    // 'disconnecting' event but then a 'connected' event, and the call is
-    // never terminated; this test times out waiting for 'disconnected', and
-    // will leave the emulator in a bad state (with an active incoming call).
-    // For now, hangUp after the 'connected' event so this test doesn't
-    // timeout; once the bug is fixed then update and remove the setTimeout
-
-    //hangUp();
-    log("==> Waiting one second, remove wait once bug 784429 is fixed <==");
-    setTimeout(hangUp, 1000);
-  };
-
-  incomingCall.onconnected = function onconnected(event) {
-    log("Received 'connected' call event.");
-  };
-  incomingCall.answer();
-}
-
-function hangUp() {
-  log("Hanging up the incoming call before fully connected.");
-
-  let gotDisconnecting = false;
-  incomingCall.ondisconnecting = function ondisconnecting(event) {
-    log("Received 'disconnecting' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  incomingCall.ondisconnected = function ondisconnected(event) {
-    log("Received 'disconnected' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnected");
-    ok(gotDisconnecting);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  incomingCall.hangUp();
-}
-
-function cleanUp() {
-  telephony.onincoming = null;
-  finish();
-}
+const inNumber = "5555552222";
+const inInfo = gInCallStrPool(inNumber);
+let inCall;
 
 startTest(function() {
-  simulateIncoming();
+  gRemoteDial(inNumber)
+    .then(call => inCall = call)
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming]))
+
+    // Answer incoming call
+    .then(() => {
+      let promise = gWaitForNamedStateEvent(inCall, "connecting");
+      inCall.answer();
+      return promise;
+    })
+
+    // Hang-up call
+    .then(() => gHangUp(inCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_incoming_connecting_remote_hangup.js
+++ b/dom/telephony/test/marionette/test_incoming_connecting_remote_hangup.js
@@ -1,77 +1,29 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let inNumber = "5555551111";
-let incomingCall;
-
-function simulateIncoming() {
-  log("Simulating an incoming call.");
-
-  telephony.onincoming = function onincoming(event) {
-    log("Received 'incoming' call event.");
-    incomingCall = event.call;
-    ok(incomingCall);
-    is(incomingCall.id.number, inNumber);
-    is(incomingCall.state, "incoming");
-
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : incoming");
-      answerIncoming();
-    });
-  };
-  emulator.runCmdWithCallback("gsm call " + inNumber);
-}
-
-function answerIncoming() {
-  log("Answering the incoming call.");
-
-  incomingCall.onconnecting = function onconnecting(event) {
-    log("Received 'connecting' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connecting");
-    // Now have the remote party hang-up the call before it is fully connected
-    remoteHangUp();
-  };
-
-  incomingCall.onconnected = function onconnected(event) {
-    log("Received 'connected' call event.");
-  };
-  incomingCall.answer();
-}
-
-function remoteHangUp() {
-  log("Hanging up the incoming call (remotely) before fully connected.");
-
-  // We get no 'disconnecting' event when remote party hangs-up the call
-
-  incomingCall.ondisconnected = function ondisconnected(event) {
-    log("Received 'disconnected' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnected");
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  emulator.runCmdWithCallback("gsm cancel " + inNumber);
-}
-
-function cleanUp() {
-  telephony.onincoming = null;
-  finish();
-}
+const inNumber = "5555552222";
+const inInfo = gInCallStrPool(inNumber);
+let inCall;
 
 startTest(function() {
-  simulateIncoming();
+  gRemoteDial(inNumber)
+    .then(call => inCall = call)
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming]))
+
+    // Answer incoming call
+    .then(() => {
+      let promise = gWaitForNamedStateEvent(inCall, "connecting");
+      inCall.answer();
+      return promise;
+    })
+
+    // Remote hang-up call
+    .then(() => gRemoteHangUp(inCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_incoming_hangup_held.js
+++ b/dom/telephony/test/marionette/test_incoming_hangup_held.js
@@ -1,125 +1,30 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let inNumber = "5555551111";
-let incomingCall;
-
-function simulateIncoming() {
-  log("Simulating an incoming call.");
-
-  telephony.onincoming = function onincoming(event) {
-    log("Received 'incoming' call event.");
-    incomingCall = event.call;
-    ok(incomingCall);
-    is(incomingCall.id.number, inNumber);
-    is(incomingCall.state, "incoming");
-
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : incoming");
-      answerIncoming();
-    });
-  };
-  emulator.runCmdWithCallback("gsm call " + inNumber);
-}
-
-function answerIncoming() {
-  log("Answering the incoming call.");
-
-  let gotConnecting = false;
-  incomingCall.onconnecting = function onconnectingIn(event) {
-    log("Received 'connecting' call event for incoming call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connecting");
-    gotConnecting = true;
-  };
-
-  incomingCall.onconnected = function onconnectedIn(event) {
-    log("Received 'connected' call event for incoming call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connected");
-    ok(gotConnecting);
-
-    is(incomingCall, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : active");
-      hold();
-    });
-  };
-  incomingCall.answer();
-}
-
-function hold() {
-  log("Putting the call on hold.");
-
-  let gotHolding = false;
-  incomingCall.onholding = function onholding(event) {
-    log("Received 'holding' call event");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "holding");
-    gotHolding = true;
-  };
-
-  incomingCall.onheld = function onheld(event) {
-    log("Received 'held' call event");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "held");
-    ok(gotHolding);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : held");
-      hangUp();
-    });
-  };
-  incomingCall.hold();
-}
-
-function hangUp() {
-  log("Hanging up the held call (local hang-up).");
-
-  let gotDisconnecting = false;
-  incomingCall.ondisconnecting = function ondisconnecting(event) {
-    log("Received 'disconnecting' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  incomingCall.ondisconnected = function ondisconnectedOut(event) {
-    log("Received 'disconnected' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnected");
-    ok(gotDisconnecting);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  incomingCall.hangUp();
-}
-
-function cleanUp() {
-  telephony.onincoming = null;
-  finish();
-}
+const inNumber = "5555552222";
+const inInfo = gInCallStrPool(inNumber);
+let inCall;
 
 startTest(function() {
-  simulateIncoming();
+  gRemoteDial(inNumber)
+    .then(call => inCall = call)
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming]))
+
+    // Answer incoming call
+    .then(() => gAnswer(inCall))
+    .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
+
+    // Hold the call.
+    .then(() => gHold(inCall))
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.held]))
+
+    // Hang-up call
+    .then(() => gHangUp(inCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_incoming_hold_resume.js
+++ b/dom/telephony/test/marionette/test_incoming_hold_resume.js
@@ -1,158 +1,34 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let number = "5555551234";
-let connectedCalls;
-let incomingCall;
-
-function simulateIncoming() {
-  log("Simulating an incoming call.");
-
-  telephony.onincoming = function onincoming(event) {
-    log("Received 'incoming' call event.");
-    incomingCall = event.call;
-    ok(incomingCall);
-    is(incomingCall.id.number, number);
-    is(incomingCall.state, "incoming");
-
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + number + " : incoming");
-      answer();
-    });
-  };
-  emulator.runCmdWithCallback("gsm call " + number);
-}
-
-function answer() {
-  log("Answering the incoming call.");
-
-  let gotConnecting = false;
-  incomingCall.onconnecting = function onconnecting(event) {
-    log("Received 'connecting' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connecting");
-    gotConnecting = true;
-  };
-
-  incomingCall.onconnected = function onconnected(event) {
-    log("Received 'connected' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connected");
-    ok(gotConnecting);
-
-    is(incomingCall, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + number + " : active");
-      hold();
-    });
-  };
-  incomingCall.answer();
-}
-
-function hold() {
-  log("Putting the call on hold.");
-
-  let gotHolding = false;
-  incomingCall.onholding = function onholding(event) {
-    log("Received 'holding' call event");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "holding");
-    gotHolding = true;
-  };
-
-  incomingCall.onheld = function onheld(event) {
-    log("Received 'held' call event");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "held");
-    ok(gotHolding);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + number + " : held");
-      // Wait on hold for a couple of seconds
-      log("Pausing 2 seconds while on hold");
-      setTimeout(resume, 2000);
-    });
-  };
-  incomingCall.hold();
-}
-
-function resume() {
-  log("Resuming the held call.");
-
-  let gotResuming = false;
-  incomingCall.onresuming = function onresuming(event) {
-    log("Received 'resuming' call event");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "resuming");
-    gotResuming = true;
-  };
-
-  incomingCall.onconnected = function onconnected(event) {
-    log("Received 'connected' call event");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connected");
-    ok(gotResuming);
-
-    is(incomingCall, telephony.active);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + number + " : active");
-      hangUp();
-    });
-  };
-  incomingCall.resume();
-}
-
-function hangUp() {
-  log("Hanging up the incoming call.");
-
-  let gotDisconnecting = false;
-  incomingCall.ondisconnecting = function ondisconnecting(event) {
-    log("Received 'disconnecting' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  incomingCall.ondisconnected = function ondisconnected(event) {
-    log("Received 'disconnected' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnected");
-    ok(gotDisconnecting);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  incomingCall.hangUp();
-}
-
-function cleanUp() {
-  telephony.onincoming = null;
-  finish();
-}
+const inNumber = "5555552222";
+const inInfo = gInCallStrPool(inNumber);
+let inCall;
 
 startTest(function() {
-  simulateIncoming();
+  gRemoteDial(inNumber)
+    .then(call => inCall = call)
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming]))
+
+    // Answer incoming call
+    .then(() => gAnswer(inCall))
+    .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
+
+    // Hold the call.
+    .then(() => gHold(inCall))
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.held]))
+
+    // Resume the call.
+    .then(() => gResume(inCall))
+    .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
+
+    // Hang-up call
+    .then(() => gHangUp(inCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_incoming_onstatechange.js
+++ b/dom/telephony/test/marionette/test_incoming_onstatechange.js
@@ -1,141 +1,54 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_HEAD_JS = 'head.js';
 MARIONETTE_TIMEOUT = 60000;
 
-let incomingCall;
-let inNumber = "5555551111";
-
-function simulateIncoming() {
-  log("Simulating an incoming call.");
-
-  telephony.onincoming = function onincoming(event) {
-    log("Received 'incoming' call event.");
-    incomingCall = event.call;
-    ok(incomingCall);
-    is(incomingCall.id.number, inNumber);
-    is(incomingCall.state, "incoming");
-
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : incoming");
-      answerIncoming();
-    });
-  };
-  emulator.runCmdWithCallback("gsm call " + inNumber);
-}
-
-function answerIncoming() {
-  log("Answering the incoming call.");
-
-  gotConnecting = false;
-  incomingCall.onstatechange = function statechangeconnect(event) {
-    log("Received 'onstatechange' call event.");
-    is(incomingCall, event.call);
-    if(!gotConnecting){
-      is(incomingCall.state, "connecting");
-      gotConnecting = true;
-    } else {
-      is(incomingCall.state, "connected");
-      is(telephony.active, incomingCall);
-      is(telephony.calls.length, 1);
-      is(telephony.calls[0], incomingCall);
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "inbound from " + inNumber + " : active");
-        hold();
-      });
-    }
-  };
-  incomingCall.answer();
-}
-
-function hold() {
-  log("Putting the call on hold.");
-
-  let gotHolding = false;
-  incomingCall.onstatechange = function onstatechangehold(event) {
-    log("Received 'onstatechange' call event.");
-    is(incomingCall, event.call);
-    if(!gotHolding){
-      is(incomingCall.state, "holding");
-      gotHolding = true;
-    } else {
-      is(incomingCall.state, "held");
-      is(telephony.active, null);
-      is(telephony.calls.length, 1);
-      is(telephony.calls[0], incomingCall);
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "inbound from " + inNumber + " : held");
-        resume();
-      });
-    }
-  };
-  incomingCall.hold();
-}
-
-function resume() {
-  log("Resuming the held call.");
-
-  let gotResuming = false;
-  incomingCall.onstatechange = function onstatechangeresume(event) {
-    log("Received 'onstatechange' call event.");
-    is(incomingCall, event.call);
-    if(!gotResuming){
-      is(incomingCall.state, "resuming");
-      gotResuming = true;
-    } else {
-      is(incomingCall.state, "connected");
-      is(telephony.active, incomingCall);
-      is(telephony.calls.length, 1);
-      is(telephony.calls[0], incomingCall);
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "inbound from " + inNumber + " : active");
-        hangUp();
-      });
-    }
-  };
-  incomingCall.resume();
-}
-
-function hangUp() {
-  log("Hanging up the incoming call (local hang-up).");
-
-  let gotDisconnecting = false;
-  incomingCall.onstatechange = function onstatechangedisconnect(event) {
-    log("Received 'onstatechange' call event.");
-    is(incomingCall, event.call);
-    if(!gotDisconnecting){
-      is(incomingCall.state, "disconnecting");
-      gotDisconnecting = true;
-    } else {
-      is(incomingCall.state, "disconnected");
-      is(telephony.active, null);
-      is(telephony.calls.length, 0);
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        cleanUp();
-      });
-    }
-  };
-  incomingCall.hangUp();
-}
-
-function cleanUp() {
-  telephony.onincoming = null;
-  finish();
-}
+const inNumber = "5555552222";
+const inInfo = gInCallStrPool(inNumber);
+let inCall;
 
 startTest(function() {
-  simulateIncoming();
+  gRemoteDial(inNumber)
+    .then(call => inCall = call)
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming]))
+
+    // Answer incoming call
+    .then(() => {
+      let p1 = gWaitForStateChangeEvent(inCall, "connecting")
+        .then(() => gWaitForStateChangeEvent(inCall, "connected"));
+      let p2 = gAnswer(inCall);
+      return Promise.all([p1, p2]);
+    })
+    .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
+
+    // Hold the call.
+    .then(() => {
+      let p1 = gWaitForStateChangeEvent(inCall, "holding")
+        .then(() => gWaitForStateChangeEvent(inCall, "held"));
+      let p2 = gHold(inCall);
+      return Promise.all([p1, p2]);
+    })
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.held]))
+
+    // Resume the call.
+    .then(() => {
+      let p1 = gWaitForStateChangeEvent(inCall, "resuming")
+        .then(() => gWaitForStateChangeEvent(inCall, "connected"));
+      let p2 = gResume(inCall);
+      return Promise.all([p1, p2]);
+    })
+    .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
+
+    // Hang-up call
+    .then(() => {
+      let p1 = gWaitForStateChangeEvent(inCall, "disconnecting")
+        .then(() => gWaitForStateChangeEvent(inCall, "disconnected"));
+      let p2 = gHangUp(inCall);
+      return Promise.all([p1, p2]);
+    })
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_incoming_reject.js
+++ b/dom/telephony/test/marionette/test_incoming_reject.js
@@ -1,69 +1,22 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let number = "5555552368";
-let incoming;
-let calls;
-
-function simulateIncoming() {
-  log("Simulating an incoming call.");
-
-  telephony.onincoming = function onincoming(event) {
-    log("Received 'incoming' call event.");
-    incoming = event.call;
-    ok(incoming);
-    is(incoming.id.number, number);
-    is(incoming.state, "incoming");
-
-    //ok(telephony.calls === calls); // bug 717414
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incoming);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + number + " : incoming");
-      reject();
-    });
-  };
-  emulator.runCmdWithCallback("gsm call " + number);
-}
-
-function reject() {
-  log("Reject the incoming call.");
-
-  let gotDisconnecting = false;
-  incoming.ondisconnecting = function ondisconnecting(event) {
-    log("Received 'disconnecting' call event.");
-    is(incoming, event.call);
-    is(incoming.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  incoming.ondisconnected = function ondisconnected(event) {
-    log("Received 'disconnected' call event.");
-    is(incoming, event.call);
-    is(incoming.state, "disconnected");
-    ok(gotDisconnecting);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  incoming.hangUp();
-}
-
-function cleanUp() {
-  telephony.onincoming = null;
-  finish();
-}
+const inNumber = "5555552222";
+const inInfo = gInCallStrPool(inNumber);
+let inCall;
 
 startTest(function() {
-  simulateIncoming();
+  gRemoteDial(inNumber)
+    .then(call => inCall = call)
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming]))
+
+    // Hang-up call
+    .then(() => gHangUp(inCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_incoming_remote_cancel.js
+++ b/dom/telephony/test/marionette/test_incoming_remote_cancel.js
@@ -1,60 +1,22 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let inNumber = "5555551111";
-let incomingCall;
-
-function simulateIncoming() {
-  log("Simulating an incoming call.");
-
-  telephony.onincoming = function onincoming(event) {
-    log("Received 'incoming' call event.");
-    incomingCall = event.call;
-    ok(incomingCall);
-    is(incomingCall.id.number, inNumber);
-    is(incomingCall.state, "incoming");
-
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : incoming");
-      cancelIncoming();
-    });
-  };
-  emulator.runCmdWithCallback("gsm call " + inNumber);
-}
-
-function cancelIncoming(){
-  log("Remote party cancelling call before it is answered.");
-
-  // We get no 'disconnecting' event when remote party cancels/hangs-up call
-
-  incomingCall.ondisconnected = function ondisconnected(event) {
-    log("Received 'disconnected' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnected");
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  emulator.runCmdWithCallback("gsm cancel " + inNumber);
-}
-
-function cleanUp() {
-  telephony.onincoming = null;
-  finish();
-}
+const inNumber = "5555552222";
+const inInfo = gInCallStrPool(inNumber);
+let inCall;
 
 startTest(function() {
-  simulateIncoming();
+  gRemoteDial(inNumber)
+    .then(call => inCall = call)
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming]))
+
+    // Remote cancel call
+    .then(() => gRemoteHangUp(inCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_incoming_remote_hangup_held.js
+++ b/dom/telephony/test/marionette/test_incoming_remote_hangup_held.js
@@ -1,118 +1,30 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let inNumber = "5555551111";
-let incomingCall;
-
-function simulateIncoming() {
-  log("Simulating an incoming call.");
-
-  telephony.onincoming = function onincoming(event) {
-    log("Received 'incoming' call event.");
-    incomingCall = event.call;
-    ok(incomingCall);
-    is(incomingCall.id.number, inNumber);
-    is(incomingCall.state, "incoming");
-
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : incoming");
-      answerIncoming();
-    });
-  };
-  emulator.runCmdWithCallback("gsm call " + inNumber);
-}
-
-function answerIncoming() {
-  log("Answering the incoming call.");
-
-  let gotConnecting = false;
-  incomingCall.onconnecting = function onconnectingIn(event) {
-    log("Received 'connecting' call event for incoming call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connecting");
-    gotConnecting = true;
-  };
-
-  incomingCall.onconnected = function onconnectedIn(event) {
-    log("Received 'connected' call event for incoming call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connected");
-    ok(gotConnecting);
-
-    is(incomingCall, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : active");
-      hold();
-    });
-  };
-  incomingCall.answer();
-}
-
-function hold() {
-  log("Putting the call on hold.");
-
-  let gotHolding = false;
-  incomingCall.onholding = function onholding(event) {
-    log("Received 'holding' call event");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "holding");
-    gotHolding = true;
-  };
-
-  incomingCall.onheld = function onheld(event) {
-    log("Received 'held' call event");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "held");
-    ok(gotHolding);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : held");
-      hangUp();
-    });
-  };
-  incomingCall.hold();
-}
-
-function hangUp() {
-  log("Hanging up the held call (remotely).");
-
-  // We get no 'disconnecting' event when remote party hangs-up the call
-
-  incomingCall.ondisconnected = function ondisconnected(event) {
-    log("Received 'disconnected' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnected");
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  emulator.runCmdWithCallback("gsm cancel " + inNumber);
-}
-
-function cleanUp() {
-  telephony.onincoming = null;
-  finish();
-}
+const inNumber = "5555552222";
+const inInfo = gInCallStrPool(inNumber);
+let inCall;
 
 startTest(function() {
-  simulateIncoming();
+  gRemoteDial(inNumber)
+    .then(call => inCall = call)
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming]))
+
+    // Answer incoming call
+    .then(() => gAnswer(inCall))
+    .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
+
+    // Hold the call.
+    .then(() => gHold(inCall))
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.held]))
+
+    // Remote hang-up call
+    .then(() => gRemoteHangUp(inCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_multiple_hold.js
+++ b/dom/telephony/test/marionette/test_multiple_hold.js
@@ -1,267 +1,57 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let inNumber = "5555551111";
-let outNumber = "5555552222";
-let incomingCall;
-let outgoingCall;
-
-function simulateIncoming() {
-  log("Simulating an incoming call.");
-
-  telephony.onincoming = function onincoming(event) {
-    log("Received 'incoming' call event.");
-    incomingCall = event.call;
-    ok(incomingCall);
-    is(incomingCall.id.number, inNumber);
-    is(incomingCall.state, "incoming");
-
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : incoming");
-      answerIncoming();
-    });
-  };
-  emulator.runCmdWithCallback("gsm call " + inNumber);
-}
-
-function answerIncoming() {
-  log("Answering the incoming call.");
-
-  let gotConnecting = false;
-  incomingCall.onconnecting = function onconnectingIn(event) {
-    log("Received 'connecting' call event for original (incoming) call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connecting");
-    gotConnecting = true;
-  };
-
-  incomingCall.onconnected = function onconnectedIn(event) {
-    log("Received 'connected' call event for original (incoming) call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connected");
-    ok(gotConnecting);
-    is(incomingCall, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : active");
-      holdCall();
-    });
-  };
-  incomingCall.answer();
-}
-
-// Put the original (incoming) call on hold
-function holdCall() {
-  log("Putting the original (incoming) call on hold.");
-
-  let gotHolding = false;
-  incomingCall.onholding = function onholding(event) {
-    log("Received 'holding' call event");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "holding");
-    gotHolding = true;
-  };
-
-  incomingCall.onheld = function onheld(event) {
-    log("Received 'held' call event");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "held");
-    ok(gotHolding);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : held");
-      dial();
-    });
-  };
-  incomingCall.hold();
-}
-
-// With one call on hold, make outgoing call
-function dial() {
-  log("Making an outgoing call (while have one call already held).");
-
-  telephony.dial(outNumber).then(call => {
-    outgoingCall = call;
-    ok(outgoingCall);
-    is(outgoingCall.id.number, outNumber);
-    is(outgoingCall.state, "dialing");
-    is(outgoingCall, telephony.active);
-    is(telephony.calls.length, 2);
-    is(telephony.calls[0], incomingCall);
-    is(telephony.calls[1], outgoingCall);
-
-    outgoingCall.onalerting = function onalerting(event) {
-      log("Received 'onalerting' call event.");
-      is(outgoingCall, event.call);
-      is(outgoingCall.state, "alerting");
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "inbound from " + inNumber + " : held");
-        is(result[1], "outbound to  " + outNumber + " : ringing");
-        answerOutgoing();
-      });
-    };
-  });
-}
-
-// Have the outgoing call answered
-function answerOutgoing() {
-  log("Answering the outgoing/2nd call");
-
-  // We get no "connecting" event when the remote party answers the call.
-  outgoingCall.onconnected = function onconnectedOut(event) {
-    log("Received 'connected' call event for outgoing/2nd call.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "connected");
-    is(outgoingCall, telephony.active);
+const outNumber = "5555551111";
+const outInfo = gOutCallStrPool(outNumber);
+let outCall;
 
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : held");
-      is(result[1], "outbound to  " + outNumber + " : active");
-      holdSecondCall();
-    });
-  };
-  emulator.runCmdWithCallback("gsm accept " + outNumber);
-}
-
-// With one held call and one active, hold the active one; expect the first
-// (held) call to automatically become active, and the 2nd call to go on hold
-function holdSecondCall() {
-  let firstCallReconnected = false;
-  let secondCallHeld = false;
-
-  log("Putting the 2nd (outgoing) call on hold.");
-
-  // Since first call will become connected again, setup handler
-  incomingCall.onconnected = function onreconnected(event) {
-    log("Received 'connected' call event for original (incoming) call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connected");
-    is(incomingCall, telephony.active);
-    firstCallReconnected = true;
-    if (firstCallReconnected && secondCallHeld) {
-      verifyCalls();
-    }
-  };
-
-  // Handlers for holding 2nd call
-  let gotHolding = false;
-  outgoingCall.onholding = function onholdingOut(event) {
-    log("Received 'holding' call event for 2nd call.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "holding");
-    gotHolding = true;
-  };
-
-  outgoingCall.onheld = function onheldOut(event) {
-    log("Received 'held' call event for 2nd call.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "held");
-    ok(gotHolding);
-    secondCallHeld = true;
-    if (firstCallReconnected && secondCallHeld) {
-      verifyCalls();
-    }
-  };
-  outgoingCall.hold();
-}
-
-function verifyCalls() {
-  is(telephony.active, incomingCall);
-  is(telephony.calls.length, 2);
-  is(telephony.calls[0], incomingCall);
-  is(telephony.calls[1], outgoingCall);
-
-  emulator.runCmdWithCallback("gsm list", function(result) {
-    log("Call list is now: " + result);
-    is(result[0], "inbound from " + inNumber + " : active");
-    is(result[1], "outbound to  " + outNumber + " : held");
-    hangUpIncoming();
-  });
-}
-
-// Hang-up the original incoming call, which is now active
-function hangUpIncoming() {
-  log("Hanging up the original incoming (now active) call.");
-
-  let gotDisconnecting = false;
-  incomingCall.ondisconnecting = function ondisconnectingIn(event) {
-    log("Received 'disconnecting' call event for original (incoming) call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  incomingCall.ondisconnected = function ondisconnectedIn(event) {
-    log("Received 'disconnected' call event for original (incoming) call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnected");
-    ok(gotDisconnecting);
-
-    // Now back to one call
-    is(telephony.active, null);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + outNumber + " : held");
-      hangUpOutgoing();
-    });
-  };
-  incomingCall.hangUp();
-}
-
-// Hang-up the remaining (outgoing) call, which is held
-function hangUpOutgoing() {
-  log("Hanging up the remaining (outgoing) held call.");
-
-  let gotDisconnecting = false;
-  outgoingCall.ondisconnecting = function ondisconnectingOut(event) {
-    log("Received 'disconnecting' call event for remaining (outgoing) call.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  outgoingCall.ondisconnected = function ondisconnectedOut(event) {
-    log("Received 'disconnected' call event for remaining (outgoing) call.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "disconnected");
-    ok(gotDisconnecting);
-
-    // Now no calls
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  outgoingCall.hangUp();
-}
-
-function cleanUp() {
-  telephony.onincoming = null;
-  finish();
-}
+const inNumber = "5555552222";
+const inInfo = gInCallStrPool(inNumber);
+let inCall;
 
 startTest(function() {
-  simulateIncoming();
+  gRemoteDial(inNumber)
+    .then(call => inCall = call)
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming]))
+
+    // Answer incoming call
+    .then(() => gAnswer(inCall))
+    .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
+
+    // Hold the call
+    .then(() => gHold(inCall))
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.held]))
+
+    // Dial out.
+    .then(() => gDial(outNumber))
+    .then(call => outCall = call)
+    .then(() => gCheckAll(outCall, [inCall, outCall], "", [],
+                          [inInfo.held, outInfo.ringing]))
+
+    // Remote answer the call
+    .then(() => gRemoteAnswer(outCall))
+    .then(() => gCheckAll(outCall, [inCall, outCall], "", [],
+                          [inInfo.held, outInfo.active]))
+
+    // With one held call and one active, hold the active one; expect the first
+    // (held) call to automatically become active, and the 2nd call to be held
+    .then(() => {
+      let p1 = gWaitForNamedStateEvent(inCall, "connected");
+      let p2 = gHold(outCall);
+      return Promise.all([p1, p2]);
+    })
+    .then(() => gCheckAll(inCall, [inCall, outCall], "", [],
+                          [inInfo.active, outInfo.held]))
+
+    .then(() => gHangUp(inCall))
+    .then(() => gCheckAll(null, [outCall], "", [], [outInfo.held]))
+
+    .then(() => gHangUp(outCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_outgoing_already_held.js
+++ b/dom/telephony/test/marionette/test_outgoing_already_held.js
@@ -1,236 +1,41 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let inNumber = "5555551111";
-let outNumber = "5555552222";
-let incomingCall;
-let outgoingCall;
-
-function simulateIncoming() {
-  log("Simulating an incoming call.");
-
-  telephony.onincoming = function onincoming(event) {
-    log("Received 'incoming' call event.");
-    incomingCall = event.call;
-    ok(incomingCall);
-    is(incomingCall.id.number, inNumber);
-    is(incomingCall.state, "incoming");
-
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    // Wait for emulator to catch up before continuing
-    waitFor(verifyCallList,function() {
-      return(rcvdEmulatorCallback);
-    });
-  };
-
-  let rcvdEmulatorCallback = false;
-  emulator.runCmdWithCallback("gsm call " + inNumber, function(result) {
-    rcvdEmulatorCallback = true;
-  });
-}
-
-function verifyCallList(){
-  emulator.runCmdWithCallback("gsm list", function(result) {
-    log("Call list is now: " + result);
-    is(result[0], "inbound from " + inNumber + " : incoming");
-    answerIncoming();
-  });
-}
-
-function answerIncoming() {
-  log("Answering the incoming call.");
-
-  let gotConnecting = false;
-  incomingCall.onconnecting = function onconnectingIn(event) {
-    log("Received 'connecting' call event for original (incoming) call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connecting");
-    gotConnecting = true;
-  };
-
-  incomingCall.onconnected = function onconnectedIn(event) {
-    log("Received 'connected' call event for original (incoming) call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connected");
-    ok(gotConnecting);
-
-    is(incomingCall, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : active");
-      holdCall();
-    });
-  };
-  incomingCall.answer();
-}
-
-// Put the original (incoming) call on hold
-function holdCall(){
-  log("Putting the original (incoming) call on hold.");
-
-  let gotHolding = false;
-  incomingCall.onholding = function onholding(event) {
-    log("Received 'holding' call event");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "holding");
-    gotHolding = true;
-  };
-
-  incomingCall.onheld = function onheld(event) {
-    log("Received 'held' call event");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "held");
-    ok(gotHolding);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : held");
-      dial();
-    });
-  };
-  incomingCall.hold();
-}
-
-// With one call on hold, make outgoing call
-function dial() {
-  log("Making an outgoing call (while have one call already held).");
-
-  telephony.dial(outNumber).then(call => {
-    outgoingCall = call;
-    ok(outgoingCall);
-    is(outgoingCall.id.number, outNumber);
-    is(outgoingCall.state, "dialing");
-
-    is(outgoingCall, telephony.active);
-    is(telephony.calls.length, 2);
-    is(telephony.calls[0], incomingCall);
-    is(telephony.calls[1], outgoingCall);
+const outNumber = "5555551111";
+const outInfo = gOutCallStrPool(outNumber);
+let outCall;
 
-    outgoingCall.onalerting = function onalerting(event) {
-      log("Received 'onalerting' call event.");
-      is(outgoingCall, event.call);
-      is(outgoingCall.state, "alerting");
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "inbound from " + inNumber + " : held");
-        is(result[1], "outbound to  " + outNumber + " : ringing");
-        answerOutgoing();
-      });
-    };
-  });
-}
-
-// Have the outgoing call answered
-function answerOutgoing() {
-  log("Answering the outgoing/2nd call");
-
-  // We get no "connecting" event when the remote party answers the call.
-  outgoingCall.onconnected = function onconnectedOut(event) {
-    log("Received 'connected' call event for outgoing/2nd call.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "connected");
-
-    is(outgoingCall, telephony.active);
-
-    // Wait for emulator to catch up before continuing
-    waitFor(checkCallList,function() {
-      return(rcvdEmulatorCallback);
-    });
-  };
-
-  let rcvdEmulatorCallback = false;
-  emulator.runCmdWithCallback("gsm accept " + outNumber, function(result) {
-    rcvdEmulatorCallback = true;
-  });
-}
-
-function checkCallList(){
-  emulator.runCmdWithCallback("gsm list", function(result) {
-    log("Call list is now: " + result);
-    is(result[0], "inbound from " + inNumber + " : held");
-    is(result[1], "outbound to  " + outNumber + " : active");
-    hangUpIncoming();
-  });
-}
-
-// Hang-up the original incoming call, which is now held
-function hangUpIncoming() {
-  log("Hanging up the original incoming (now held) call.");
-
-  let gotDisconnecting = false;
-  incomingCall.ondisconnecting = function ondisconnectingIn(event) {
-    log("Received 'disconnecting' call event for original (incoming) call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  incomingCall.ondisconnected = function ondisconnectedIn(event) {
-    log("Received 'disconnected' call event for original (incoming) call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnected");
-    ok(gotDisconnecting);
-
-    // Now back to one call
-    is(telephony.active, outgoingCall);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + outNumber + " : active");
-      hangUpOutgoing();
-    });
-  };
-  incomingCall.hangUp();
-}
-
-// Hang-up the remaining (outgoing) call
-function hangUpOutgoing() {
-  log("Hanging up the remaining (outgoing) call.");
-
-  let gotDisconnecting = false;
-  outgoingCall.ondisconnecting = function ondisconnectingOut(event) {
-    log("Received 'disconnecting' call event for remaining (outgoing) call.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  outgoingCall.ondisconnected = function ondisconnectedOut(event) {
-    log("Received 'disconnected' call event for remaining (outgoing) call.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "disconnected");
-    ok(gotDisconnecting);
-
-    // Now no calls
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  outgoingCall.hangUp();
-}
-
-function cleanUp() {
-  telephony.onincoming = null;
-  finish();
-}
+const inNumber = "5555552222";
+const inInfo = gInCallStrPool(inNumber);
+let inCall;
 
 startTest(function() {
-  simulateIncoming();
+  gRemoteDial(inNumber)
+    .then(call => inCall = call)
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.incoming]))
+    .then(() => gAnswer(inCall))
+    .then(() => gCheckAll(inCall, [inCall], "", [], [inInfo.active]))
+    .then(() => gHold(inCall))
+    .then(() => gCheckAll(null, [inCall], "", [], [inInfo.held]))
+
+    // With one call on hold, make outgoing call
+    .then(() => gDial(outNumber))
+    .then(call => outCall = call)
+    .then(() => gCheckAll(outCall, [inCall, outCall], "", [],
+                          [inInfo.held, outInfo.ringing]))
+    .then(() => gRemoteAnswer(outCall))
+    .then(() => gCheckAll(outCall, [inCall, outCall], "", [],
+                          [inInfo.held, outInfo.active]))
+
+    // Hang-up
+    .then(() => gHangUp(inCall))
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active]))
+    .then(() => gHangUp(outCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_outgoing_answer_hangup.js
+++ b/dom/telephony/test/marionette/test_outgoing_answer_hangup.js
@@ -1,87 +1,24 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let number = "5555552368";
-let outgoing;
-let calls;
-
-function dial() {
-  log("Make an outgoing call.");
-
-  telephony.dial(number).then(call => {
-    outgoing = call;
-    ok(outgoing);
-    is(outgoing.id.number, number);
-    is(outgoing.state, "dialing");
-
-    is(outgoing, telephony.active);
-    //ok(telephony.calls === calls); // bug 717414
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoing);
-
-    outgoing.onalerting = function onalerting(event) {
-      log("Received 'onalerting' call event.");
-      is(outgoing, event.call);
-      is(outgoing.state, "alerting");
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "outbound to  " + number + " : ringing");
-        answer();
-      });
-    };
-  });
-}
-
-function answer() {
-  log("Answering the outgoing call.");
-
-  // We get no "connecting" event when the remote party answers the call.
-
-  outgoing.onconnected = function onconnected(event) {
-    log("Received 'connected' call event.");
-    is(outgoing, event.call);
-    is(outgoing.state, "connected");
-
-    is(outgoing, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + number + " : active");
-      hangUp();
-    });
-  };
-  emulator.runCmdWithCallback("gsm accept " + number);
-}
-
-function hangUp() {
-  log("Hanging up the outgoing call.");
-
-  // We get no "disconnecting" event when the remote party terminates the call.
-
-  outgoing.ondisconnected = function ondisconnected(event) {
-    log("Received 'disconnected' call event.");
-    is(outgoing, event.call);
-    is(outgoing.state, "disconnected");
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  emulator.runCmdWithCallback("gsm cancel " + number);
-}
-
-function cleanUp() {
-  finish();
-}
+const outNumber = "5555551111";
+const outInfo = gOutCallStrPool(outNumber);
+let outCall;
 
 startTest(function() {
-  dial();
+  gDial(outNumber)
+    .then(call => outCall = call)
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing]))
+    .then(() => gRemoteAnswer(outCall))
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active]))
+
+    // Hang-up
+    .then(() => gRemoteHangUp(outCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_outgoing_answer_hangup_oncallschanged.js
+++ b/dom/telephony/test/marionette/test_outgoing_answer_hangup_oncallschanged.js
@@ -1,92 +1,40 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let number = "5555552368";
-let outgoing;
-
-function dial() {
-  log("Make an outgoing call.");
-
-  telephony.oncallschanged = function oncallschanged(event) {
-    log("Received 'callschanged' call event.");
-
-    // Check whether the 'calls' array has changed
-    ok(event.call, "undesired callschanged event");
-
-    let expected_states = ["dialing", "disconnected"];
-    ok(expected_states.indexOf(event.call.state) != -1,
-      "Unexpected call state: " + event.call.state);
-
-    if (event.call.state == "dialing") {
-      outgoing = event.call;
-      ok(outgoing);
-      is(outgoing.id.number, number);
-
-      is(outgoing, telephony.active);
-      is(telephony.calls.length, 1);
-      is(telephony.calls[0], outgoing);
-
-      checkCallList();
-    }
-
-    if (event.call.state == "disconnected") {
-      is(outgoing.state, "disconnected");
-      is(telephony.active, null);
-      is(telephony.calls.length, 0);
-      cleanUp();
-    }
-  };
-
-  telephony.dial(number);
-}
-
-function checkCallList() {
-  emulator.runCmdWithCallback("gsm list", function(result) {
-    log("Call list is now: " + result);
-    if (((result[0] == "outbound to  " + number + " : unknown") ||
-         (result[0] == "outbound to  " + number + " : dialing"))) {
-      answer();
-    } else {
-      window.setTimeout(checkCallList, 100);
-    }
-  });
-}
-
-function answer() {
-  log("Answering the outgoing call.");
-
-  // We get no "connecting" event when the remote party answers the call.
-
-  outgoing.onconnected = function onconnected(event) {
-    log("Received 'connected' call event.");
-    is(outgoing, event.call);
-    is(outgoing.state, "connected");
-
-    is(outgoing, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list (after 'connected' event) is now: " + result);
-      is(result[0], "outbound to  " + number + " : active");
-      hangUp();
-    });
-  };
-  emulator.runCmdWithCallback("gsm accept " + number);
-}
-
-function hangUp() {
-  log("Hanging up the outgoing call.");
-
-  emulator.runCmdWithCallback("gsm cancel " + number);
-}
-
-function cleanUp() {
-  telephony.oncallschanged = null;
-  finish();
-}
+const outNumber = "5555551111";
+const outInfo = gOutCallStrPool(outNumber);
+let outCall;
 
 startTest(function() {
-  dial();
+  Promise.resolve()
+    // Dial.
+    .then(() => {
+      let tmpCall;
+
+      let p1 = gWaitForCallsChangedEvent(telephony)
+        .then(call => tmpCall = call);
+
+      let p2 = gDial(outNumber)
+        .then(call => outCall = call);
+
+      return Promise.all([p1, p2]).then(() => is(outCall, tmpCall));
+    })
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing]))
+
+    .then(() => gRemoteAnswer(outCall))
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active]))
+
+    // Hang-up.
+    .then(() => {
+      let p1 = gWaitForCallsChangedEvent(telephony, outCall);
+      let p2 = gRemoteHangUp(outCall);
+      return Promise.all([p1, p2]);
+    })
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_outgoing_answer_local_hangup.js
+++ b/dom/telephony/test/marionette/test_outgoing_answer_local_hangup.js
@@ -1,93 +1,24 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let outgoingCall;
-let outNumber = "5555551111";
-
-function dial() {
-  log("Make an outgoing call.");
-
-  telephony.dial(outNumber).then(call => {
-    outgoingCall = call;
-    ok(outgoingCall);
-    is(outgoingCall.id.number, outNumber);
-    is(outgoingCall.state, "dialing");
-
-    is(outgoingCall, telephony.active);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoingCall);
-
-    outgoingCall.onalerting = function onalerting(event) {
-      log("Received 'alerting' call event.");
-
-      is(outgoingCall, event.call);
-      is(outgoingCall.state, "alerting");
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "outbound to  " + outNumber + " : ringing");
-        answer();
-      });
-    };
-  });
-}
-
-function answer() {
-  log("Answering the outgoing call.");
-
-  // We get no "connecting" event when the remote party answers the call.
-
-  outgoingCall.onconnected = function onconnected(event) {
-    log("Received 'connected' call event.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "connected");
-
-    is(outgoingCall, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + outNumber + " : active");
-      hangUp();
-    });
-  };
-  emulator.runCmdWithCallback("gsm accept " + outNumber);
-}
-
-function hangUp() {
-  log("Hanging up the outgoing call (local hang-up).");
-
-  let gotDisconnecting = false;
-  outgoingCall.ondisconnecting = function ondisconnectingOut(event) {
-    log("Received 'disconnecting' call event.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  outgoingCall.ondisconnected = function ondisconnectedOut(event) {
-    log("Received 'disconnected' call event.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "disconnected");
-    ok(gotDisconnecting);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  outgoingCall.hangUp();
-}
-
-function cleanUp() {
-  finish();
-}
+const outNumber = "5555551111";
+const outInfo = gOutCallStrPool(outNumber);
+let outCall;
 
 startTest(function() {
-  dial();
+  gDial(outNumber)
+    .then(call => outCall = call)
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing]))
+    .then(() => gRemoteAnswer(outCall))
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active]))
+
+    // Hang-up
+    .then(() => gHangUp(outCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_outgoing_answer_radio_off.js
+++ b/dom/telephony/test/marionette/test_outgoing_answer_radio_off.js
@@ -1,103 +1,26 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-function setRadioEnabled(enabled) {
-  log("Set radio enabled: " + enabled + ".");
-
-  let desiredRadioState = enabled ? 'enabled' : 'disabled';
-  let deferred = Promise.defer();
+// Make an outgoing call then power off radio.
+startTestWithPermissions(['mobileconnection'], function() {
   let connection = navigator.mozMobileConnections[0];
-
-  connection.onradiostatechange = function() {
-    let state = connection.radioState;
-    log("Received 'radiostatechange' event, radioState: " + state);
-
-    // We are waiting for 'desiredRadioState.' Ignore any transient state.
-    if (state === desiredRadioState) {
-      connection.onradiostatechange = null;
-      deferred.resolve();
-    }
-  };
-  connection.setRadioEnabled(enabled);
-
-  return deferred.promise;
-}
+  ok(connection instanceof MozMobileConnection,
+     "connection is instanceof " + connection.constructor);
 
-function dial(number) {
-  log("Make an outgoing call.");
-
-  let deferred = Promise.defer();
-  telephony.dial(number).then(call => {
-    ok(call);
-    is(call.id.number, number);
-    is(call.state, "dialing");
-
-    call.onalerting = function(event) {
-      log("Received 'onalerting' call event.");
-      call.onalerting = null;
-      is(call, event.call);
-      is(call.state, "alerting");
-      deferred.resolve(call);
-    };
-  });
-
-  return deferred.promise;
-}
-
-function remoteAnswer(call) {
-  log("Remote answering the call.");
+  let outCall;
 
-  let deferred = Promise.defer();
-
-  call.onconnected = function(event) {
-    log("Received 'connected' call event.");
-    call.onconnected = null;
-    is(call, event.call);
-    is(call.state, "connected");
-    deferred.resolve(call);
-  };
-  emulator.runCmdWithCallback("gsm accept " + call.id.number);
-
-  return deferred.promise;
-}
-
-function disableRadioAndWaitForCallEvent(call) {
-  log("Disable radio and wait for call event.");
-
-  let deferred = Promise.defer();
-
-  call.ondisconnected = function(event) {
-    log("Received 'disconnected' call event.");
-    call.ondisconnected = null;
-    is(call, event.call);
-    is(call.state, "disconnected");
-    deferred.resolve();
-  };
-  navigator.mozMobileConnections[0].setRadioEnabled(false);
-
-  return deferred.promise;
-}
-
-/**
- * Make an outgoing call then power off radio.
- */
-function testOutgoingCallRadioOff() {
-  log("= testOutgoingCallRadioOff =");
-  let number = "0912345000";
-
-  return Promise.resolve()
-    .then(() => dial(number))
-    .then(call => remoteAnswer(call))
-    .then(call => disableRadioAndWaitForCallEvent(call))
-    .then(() => setRadioEnabled(true));
-}
-
-// Start test
-startTestWithPermissions(['mobileconnection'], function() {
-  testOutgoingCallRadioOff()
+  gDial("0912345000")
+    .then(call => outCall = call)
+    .then(() => gRemoteAnswer(outCall))
+    .then(() => {
+      let p1 = gWaitForNamedStateEvent(outCall, "disconnected");
+      let p2 = gSetRadioEnabled(connection, false);
+      return Promise.all([p1, p2]);
+    })
+    .then(() => gSetRadioEnabled(connection, true))
     .catch(error => ok(false, "Promise reject: " + error))
     .then(finish);
 });
--- a/dom/telephony/test/marionette/test_outgoing_badNumber.js
+++ b/dom/telephony/test/marionette/test_outgoing_badNumber.js
@@ -1,47 +1,39 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let number = "****5555552368****";
-let outgoing;
+const number = "****5555552368****";
+let outCall;
 
-
-function dial() {
-  log("Make an outgoing call to an invalid number.");
+function testDialOutInvalidNumber() {
+  log("Make an outCall call to an invalid number.");
 
   // Note: The number is valid from the view of phone and the call could be
   // dialed out successfully. However, it will later receive the BadNumberError
   // from network side.
-  telephony.dial(number).then(call => {
-    outgoing = call;
-    ok(outgoing);
-    is(outgoing.id.number, number);
-    is(outgoing.state, "dialing");
+  return telephony.dial(number).then(call => {
+    outCall = call;
+    ok(outCall);
+    is(outCall.id.number, number);
+    is(outCall.state, "dialing");
 
-    is(outgoing, telephony.active);
+    is(outCall, telephony.active);
     is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoing);
+    is(telephony.calls[0], outCall);
 
-    outgoing.onerror = function onerror(event) {
-      log("Received 'error' event.");
-      is(event.call, outgoing);
+    return gWaitForEvent(outCall, "error").then(event => {
+      is(event.call, outCall);
       ok(event.call.error);
       is(event.call.error.name, "BadNumberError");
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Initial call list: " + result);
-        cleanUp();
-      });
-    };
+    })
+    .then(() => gCheckAll(null, [], "", [], []));
   });
 }
 
-function cleanUp() {
-  finish();
-}
-
 startTest(function() {
-  dial();
+  testDialOutInvalidNumber()
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_outgoing_busy.js
+++ b/dom/telephony/test/marionette/test_outgoing_busy.js
@@ -1,60 +1,27 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let number = "5555552368";
-let outgoing;
-
-function dial() {
-  log("Make an outgoing call.");
-
-  telephony.dial(number).then(call => {
-    outgoing = call;
-    ok(outgoing);
-    is(outgoing.id.number, number);
-    is(outgoing.state, "dialing");
-
-    is(outgoing, telephony.active);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoing);
-
-    outgoing.onalerting = function onalerting(event) {
-      log("Received 'onalerting' call event.");
-      is(outgoing, event.call);
-      is(outgoing.state, "alerting");
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "outbound to  " + number + " : ringing");
-        busy();
-      });
-    };
-  });
-}
-
-function busy() {
-  log("The receiver is busy.");
-
-  outgoing.onerror = function onerror(event) {
-    log("Received 'error' call event.");
-    is(outgoing, event.call);
-    is(event.call.error.name, "BusyError");
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-
-  emulator.runCmdWithCallback("gsm busy " + number);
-}
-
-function cleanUp() {
-  finish();
-}
+const outNumber = "5555551111";
+const outInfo = gOutCallStrPool(outNumber);
+let outCall;
 
 startTest(function() {
-  dial();
+  gDial(outNumber)
+    .then(call => outCall = call)
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing]))
+    .then(() => {
+      let p1 = gWaitForEvent(outCall, "error")
+        .then(event => {
+          is(event.call, outCall);
+          is(event.call.error.name, "BusyError");
+        });
+      let p2 = emulator.runCmd("gsm busy " + outNumber);
+      return Promise.all([p1, p2]);
+    })
+    .then(() => gCheckAll(null, [], "", [], []))
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_outgoing_emergency_in_airplane_mode.js
+++ b/dom/telephony/test/marionette/test_outgoing_emergency_in_airplane_mode.js
@@ -1,41 +1,22 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-function setRadioEnabled(enabled) {
-  log("Set radio enabled: " + enabled + ".");
-
-  let desiredRadioState = enabled ? 'enabled' : 'disabled';
-  let deferred = Promise.defer();
+startTestWithPermissions(['mobileconnection'], function() {
   let connection = navigator.mozMobileConnections[0];
   ok(connection instanceof MozMobileConnection,
      "connection is instanceof " + connection.constructor);
 
-  connection.onradiostatechange = function() {
-    let state = connection.radioState;
-    log("Received 'radiostatechange' event, radioState: " + state);
+  let outCall;
 
-    // We are waiting for 'desiredRadioState.' Ignore any transient state.
-    if (state === desiredRadioState) {
-      connection.onradiostatechange = null;
-      deferred.resolve();
-    }
-  };
-  connection.setRadioEnabled(enabled);
-
-  return deferred.promise;
-}
-
-startTestWithPermissions(['mobileconnection'], function() {
-  let outCall;
-  setRadioEnabled(false)
+  gSetRadioEnabled(connection, false)
     .then(() => gDial("112"))
     .then(call => { outCall = call; })
     .then(() => gRemoteAnswer(outCall))
     .then(() => gDelay(1000))  // See Bug 1018051 for the purpose of the delay.
     .then(() => gRemoteHangUp(outCall))
     .catch(error => ok(false, "Promise reject: " + error))
     .then(finish);
 });
--- a/dom/telephony/test/marionette/test_outgoing_error_state.js
+++ b/dom/telephony/test/marionette/test_outgoing_error_state.js
@@ -1,44 +1,25 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
 const number = "0912345678";
 
-function setRadioEnabled(enabled) {
-  log("Set radio enabled: " + enabled + ".");
-
-  let desiredRadioState = enabled ? 'enabled' : 'disabled';
-  let deferred = Promise.defer();
+startTestWithPermissions(['mobileconnection'], function() {
   let connection = navigator.mozMobileConnections[0];
   ok(connection instanceof MozMobileConnection,
      "connection is instanceof " + connection.constructor);
 
-  connection.onradiostatechange = function() {
-    let state = connection.radioState;
-    log("Received 'radiostatechange' event, radioState: " + state);
+  let outCall;
 
-    // We are waiting for 'desiredRadioState.' Ignore any transient state.
-    if (state === desiredRadioState) {
-      connection.onradiostatechange = null;
-      deferred.resolve();
-    }
-  };
-  connection.setRadioEnabled(enabled);
-
-  return deferred.promise;
-}
-
-startTestWithPermissions(['mobileconnection'], function() {
-  let outCall;
-  setRadioEnabled(false)
+  gSetRadioEnabled(connection, false)
     .then(() => gDial(number))
     .then(null, cause => { is(cause, "RadioNotAvailable"); })
     .then(() => gDialEmergency(number))
     .then(null, cause => { is(cause, "RadioNotAvailable"); })
-    .then(() => setRadioEnabled(true))
+    .then(() => gSetRadioEnabled(connection, true))
     .then(() => gDialEmergency(number))
     .then(null, cause => { is(cause, "BadNumberError"); })
     .then(finish);
 });
--- a/dom/telephony/test/marionette/test_outgoing_hangup_alerting.js
+++ b/dom/telephony/test/marionette/test_outgoing_hangup_alerting.js
@@ -1,72 +1,22 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let number = "5555552368";
-let outgoing;
-let calls;
-
-function dial() {
-  log("Make an outgoing call.");
-
-  telephony.dial(number).then(call => {
-    outgoing = call;
-    ok(outgoing);
-    is(outgoing.id.number, number);
-    is(outgoing.state, "dialing");
-
-    is(outgoing, telephony.active);
-    //ok(telephony.calls === calls); // bug 717414
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoing);
-
-    outgoing.onalerting = function onalerting(event) {
-      log("Received 'alerting' call event.");
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "outbound to  " + number + " : ringing");
-        hangUp();
-      });
-    };
-  });
-}
-
-function hangUp() {
-  log("Hang up the outgoing call.");
-
-  let gotDisconnecting = false;
-
-  outgoing.ondisconnecting = function ondisconnecting(event) {
-    log("Received 'disconnecting' call event.");
-    is(outgoing, event.call);
-    is(outgoing.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  outgoing.ondisconnected = function ondisconnected(event) {
-    log("Received 'disconnected' call event.");
-    is(outgoing, event.call);
-    is(outgoing.state, "disconnected");
-    ok(gotDisconnecting);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-
-  outgoing.hangUp();
-}
-
-function cleanUp() {
-  finish();
-}
+const outNumber = "5555551111";
+const outInfo = gOutCallStrPool(outNumber);
+let outCall;
 
 startTest(function() {
-  dial();
+  gDial(outNumber)
+    .then(call => outCall = call)
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing]))
+
+    // Hang-up
+    .then(() => gRemoteHangUp(outCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_outgoing_hangup_held.js
+++ b/dom/telephony/test/marionette/test_outgoing_hangup_held.js
@@ -1,122 +1,26 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let number = "5555552368";
-let outgoing;
-let calls;
-
-function dial() {
-  log("Make an outgoing call.");
-
-  telephony.dial(number).then(call => {
-    outgoing = call;
-    ok(outgoing);
-    is(outgoing.id.number, number);
-    is(outgoing.state, "dialing");
-    is(outgoing, telephony.active);
-    //ok(telephony.calls === calls); // bug 717414
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoing);
-
-    outgoing.onalerting = function onalerting(event) {
-      log("Received 'onalerting' call event.");
-      is(outgoing, event.call);
-      is(outgoing.state, "alerting");
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "outbound to  " + number + " : ringing");
-        answer();
-      });
-    };
-  });
-}
-
-function answer() {
-  log("Answering the outgoing call.");
-
-  // We get no "connecting" event when the remote party answers the call.
-
-  outgoing.onconnected = function onconnected(event) {
-    log("Received 'connected' call event.");
-    is(outgoing, event.call);
-    is(outgoing.state, "connected");
-
-    is(outgoing, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + number + " : active");
-      hold();
-    });
-  };
-  emulator.runCmdWithCallback("gsm accept " + number);
-}
-
-function hold() {
-  log("Holding the outgoing call.");
-
-  outgoing.onholding = function onholding(event) {
-    log("Received 'holding' call event.");
-    is(outgoing, event.call);
-    is(outgoing.state, "holding");
-
-    is(outgoing, telephony.active);
-  };
-
-  outgoing.onheld = function onheld(event) {
-    log("Received 'held' call event.");
-    is(outgoing, event.call);
-    is(outgoing.state, "held");
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 1);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + number + " : held");
-      hangUp();
-    });
-  };
-  outgoing.hold();
-}
-
-function hangUp() {
-  log("Hanging up the outgoing call.");
-
-  let gotDisconnecting = false;
-  outgoing.ondisconnecting = function ondisconnecting(event) {
-    log("Received disconnecting call event.");
-    is(outgoing, event.call);
-    is(outgoing.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  outgoing.ondisconnected = function ondisconnected(event) {
-    log("Received 'disconnected' call event.");
-    is(outgoing, event.call);
-    is(outgoing.state, "disconnected");
-    ok(gotDisconnecting);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-
-  outgoing.hangUp();
-}
-
-function cleanUp() {
-  finish();
-}
+const outNumber = "5555551111";
+const outInfo = gOutCallStrPool(outNumber);
+let outCall;
 
 startTest(function() {
-  dial();
+  gDial(outNumber)
+    .then(call => outCall = call)
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing]))
+    .then(() => gRemoteAnswer(outCall))
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active]))
+    .then(() => gHold(outCall))
+    .then(() => gCheckAll(null, [outCall], "", [], [outInfo.held]))
+
+    // Hang-up
+    .then(() => gHangUp(outCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_outgoing_hold_resume.js
+++ b/dom/telephony/test/marionette/test_outgoing_hold_resume.js
@@ -1,157 +1,28 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let number = "5555557777";
-let connectedCalls;
-let outgoingCall;
-
-function dial() {
-  log("Make an outgoing call.");
-
-  telephony.dial(number).then(call => {
-    outgoingCall = call;
-    ok(outgoingCall);
-    is(outgoingCall.id.number, number);
-    is(outgoingCall.state, "dialing");
-
-    is(outgoingCall, telephony.active);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoingCall);
-
-    outgoingCall.onalerting = function onalerting(event) {
-      log("Received 'onalerting' call event.");
-      is(outgoingCall, event.call);
-      is(outgoingCall.state, "alerting");
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "outbound to  " + number + " : ringing");
-        answer();
-      });
-    };
-  });
-}
-
-function answer() {
-  log("Answering the outgoing call.");
-
-  // We get no "connecting" event when the remote party answers the call.
-
-  outgoingCall.onconnected = function onconnected(event) {
-    log("Received 'connected' call event.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "connected");
-
-    is(outgoingCall, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + number + " : active");
-      hold();
-    });
-  };
-  emulator.runCmdWithCallback("gsm accept " + number);
-}
-
-function hold() {
-  log("Putting the call on hold.");
-
-  let gotHolding = false;
-  outgoingCall.onholding = function onholding(event) {
-    log("Received 'holding' call event");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "holding");
-    gotHolding = true;
-  };
-
-  outgoingCall.onheld = function onheld(event) {
-    log("Received 'held' call event");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "held");
-    ok(gotHolding);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + number + " : held");
-      // Bug 781604: emulator assertion if outgoing call kept on hold
-      // Wait on hold for a couple of seconds
-      //log("Pausing 2 seconds while on hold");
-      //setTimeout(resume, 2000);
-      resume();
-    });
-  };
-  outgoingCall.hold();
-}
-
-function resume() {
-  log("Resuming the held call.");
-
-  let gotResuming = false;
-  outgoingCall.onresuming = function onresuming(event) {
-    log("Received 'resuming' call event");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "resuming");
-    gotResuming = true;
-  };
-
-  outgoingCall.onconnected = function onconnected(event) {
-    log("Received 'connected' call event");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "connected");
-    ok(gotResuming);
-
-    is(outgoingCall, telephony.active);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + number + " : active");
-      hangUp();
-    });
-  };
-  outgoingCall.resume();
-}
-
-function hangUp() {
-  log("Hanging up the outgoing call.");
-
-  let gotDisconnecting = false;
-  outgoingCall.ondisconnecting = function ondisconnecting(event) {
-    log("Received 'disconnecting' call event.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  outgoingCall.ondisconnected = function ondisconnected(event) {
-    log("Received 'disconnected' call event.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "disconnected");
-    ok(gotDisconnecting);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  outgoingCall.hangUp();
-}
-
-function cleanUp() {
-  finish();
-}
+const outNumber = "5555551111";
+const outInfo = gOutCallStrPool(outNumber);
+let outCall;
 
 startTest(function() {
-  dial();
+  gDial(outNumber)
+    .then(call => outCall = call)
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing]))
+    .then(() => gRemoteAnswer(outCall))
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active]))
+    .then(() => gHold(outCall))
+    .then(() => gCheckAll(null, [outCall], "", [], [outInfo.held]))
+    .then(() => gResume(outCall))
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active]))
+
+    // Hang-up
+    .then(() => gRemoteHangUp(outCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_outgoing_onstatechange.js
+++ b/dom/telephony/test/marionette/test_outgoing_onstatechange.js
@@ -1,143 +1,53 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let outgoingCall;
-let outNumber = "5555551111";
-
-function dial() {
-  log("Make an outgoing call.");
-
-  telephony.dial(outNumber).then(call => {
-    outgoingCall = call;
-    ok(outgoingCall);
-    is(outgoingCall.id.number, outNumber);
-    is(outgoingCall.state, "dialing");
-
-    is(outgoingCall, telephony.active);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoingCall);
-
-    outgoingCall.onstatechange = function statechangering(event) {
-      log("Received 'onstatechange' call event.");
-
-      is(outgoingCall, event.call);
-      let expectedStates = ["dialing", "alerting"];
-      ok(expectedStates.indexOf(event.call.state) != -1);
-
-      if (event.call.state == "alerting") {
-        emulator.runCmdWithCallback("gsm list", function(result) {
-          log("Call list is now: " + result);
-          is(result[0], "outbound to  " + outNumber + " : ringing");
-          answer();
-        });
-      }
-    };
-  });
-}
-
-function answer() {
-  log("Answering the outgoing call.");
-
-  // We get no "connecting" event when the remote party answers the call.
-
-  outgoingCall.onstatechange = function onstatechangeanswer(event) {
-    log("Received 'onstatechange' call event.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "connected");
-    is(outgoingCall, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + outNumber + " : active");
-      hold();
-    });
-  };
-  emulator.runCmdWithCallback("gsm accept " + outNumber);
-}
-
-function hold() {
-  log("Putting the call on hold.");
-
-  let gotHolding = false;
-  outgoingCall.onstatechange = function onstatechangehold(event) {
-    log("Received 'onstatechange' call event.");
-    is(outgoingCall, event.call);
-    if(!gotHolding){
-      is(outgoingCall.state, "holding");
-      gotHolding = true;
-    } else {
-      is(outgoingCall.state, "held");
-      is(telephony.active, null);
-      is(telephony.calls.length, 1);
-      is(telephony.calls[0], outgoingCall);
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "outbound to  " + outNumber + " : held");
-        resume();
-      });
-    }
-  };
-  outgoingCall.hold();
-}
-
-function resume() {
-  log("Resuming the held call.");
-
-  let gotResuming = false;
-  outgoingCall.onstatechange = function onstatechangeresume(event) {
-    log("Received 'onstatechange' call event.");
-    is(outgoingCall, event.call);
-    if(!gotResuming){
-      is(outgoingCall.state, "resuming");
-      gotResuming = true;
-    } else {
-      is(outgoingCall.state, "connected");
-      is(telephony.active, outgoingCall);
-      is(telephony.calls.length, 1);
-      is(telephony.calls[0], outgoingCall);
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "outbound to  " + outNumber + " : active");
-        hangUp();
-      });
-    }
-  };
-  outgoingCall.resume();
-}
-
-function hangUp() {
-  log("Hanging up the outgoing call (local hang-up).");
-
-  let gotDisconnecting = false;
-  outgoingCall.onstatechange = function onstatechangedisconnect(event) {
-    log("Received 'onstatechange' call event.");
-    is(outgoingCall, event.call);
-    if(!gotDisconnecting){
-      is(outgoingCall.state, "disconnecting");
-      gotDisconnecting = true;
-    } else {
-      is(outgoingCall.state, "disconnected");
-      is(telephony.active, null);
-      is(telephony.calls.length, 0);
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        cleanUp();
-      });
-    }
-  };
-  outgoingCall.hangUp();
-}
-
-function cleanUp() {
-  finish();
-}
+const outNumber = "5555551111";
+const outInfo = gOutCallStrPool(outNumber);
+let outCall;
 
 startTest(function() {
-  dial();
+  gDial(outNumber)
+    .then(call => outCall = call)
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing]))
+
+    // Remote answer.
+    .then(() => {
+      let p1 = gWaitForStateChangeEvent(outCall, "connected");
+      let p2 = gRemoteAnswer(outCall);
+      return Promise.all([p1, p2]);
+    })
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active]))
+
+    // Hold the call.
+    .then(() => {
+      let p1 = gWaitForStateChangeEvent(outCall, "holding")
+        .then(() => gWaitForStateChangeEvent(outCall, "held"));
+      let p2 = gHold(outCall);
+      return Promise.all([p1, p2]);
+    })
+    .then(() => gCheckAll(null, [outCall], "", [], [outInfo.held]))
+
+    // Resume the call.
+    .then(() => {
+      let p1 = gWaitForStateChangeEvent(outCall, "resuming")
+        .then(() => gWaitForStateChangeEvent(outCall, "connected"));
+      let p2 = gResume(outCall);
+      return Promise.all([p1, p2]);
+    })
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active]))
+
+    // Hang-up call
+    .then(() => {
+      let p1 = gWaitForStateChangeEvent(outCall, "disconnecting")
+        .then(() => gWaitForStateChangeEvent(outCall, "disconnected"));
+      let p2 = gHangUp(outCall);
+      return Promise.all([p1, p2]);
+    })
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_outgoing_radio_off.js
+++ b/dom/telephony/test/marionette/test_outgoing_radio_off.js
@@ -1,42 +1,22 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let connection;
-
-function setRadioEnabled(enabled) {
-  let desiredRadioState = enabled ? 'enabled' : 'disabled';
-  log("Set radio: " + desiredRadioState);
-
-  let promises = [];
-
-  let promise = gWaitForEvent(connection, "radiostatechange", event => {
-    let state = connection.radioState;
-    log("current radioState: " + state);
-    return state == desiredRadioState;
-  });
-  promises.push(promise);
-
-  promises.push(connection.setRadioEnabled(enabled));
-
-  return Promise.all(promises);
-}
-
 startTestWithPermissions(['mobileconnection'], function() {
-  connection = navigator.mozMobileConnections[0];
+  let connection = navigator.mozMobileConnections[0];
   ok(connection instanceof MozMobileConnection,
      "connection is instanceof " + connection.constructor);
 
-  setRadioEnabled(false)
+  gSetRadioEnabled(connection, false)
     .then(() => gDial("0912345678"))
     .catch(cause => {
       is(telephony.active, null);
       is(telephony.calls.length, 0);
       is(cause, "RadioNotAvailable");
     })
-    .then(() => setRadioEnabled(true))
+    .then(() => gSetRadioEnabled(connection, true))
     .catch(error => ok(false, "Promise reject: " + error))
     .then(finish);
 });
--- a/dom/telephony/test/marionette/test_outgoing_reject.js
+++ b/dom/telephony/test/marionette/test_outgoing_reject.js
@@ -1,74 +1,22 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let number = "5555552368";
-let outgoing;
-
-function dial() {
-  log("Make an outgoing call.");
-
-  telephony.dial(number).then(call => {
-    outgoing = call;
-    ok(outgoing);
-    is(outgoing.id.number, number);
-    is(outgoing.state, "dialing");
-
-    is(outgoing, telephony.active);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoing);
-
-    outgoing.onalerting = function onalerting(event) {
-      log("Received 'onalerting' call event.");
-      is(outgoing, event.call);
-      is(outgoing.state, "alerting");
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "outbound to  " + number + " : ringing");
-        reject();
-      });
-    };
-  });
-}
-
-function reject() {
-  log("Reject the outgoing call on the other end.");
-  // We get no "disconnecting" event when the remote party rejects the call.
-
-  outgoing.ondisconnected = function ondisconnected(event) {
-    log("Received 'disconnected' call event.");
-    is(outgoing, event.call);
-    is(outgoing.state, "disconnected");
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    // Wait for emulator to catch up before continuing
-    waitFor(verifyCallList,function() {
-      return(rcvdEmulatorCallback);
-    });
-  };
-
-  let rcvdEmulatorCallback = false;
-  emulator.runCmdWithCallback("gsm cancel " + number, function(result) {
-    rcvdEmulatorCallback = true;
-  });
-}
-
-function verifyCallList(){
-  emulator.runCmdWithCallback("gsm list", function(result) {
-    log("Call list is now: " + result);
-    cleanUp();
-  });
-}
-
-function cleanUp() {
-  finish();
-}
+const outNumber = "5555551111";
+const outInfo = gOutCallStrPool(outNumber);
+let outCall;
 
 startTest(function() {
-  dial();
+  gDial(outNumber)
+    .then(call => outCall = call)
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing]))
+
+    // Hang-up
+    .then(() => gRemoteHangUp(outCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_outgoing_remote_hangup_held.js
+++ b/dom/telephony/test/marionette/test_outgoing_remote_hangup_held.js
@@ -1,114 +1,26 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
-
-let outNumber = "5555551111";
-let outgoingCall;
-
-function dial() {
-  log("Make an outgoing call.");
-
-  telephony.dial(outNumber).then(call => {
-    outgoingCall = call;
-    ok(outgoingCall);
-    is(outgoingCall.id.number, outNumber);
-    is(outgoingCall.state, "dialing");
-
-    is(outgoingCall, telephony.active);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoingCall);
-
-    outgoingCall.onalerting = function onalerting(event) {
-      log("Received 'alerting' call event.");
-
-      is(outgoingCall, event.call);
-      is(outgoingCall.state, "alerting");
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "outbound to  " + outNumber + " : ringing");
-        answer();
-      });
-    };
-  });
-}
-
-function answer() {
-  log("Answering the outgoing call.");
-
-  // We get no "connecting" event when the remote party answers the call.
-
-  outgoingCall.onconnected = function onconnected(event) {
-    log("Received 'connected' call event.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "connected");
-
-    is(outgoingCall, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + outNumber + " : active");
-      hold();
-    });
-  };
-  emulator.runCmdWithCallback("gsm accept " + outNumber);
-}
+MARIONETTE_HEAD_JS = 'head.js';
 
-function hold() {
-  log("Holding the outgoing call.");
-
-  outgoingCall.onholding = function onholding(event) {
-    log("Received 'holding' call event.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "holding");
-
-    is(outgoingCall, telephony.active);
-  };
-
-  outgoingCall.onheld = function onheld(event) {
-    log("Received 'held' call event.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "held");
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + outNumber + " : held");
-      hangUp();
-    });
-  };
-  outgoingCall.hold();
-}
-
-function hangUp() {
-  log("Hanging up the outgoing call (remotely).");
-
-  // We get no 'disconnecting' event when remote party hangs-up the call
-
-  outgoingCall.ondisconnected = function ondisconnected(event) {
-    log("Received 'disconnected' call event.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "disconnected");
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  emulator.runCmdWithCallback("gsm cancel " + outNumber);
-}
-
-function cleanUp() {
-  finish();
-}
+const outNumber = "5555551111";
+const outInfo = gOutCallStrPool(outNumber);
+let outCall;
 
 startTest(function() {
-  dial();
+  gDial(outNumber)
+    .then(call => outCall = call)
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.ringing]))
+    .then(() => gRemoteAnswer(outCall))
+    .then(() => gCheckAll(outCall, [outCall], "", [], [outInfo.active]))
+    .then(() => gHold(outCall))
+    .then(() => gCheckAll(null, [outCall], "", [], [outInfo.held]))
+
+    // Hang-up
+    .then(() => gRemoteHangUp(outCall))
+    .then(() => gCheckAll(null, [], "", [], []))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_redundant_operations.js
+++ b/dom/telephony/test/marionette/test_redundant_operations.js
@@ -1,325 +1,66 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let inNumber = "5555551111";
-let incomingCall;
-
-function simulateIncoming() {
-  log("Simulating an incoming call.");
-
-  telephony.onincoming = function onincoming(event) {
-    log("Received 'incoming' call event.");
-    incomingCall = event.call;
-    ok(incomingCall);
-    is(incomingCall.id.number, inNumber);
-    is(incomingCall.state, "incoming");
-
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : incoming");
-      answerIncoming();
-    });
-  };
-  emulator.runCmdWithCallback("gsm call " + inNumber);
-}
-
-function answerIncoming() {
-  log("Answering the incoming call.");
-
-  let gotConnecting = false;
-  incomingCall.onconnecting = function onconnectingIn(event) {
-    log("Received 'connecting' call event for incoming call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connecting");
-    gotConnecting = true;
-  };
-
-  incomingCall.onconnected = function onconnectedIn(event) {
-    log("Received 'connected' call event for incoming call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connected");
-    ok(gotConnecting);
-
-    is(incomingCall, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : active");
-      answerAlreadyConnected();
-    });
-  };
-  incomingCall.answer();
-}
-
-function answerAlreadyConnected() {
-  log("Attempting to answer already connected call, should be ignored.");
-
-  incomingCall.onconnecting = function onconnectingErr(event) {
-    log("Received 'connecting' call event, but should not have.");
-    ok(false, "Received 'connecting' event when answered already active call");
-  };
-
-  incomingCall.onconnected = function onconnectedErr(event) {
-    log("Received 'connected' call event, but should not have.");
-    ok(false, "Received 'connected' event when answered already active call");
-  };
-
-  incomingCall.answer();
-
-  is(incomingCall.state, "connected");
-  is(telephony.calls.length, 1);
-  is(telephony.calls[0], incomingCall);
-  is(incomingCall, telephony.active);
-  hold();
-}
+const inNumber = "5555552222";
+const inInfo = gInCallStrPool(inNumber);
+let inCall;
 
-function hold() {
-  log("Putting the call on hold.");
-
-  let gotHolding = false;
-  incomingCall.onholding = function onholding(event) {
-    log("Received 'holding' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "holding");
-    gotHolding = true;
-  };
-
-  incomingCall.onheld = function onheld(event) {
-    log("Received 'held' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "held");
-    ok(gotHolding);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : held");
-      holdAlreadyHeld();
-    });
-  };
-  incomingCall.hold();
-}
-
-function holdAlreadyHeld() {
-  log("Attempting to hold an already held call, should be ignored.");
-
-  incomingCall.onholding = function onholding(event) {
-    log("Received 'holding' call event, but should not have.");
-    ok(false, "Received 'holding' event when held an already held call");
-  };
-
-  incomingCall.onheld = function onheldErr(event) {
-    log("Received 'held' call event, but should not have.");
-    ok(false, "Received 'held' event when held an already held call");
-  };
-
-  incomingCall.hold();
-
-  is(incomingCall.state, "held");
-  is(telephony.active, null);
-  is(telephony.calls.length, 1);
-  is(telephony.calls[0], incomingCall);
-
-  answerHeld();
-}
-
-function answerHeld() {
-  log("Attempting to answer a held call, should be ignored.");
-
-  incomingCall.onconnecting = function onconnectingErr(event) {
-    log("Received 'connecting' call event, but should not have.");
-    ok(false, "Received 'connecting' event when answered a held call");
-  };
-
-  incomingCall.onconnected = function onconnectedErr(event) {
-    log("Received 'connected' call event, but should not have.");
-    ok(false, "Received 'connected' event when answered a held call");
-  };
-
-  incomingCall.answer();
-
-  is(incomingCall.state, "held");
-  is(telephony.active, null);
-  is(telephony.calls.length, 1);
-  is(telephony.calls[0], incomingCall);
-
-  resume();
+function error(event, action) {
+  ok(false, "Received '" + event + "' event when " + action);
 }
 
-function resume() {
-  log("Resuming the held call.");
-
-  let gotResuming = false;
-  incomingCall.onresuming = function onresuming(event) {
-    log("Received 'resuming' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "resuming");
-    gotResuming = true;
-  };
-
-  incomingCall.onconnected = function onconnected(event) {
-    log("Received 'connected' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connected");
-    ok(gotResuming);
-
-    is(incomingCall, telephony.active);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : active");
-      resumeNonHeld();
-    });
-  };
-  incomingCall.resume();
-}
-
-function resumeNonHeld() {
-  log("Attempting to resume non-held call, should be ignored.");
-
-  incomingCall.onresuming = function onresumingErr(event) {
-    log("Received 'resuming' call event, but should not have.");
-    ok(false, "Received 'resuming' event when resumed non-held call");
-  };
-
-  incomingCall.onconnected = function onconnectedErr(event) {
-    log("Received 'connected' call event, but should not have.");
-    ok(false, "Received 'connected' event when resumed non-held call");
-  };
-
-  incomingCall.resume();
-
-  is(incomingCall.state, "connected");
-  is(telephony.calls.length, 1);
-  is(telephony.calls[0], incomingCall);
-  is(incomingCall, telephony.active);
-  hangUp();
-}
-
-function hangUp() {
-  log("Hanging up the call (local hang-up).");
-
-  let gotDisconnecting = false;
-  incomingCall.ondisconnecting = function ondisconnecting(event) {
-    log("Received 'disconnecting' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  incomingCall.ondisconnected = function ondisconnectedOut(event) {
-    log("Received 'disconnected' call event.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnected");
-    ok(gotDisconnecting);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      answerDisconnected();
-    });
-  };
-  incomingCall.hangUp();
-}
+function checkUnexpected(msg, call, event1, event2, actionCallback) {
+  let error1 = error.bind(this, event1, msg);
+  let error2 = error.bind(this, event2, msg);
 
-function answerDisconnected() {
-  log("Attempting to answer disconnected call, should be ignored.");
-
-  incomingCall.onconnecting = function onconnectingErr(event) {
-    log("Received 'connecting' call event, but should not have.");
-    ok(false, "Received 'connecting' event when answered disconnected call");
-  };
-
-  incomingCall.onconnected = function onconnectedErr(event) {
-    log("Received 'connected' call event, but should not have.");
-    ok(false, "Received 'connected' event when answered disconnected call");
-  };
-
-  incomingCall.answer();
-
-  is(telephony.active, null);
-  is(telephony.calls.length, 0);
-  holdDisconnected();
-}
-
-function holdDisconnected() {
-  log("Attempting to hold disconnected call, should be ignored.");
-
-  incomingCall.onholding = function onholdingErr(event) {
-    log("Received 'holding' call event, but should not have.");
-    ok(false, "Received 'holding' event when held a disconnected call");
-  };
-
-  incomingCall.onheld = function onheldErr(event) {
-    log("Received 'held' call event, but should not have.");
-    ok(false, "Received 'held' event when held a disconnected call");
-  };
-
-  incomingCall.hold();
-
-  is(telephony.active, null);
-  is(telephony.calls.length, 0);
-  resumeDisconnected();
-}
+  call.addEventListener(event1, error1);
+  call.addEventListener(event2, error2);
+  actionCallback();
 
-function resumeDisconnected() {
-  log("Attempting to resume disconnected call, should be ignored.");
-
-  incomingCall.onresuming = function onresumingErr(event) {
-    log("Received 'resuming' call event, but should not have.");
-    ok(false, "Received 'resuming' event when resumed disconnected call");
-  };
-
-  incomingCall.onconnected = function onconnectedErr(event) {
-    log("Received 'connected' call event, but should not have.");
-    ok(false, "Received 'connected' event when resumed disconnected call");
-  };
-
-  incomingCall.resume();
-
-  is(telephony.active, null);
-  is(telephony.calls.length, 0);
-  hangUpNonConnected();
-}
-
-function hangUpNonConnected() {
-  log("Attempting to hang-up disconnected call, should be ignored.");
-
-  incomingCall.ondisconnecting = function ondisconnectingErr(event) {
-    log("Received 'disconnecting' call event, but should not have.");
-    ok(false, "Received 'disconnecting' event when hung-up non-active call");
-  };
-
-  incomingCall.ondisconnected = function ondisconnectedErr(event) {
-    log("Received 'disconnected' call event, but should not have.");
-    ok(false, "Received 'disconnected' event when hung-up non-active call");
-  };
-
-  incomingCall.hangUp();
-
-  is(telephony.active, null);
-  is(telephony.calls.length, 0);
-  cleanUp();
-}
-
-function cleanUp() {
-  telephony.onincoming = null;
-  finish();
+  return gDelay(2000).then(() => {
+    call.removeEventListener(event1, error1);
+    call.removeEventListener(event2, error2);
+  });
 }
 
 startTest(function() {
-  simulateIncoming();
+  gRemoteDial(inNumber)
+    .then(call => inCall = call)
+    .then(() => gAnswer(inCall))
+    .then(() => checkUnexpected("answered an active call", inCall,
+                                "connecting", "connected",
+                                () => inCall.answer()))
+
+    .then(() => gHold(inCall))
+    .then(() => checkUnexpected("held a held call", inCall,
+                                "holding", "held",
+                                () => inCall.hold()))
+    .then(() => checkUnexpected("answered a held call", inCall,
+                                "connecting", "connected",
+                                () => inCall.answer()))
+
+    .then(() => gResume(inCall))
+    .then(() => checkUnexpected("resumed non-held call", inCall,
+                                "resuming", "connected",
+                                () => inCall.resume()))
+
+    .then(() => gHangUp(inCall))
+    .then(() => checkUnexpected("answered a disconnected call", inCall,
+                                "connecting", "connected",
+                                () => inCall.answer()))
+    .then(() => checkUnexpected("held a disconnected call", inCall,
+                                "holding", "held",
+                                () => inCall.hold()))
+    .then(() => checkUnexpected("resumed a disconnected call", inCall,
+                                "resuming", "connected",
+                                () => inCall.resume()))
+    .then(() => checkUnexpected("hang-up a disconnected call", inCall,
+                                "disconnecting", "disconnected",
+                                () => inCall.hangUp()))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_swap_held_and_active.js
+++ b/dom/telephony/test/marionette/test_swap_held_and_active.js
@@ -1,279 +1,42 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_HEAD_JS = 'head.js';
 
-let outNumber = "5555551111";
-let inNumber = "5555552222";
-let outgoingCall;
-let incomingCall;
-let gotOriginalConnected = false;
-let gotHeld = false;
-let gotConnected = false;
-
-function dial() {
-  log("Make an outgoing call.");
-  telephony.dial(outNumber).then(call => {
-    outgoingCall = call;
-    ok(outgoingCall);
-    is(outgoingCall.id.number, outNumber);
-    is(outgoingCall.state, "dialing");
-
-    outgoingCall.onalerting = function onalerting(event) {
-      log("Received 'alerting' call event.");
-
-      is(outgoingCall, event.call);
-      is(outgoingCall.state, "alerting");
-      is(outgoingCall, telephony.active);
-      is(telephony.calls.length, 1);
-      is(telephony.calls[0], outgoingCall);
-
-      emulator.runCmdWithCallback("gsm list", function(result) {
-        log("Call list is now: " + result);
-        is(result[0], "outbound to  " + outNumber + " : ringing");
-        answer();
-      });
-    };
-  });
-}
-
-function answer() {
-  log("Answering the outgoing call.");
-
-  // We get no "connecting" event when the remote party answers the call.
-  outgoingCall.onconnected = function onconnectedOut(event) {
-    log("Received 'connected' call event for the original outgoing call.");
-
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "connected");
-    is(outgoingCall, telephony.active);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + outNumber + " : active");
-
-      if(!gotOriginalConnected){
-        gotOriginalConnected = true;
-        holdCall();
-      } else {
-        // Received connected event for original call multiple times (fail)
-        ok(false,
-           "Received 'connected' event for original call multiple times.");
-      }
-    });
-  };
-  emulator.runCmdWithCallback("gsm accept " + outNumber);
-}
-
-function holdCall() {
-  log("Putting the original (outgoing) call on hold.");
-
-  let gotHolding = false;
-  outgoingCall.onholding = function onholding(event) {
-    log("Received 'holding' call event");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "holding");
-    gotHolding = true;
-  };
-
-  outgoingCall.onheld = function onheld(event) {
-    log("Received 'held' call event");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "held");
-    ok(gotHolding);
-
-    is(telephony.active, null);
-    is(telephony.calls.length, 1);
-    is(telephony.calls[0], outgoingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + outNumber + " : held");
-      simulateIncoming();
-    });
-  };
-  outgoingCall.hold();
-}
-
-// With one call on hold, simulate an incoming call
-function simulateIncoming() {
-  log("Simulating an incoming call (with one call already held).");
-
-  telephony.onincoming = function onincoming(event) {
-    log("Received 'incoming' call event.");
-    incomingCall = event.call;
-    ok(incomingCall);
-    is(incomingCall.id.number, inNumber);
-    is(incomingCall.state, "incoming");
-
-    // Should be two calls now
-    is(telephony.calls.length, 2);
-    is(telephony.calls[0], outgoingCall);
-    is(telephony.calls[1], incomingCall);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + outNumber + " : held");
-      is(result[1], "inbound from " + inNumber + " : incoming");
-      answerIncoming();
-    });
-  };
-  emulator.runCmdWithCallback("gsm call " + inNumber);
-}
-
-// Answer incoming call; original outgoing call should be held
-function answerIncoming() {
-  log("Answering the incoming call.");
-
-  let gotConnecting = false;
-  incomingCall.onconnecting = function onconnectingIn(event) {
-    log("Received 'connecting' call event for incoming/2nd call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "connecting");
-    gotConnecting = true;
-  };
-
-  incomingCall.onconnected = function onconnectedIn(event) {
-    log("Received 'connected' call event for incoming/2nd call.");
-    is(incomingCall, event.call);
-    ok(gotConnecting);
+const outNumber = "5555551111";
+const outInfo = gOutCallStrPool(outNumber);
+let outCall;
 
-    is(incomingCall, telephony.active);
-
-    // Original outbound call now held, incoming call active
-    is(outgoingCall.state, "held");
-    is(incomingCall.state, "connected");
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "outbound to  " + outNumber + " : held");
-      is(result[1], "inbound from " + inNumber + " : active");
-      swapCalls();
-    });
-  };
-  incomingCall.answer();
-}
-
-// Now swap the held and active calls
-function swapCalls() {
-  log("Swapping the held and active calls.");
-
-  // Swap calls by resuming the held (outgoing) call. Will force active
-  // (incoming) call to hold.
-
-  incomingCall.onheld = function onheldIn(event) {
-    log("Received 'held' call event for incoming call.");
-    gotHeld = true;
-
-    if (gotHeld && gotConnected) { verifySwap(); }
-  };
-
-  let gotResuming = false;
-  outgoingCall.onresuming = function onresuming(event) {
-    log("Received 'resuming' call event for outbound call.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "resuming");
-    gotResuming = true;
-  };
-
-  outgoingCall.onconnected = function onconnected(event) {
-    log("Received 'connected' call event for outbound call.");
-    is(outgoingCall, event.call);
-    ok(gotResuming);
-
-    is(outgoingCall, telephony.active);
-    is(telephony.calls.length, 2);
-    is(telephony.calls[0], outgoingCall);
-    is(telephony.calls[1], incomingCall);
-    gotConnected = true;
-
-    if (gotHeld && gotConnected) { verifySwap(); }
-  };
-  outgoingCall.resume();
-}
-
-function verifySwap() {
-  // Call status reflects swap
-  is(outgoingCall.state, "connected");
-  is(incomingCall.state, "held");
-
-  emulator.runCmdWithCallback("gsm list", function(result) {
-    log("Call list is now: " + result);
-    is(result[0], "outbound to  " + outNumber + " : active");
-    is(result[1], "inbound from " + inNumber + " : held");
-
-    // Begin hang-up
-    hangUpOutgoing();
-  });
-}
-
-// Hang-up original outgoing (now active) call
-function hangUpOutgoing() {
-  log("Hanging up the original outgoing (now active) call.");
-
-  let gotDisconnecting = false;
-  outgoingCall.ondisconnecting = function ondisconnectingOut(event) {
-    log("Received 'disconnecting' call event for original outgoing call.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  outgoingCall.ondisconnected = function ondisconnectedOut(event) {
-    log("Received 'disconnected' call event for original outgoing call.");
-    is(outgoingCall, event.call);
-    is(outgoingCall.state, "disconnected");
-    ok(gotDisconnecting);
-
-    // Back to one call now
-    is(telephony.calls.length, 1);
-    is(incomingCall.state, "held");
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      is(result[0], "inbound from " + inNumber + " : held");
-      hangUpIncoming();
-    });
-  };
-  outgoingCall.hangUp();
-}
-
-// Hang-up remaining (now held) call
-function hangUpIncoming() {
-  log("Hanging up the remaining (now held) call.");
-
-  let gotDisconnecting = false;
-  incomingCall.ondisconnecting = function ondisconnectingIn(event) {
-    log("Received 'disconnecting' call event for remaining (held) call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnecting");
-    gotDisconnecting = true;
-  };
-
-  incomingCall.ondisconnected = function ondisconnectedIn(event) {
-    log("Received 'disconnected' call event for remaining (incoming) call.");
-    is(incomingCall, event.call);
-    is(incomingCall.state, "disconnected");
-    ok(gotDisconnecting);
-
-    // Zero calls left
-    is(telephony.active, null);
-    is(telephony.calls.length, 0);
-
-    emulator.runCmdWithCallback("gsm list", function(result) {
-      log("Call list is now: " + result);
-      cleanUp();
-    });
-  };
-  incomingCall.hangUp();
-}
-
-function cleanUp() {
-  telephony.onincoming = null;
-  finish();
-}
+const inNumber = "5555552222";
+const inInfo = gInCallStrPool(inNumber);
+let inCall;
 
 startTest(function() {
-  dial();
+  gDial(outNumber)
+    .then(call => outCall = call)
+    .then(() => gRemoteAnswer(outCall))
+    .then(() => gHold(outCall))
+
+    .then(() => gRemoteDial(inNumber))
+    .then(call => inCall = call)
+    .then(() => gAnswer(inCall))
+    .then(() => gCheckAll(inCall, [outCall, inCall], "", [],
+                          [outInfo.held, inInfo.active]))
+
+    // Swap calls by resuming the held (outgoing) call. Will force active
+    // (incoming) call to hold.
+    .then(() => {
+      let p1 = gWaitForNamedStateEvent(inCall, "held");
+      let p2 = gResume(outCall);
+      return Promise.all([p1, p2]);
+    })
+    .then(() => gCheckAll(outCall, [outCall, inCall], "", [],
+                          [outInfo.active, inInfo.held]))
+
+    .then(() => gHangUp(outCall))
+    .then(() => gHangUp(inCall))
+
+    .catch(error => ok(false, "Promise reject: " + error))
+    .then(finish);
 });
--- a/dom/telephony/test/marionette/test_temporary_clir.js
+++ b/dom/telephony/test/marionette/test_temporary_clir.js
@@ -9,26 +9,14 @@ const number = "0912345678";
 
 startTest(function() {
   let outCall;
 
   telephony.dial(clirPrefix + number).then(call => {
     outCall = call;
 
     ok(call);
-    is(call.id.number, number);
-    is(call.state, "dialing");
-
-    let deferred = Promise.defer();
-
-    call.onalerting = function onalerting(event) {
-      call.onalerting = null;
-      log("Received 'onalerting' call event.");
-      is(call.id.number, number);
-      deferred.resolve(call);
-    };
-
-    return deferred.promise;
+    is(call.id.number, number);  // Should display the number w/o clir prefix.
   })
   .then(() => gRemoteHangUp(outCall))
   .catch(error => ok(false, "Promise reject: " + error))
   .then(finish);
 });