mocha.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. var q = require('q');
  2. /**
  3. * Execute the Runner's test cases through Mocha.
  4. *
  5. * @param {Runner} runner The current Protractor Runner.
  6. * @param {Array} specs Array of Directory Path Strings.
  7. * @return {q.Promise} Promise resolved with the test results
  8. */
  9. exports.run = function(runner, specs) {
  10. var Mocha = require('mocha'),
  11. mocha = new Mocha(runner.getConfig().mochaOpts);
  12. // Add hooks for afterEach
  13. require('./setupAfterEach').setup(runner, specs);
  14. var deferred = q.defer();
  15. // Mocha doesn't set up the ui until the pre-require event, so
  16. // wait until then to load mocha-webdriver adapters as well.
  17. mocha.suite.on('pre-require', function() {
  18. try {
  19. // We need to re-wrap all of the global functions, which `selenium-webdriver/testing` only
  20. // does when it is required. So first we must remove it from the cache.
  21. delete require.cache[require.resolve('selenium-webdriver/testing')];
  22. var seleniumAdapter = require('selenium-webdriver/testing');
  23. // Save unwrapped version
  24. var unwrappedFns = {};
  25. ['after', 'afterEach', 'before', 'beforeEach', 'it', 'xit', 'iit'].forEach(function(fnName) {
  26. unwrappedFns[fnName] = global[fnName] || Mocha[fnName];
  27. });
  28. var wrapFn = function(seleniumWrappedFn, opt_fnName) {
  29. // This does not work on functions that can be nested (e.g. `describe`)
  30. return function() {
  31. // Set globals to unwrapped version to avoid circular reference
  32. var wrappedFns = {};
  33. for (var fnName in unwrappedFns) {
  34. wrappedFns[fnName] = global[fnName];
  35. global[fnName] = unwrappedFns[fnName];
  36. }
  37. var args = arguments;
  38. // Allow before/after hooks to use names
  39. if (opt_fnName && (arguments.length > 1) && (seleniumWrappedFn.length < 2)) {
  40. global[opt_fnName] = global[opt_fnName].bind(this, args[0]);
  41. args = Array.prototype.slice.call(arguments, 1);
  42. }
  43. try {
  44. seleniumWrappedFn.apply(this, args);
  45. } finally {
  46. // Restore wrapped version
  47. for (fnName in wrappedFns) {
  48. global[fnName] = wrappedFns[fnName];
  49. }
  50. }
  51. };
  52. };
  53. // Wrap functions
  54. global.after = wrapFn(seleniumAdapter.after, 'after');
  55. global.afterEach = wrapFn(seleniumAdapter.afterEach, 'afterEach');
  56. global.before = wrapFn(seleniumAdapter.before, 'before');
  57. global.beforeEach = wrapFn(seleniumAdapter.beforeEach, 'beforeEach');
  58. global.it = wrapFn(seleniumAdapter.it);
  59. global.iit = wrapFn(seleniumAdapter.it.only);
  60. global.xit = wrapFn(seleniumAdapter.xit);
  61. global.it.only = wrapFn(seleniumAdapter.it.only);
  62. global.it.skip = wrapFn(seleniumAdapter.it.skip);
  63. } catch (err) {
  64. deferred.reject(err);
  65. }
  66. });
  67. mocha.loadFiles();
  68. runner.runTestPreparer().then(function() {
  69. specs.forEach(function(file) {
  70. mocha.addFile(file);
  71. });
  72. var testResult = [];
  73. var mochaRunner = mocha.run(function(failures) {
  74. try {
  75. var completed = q();
  76. if (runner.getConfig().onComplete) {
  77. completed = q(runner.getConfig().onComplete());
  78. }
  79. completed.then(function() {
  80. deferred.resolve({
  81. failedCount: failures,
  82. specResults: testResult
  83. });
  84. });
  85. } catch (err) {
  86. deferred.reject(err);
  87. }
  88. });
  89. mochaRunner.on('pass', function(test) {
  90. var testInfo = {
  91. name: test.title,
  92. category: test.fullTitle().slice(0, -test.title.length).trim()
  93. };
  94. runner.emit('testPass', testInfo);
  95. testResult.push({
  96. description: test.title,
  97. assertions: [{
  98. passed: true
  99. }],
  100. duration: test.duration
  101. });
  102. });
  103. mochaRunner.on('fail', function(test) {
  104. var testInfo = {
  105. name: test.title,
  106. category: test.fullTitle().slice(0, -test.title.length).trim()
  107. };
  108. runner.emit('testFail', testInfo);
  109. testResult.push({
  110. description: test.title,
  111. assertions: [{
  112. passed: false,
  113. errorMsg: test.err.message,
  114. stackTrace: test.err.stack
  115. }],
  116. duration: test.duration
  117. });
  118. });
  119. }).catch (function(reason) {
  120. deferred.reject(reason);
  121. });
  122. return deferred.promise;
  123. };