258 lines
10 KiB
JavaScript
258 lines
10 KiB
JavaScript
"use strict";
|
|
|
|
var assert = require("assert");
|
|
var sinon = require("sinon");
|
|
var testFulfilled = require("./helpers/testThreeCases").testFulfilled;
|
|
var testRejected = require("./helpers/testThreeCases").testRejected;
|
|
|
|
var dummy = { dummy: "dummy" }; // we fulfill or reject with this when we don't intend to test against it
|
|
var other = { other: "other" }; // a value we don't want to be strict equal to
|
|
var sentinel = { sentinel: "sentinel" }; // a sentinel fulfillment value to test for with strict equality
|
|
var sentinel2 = { sentinel2: "sentinel2" };
|
|
var sentinel3 = { sentinel3: "sentinel3" };
|
|
|
|
function callbackAggregator(times, ultimateCallback) {
|
|
var soFar = 0;
|
|
return function () {
|
|
if (++soFar === times) {
|
|
ultimateCallback();
|
|
}
|
|
};
|
|
}
|
|
|
|
describe("2.2.6: `then` may be called multiple times on the same promise.", function () {
|
|
describe("2.2.6.1: If/when `promise` is fulfilled, all respective `onFulfilled` callbacks must execute in the " +
|
|
"order of their originating calls to `then`.", function () {
|
|
describe("multiple boring fulfillment handlers", function () {
|
|
testFulfilled(sentinel, function (promise, done) {
|
|
var handler1 = sinon.stub().returns(other);
|
|
var handler2 = sinon.stub().returns(other);
|
|
var handler3 = sinon.stub().returns(other);
|
|
|
|
var spy = sinon.spy();
|
|
promise.then(handler1, spy);
|
|
promise.then(handler2, spy);
|
|
promise.then(handler3, spy);
|
|
|
|
promise.then(function (value) {
|
|
assert.strictEqual(value, sentinel);
|
|
|
|
sinon.assert.calledWith(handler1, sinon.match.same(sentinel));
|
|
sinon.assert.calledWith(handler2, sinon.match.same(sentinel));
|
|
sinon.assert.calledWith(handler3, sinon.match.same(sentinel));
|
|
sinon.assert.notCalled(spy);
|
|
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("multiple fulfillment handlers, one of which throws", function () {
|
|
testFulfilled(sentinel, function (promise, done) {
|
|
var handler1 = sinon.stub().returns(other);
|
|
var handler2 = sinon.stub().throws(other);
|
|
var handler3 = sinon.stub().returns(other);
|
|
|
|
var spy = sinon.spy();
|
|
promise.then(handler1, spy);
|
|
promise.then(handler2, spy).caught(function(){});
|
|
promise.then(handler3, spy);
|
|
|
|
promise.then(function (value) {
|
|
assert.strictEqual(value, sentinel);
|
|
|
|
sinon.assert.calledWith(handler1, sinon.match.same(sentinel));
|
|
sinon.assert.calledWith(handler2, sinon.match.same(sentinel));
|
|
sinon.assert.calledWith(handler3, sinon.match.same(sentinel));
|
|
sinon.assert.notCalled(spy);
|
|
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("results in multiple branching chains with their own fulfillment values", function () {
|
|
testFulfilled(dummy, function (promise, done) {
|
|
var semiDone = callbackAggregator(3, done);
|
|
|
|
promise.then(function () {
|
|
return sentinel;
|
|
}).then(function (value) {
|
|
assert.strictEqual(value, sentinel);
|
|
semiDone();
|
|
});
|
|
|
|
promise.then(function () {
|
|
throw sentinel2;
|
|
}).then(null, function (reason) {
|
|
assert.strictEqual(reason, sentinel2);
|
|
semiDone();
|
|
});
|
|
|
|
promise.then(function () {
|
|
return sentinel3;
|
|
}).then(function (value) {
|
|
assert.strictEqual(value, sentinel3);
|
|
semiDone();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("`onFulfilled` handlers are called in the original order", function () {
|
|
testFulfilled(dummy, function (promise, done) {
|
|
var handler1 = sinon.spy(function handler1() {});
|
|
var handler2 = sinon.spy(function handler2() {});
|
|
var handler3 = sinon.spy(function handler3() {});
|
|
|
|
promise.then(handler1);
|
|
promise.then(handler2);
|
|
promise.then(handler3);
|
|
|
|
promise.then(function () {
|
|
sinon.assert.callOrder(handler1, handler2, handler3);
|
|
done();
|
|
});
|
|
});
|
|
|
|
describe("even when one handler is added inside another handler", function () {
|
|
testFulfilled(dummy, function (promise, done) {
|
|
var handler1 = sinon.spy(function handler1() {});
|
|
var handler2 = sinon.spy(function handler2() {});
|
|
var handler3 = sinon.spy(function handler3() {});
|
|
|
|
promise.then(function () {
|
|
handler1();
|
|
promise.then(handler3);
|
|
});
|
|
promise.then(handler2);
|
|
|
|
promise.then(function () {
|
|
// Give implementations a bit of extra time to flush their internal queue, if necessary.
|
|
setTimeout(function () {
|
|
sinon.assert.callOrder(handler1, handler2, handler3);
|
|
done();
|
|
}, 15);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("2.2.6.2: If/when `promise` is rejected, all respective `onRejected` callbacks must execute in the " +
|
|
"order of their originating calls to `then`.", function () {
|
|
describe("multiple boring rejection handlers", function () {
|
|
testRejected(sentinel, function (promise, done) {
|
|
var handler1 = sinon.stub().returns(other);
|
|
var handler2 = sinon.stub().returns(other);
|
|
var handler3 = sinon.stub().returns(other);
|
|
|
|
var spy = sinon.spy();
|
|
promise.then(spy, handler1);
|
|
promise.then(spy, handler2);
|
|
promise.then(spy, handler3);
|
|
|
|
promise.then(null, function (reason) {
|
|
assert.strictEqual(reason, sentinel);
|
|
|
|
sinon.assert.calledWith(handler1, sinon.match.same(sentinel));
|
|
sinon.assert.calledWith(handler2, sinon.match.same(sentinel));
|
|
sinon.assert.calledWith(handler3, sinon.match.same(sentinel));
|
|
sinon.assert.notCalled(spy);
|
|
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("multiple rejection handlers, one of which throws", function () {
|
|
testRejected(sentinel, function (promise, done) {
|
|
var handler1 = sinon.stub().returns(other);
|
|
var handler2 = sinon.stub().throws(other);
|
|
var handler3 = sinon.stub().returns(other);
|
|
|
|
var spy = sinon.spy();
|
|
promise.then(spy, handler1);
|
|
promise.then(spy, handler2).caught(function(){});
|
|
promise.then(spy, handler3);
|
|
|
|
promise.then(null, function (reason) {
|
|
assert.strictEqual(reason, sentinel);
|
|
|
|
sinon.assert.calledWith(handler1, sinon.match.same(sentinel));
|
|
sinon.assert.calledWith(handler2, sinon.match.same(sentinel));
|
|
sinon.assert.calledWith(handler3, sinon.match.same(sentinel));
|
|
sinon.assert.notCalled(spy);
|
|
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("results in multiple branching chains with their own fulfillment values", function () {
|
|
testRejected(sentinel, function (promise, done) {
|
|
var semiDone = callbackAggregator(3, done);
|
|
|
|
promise.then(null, function () {
|
|
return sentinel;
|
|
}).then(function (value) {
|
|
assert.strictEqual(value, sentinel);
|
|
semiDone();
|
|
});
|
|
|
|
promise.then(null, function () {
|
|
throw sentinel2;
|
|
}).then(null, function (reason) {
|
|
assert.strictEqual(reason, sentinel2);
|
|
semiDone();
|
|
});
|
|
|
|
promise.then(null, function () {
|
|
return sentinel3;
|
|
}).then(function (value) {
|
|
assert.strictEqual(value, sentinel3);
|
|
semiDone();
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("`onRejected` handlers are called in the original order", function () {
|
|
testRejected(dummy, function (promise, done) {
|
|
var handler1 = sinon.spy(function handler1() {});
|
|
var handler2 = sinon.spy(function handler2() {});
|
|
var handler3 = sinon.spy(function handler3() {});
|
|
|
|
promise.then(null, handler1);
|
|
promise.then(null, handler2);
|
|
promise.then(null, handler3);
|
|
|
|
promise.then(null, function () {
|
|
sinon.assert.callOrder(handler1, handler2, handler3);
|
|
done();
|
|
});
|
|
});
|
|
|
|
describe("even when one handler is added inside another handler", function () {
|
|
testRejected(dummy, function (promise, done) {
|
|
var handler1 = sinon.spy(function handler1() {});
|
|
var handler2 = sinon.spy(function handler2() {});
|
|
var handler3 = sinon.spy(function handler3() {});
|
|
|
|
promise.then(null, function () {
|
|
handler1();
|
|
promise.then(null, handler3);
|
|
});
|
|
promise.then(null, handler2);
|
|
|
|
promise.then(null, function () {
|
|
// Give implementations a bit of extra time to flush their internal queue, if necessary.
|
|
setTimeout(function () {
|
|
sinon.assert.callOrder(handler1, handler2, handler3);
|
|
done();
|
|
}, 15);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|