Repositorio del curso CCOM4030 el semestre B91 del proyecto Artesanías con el Instituto de Cultura

results.js 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. var defined = require('defined');
  2. var EventEmitter = require('events').EventEmitter;
  3. var inherits = require('inherits');
  4. var through = require('through');
  5. var resumer = require('resumer');
  6. var inspect = require('object-inspect');
  7. var bind = require('function-bind');
  8. var has = require('has');
  9. var regexpTest = bind.call(Function.call, RegExp.prototype.test);
  10. var yamlIndicators = /\:|\-|\?/;
  11. var nextTick = typeof setImmediate !== 'undefined'
  12. ? setImmediate
  13. : process.nextTick
  14. ;
  15. module.exports = Results;
  16. inherits(Results, EventEmitter);
  17. function coalesceWhiteSpaces(str) {
  18. return String(str).replace(/\s+/g, ' ');
  19. }
  20. function Results() {
  21. if (!(this instanceof Results)) return new Results;
  22. this.count = 0;
  23. this.fail = 0;
  24. this.pass = 0;
  25. this.todo = 0;
  26. this._stream = through();
  27. this.tests = [];
  28. this._only = null;
  29. this._isRunning = false;
  30. }
  31. Results.prototype.createStream = function (opts) {
  32. if (!opts) opts = {};
  33. var self = this;
  34. var output, testId = 0;
  35. if (opts.objectMode) {
  36. output = through();
  37. self.on('_push', function ontest(t, extra) {
  38. if (!extra) extra = {};
  39. var id = testId++;
  40. t.once('prerun', function () {
  41. var row = {
  42. type: 'test',
  43. name: t.name,
  44. id: id,
  45. skip: t._skip,
  46. todo: t._todo
  47. };
  48. if (has(extra, 'parent')) {
  49. row.parent = extra.parent;
  50. }
  51. output.queue(row);
  52. });
  53. t.on('test', function (st) {
  54. ontest(st, { parent: id });
  55. });
  56. t.on('result', function (res) {
  57. res.test = id;
  58. res.type = 'assert';
  59. output.queue(res);
  60. });
  61. t.on('end', function () {
  62. output.queue({ type: 'end', test: id });
  63. });
  64. });
  65. self.on('done', function () { output.queue(null); });
  66. } else {
  67. output = resumer();
  68. output.queue('TAP version 13\n');
  69. self._stream.pipe(output);
  70. }
  71. if (!this._isRunning) {
  72. this._isRunning = true;
  73. nextTick(function next() {
  74. var t;
  75. while (t = getNextTest(self)) {
  76. t.run();
  77. if (!t.ended) return t.once('end', function () { nextTick(next); });
  78. }
  79. self.emit('done');
  80. });
  81. }
  82. return output;
  83. };
  84. Results.prototype.push = function (t) {
  85. var self = this;
  86. self.tests.push(t);
  87. self._watch(t);
  88. self.emit('_push', t);
  89. };
  90. Results.prototype.only = function (t) {
  91. this._only = t;
  92. };
  93. Results.prototype._watch = function (t) {
  94. var self = this;
  95. var write = function (s) { self._stream.queue(s); };
  96. t.once('prerun', function () {
  97. var premsg = '';
  98. if (t._skip) premsg = 'SKIP ';
  99. else if (t._todo) premsg = 'TODO ';
  100. write('# ' + premsg + coalesceWhiteSpaces(t.name) + '\n');
  101. });
  102. t.on('result', function (res) {
  103. if (typeof res === 'string') {
  104. write('# ' + res + '\n');
  105. return;
  106. }
  107. write(encodeResult(res, self.count + 1));
  108. self.count ++;
  109. if (res.ok || res.todo) self.pass ++;
  110. else {
  111. self.fail ++;
  112. self.emit('fail');
  113. }
  114. });
  115. t.on('test', function (st) { self._watch(st); });
  116. };
  117. Results.prototype.close = function () {
  118. var self = this;
  119. if (self.closed) self._stream.emit('error', new Error('ALREADY CLOSED'));
  120. self.closed = true;
  121. var write = function (s) { self._stream.queue(s); };
  122. write('\n1..' + self.count + '\n');
  123. write('# tests ' + self.count + '\n');
  124. write('# pass ' + (self.pass + self.todo) + '\n');
  125. if (self.todo) write('# todo ' + self.todo + '\n');
  126. if (self.fail) write('# fail ' + self.fail + '\n');
  127. else write('\n# ok\n');
  128. self._stream.queue(null);
  129. };
  130. function encodeResult(res, count) {
  131. var output = '';
  132. output += (res.ok ? 'ok ' : 'not ok ') + count;
  133. output += res.name ? ' ' + coalesceWhiteSpaces(res.name) : '';
  134. if (res.skip) {
  135. output += ' # SKIP' + ((typeof res.skip === 'string') ? ' ' + coalesceWhiteSpaces(res.skip) : '');
  136. } else if (res.todo) {
  137. output += ' # TODO' + ((typeof res.todo === 'string') ? ' ' + coalesceWhiteSpaces(res.todo) : '');
  138. };
  139. output += '\n';
  140. if (res.ok) return output;
  141. var outer = ' ';
  142. var inner = outer + ' ';
  143. output += outer + '---\n';
  144. output += inner + 'operator: ' + res.operator + '\n';
  145. if (has(res, 'expected') || has(res, 'actual')) {
  146. var ex = inspect(res.expected, {depth: res.objectPrintDepth});
  147. var ac = inspect(res.actual, {depth: res.objectPrintDepth});
  148. if (Math.max(ex.length, ac.length) > 65 || invalidYaml(ex) || invalidYaml(ac)) {
  149. output += inner + 'expected: |-\n' + inner + ' ' + ex + '\n';
  150. output += inner + 'actual: |-\n' + inner + ' ' + ac + '\n';
  151. } else {
  152. output += inner + 'expected: ' + ex + '\n';
  153. output += inner + 'actual: ' + ac + '\n';
  154. }
  155. }
  156. if (res.at) {
  157. output += inner + 'at: ' + res.at + '\n';
  158. }
  159. var actualStack = res.actual && (typeof res.actual === 'object' || typeof res.actual === 'function') ? res.actual.stack : undefined;
  160. var errorStack = res.error && res.error.stack;
  161. var stack = defined(actualStack, errorStack);
  162. if (stack) {
  163. var lines = String(stack).split('\n');
  164. output += inner + 'stack: |-\n';
  165. for (var i = 0; i < lines.length; i++) {
  166. output += inner + ' ' + lines[i] + '\n';
  167. }
  168. }
  169. output += outer + '...\n';
  170. return output;
  171. }
  172. function getNextTest(results) {
  173. if (!results._only) {
  174. return results.tests.shift();
  175. }
  176. do {
  177. var t = results.tests.shift();
  178. if (!t) continue;
  179. if (results._only === t) {
  180. return t;
  181. }
  182. } while (results.tests.length !== 0);
  183. }
  184. function invalidYaml(str) {
  185. return regexpTest(yamlIndicators, str);
  186. }