11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ciconst assert = require('assert');
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci// Run all tests in parallel and check their outcome at the end.
61cb0ef41Sopenharmony_ciconst promises = [];
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci// Thenable object without `catch` method,
91cb0ef41Sopenharmony_ci// shouldn't be considered as a valid Thenable
101cb0ef41Sopenharmony_ciconst invalidThenable = {
111cb0ef41Sopenharmony_ci  then: (fulfill, reject) => {
121cb0ef41Sopenharmony_ci    fulfill();
131cb0ef41Sopenharmony_ci  },
141cb0ef41Sopenharmony_ci};
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci// Function that returns a Thenable function,
171cb0ef41Sopenharmony_ci// a function with `catch` and `then` methods attached,
181cb0ef41Sopenharmony_ci// shouldn't be considered as a valid Thenable.
191cb0ef41Sopenharmony_ciconst invalidThenableFunc = () => {
201cb0ef41Sopenharmony_ci  function f() {}
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci  f.then = (fulfill, reject) => {
231cb0ef41Sopenharmony_ci    fulfill();
241cb0ef41Sopenharmony_ci  };
251cb0ef41Sopenharmony_ci  f.catch = () => {};
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci  return f;
281cb0ef41Sopenharmony_ci};
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ci// Test assert.rejects() and assert.doesNotReject() by checking their
311cb0ef41Sopenharmony_ci// expected output and by verifying that they do not work sync
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci// Check `assert.rejects`.
341cb0ef41Sopenharmony_ci{
351cb0ef41Sopenharmony_ci  const rejectingFn = async () => assert.fail();
361cb0ef41Sopenharmony_ci  const errObj = {
371cb0ef41Sopenharmony_ci    code: 'ERR_ASSERTION',
381cb0ef41Sopenharmony_ci    name: 'AssertionError',
391cb0ef41Sopenharmony_ci    message: 'Failed'
401cb0ef41Sopenharmony_ci  };
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ci  // `assert.rejects` accepts a function or a promise
431cb0ef41Sopenharmony_ci  // or a thenable as first argument.
441cb0ef41Sopenharmony_ci  promises.push(assert.rejects(rejectingFn, errObj));
451cb0ef41Sopenharmony_ci  promises.push(assert.rejects(rejectingFn(), errObj));
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci  const validRejectingThenable = {
481cb0ef41Sopenharmony_ci    then: (fulfill, reject) => {
491cb0ef41Sopenharmony_ci      reject({ code: 'FAIL' });
501cb0ef41Sopenharmony_ci    },
511cb0ef41Sopenharmony_ci    catch: () => {}
521cb0ef41Sopenharmony_ci  };
531cb0ef41Sopenharmony_ci  promises.push(assert.rejects(validRejectingThenable, { code: 'FAIL' }));
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci  // `assert.rejects` should not accept thenables that
561cb0ef41Sopenharmony_ci  // use a function as `obj` and that have no `catch` handler.
571cb0ef41Sopenharmony_ci  promises.push(assert.rejects(
581cb0ef41Sopenharmony_ci    assert.rejects(invalidThenable, {}),
591cb0ef41Sopenharmony_ci    {
601cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE'
611cb0ef41Sopenharmony_ci    })
621cb0ef41Sopenharmony_ci  );
631cb0ef41Sopenharmony_ci  promises.push(assert.rejects(
641cb0ef41Sopenharmony_ci    assert.rejects(invalidThenableFunc, {}),
651cb0ef41Sopenharmony_ci    {
661cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_RETURN_VALUE'
671cb0ef41Sopenharmony_ci    })
681cb0ef41Sopenharmony_ci  );
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  const err = new Error('foobar');
711cb0ef41Sopenharmony_ci  const validate = () => { return 'baz'; };
721cb0ef41Sopenharmony_ci  promises.push(assert.rejects(
731cb0ef41Sopenharmony_ci    () => assert.rejects(Promise.reject(err), validate),
741cb0ef41Sopenharmony_ci    {
751cb0ef41Sopenharmony_ci      message: 'The "validate" validation function is expected to ' +
761cb0ef41Sopenharmony_ci               "return \"true\". Received 'baz'\n\nCaught error:\n\n" +
771cb0ef41Sopenharmony_ci               'Error: foobar',
781cb0ef41Sopenharmony_ci      code: 'ERR_ASSERTION',
791cb0ef41Sopenharmony_ci      actual: err,
801cb0ef41Sopenharmony_ci      expected: validate,
811cb0ef41Sopenharmony_ci      name: 'AssertionError',
821cb0ef41Sopenharmony_ci      operator: 'rejects',
831cb0ef41Sopenharmony_ci    }
841cb0ef41Sopenharmony_ci  ));
851cb0ef41Sopenharmony_ci}
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci{
881cb0ef41Sopenharmony_ci  const handler = (err) => {
891cb0ef41Sopenharmony_ci    assert(err instanceof assert.AssertionError,
901cb0ef41Sopenharmony_ci           `${err.name} is not instance of AssertionError`);
911cb0ef41Sopenharmony_ci    assert.strictEqual(err.code, 'ERR_ASSERTION');
921cb0ef41Sopenharmony_ci    assert.strictEqual(err.message,
931cb0ef41Sopenharmony_ci                       'Missing expected rejection (mustNotCall).');
941cb0ef41Sopenharmony_ci    assert.strictEqual(err.operator, 'rejects');
951cb0ef41Sopenharmony_ci    assert.ok(!err.stack.includes('at Function.rejects'));
961cb0ef41Sopenharmony_ci    return true;
971cb0ef41Sopenharmony_ci  };
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci  let promise = assert.rejects(async () => {}, common.mustNotCall());
1001cb0ef41Sopenharmony_ci  promises.push(assert.rejects(promise, common.mustCall(handler)));
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci  promise = assert.rejects(() => {}, common.mustNotCall());
1031cb0ef41Sopenharmony_ci  promises.push(assert.rejects(promise, {
1041cb0ef41Sopenharmony_ci    name: 'TypeError',
1051cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_RETURN_VALUE',
1061cb0ef41Sopenharmony_ci    // FIXME(JakobJingleheimer): This should match on key words, like /Promise/ and /undefined/.
1071cb0ef41Sopenharmony_ci    message: 'Expected instance of Promise to be returned ' +
1081cb0ef41Sopenharmony_ci             'from the "promiseFn" function but got undefined.'
1091cb0ef41Sopenharmony_ci  }));
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci  promise = assert.rejects(Promise.resolve(), common.mustNotCall());
1121cb0ef41Sopenharmony_ci  promises.push(assert.rejects(promise, common.mustCall(handler)));
1131cb0ef41Sopenharmony_ci}
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci{
1161cb0ef41Sopenharmony_ci  const THROWN_ERROR = new Error();
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ci  promises.push(assert.rejects(() => {
1191cb0ef41Sopenharmony_ci    throw THROWN_ERROR;
1201cb0ef41Sopenharmony_ci  }, {}).catch(common.mustCall((err) => {
1211cb0ef41Sopenharmony_ci    assert.strictEqual(err, THROWN_ERROR);
1221cb0ef41Sopenharmony_ci  })));
1231cb0ef41Sopenharmony_ci}
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_cipromises.push(assert.rejects(
1261cb0ef41Sopenharmony_ci  assert.rejects('fail', {}),
1271cb0ef41Sopenharmony_ci  {
1281cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE',
1291cb0ef41Sopenharmony_ci    message: 'The "promiseFn" argument must be of type function or an ' +
1301cb0ef41Sopenharmony_ci             "instance of Promise. Received type string ('fail')"
1311cb0ef41Sopenharmony_ci  }
1321cb0ef41Sopenharmony_ci));
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci{
1351cb0ef41Sopenharmony_ci  const handler = (generated, actual, err) => {
1361cb0ef41Sopenharmony_ci    assert.strictEqual(err.generatedMessage, generated);
1371cb0ef41Sopenharmony_ci    assert.strictEqual(err.code, 'ERR_ASSERTION');
1381cb0ef41Sopenharmony_ci    assert.strictEqual(err.actual, actual);
1391cb0ef41Sopenharmony_ci    assert.strictEqual(err.operator, 'rejects');
1401cb0ef41Sopenharmony_ci    assert.match(err.stack, /rejects/);
1411cb0ef41Sopenharmony_ci    return true;
1421cb0ef41Sopenharmony_ci  };
1431cb0ef41Sopenharmony_ci  const err = new Error();
1441cb0ef41Sopenharmony_ci  promises.push(assert.rejects(
1451cb0ef41Sopenharmony_ci    assert.rejects(Promise.reject(null), { code: 'FOO' }),
1461cb0ef41Sopenharmony_ci    handler.bind(null, true, null)
1471cb0ef41Sopenharmony_ci  ));
1481cb0ef41Sopenharmony_ci  promises.push(assert.rejects(
1491cb0ef41Sopenharmony_ci    assert.rejects(Promise.reject(5), { code: 'FOO' }, 'AAAAA'),
1501cb0ef41Sopenharmony_ci    handler.bind(null, false, 5)
1511cb0ef41Sopenharmony_ci  ));
1521cb0ef41Sopenharmony_ci  promises.push(assert.rejects(
1531cb0ef41Sopenharmony_ci    assert.rejects(Promise.reject(err), { code: 'FOO' }, 'AAAAA'),
1541cb0ef41Sopenharmony_ci    handler.bind(null, false, err)
1551cb0ef41Sopenharmony_ci  ));
1561cb0ef41Sopenharmony_ci}
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci// Check `assert.doesNotReject`.
1591cb0ef41Sopenharmony_ci{
1601cb0ef41Sopenharmony_ci  // `assert.doesNotReject` accepts a function or a promise
1611cb0ef41Sopenharmony_ci  // or a thenable as first argument.
1621cb0ef41Sopenharmony_ci  /* eslint-disable no-restricted-syntax */
1631cb0ef41Sopenharmony_ci  let promise = assert.doesNotReject(() => new Map(), common.mustNotCall());
1641cb0ef41Sopenharmony_ci  promises.push(assert.rejects(promise, {
1651cb0ef41Sopenharmony_ci    message: 'Expected instance of Promise to be returned ' +
1661cb0ef41Sopenharmony_ci             'from the "promiseFn" function but got an instance of Map.',
1671cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_RETURN_VALUE',
1681cb0ef41Sopenharmony_ci    name: 'TypeError'
1691cb0ef41Sopenharmony_ci  }));
1701cb0ef41Sopenharmony_ci  promises.push(assert.doesNotReject(async () => {}));
1711cb0ef41Sopenharmony_ci  promises.push(assert.doesNotReject(Promise.resolve()));
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_ci  // `assert.doesNotReject` should not accept thenables that
1741cb0ef41Sopenharmony_ci  // use a function as `obj` and that have no `catch` handler.
1751cb0ef41Sopenharmony_ci  const validFulfillingThenable = {
1761cb0ef41Sopenharmony_ci    then: (fulfill, reject) => {
1771cb0ef41Sopenharmony_ci      fulfill();
1781cb0ef41Sopenharmony_ci    },
1791cb0ef41Sopenharmony_ci    catch: () => {}
1801cb0ef41Sopenharmony_ci  };
1811cb0ef41Sopenharmony_ci  promises.push(assert.doesNotReject(validFulfillingThenable));
1821cb0ef41Sopenharmony_ci  promises.push(assert.rejects(
1831cb0ef41Sopenharmony_ci    assert.doesNotReject(invalidThenable),
1841cb0ef41Sopenharmony_ci    {
1851cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE'
1861cb0ef41Sopenharmony_ci    })
1871cb0ef41Sopenharmony_ci  );
1881cb0ef41Sopenharmony_ci  promises.push(assert.rejects(
1891cb0ef41Sopenharmony_ci    assert.doesNotReject(invalidThenableFunc),
1901cb0ef41Sopenharmony_ci    {
1911cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_RETURN_VALUE'
1921cb0ef41Sopenharmony_ci    })
1931cb0ef41Sopenharmony_ci  );
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci  const handler1 = (err) => {
1961cb0ef41Sopenharmony_ci    assert(err instanceof assert.AssertionError,
1971cb0ef41Sopenharmony_ci           `${err.name} is not instance of AssertionError`);
1981cb0ef41Sopenharmony_ci    assert.strictEqual(err.code, 'ERR_ASSERTION');
1991cb0ef41Sopenharmony_ci    assert.strictEqual(err.message, 'Failed');
2001cb0ef41Sopenharmony_ci    return true;
2011cb0ef41Sopenharmony_ci  };
2021cb0ef41Sopenharmony_ci  const handler2 = (err) => {
2031cb0ef41Sopenharmony_ci    assert(err instanceof assert.AssertionError,
2041cb0ef41Sopenharmony_ci           `${err.name} is not instance of AssertionError`);
2051cb0ef41Sopenharmony_ci    assert.strictEqual(err.code, 'ERR_ASSERTION');
2061cb0ef41Sopenharmony_ci    assert.strictEqual(err.message,
2071cb0ef41Sopenharmony_ci                       'Got unwanted rejection.\nActual message: "Failed"');
2081cb0ef41Sopenharmony_ci    assert.strictEqual(err.operator, 'doesNotReject');
2091cb0ef41Sopenharmony_ci    assert.ok(err.stack);
2101cb0ef41Sopenharmony_ci    assert.ok(!err.stack.includes('at Function.doesNotReject'));
2111cb0ef41Sopenharmony_ci    return true;
2121cb0ef41Sopenharmony_ci  };
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci  const rejectingFn = async () => assert.fail();
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci  promise = assert.doesNotReject(rejectingFn, common.mustCall(handler1));
2171cb0ef41Sopenharmony_ci  promises.push(assert.rejects(promise, common.mustCall(handler2)));
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ci  promise = assert.doesNotReject(rejectingFn(), common.mustCall(handler1));
2201cb0ef41Sopenharmony_ci  promises.push(assert.rejects(promise, common.mustCall(handler2)));
2211cb0ef41Sopenharmony_ci
2221cb0ef41Sopenharmony_ci  promise = assert.doesNotReject(() => assert.fail(), common.mustNotCall());
2231cb0ef41Sopenharmony_ci  promises.push(assert.rejects(promise, common.mustCall(handler1)));
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci  promises.push(assert.rejects(
2261cb0ef41Sopenharmony_ci    assert.doesNotReject(123),
2271cb0ef41Sopenharmony_ci    {
2281cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE',
2291cb0ef41Sopenharmony_ci      message: 'The "promiseFn" argument must be of type ' +
2301cb0ef41Sopenharmony_ci               'function or an instance of Promise. Received type number (123)'
2311cb0ef41Sopenharmony_ci    }
2321cb0ef41Sopenharmony_ci  ));
2331cb0ef41Sopenharmony_ci  /* eslint-enable no-restricted-syntax */
2341cb0ef41Sopenharmony_ci}
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci// Make sure all async code gets properly executed.
2371cb0ef41Sopenharmony_ciPromise.all(promises).then(common.mustCall());
238