var q = require('q'),
    path = require('path'),
    glob = require('glob'),
    debug = require('debug')('protractor-cucumber-framework'),
    Cucumber = require('cucumber'),
    state = require('./lib/runState');

/**
 * Execute the Runner's test cases through Cucumber.
 *
 * @param {Runner} runner The current Protractor Runner.
 * @param {Array} specs Array of Directory Path Strings.
 * @return {q.Promise} Promise resolved with the test results
 */
exports.run = function(runner, specs) {
  var results = {}

  return runner.runTestPreparer().then(function() {
    var opts = runner.getConfig().cucumberOpts;
    state.initialize(runner, results, opts.strict);

    return q.promise(function(resolve, reject) {
      var cliArguments = convertOptionsToCliArguments(opts);
      cliArguments.push('--require', path.resolve(__dirname, 'lib', 'resultsCapturer.js'));
      cliArguments = cliArguments.concat(specs);

      debug('cucumber command: "' + cliArguments.join(' ') + '"');

      Cucumber.Cli(cliArguments).run(function (isSuccessful) {
        try {
          if (runner.getConfig().onComplete) {
            runner.getConfig().onComplete();
          }
          resolve(results);
        } catch (err) {
          reject(err);
        }
      });
    });
  });

  function convertOptionsToCliArguments(options) {
    var cliArguments = ['node', 'cucumberjs'];

    for (var option in options) {
      var cliArgumentValues = convertOptionValueToCliValues(option, options[option]);

      if (Array.isArray(cliArgumentValues)) {
        cliArgumentValues.forEach(function (value) {
          cliArguments.push('--' + option, value);
        });
      } else if (cliArgumentValues) {
        cliArguments.push('--' + option);
      }
    }

    return cliArguments;
  }

  function convertRequireOptionValuesToCliValues(values) {
    var configDir = runner.getConfig().configDir;

    return toArray(values).map(function(path) {
      // Handle glob matching
      return glob.sync(path, {cwd: configDir});
    }).reduce(function(opts, globPaths) {
      // Combine paths into flattened array
      return opts.concat(globPaths);
    }, []).map(function(requirePath) {
      // Resolve require absolute path
      return path.resolve(configDir, requirePath)
    }).filter(function(item, pos, orig) {
      // Make sure requires are unique
      return orig.indexOf(item) == pos;
    });
  }

  function convertGenericOptionValuesToCliValues(values) {
    if (values === true || !values) {
      return values;
    } else {
      return toArray(values);
    }
  }

  function convertOptionValueToCliValues(option, values) {
    if (option === 'require') {
      return convertRequireOptionValuesToCliValues(values);
    } else {
      return convertGenericOptionValuesToCliValues(values);
    }
  }

  function toArray(values) {
    return Array.isArray(values) ? values : [values];
  }
};

@@ -1060,16 +1060,46 @@
   try %7B%0A
+          var complete = q();%0A
         
@@ -1149,16 +1149,29 @@
         
+complete = q(
 runner.g
@@ -1193,16 +1193,17 @@
 mplete()
+)
 ;%0A      
@@ -1204,24 +1204,63 @@
           %7D%0A
+          complete.then(function() %7B%0A  
           re
@@ -1271,24 +1271,38 @@
 e(results);%0A
+          %7D);%0A
         %7D ca

Allow config.onComplete to return a promise.