throws.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. 'use strict';
  2. var tape = require('../');
  3. var tap = require('tap');
  4. var concat = require('concat-stream');
  5. var stripFullStack = require('./common').stripFullStack;
  6. function getNonFunctionMessage(fn) {
  7. try {
  8. fn();
  9. } catch (e) {
  10. return e.message;
  11. }
  12. return '';
  13. }
  14. var getter = function () { return 'message'; };
  15. var messageGetterError = Object.defineProperty(
  16. { custom: 'error' },
  17. 'message',
  18. { configurable: true, enumerable: true, get: getter }
  19. );
  20. var thrower = function () { throw messageGetterError; };
  21. tap.test('failures', function (tt) {
  22. tt.plan(1);
  23. var test = tape.createHarness();
  24. test.createStream().pipe(concat(function (body) {
  25. tt.same(stripFullStack(body.toString('utf8')), [
  26. 'TAP version 13',
  27. '# non functions',
  28. 'not ok 1 should throw',
  29. ' ---',
  30. ' operator: throws',
  31. ' expected: |-',
  32. ' undefined',
  33. ' actual: |-',
  34. ' { [TypeError: ' + getNonFunctionMessage() + "] message: '" + getNonFunctionMessage() + "' }",
  35. ' at: Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  36. ' stack: |-',
  37. String(' TypeError: ' + getNonFunctionMessage(undefined)),
  38. ' [... stack stripped ...]',
  39. ' at Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  40. ' [... stack stripped ...]',
  41. ' ...',
  42. 'not ok 2 should throw',
  43. ' ---',
  44. ' operator: throws',
  45. ' expected: |-',
  46. ' undefined',
  47. ' actual: |-',
  48. ' { [TypeError: ' + getNonFunctionMessage(null) + "] message: '" + getNonFunctionMessage(null) + "' }",
  49. ' at: Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  50. ' stack: |-',
  51. String(' TypeError: ' + getNonFunctionMessage(null)),
  52. ' [... stack stripped ...]',
  53. ' at Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  54. ' [... stack stripped ...]',
  55. ' ...',
  56. 'not ok 3 should throw',
  57. ' ---',
  58. ' operator: throws',
  59. ' expected: |-',
  60. ' undefined',
  61. ' actual: |-',
  62. ' { [TypeError: ' + getNonFunctionMessage(true) + "] message: '" + getNonFunctionMessage(true) + "' }",
  63. ' at: Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  64. ' stack: |-',
  65. String(' TypeError: ' + getNonFunctionMessage(true)),
  66. ' [... stack stripped ...]',
  67. ' at Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  68. ' [... stack stripped ...]',
  69. ' ...',
  70. 'not ok 4 should throw',
  71. ' ---',
  72. ' operator: throws',
  73. ' expected: |-',
  74. ' undefined',
  75. ' actual: |-',
  76. ' { [TypeError: ' + getNonFunctionMessage(false) + "] message: '" + getNonFunctionMessage(false) + "' }",
  77. ' at: Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  78. ' stack: |-',
  79. String(' TypeError: ' + getNonFunctionMessage(false)),
  80. ' [... stack stripped ...]',
  81. ' at Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  82. ' [... stack stripped ...]',
  83. ' ...',
  84. 'not ok 5 should throw',
  85. ' ---',
  86. ' operator: throws',
  87. ' expected: |-',
  88. ' undefined',
  89. ' actual: |-',
  90. ' { [TypeError: ' + getNonFunctionMessage('abc') + "] message: '" + getNonFunctionMessage('abc') + "' }",
  91. ' at: Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  92. ' stack: |-',
  93. String(' TypeError: ' + getNonFunctionMessage('abc')),
  94. ' [... stack stripped ...]',
  95. ' at Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  96. ' [... stack stripped ...]',
  97. ' ...',
  98. 'not ok 6 should throw',
  99. ' ---',
  100. ' operator: throws',
  101. ' expected: |-',
  102. ' undefined',
  103. ' actual: |-',
  104. ' { [TypeError: ' + getNonFunctionMessage(/a/g) + "] message: '" + getNonFunctionMessage(/a/g) + "' }",
  105. ' at: Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  106. ' stack: |-',
  107. String(' TypeError: ' + getNonFunctionMessage(/a/g)),
  108. ' [... stack stripped ...]',
  109. ' at Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  110. ' [... stack stripped ...]',
  111. ' ...',
  112. 'not ok 7 should throw',
  113. ' ---',
  114. ' operator: throws',
  115. ' expected: |-',
  116. ' undefined',
  117. ' actual: |-',
  118. ' { [TypeError: ' + getNonFunctionMessage([]) + "] message: '" + getNonFunctionMessage([]) + "' }",
  119. ' at: Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  120. ' stack: |-',
  121. String(' TypeError: ' + getNonFunctionMessage([])),
  122. ' [... stack stripped ...]',
  123. ' at Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  124. ' [... stack stripped ...]',
  125. ' ...',
  126. 'not ok 8 should throw',
  127. ' ---',
  128. ' operator: throws',
  129. ' expected: |-',
  130. ' undefined',
  131. ' actual: |-',
  132. ' { [TypeError: ' + getNonFunctionMessage({}) + "] message: '" + getNonFunctionMessage({}) + "' }",
  133. ' at: Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  134. ' stack: |-',
  135. String(' TypeError: ' + getNonFunctionMessage({})),
  136. ' [... stack stripped ...]',
  137. ' at Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  138. ' [... stack stripped ...]',
  139. ' ...',
  140. '# function',
  141. 'not ok 9 should throw',
  142. ' ---',
  143. ' operator: throws',
  144. ' expected: undefined',
  145. ' actual: undefined',
  146. ' at: Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  147. ' stack: |-',
  148. ' Error: should throw',
  149. ' [... stack stripped ...]',
  150. ' at Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  151. ' [... stack stripped ...]',
  152. ' ...',
  153. '# custom error messages',
  154. 'ok 10 "message" is enumerable',
  155. "ok 11 { custom: 'error', message: 'message' }",
  156. 'ok 12 getter is still the same',
  157. '# throws null',
  158. 'ok 13 throws null',
  159. '# wrong type of error',
  160. 'not ok 14 throws actual',
  161. ' ---',
  162. ' operator: throws',
  163. ' expected: |-',
  164. ' [Function: TypeError]',
  165. ' actual: |-',
  166. " { [RangeError: actual!] message: 'actual!' }",
  167. ' at: Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  168. ' stack: |-',
  169. ' RangeError: actual!',
  170. ' at Test.<anonymous> ($TEST/throws.js:$LINE:$COL)',
  171. ' [... stack stripped ...]',
  172. ' ...',
  173. '# non-extensible throw match',
  174. 'ok 15 error is non-extensible',
  175. 'ok 16 non-extensible error matches',
  176. 'ok 17 errorWithMessage is non-extensible',
  177. 'ok 18 non-extensible error with message matches',
  178. '# frozen `message` property',
  179. 'ok 19 error is non-writable',
  180. 'ok 20 error is non-configurable',
  181. 'ok 21 non-writable error matches',
  182. '',
  183. '1..21',
  184. '# tests 21',
  185. '# pass 11',
  186. '# fail 10',
  187. ''
  188. ]);
  189. }));
  190. test('non functions', function (t) {
  191. t.plan(8);
  192. t['throws']();
  193. t['throws'](null);
  194. t['throws'](true);
  195. t['throws'](false);
  196. t['throws']('abc');
  197. t['throws'](/a/g);
  198. t['throws']([]);
  199. t['throws']({});
  200. });
  201. test('function', function (t) {
  202. t.plan(1);
  203. t['throws'](function () {});
  204. });
  205. test('custom error messages', function (t) {
  206. t.plan(3);
  207. t.equal(Object.prototype.propertyIsEnumerable.call(messageGetterError, 'message'), true, '"message" is enumerable');
  208. t['throws'](thrower, "{ custom: 'error', message: 'message' }");
  209. t.equal(Object.getOwnPropertyDescriptor(messageGetterError, 'message').get, getter, 'getter is still the same');
  210. });
  211. test('throws null', function (t) {
  212. t.plan(1);
  213. t['throws'](function () { throw null; }, 'throws null');
  214. t.end();
  215. });
  216. test('wrong type of error', function (t) {
  217. t.plan(1);
  218. var actual = new RangeError('actual!');
  219. t['throws'](function () { throw actual; }, TypeError, 'throws actual');
  220. t.end();
  221. });
  222. test('non-extensible throw match', { skip: !Object.seal }, function (t) {
  223. var error = { foo: 1 };
  224. Object.seal(error);
  225. t.throws(function () { error.x = 1; }, TypeError, 'error is non-extensible');
  226. t.throws(function () { throw error; }, error, 'non-extensible error matches');
  227. var errorWithMessage = { message: 'abc' };
  228. Object.seal(errorWithMessage);
  229. t.throws(function () { errorWithMessage.x = 1; }, TypeError, 'errorWithMessage is non-extensible');
  230. t.throws(function () { throw errorWithMessage; }, error, 'non-extensible error with message matches');
  231. t.end();
  232. });
  233. test('frozen `message` property', { skip: !Object.defineProperty }, function (t) {
  234. var error = { message: 'abc' };
  235. Object.defineProperty(error, 'message', { configurable: false, enumerable: false, writable: false });
  236. t.throws(function () { error.message = 'def'; }, TypeError, 'error is non-writable');
  237. t.throws(function () { delete error.message; }, TypeError, 'error is non-configurable');
  238. t.throws(function () { throw error; }, { message: 'abc' }, 'non-writable error matches');
  239. t.end();
  240. });
  241. });