stackTrace.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. 'use strict';
  2. var tape = require('../');
  3. var tap = require('tap');
  4. var concat = require('concat-stream');
  5. var tapParser = require('tap-parser');
  6. var common = require('./common');
  7. var getDiag = common.getDiag;
  8. function stripAt(body) {
  9. return body.replace(/^\s*at:\s+Test.*$\n/m, '');
  10. }
  11. tap.test('preserves stack trace with newlines', function (tt) {
  12. tt.plan(3);
  13. var test = tape.createHarness();
  14. var stream = test.createStream();
  15. var parser = stream.pipe(tapParser());
  16. var stackTrace = 'foo\n bar';
  17. parser.once('assert', function (data) {
  18. delete data.diag.at;
  19. tt.deepEqual(data, {
  20. ok: false,
  21. id: 1,
  22. name: 'Error: Preserve stack',
  23. diag: {
  24. stack: stackTrace,
  25. operator: 'error',
  26. expected: 'undefined',
  27. actual: '[Error: Preserve stack]'
  28. }
  29. });
  30. });
  31. stream.pipe(concat(function (body) {
  32. var strippedBody = stripAt(body.toString('utf8'));
  33. tt.deepEqual(strippedBody.split('\n'), [].concat(
  34. 'TAP version 13',
  35. '# multiline stack trace',
  36. 'not ok 1 Error: Preserve stack',
  37. ' ---',
  38. ' operator: error',
  39. ' expected: |-',
  40. ' undefined',
  41. ' actual: |-',
  42. ' [Error: Preserve stack]',
  43. ' stack: |-',
  44. ' foo',
  45. ' bar',
  46. ' ...',
  47. '',
  48. '1..1',
  49. '# tests 1',
  50. '# pass 0',
  51. '# fail 1',
  52. ''
  53. ));
  54. tt.deepEqual(getDiag(strippedBody, true), {
  55. stack: stackTrace,
  56. operator: 'error',
  57. expected: 'undefined',
  58. actual: '[Error: Preserve stack]'
  59. });
  60. }));
  61. test('multiline stack trace', function (t) {
  62. t.plan(1);
  63. var err = new Error('Preserve stack');
  64. err.stack = stackTrace;
  65. t.error(err);
  66. });
  67. });
  68. tap.test('parses function info from original stack', function (tt) {
  69. tt.plan(4);
  70. var test = tape.createHarness();
  71. test.createStream();
  72. test._results._watch = function (t) {
  73. t.on('result', function (res) {
  74. tt.equal('Test.testFunctionNameParsing', res.functionName);
  75. tt.match(res.file, /stackTrace.js/i);
  76. tt.ok(Number(res.line) > 0);
  77. tt.ok(Number(res.column) > 0);
  78. });
  79. };
  80. test('t.equal stack trace', function testFunctionNameParsing(t) {
  81. t.equal(true, false, 'true should be false');
  82. t.end();
  83. });
  84. });
  85. tap.test('parses function info from original stack for anonymous function', function (tt) {
  86. tt.plan(4);
  87. var test = tape.createHarness();
  88. test.createStream();
  89. test._results._watch = function (t) {
  90. t.on('result', function (res) {
  91. tt.equal('Test.<anonymous>', res.functionName);
  92. tt.match(res.file, /stackTrace.js/i);
  93. tt.ok(Number(res.line) > 0);
  94. tt.ok(Number(res.column) > 0);
  95. });
  96. };
  97. test('t.equal stack trace', function (t) {
  98. t.equal(true, false, 'true should be false');
  99. t.end();
  100. });
  101. });
  102. if (typeof Promise === 'function' && typeof Promise.resolve === 'function') {
  103. tap.test('parses function info from original stack for Promise scenario', function (tt) {
  104. tt.plan(4);
  105. var test = tape.createHarness();
  106. test.createStream();
  107. test._results._watch = function (t) {
  108. t.on('result', function (res) {
  109. tt.equal('onfulfilled', res.functionName);
  110. tt.match(res.file, /stackTrace.js/i);
  111. tt.ok(Number(res.line) > 0);
  112. tt.ok(Number(res.column) > 0);
  113. });
  114. };
  115. test('t.equal stack trace', function testFunctionNameParsing(t) {
  116. new Promise(function (resolve) {
  117. resolve();
  118. }).then(function onfulfilled() {
  119. t.equal(true, false, 'true should be false');
  120. t.end();
  121. });
  122. });
  123. });
  124. tap.test('parses function info from original stack for Promise scenario with anonymous function', function (tt) {
  125. tt.plan(4);
  126. var test = tape.createHarness();
  127. test.createStream();
  128. test._results._watch = function (t) {
  129. t.on('result', function (res) {
  130. tt.equal('<anonymous>', res.functionName);
  131. tt.match(res.file, /stackTrace.js/i);
  132. tt.ok(Number(res.line) > 0);
  133. tt.ok(Number(res.column) > 0);
  134. });
  135. };
  136. test('t.equal stack trace', function testFunctionNameParsing(t) {
  137. new Promise(function (resolve) {
  138. resolve();
  139. }).then(function () {
  140. t.equal(true, false, 'true should be false');
  141. t.end();
  142. });
  143. });
  144. });
  145. }
  146. tap.test('preserves stack trace for failed assertions', function (tt) {
  147. tt.plan(6);
  148. var test = tape.createHarness();
  149. var stream = test.createStream();
  150. var parser = stream.pipe(tapParser());
  151. var stack = '';
  152. parser.once('assert', function (data) {
  153. tt.equal(typeof data.diag.at, 'string');
  154. tt.equal(typeof data.diag.stack, 'string');
  155. var at = data.diag.at || '';
  156. stack = data.diag.stack || '';
  157. tt.ok((/^Error: true should be false(\n {4}at .+)+/).exec(stack), 'stack should be a stack');
  158. tt.deepEqual(data, {
  159. ok: false,
  160. id: 1,
  161. name: 'true should be false',
  162. diag: {
  163. at: at,
  164. stack: stack,
  165. operator: 'equal',
  166. expected: false,
  167. actual: true
  168. }
  169. });
  170. });
  171. stream.pipe(concat(function (body) {
  172. var strippedBody = stripAt(body.toString('utf8'));
  173. tt.deepEqual(strippedBody.split('\n'), [].concat(
  174. 'TAP version 13',
  175. '# t.equal stack trace',
  176. 'not ok 1 true should be false',
  177. ' ---',
  178. ' operator: equal',
  179. ' expected: false',
  180. ' actual: true',
  181. ' stack: |-',
  182. ('\n' + stack).replace(/\n/g, '\n ').split('\n').slice(1),
  183. ' ...',
  184. '',
  185. '1..1',
  186. '# tests 1',
  187. '# pass 0',
  188. '# fail 1',
  189. ''
  190. ));
  191. tt.deepEqual(getDiag(strippedBody, true), {
  192. stack: stack,
  193. operator: 'equal',
  194. expected: false,
  195. actual: true
  196. });
  197. }));
  198. test('t.equal stack trace', function (t) {
  199. t.plan(1);
  200. t.equal(true, false, 'true should be false');
  201. });
  202. });
  203. tap.test('preserves stack trace for failed assertions where actual===falsy', function (tt) {
  204. tt.plan(6);
  205. var test = tape.createHarness();
  206. var stream = test.createStream();
  207. var parser = stream.pipe(tapParser());
  208. var stack = '';
  209. parser.once('assert', function (data) {
  210. tt.equal(typeof data.diag.at, 'string');
  211. tt.equal(typeof data.diag.stack, 'string');
  212. var at = data.diag.at || '';
  213. stack = data.diag.stack || '';
  214. tt.ok((/^Error: false should be true(\n {4}at .+)+/).exec(stack), 'stack should be a stack');
  215. tt.deepEqual(data, {
  216. ok: false,
  217. id: 1,
  218. name: 'false should be true',
  219. diag: {
  220. at: at,
  221. stack: stack,
  222. operator: 'equal',
  223. expected: true,
  224. actual: false
  225. }
  226. });
  227. });
  228. stream.pipe(concat(function (body) {
  229. var strippedBody = stripAt(body.toString('utf8'));
  230. tt.deepEqual(strippedBody.split('\n'), [].concat(
  231. 'TAP version 13',
  232. '# t.equal stack trace',
  233. 'not ok 1 false should be true',
  234. ' ---',
  235. ' operator: equal',
  236. ' expected: true',
  237. ' actual: false',
  238. ' stack: |-',
  239. ('\n' + stack).replace(/\n/g, '\n ').split('\n').slice(1),
  240. ' ...',
  241. '',
  242. '1..1',
  243. '# tests 1',
  244. '# pass 0',
  245. '# fail 1',
  246. ''
  247. ));
  248. tt.deepEqual(getDiag(strippedBody, true), {
  249. stack: stack,
  250. operator: 'equal',
  251. expected: true,
  252. actual: false
  253. });
  254. }));
  255. test('t.equal stack trace', function (t) {
  256. t.plan(1);
  257. t.equal(false, true, 'false should be true');
  258. });
  259. });