mocha-test.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. var MochaWrapper = require('./lib/MochaWrapper');
  2. var fs = require('fs');
  3. var path = require('path');
  4. var hooker = require('hooker');
  5. var mkdirpSync = require('mkdirp').sync;
  6. module.exports = function(grunt) {
  7. // Helper to capture task output (adapted from tests for grunt-contrib-jshint)
  8. var capture = function(captureFile, quiet, run, done) {
  9. var fd;
  10. if (captureFile) {
  11. mkdirpSync(path.dirname(captureFile));
  12. fd = fs.openSync(captureFile, 'w');
  13. }
  14. // Hook process.stdout.write
  15. hooker.hook(process.stdout, 'write', {
  16. // This gets executed before the original process.stdout.write
  17. pre: function(result) {
  18. // Write result to file if it was opened
  19. if (fd) {
  20. fs.writeSync(fd, result);
  21. }
  22. // Prevent the original process.stdout.write from executing if quiet was specified
  23. if (quiet) {
  24. return hooker.preempt();
  25. }
  26. }
  27. });
  28. // Execute the code whose output is to be captured
  29. run(function(error, failureCount) {
  30. // close the file if it was opened
  31. if (fd) {
  32. fs.closeSync(fd);
  33. }
  34. // Restore process.stdout.write to its original value
  35. hooker.unhook(process.stdout, 'write');
  36. // Actually test the actually-logged stdout string to the expected value
  37. done(error, failureCount);
  38. });
  39. };
  40. grunt.registerMultiTask('mochaTest', 'Run node unit tests with Mocha', function() {
  41. var done = this.async();
  42. var options = this.options();
  43. var files = this.files;
  44. // mocha CLI parameters
  45. var params = ['grep', 'ui', 'reporter', 'timeout', 'invert', 'ignoreLeaks', 'growl', 'globals', 'require', 'colors', 'slow'];
  46. // for every supplied CLI parameter overwrite task option
  47. params.forEach(function(param) {
  48. options[param] = grunt.option(param) || options[param];
  49. });
  50. // check if there are files to test
  51. if (this.filesSrc.length === 0) {
  52. grunt.log.write('No files to check...');
  53. grunt.log.ok();
  54. done(true);
  55. return;
  56. }
  57. // Another hack copied from
  58. // https://github.com/gregrperkins/grunt-mocha-hack
  59. // This time we are preventing grunt handling asynchronous
  60. // exceptions that are thrown when handling asynchronous exceptions
  61. // (I think)
  62. var uncaughtExceptionHandlers = process.listeners('uncaughtException');
  63. process.removeAllListeners('uncaughtException');
  64. var unmanageExceptions = function() {
  65. uncaughtExceptionHandlers.forEach(
  66. process.on.bind(process, 'uncaughtException'));
  67. };
  68. var restore = function() {
  69. unmanageExceptions();
  70. };
  71. capture(options.captureFile, options.quiet, function(complete) {
  72. var mochaWrapper = new MochaWrapper({
  73. files: files,
  74. options: options
  75. });
  76. mochaWrapper.run(function(error, failureCount) {
  77. if (error) {
  78. grunt.log.error('Mocha exploded!');
  79. grunt.log.error(error.stack);
  80. complete(error);
  81. } else {
  82. complete(null, failureCount);
  83. }
  84. });
  85. }, function(error, failureCount) {
  86. // restore the uncaught exception handlers
  87. restore();
  88. if (error) {
  89. done(false);
  90. } else if (options.noFail) {
  91. done(true);
  92. } else {
  93. done(failureCount === 0);
  94. }
  95. });
  96. });
  97. };