• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2const common = require('../common');
3const assert = require('assert');
4
5// Run all tests in parallel and check their outcome at the end.
6const promises = [];
7
8// Thenable object without `catch` method,
9// shouldn't be considered as a valid Thenable
10const invalidThenable = {
11  then: (fulfill, reject) => {
12    fulfill();
13  },
14};
15
16// Function that returns a Thenable function,
17// a function with `catch` and `then` methods attached,
18// shouldn't be considered as a valid Thenable.
19const invalidThenableFunc = () => {
20  function f() {}
21
22  f.then = (fulfill, reject) => {
23    fulfill();
24  };
25  f.catch = () => {};
26
27  return f;
28};
29
30// Test assert.rejects() and assert.doesNotReject() by checking their
31// expected output and by verifying that they do not work sync
32
33// Check `assert.rejects`.
34{
35  const rejectingFn = async () => assert.fail();
36  const errObj = {
37    code: 'ERR_ASSERTION',
38    name: 'AssertionError',
39    message: 'Failed'
40  };
41
42  // `assert.rejects` accepts a function or a promise
43  // or a thenable as first argument.
44  promises.push(assert.rejects(rejectingFn, errObj));
45  promises.push(assert.rejects(rejectingFn(), errObj));
46
47  const validRejectingThenable = {
48    then: (fulfill, reject) => {
49      reject({ code: 'FAIL' });
50    },
51    catch: () => {}
52  };
53  promises.push(assert.rejects(validRejectingThenable, { code: 'FAIL' }));
54
55  // `assert.rejects` should not accept thenables that
56  // use a function as `obj` and that have no `catch` handler.
57  promises.push(assert.rejects(
58    assert.rejects(invalidThenable, {}),
59    {
60      code: 'ERR_INVALID_ARG_TYPE'
61    })
62  );
63  promises.push(assert.rejects(
64    assert.rejects(invalidThenableFunc, {}),
65    {
66      code: 'ERR_INVALID_RETURN_VALUE'
67    })
68  );
69}
70
71{
72  const handler = (err) => {
73    assert(err instanceof assert.AssertionError,
74           `${err.name} is not instance of AssertionError`);
75    assert.strictEqual(err.code, 'ERR_ASSERTION');
76    assert.strictEqual(err.message,
77                       'Missing expected rejection (mustNotCall).');
78    assert.strictEqual(err.operator, 'rejects');
79    assert.ok(!err.stack.includes('at Function.rejects'));
80    return true;
81  };
82
83  let promise = assert.rejects(async () => {}, common.mustNotCall());
84  promises.push(assert.rejects(promise, common.mustCall(handler)));
85
86  promise = assert.rejects(() => {}, common.mustNotCall());
87  promises.push(assert.rejects(promise, {
88    name: 'TypeError',
89    code: 'ERR_INVALID_RETURN_VALUE',
90    message: 'Expected instance of Promise to be returned ' +
91             'from the "promiseFn" function but got type undefined.'
92  }));
93
94  promise = assert.rejects(Promise.resolve(), common.mustNotCall());
95  promises.push(assert.rejects(promise, common.mustCall(handler)));
96}
97
98{
99  const THROWN_ERROR = new Error();
100
101  promises.push(assert.rejects(() => {
102    throw THROWN_ERROR;
103  }, {}).catch(common.mustCall((err) => {
104    assert.strictEqual(err, THROWN_ERROR);
105  })));
106}
107
108promises.push(assert.rejects(
109  assert.rejects('fail', {}),
110  {
111    code: 'ERR_INVALID_ARG_TYPE',
112    message: 'The "promiseFn" argument must be of type function or an ' +
113             "instance of Promise. Received type string ('fail')"
114  }
115));
116
117{
118  const handler = (generated, actual, err) => {
119    assert.strictEqual(err.generatedMessage, generated);
120    assert.strictEqual(err.code, 'ERR_ASSERTION');
121    assert.strictEqual(err.actual, actual);
122    assert.strictEqual(err.operator, 'rejects');
123    assert(/rejects/.test(err.stack));
124    return true;
125  };
126  const err = new Error();
127  promises.push(assert.rejects(
128    assert.rejects(Promise.reject(null), { code: 'FOO' }),
129    handler.bind(null, true, null)
130  ));
131  promises.push(assert.rejects(
132    assert.rejects(Promise.reject(5), { code: 'FOO' }, 'AAAAA'),
133    handler.bind(null, false, 5)
134  ));
135  promises.push(assert.rejects(
136    assert.rejects(Promise.reject(err), { code: 'FOO' }, 'AAAAA'),
137    handler.bind(null, false, err)
138  ));
139}
140
141// Check `assert.doesNotReject`.
142{
143  // `assert.doesNotReject` accepts a function or a promise
144  // or a thenable as first argument.
145  /* eslint-disable no-restricted-syntax */
146  let promise = assert.doesNotReject(() => new Map(), common.mustNotCall());
147  promises.push(assert.rejects(promise, {
148    message: 'Expected instance of Promise to be returned ' +
149             'from the "promiseFn" function but got instance of Map.',
150    code: 'ERR_INVALID_RETURN_VALUE',
151    name: 'TypeError'
152  }));
153  promises.push(assert.doesNotReject(async () => {}));
154  promises.push(assert.doesNotReject(Promise.resolve()));
155
156  // `assert.doesNotReject` should not accept thenables that
157  // use a function as `obj` and that have no `catch` handler.
158  const validFulfillingThenable = {
159    then: (fulfill, reject) => {
160      fulfill();
161    },
162    catch: () => {}
163  };
164  promises.push(assert.doesNotReject(validFulfillingThenable));
165  promises.push(assert.rejects(
166    assert.doesNotReject(invalidThenable),
167    {
168      code: 'ERR_INVALID_ARG_TYPE'
169    })
170  );
171  promises.push(assert.rejects(
172    assert.doesNotReject(invalidThenableFunc),
173    {
174      code: 'ERR_INVALID_RETURN_VALUE'
175    })
176  );
177
178  const handler1 = (err) => {
179    assert(err instanceof assert.AssertionError,
180           `${err.name} is not instance of AssertionError`);
181    assert.strictEqual(err.code, 'ERR_ASSERTION');
182    assert.strictEqual(err.message, 'Failed');
183    return true;
184  };
185  const handler2 = (err) => {
186    assert(err instanceof assert.AssertionError,
187           `${err.name} is not instance of AssertionError`);
188    assert.strictEqual(err.code, 'ERR_ASSERTION');
189    assert.strictEqual(err.message,
190                       'Got unwanted rejection.\nActual message: "Failed"');
191    assert.strictEqual(err.operator, 'doesNotReject');
192    assert.ok(err.stack);
193    assert.ok(!err.stack.includes('at Function.doesNotReject'));
194    return true;
195  };
196
197  const rejectingFn = async () => assert.fail();
198
199  promise = assert.doesNotReject(rejectingFn, common.mustCall(handler1));
200  promises.push(assert.rejects(promise, common.mustCall(handler2)));
201
202  promise = assert.doesNotReject(rejectingFn(), common.mustCall(handler1));
203  promises.push(assert.rejects(promise, common.mustCall(handler2)));
204
205  promise = assert.doesNotReject(() => assert.fail(), common.mustNotCall());
206  promises.push(assert.rejects(promise, common.mustCall(handler1)));
207
208  promises.push(assert.rejects(
209    assert.doesNotReject(123),
210    {
211      code: 'ERR_INVALID_ARG_TYPE',
212      message: 'The "promiseFn" argument must be of type ' +
213               'function or an instance of Promise. Received type number (123)'
214    }
215  ));
216  /* eslint-enable no-restricted-syntax */
217}
218
219// Make sure all async code gets properly executed.
220Promise.all(promises).then(common.mustCall());
221