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