run_from_console.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. #!/usr/bin/env node
  2. var ansi = require('ansi');
  3. var program = require('commander');
  4. var path = require('path');
  5. var make_list = function(val) {
  6. return val.split(',');
  7. }
  8. program
  9. .option('-t, --tests <testlist>', 'Run the specified html-file-based test(s). \'testlist\' should be a comma-separated list', make_list, [])
  10. .option('-a, --print-all', 'Print all tests, not just the failures')
  11. .option('--disable-color', 'Explicitly disable color')
  12. .option('-c, --color', 'Explicitly enable color (default is to use color when not outputting to a pipe)')
  13. .option('-i, --auto-inject <includefiles>', 'Treat the test list as a set of mocha JS files, and automatically generate HTML files with which to test test. \'includefiles\' should be a comma-separated list of paths to javascript files to include in each of the generated HTML files', make_list, null)
  14. .option('-p, --provider <name>', 'Use the given provider (defaults to "casper"). Currently, may be "casper" or "zombie"', 'casper')
  15. .option('-g, --generate-html', 'Instead of running the tests, just return the path to the generated HTML file, then wait for user interaction to exit (should be used with -i)')
  16. .option('-o, --output-html', 'Instead of running the tests, just output the generated HTML source to STDOUT (should be used with -i)')
  17. .parse(process.argv);
  18. var file_paths = [];
  19. if (program.autoInject) {
  20. var temp = require('temp');
  21. var fs = require('fs');
  22. temp.track();
  23. var template = {
  24. header: "<html>\n<head>\n<meta charset='utf-8' />\<link rel='stylesheet' href='node_modules/mocha/mocha.css'/>\n</head>\n<body><div id='mocha'></div>",
  25. script_tag: function(p) { return "<script src='" + p + "'></script>" },
  26. footer: "<script>\nmocha.checkLeaks();\nmocha.globals(['navigator', 'create', 'ClientUtils', '__utils__']);\nmocha.run();\n</script>\n</body>\n</html>"
  27. };
  28. template.header += "\n" + template.script_tag(path.resolve(__dirname, 'node_modules/chai/chai.js'));
  29. template.header += "\n" + template.script_tag(path.resolve(__dirname, 'node_modules/mocha/mocha.js'));
  30. template.header += "\n<script>mocha.setup('bdd');</script>";
  31. template.header = program.autoInject.reduce(function(acc, sn) {
  32. return acc + "\n" + template.script_tag(path.resolve(process.cwd(), sn));
  33. }, template.header);
  34. file_paths = program.tests.map(function(jsn, ind) {
  35. var templ = template.header;
  36. templ += "\n";
  37. templ += template.script_tag(path.resolve(process.cwd(), jsn));
  38. templ += template.footer;
  39. var tempfile = temp.openSync({ prefix: 'novnc-zombie-inject-', suffix: '-file_num-'+ind+'.html' });
  40. fs.writeSync(tempfile.fd, templ);
  41. fs.closeSync(tempfile.fd);
  42. return tempfile.path;
  43. });
  44. }
  45. else {
  46. file_paths = program.tests.map(function(fn) {
  47. return path.resolve(process.cwd(), fn);
  48. });
  49. }
  50. var use_ansi = false;
  51. if (program.color) use_ansi = true;
  52. else if (program.disableColor) use_ansi = false;
  53. else if (process.stdout.isTTY) use_ansi = true;
  54. var cursor = ansi(process.stdout, { enabled: use_ansi });
  55. if (program.outputHtml) {
  56. var fs = require('fs');
  57. file_paths.forEach(function(path, path_ind) {
  58. fs.readFile(path, function(err, data) {
  59. if (err) {
  60. console.warn(error.stack);
  61. return;
  62. }
  63. cursor
  64. .bold()
  65. .write(program.tests[path_ind])
  66. .reset()
  67. .write("\n")
  68. .write(Array(program.tests[path_ind].length+1).join('='))
  69. .write("\n\n")
  70. .write(data)
  71. .write("\n");
  72. });
  73. });
  74. }
  75. if (program.generateHtml) {
  76. file_paths.forEach(function(path, path_ind) {
  77. cursor
  78. .bold()
  79. .write(program.tests[path_ind])
  80. .write(": ")
  81. .reset()
  82. .write(path)
  83. .write("\n");
  84. });
  85. console.log('');
  86. }
  87. if (program.generateHtml) {
  88. process.stdin.resume(); // pause until C-c
  89. process.on('SIGINT', function() {
  90. process.stdin.pause(); // exit
  91. });
  92. }
  93. if (!program.outputHtml && !program.generateHtml) {
  94. var failure_count = 0;
  95. var prov = require(path.resolve(__dirname, 'run_from_console.'+program.provider+'.js'));
  96. cursor
  97. .write("Running tests ")
  98. .bold()
  99. .write(program.tests.join(', '))
  100. .reset()
  101. .grey()
  102. .write(' using provider '+prov.name)
  103. .reset()
  104. .write("\n");
  105. //console.log("Running tests %s using provider %s", program.tests.join(', '), prov.name);
  106. var provider = prov.provide_emitter(file_paths);
  107. provider.on('test_ready', function(test_json) {
  108. console.log('');
  109. filename = program.tests[test_json.file_ind];
  110. cursor.bold();
  111. console.log('Results for %s:', filename);
  112. console.log(Array('Results for :'.length+filename.length+1).join('='));
  113. cursor.reset();
  114. console.log('');
  115. cursor.write(''+test_json.num_tests+' tests run, ')
  116. cursor
  117. .green()
  118. .write(''+test_json.num_passes+' passed');
  119. if (test_json.num_slow > 0) {
  120. cursor
  121. .reset()
  122. .write(' (');
  123. cursor
  124. .yellow()
  125. .write(''+test_json.num_slow+' slow')
  126. .reset()
  127. .write(')');
  128. }
  129. cursor
  130. .reset()
  131. .write(', ');
  132. cursor
  133. .red()
  134. .write(''+test_json.num_fails+' failed');
  135. cursor
  136. .reset()
  137. .write(' -- duration: '+test_json.duration+"\n");
  138. console.log('');
  139. if (test_json.num_fails > 0 || program.printAll) {
  140. var traverse_tree = function(indentation, node) {
  141. if (node.type == 'suite') {
  142. if (!node.has_subfailures && !program.printAll) return;
  143. if (indentation == 0) {
  144. cursor.bold();
  145. console.log(node.name);
  146. console.log(Array(node.name.length+1).join('-'));
  147. cursor.reset();
  148. }
  149. else {
  150. cursor
  151. .write(Array(indentation+3).join('#'))
  152. .bold()
  153. .write(' '+node.name+' ')
  154. .reset()
  155. .write(Array(indentation+3).join('#'))
  156. .write("\n");
  157. }
  158. console.log('');
  159. for (var i = 0; i < node.children.length; i++) {
  160. traverse_tree(indentation+1, node.children[i]);
  161. }
  162. }
  163. else {
  164. if (!node.pass) {
  165. cursor.magenta();
  166. console.log('- failed: '+node.text+test_json.replay);
  167. cursor.red();
  168. console.log(' '+node.error.split("\n")[0]); // the split is to avoid a weird thing where in PhantomJS, we get a stack trace too
  169. cursor.reset();
  170. console.log('');
  171. }
  172. else if (program.printAll) {
  173. if (node.slow) cursor.yellow();
  174. else cursor.green();
  175. cursor
  176. .write('- pass: '+node.text)
  177. .grey()
  178. .write(' ('+node.duration+') ');
  179. /*if (node.slow) cursor.yellow();
  180. else cursor.green();*/
  181. cursor
  182. //.write(test_json.replay)
  183. .reset()
  184. .write("\n");
  185. console.log('');
  186. }
  187. }
  188. }
  189. for (var i = 0; i < test_json.suites.length; i++) {
  190. traverse_tree(0, test_json.suites[i]);
  191. }
  192. }
  193. if (test_json.num_fails == 0) {
  194. cursor.fg.green();
  195. console.log('all tests passed :-)');
  196. cursor.reset();
  197. }
  198. });
  199. /*provider.on('console', function(line) {
  200. //console.log(line);
  201. });*/
  202. /*gprom.finally(function(ph) {
  203. ph.exit();
  204. // exit with a status code that actually gives information
  205. if (program.exitWithFailureCount) process.exit(failure_count);
  206. });*/
  207. }