1 | 'use strict';
|
2 |
|
3 | var tape = require('../');
|
4 | var tap = require('tap');
|
5 | var concat = require('concat-stream');
|
6 | var inspect = require('object-inspect');
|
7 | var assign = require('object.assign');
|
8 |
|
9 | var stripFullStack = require('./common').stripFullStack;
|
10 |
|
11 | function fn() {
|
12 | throw new TypeError('RegExp');
|
13 | }
|
14 |
|
15 | function getNonFunctionMessage(fn) {
|
16 | try {
|
17 | fn();
|
18 | } catch (e) {
|
19 | return e.message;
|
20 | }
|
21 | }
|
22 |
|
23 | var getter = function () { return 'message'; };
|
24 | var messageGetterError = Object.defineProperty(
|
25 | { custom: 'error' },
|
26 | 'message',
|
27 | { configurable: true, enumerable: true, get: getter }
|
28 | );
|
29 | var thrower = function () { throw messageGetterError; };
|
30 |
|
31 | tap.test('failures', function (tt) {
|
32 | tt.plan(1);
|
33 |
|
34 | var test = tape.createHarness();
|
35 | test.createStream().pipe(concat(function (body) {
|
36 | tt.equal(
|
37 | stripFullStack(body.toString('utf8')),
|
38 | 'TAP version 13\n'
|
39 | + '# non functions\n'
|
40 | + 'ok 1 should throw\n'
|
41 | + 'ok 2 should throw\n'
|
42 | + 'ok 3 should throw\n'
|
43 | + 'ok 4 should throw\n'
|
44 | + 'ok 5 should throw\n'
|
45 | + 'ok 6 should throw\n'
|
46 | + 'ok 7 should throw\n'
|
47 | + 'ok 8 should throw\n'
|
48 | + '# function\n'
|
49 | + 'not ok 9 should throw\n'
|
50 | + ' ---\n'
|
51 | + ' operator: throws\n'
|
52 | + ' expected: undefined\n'
|
53 | + ' actual: undefined\n'
|
54 | + ' at: Test.<anonymous> ($TEST/throws.js:$LINE:$COL)\n'
|
55 | + ' stack: |-\n'
|
56 | + ' Error: should throw\n'
|
57 | + ' [... stack stripped ...]\n'
|
58 | + ' at Test.<anonymous> ($TEST/throws.js:$LINE:$COL)\n'
|
59 | + ' [... stack stripped ...]\n'
|
60 | + ' ...\n'
|
61 | + '# custom error messages\n'
|
62 | + 'ok 10 "message" is enumerable\n'
|
63 | + "ok 11 { custom: 'error', message: 'message' }\n"
|
64 | + 'ok 12 getter is still the same\n'
|
65 | + '# throws null\n'
|
66 | + 'ok 13 throws null\n'
|
67 | + '# wrong type of error\n'
|
68 | + 'not ok 14 throws actual\n'
|
69 | + ' ---\n'
|
70 | + ' operator: throws\n'
|
71 | + ' expected: |-\n'
|
72 | + ' [Function: TypeError]\n'
|
73 | + ' actual: |-\n'
|
74 | + " { [RangeError: actual!] message: 'actual!' }\n"
|
75 | + ' at: Test.<anonymous> ($TEST/throws.js:$LINE:$COL)\n'
|
76 | + ' stack: |-\n'
|
77 | + ' RangeError: actual!\n'
|
78 | + ' at Test.<anonymous> ($TEST/throws.js:$LINE:$COL)\n'
|
79 | + ' [... stack stripped ...]\n'
|
80 | + ' ...\n'
|
81 | + '# object\n'
|
82 | + 'ok 15 object properties are validated\n'
|
83 | + '# object with regexes\n'
|
84 | + 'ok 16 object with regex values is validated\n'
|
85 | + '# similar error object\n'
|
86 | + 'ok 17 throwing a similar error\n'
|
87 | + '# validate with regex\n'
|
88 | + 'ok 18 regex against toString of error\n'
|
89 | + '# custom error validation\n'
|
90 | + 'ok 19 error is SyntaxError\n'
|
91 | + 'ok 20 error matches /value/\n'
|
92 | + 'ok 21 unexpected error\n'
|
93 | + '# throwing primitives\n'
|
94 | + 'ok 22 primitive: null\n'
|
95 | + 'ok 23 primitive: undefined\n'
|
96 | + 'ok 24 primitive: 0\n'
|
97 | + 'ok 25 primitive: NaN\n'
|
98 | + 'ok 26 primitive: 42\n'
|
99 | + 'ok 27 primitive: Infinity\n'
|
100 | + 'ok 28 primitive: \'\'\n'
|
101 | + 'ok 29 primitive: \'foo\'\n'
|
102 | + 'ok 30 primitive: true\n'
|
103 | + 'ok 31 primitive: false\n'
|
104 | + '# ambiguous arguments\n'
|
105 | + 'ok 32 Second\n'
|
106 | + 'ok 33 Second\n'
|
107 | + 'ok 34 Second\n'
|
108 | + 'ok 35 should throw\n'
|
109 | + 'not ok 36 should throw\n'
|
110 | + ' ---\n'
|
111 | + ' operator: throws\n'
|
112 | + ' expected: |-\n'
|
113 | + ' \'/Second$/\'\n'
|
114 | + ' actual: |-\n'
|
115 | + ' { [Error: First] message: \'First\' }\n'
|
116 | + ' at: Test.<anonymous> ($TEST/throws.js:$LINE:$COL)\n'
|
117 | + ' stack: |-\n'
|
118 | + ' Error: First\n'
|
119 | + ' at throwingFirst ($TEST/throws.js:$LINE:$COL)\n'
|
120 | + ' [... stack stripped ...]\n'
|
121 | + ' at Test.<anonymous> ($TEST/throws.js:$LINE:$COL)\n'
|
122 | + ' [... stack stripped ...]\n'
|
123 | + ' ...\n'
|
124 | + '\n1..36\n'
|
125 | + '# tests 36\n'
|
126 | + '# pass 33\n'
|
127 | + '# fail 3\n'
|
128 | );
|
129 | }));
|
130 |
|
131 | test('non functions', function (t) {
|
132 | t.plan(8);
|
133 | t.throws();
|
134 | t.throws(null);
|
135 | t.throws(true);
|
136 | t.throws(false);
|
137 | t.throws('abc');
|
138 | t.throws(/a/g);
|
139 | t.throws([]);
|
140 | t.throws({});
|
141 | });
|
142 |
|
143 | test('function', function (t) {
|
144 | t.plan(1);
|
145 | t.throws(function () {});
|
146 | });
|
147 |
|
148 | test('custom error messages', function (t) {
|
149 | t.plan(3);
|
150 | t.equal(Object.prototype.propertyIsEnumerable.call(messageGetterError, 'message'), true, '"message" is enumerable');
|
151 | t.throws(thrower, "{ custom: 'error', message: 'message' }");
|
152 | t.equal(Object.getOwnPropertyDescriptor(messageGetterError, 'message').get, getter, 'getter is still the same');
|
153 | });
|
154 |
|
155 | test('throws null', function (t) {
|
156 | t.plan(1);
|
157 | t.throws(function () { throw null; }, 'throws null');
|
158 | t.end();
|
159 | });
|
160 |
|
161 | test('wrong type of error', function (t) {
|
162 | t.plan(1);
|
163 | var actual = new RangeError('actual!');
|
164 | t.throws(function () { throw actual; }, TypeError, 'throws actual');
|
165 | t.end();
|
166 | });
|
167 |
|
168 |
|
169 | var err = new TypeError('Wrong value');
|
170 | err.code = 404;
|
171 | err.foo = 'bar';
|
172 | err.info = {
|
173 | nested: true,
|
174 | baz: 'text'
|
175 | };
|
176 | err.reg = /abc/i;
|
177 |
|
178 | test('object', function (t) {
|
179 | t.plan(1);
|
180 |
|
181 | t.throws(
|
182 | function () { throw err; },
|
183 | {
|
184 | name: 'TypeError',
|
185 | message: 'Wrong value',
|
186 | info: {
|
187 | nested: true,
|
188 | baz: 'text'
|
189 | }
|
190 |
|
191 |
|
192 |
|
193 | },
|
194 | 'object properties are validated'
|
195 | );
|
196 |
|
197 | t.end();
|
198 | });
|
199 |
|
200 | test('object with regexes', function (t) {
|
201 | t.plan(1);
|
202 | t.throws(
|
203 | function () { throw err; },
|
204 | {
|
205 |
|
206 |
|
207 |
|
208 | name: /^TypeError$/,
|
209 | message: /Wrong/,
|
210 | foo: 'bar',
|
211 | info: {
|
212 | nested: true,
|
213 |
|
214 | baz: 'text'
|
215 | },
|
216 |
|
217 |
|
218 |
|
219 | reg: /abc/i
|
220 | },
|
221 | 'object with regex values is validated'
|
222 | );
|
223 | t.end();
|
224 | });
|
225 |
|
226 | test('similar error object', function (t) {
|
227 | t.plan(1);
|
228 | t.throws(
|
229 | function () {
|
230 | var otherErr = new TypeError('Not found');
|
231 |
|
232 | assign(otherErr, err);
|
233 | throw otherErr;
|
234 | },
|
235 |
|
236 |
|
237 | err,
|
238 | 'throwing a similar error'
|
239 | );
|
240 | t.end();
|
241 | });
|
242 |
|
243 | test('validate with regex', function (t) {
|
244 | t.plan(1);
|
245 | t.throws(
|
246 | function () { throw new Error('Wrong value'); },
|
247 | /^Error: Wrong value$/,
|
248 | 'regex against toString of error'
|
249 | );
|
250 | t.end();
|
251 | });
|
252 |
|
253 | test('custom error validation', function (t) {
|
254 | t.plan(3);
|
255 | t.throws(
|
256 | function () { throw new SyntaxError('Wrong value'); },
|
257 | function (error) {
|
258 | t.ok(error instanceof SyntaxError, 'error is SyntaxError');
|
259 | t.ok((/value/).test(error), 'error matches /value/');
|
260 |
|
261 |
|
262 |
|
263 |
|
264 |
|
265 | return true;
|
266 | },
|
267 | 'unexpected error'
|
268 | );
|
269 | t.end();
|
270 | });
|
271 |
|
272 | test('throwing primitives', function (t) {
|
273 | [null, undefined, 0, NaN, 42, Infinity, '', 'foo', true, false].forEach(function (primitive) {
|
274 | t.throws(function () { throw primitive; }, 'primitive: ' + inspect(primitive));
|
275 | });
|
276 |
|
277 | t.end();
|
278 | });
|
279 |
|
280 | test('ambiguous arguments', function (t) {
|
281 | function throwingFirst() {
|
282 | throw new Error('First');
|
283 | }
|
284 |
|
285 | function throwingSecond() {
|
286 | throw new Error('Second');
|
287 | }
|
288 |
|
289 | function notThrowing() {}
|
290 |
|
291 |
|
292 |
|
293 |
|
294 | t.throws(throwingFirst, 'Second');
|
295 |
|
296 |
|
297 |
|
298 | t.throws(throwingSecond, 'Second');
|
299 |
|
300 |
|
301 |
|
302 | t.doesNotThrow(notThrowing, 'Second');
|
303 |
|
304 |
|
305 |
|
306 |
|
307 | t.throws(throwingSecond, /Second$/);
|
308 |
|
309 |
|
310 | t.throws(throwingFirst, /Second$/);
|
311 |
|
312 | t.end();
|
313 | });
|
314 | });
|