docs: function runDriver(location, driver, options) {
    options.testComplete = options.testComplete || 'return window.TESTS_COMPLETE';
    options.testPassed = options.testPassed || 'return window.TESTS_PASSED && !window.TESTS_FAILED';
    var startTime = Date.now();
    var jobInfo = {
      name: options.name,
      build: process.env.TRAVIS_JOB_ID
    };
    Object.keys(options.jobInfo || {}).forEach(function (key) {
      jobInfo[key] = options.jobInfo[key];
    });
    return Promise.resolve(null).then(function () {
      return retry(function () {
        return driver.sauceJobUpdate(jobInfo);
      }, 3, '500ms', {debug: options.debug})
    }).then(function () {
      return retry(function () {
        return driver.browser().activeWindow().navigator().navigateTo(location.url)
      }, 3, '500ms', {debug: options.debug}).catch(err => {
        err.message += ' (while navigating to url)';
        throw err;
      });
    }).then(function () {
      return waitForJobToFinish(driver, {
        allowExceptions: options.allowExceptions,
        testComplete: options.testComplete,
        timeout: options.timeout,
        debug: options.debug
      });
    }).then(function () {
      return retry(function () {
        if (typeof options.testPassed === 'string') {
          return driver.browser().activeWindow().execute(options.testPassed);
        } else {
          return Promise.resolve(options.testPassed(driver));
        }
      }, 5, '500ms', {debug: options.debug});
    }).then(function (result) {
      result = {passed: result, duration: Date.now() - startTime};
      return retry(function () { return driver.dispose({passed: result.passed}); }, 5, {debug: options.debug}).then(function () {
        return result;
      });
    }, function (err) {
      err.duration = Date.now() - startTime;
      return retry(function () { return driver.dispose({passed: false}); }, 2, {debug: options.debug}).then(function () {
        throw err;
      }, function () {
        throw err;
      });
    });
  }