"use strict"; var assert = require("assert"); var testFulfilled = require("./helpers/testThreeCases").testFulfilled; var testRejected = require("./helpers/testThreeCases").testRejected; var reasons = require("./helpers/reasons"); var adapter = global.adapter; var deferred = adapter.deferred; var dummy = { dummy: "dummy" }; // we fulfill or reject with this when we don't intend to test against it var sentinel = { sentinel: "sentinel" }; // a sentinel fulfillment value to test for with strict equality var other = { other: "other" }; // a value we don't want to be strict equal to describe("2.2.7: `then` must return a promise: `promise2 = promise1.then(onFulfilled, onRejected)`", function () { specify("is a promise", function () { var promise1 = deferred().promise; var promise2 = promise1.then(); assert(typeof promise2 === "object" || typeof promise2 === "function"); assert.notStrictEqual(promise2, null); assert.strictEqual(typeof promise2.then, "function"); }); describe("2.2.7.1: If either `onFulfilled` or `onRejected` returns a value `x`, run the Promise Resolution " + "Procedure `[[Resolve]](promise2, x)`", function () { specify("see separate 3.3 tests", function () { }); }); describe("2.2.7.2: If either `onFulfilled` or `onRejected` throws an exception `e`, `promise2` must be rejected " + "with `e` as the reason.", function () { function testReason(expectedReason, stringRepresentation) { describe("The reason is " + stringRepresentation, function () { testFulfilled(dummy, function (promise1, done) { var promise2 = promise1.then(function onFulfilled() { throw expectedReason; }); promise2.then(null, function onPromise2Rejected(actualReason) { assert.strictEqual(actualReason, expectedReason); done(); }); }); testRejected(dummy, function (promise1, done) { var promise2 = promise1.then(null, function onRejected() { throw expectedReason; }); promise2.then(null, function onPromise2Rejected(actualReason) { assert.strictEqual(actualReason, expectedReason); done(); }); }); }); } Object.keys(reasons).forEach(function (stringRepresentation) { testReason(reasons[stringRepresentation](), stringRepresentation); }); }); describe("2.2.7.3: If `onFulfilled` is not a function and `promise1` is fulfilled, `promise2` must be fulfilled " + "with the same value.", function () { function testNonFunction(nonFunction, stringRepresentation) { describe("`onFulfilled` is " + stringRepresentation, function () { testFulfilled(sentinel, function (promise1, done) { var promise2 = promise1.then(nonFunction); promise2.then(function onPromise2Fulfilled(value) { assert.strictEqual(value, sentinel); done(); }); }); }); } testNonFunction(undefined, "`undefined`"); testNonFunction(null, "`null`"); testNonFunction(false, "`false`"); testNonFunction(5, "`5`"); testNonFunction({}, "an object"); testNonFunction([function () { return other; }], "an array containing a function"); }); describe("2.2.7.4: If `onRejected` is not a function and `promise1` is rejected, `promise2` must be rejected " + "with the same reason.", function () { function testNonFunction(nonFunction, stringRepresentation) { describe("`onRejected` is " + stringRepresentation, function () { testRejected(sentinel, function (promise1, done) { var promise2 = promise1.then(null, nonFunction); promise2.then(null, function onPromise2Rejected(reason) { assert.strictEqual(reason, sentinel); done(); }); }); }); } testNonFunction(undefined, "`undefined`"); testNonFunction(null, "`null`"); testNonFunction(false, "`false`"); testNonFunction(5, "`5`"); testNonFunction({}, "an object"); testNonFunction([function () { return other; }], "an array containing a function"); }); });