Skip to content

Instantly share code, notes, and snippets.

@skaegi
Last active December 12, 2015 07:28
Show Gist options
  • Save skaegi/4736504 to your computer and use it in GitHub Desktop.
Save skaegi/4736504 to your computer and use it in GitHub Desktop.
Promises A+ - Cancel Tests
/*global describe specify require global*/
"use strict";
var assert = require("assert");
var adapter = global.adapter;
var fulfilled = adapter.fulfilled;
var rejected = adapter.rejected;
var pending = adapter.pending;
var sentinel = {
sentinel: "sentinel"
}; // a sentinel fulfillment value to test for with strict equality
var dummy = {
dummy: "dummy"
}; // we fulfill or reject with this when we don't intend to test against it
function isCancellationError(error) {
return error instanceof Error && error.name === "Cancel";
}
describe("Cancel.1: If the promise is not pending the 'cancel' call has no effect.", function() {
specify("already-fulfilled", function(done) {
var promise = fulfilled(sentinel);
var result = promise.then(function(value) {
assert.strictEqual(value, sentinel);
done();
}, assert.fail);
promise.cancel();
return result;
});
specify("already-rejected", function(done) {
var promise = rejected(sentinel);
var result = promise.then(assert.fail, function(reason) {
assert.strictEqual(reason, sentinel);
done();
});
promise.cancel();
return result;
});
});
describe("Cancel.2: If the promise is pending and waiting on another promise the 'cancel' call should instead propagate to this parent promise but MUST be done asynchronously after this call returns.", function() {
specify("parent pending", function(done) {
var parentCancelled = false;
var tuple = pending();
var parent = tuple.promise;
parent.then(assert.fail, function(reason) {
assert.ok(isCancellationError(reason));
parentCancelled = true;
throw reason;
});
var promise = parent.then(assert.fail, function(reason) {
assert.ok(isCancellationError(reason));
assert.ok(parentCancelled);
done();
});
promise.cancel();
return promise;
});
specify("grand parent pending", function(done) {
var grandparentCancelled = false;
var parentCancelled = false;
var uncleCancelled = false;
var tuple = pending();
var grandparent = tuple.promise;
var grandparentCancel = grandparent.cancel.bind(grandparent);
grandparent.cancel = function() {
grandparentCancelled = true;
grandparentCancel();
};
grandparent.then(null, function(reason) {
assert.ok(isCancellationError(reason));
uncleCancelled = true;
throw reason;
});
var parent = grandparent.then(assert.fail, function(reason) {
assert.ok(isCancellationError(reason));
parentCancelled = true;
throw reason;
});
var promise = parent.then(assert.fail, function(reason) {
assert.ok(isCancellationError(reason));
assert.ok(grandparentCancelled);
assert.ok(uncleCancelled);
assert.ok(parentCancelled);
done();
});
promise.cancel();
return promise;
});
});
describe("Cancel.3: Otherwise the promise is rejected with a CancellationError.", function() {
specify("simple", function(done) {
var promise = pending().promise;
var result = promise.then(assert.fail, function(reason) {
assert.ok(isCancellationError(reason));
done();
});
promise.cancel();
return result;
});
specify("then fulfilled assumption", function(done) {
var assumedCancelled = false;
var assumed = pending().promise;
var assumedCancel = assumed.cancel.bind(assumed);
assumed.cancel = function() {
assumedCancelled = true;
assumedCancel();
};
var promise = fulfilled().then(function() {
return assumed;
}).then(assert.fail, function(reason) {
assert.ok(isCancellationError(reason));
assert.ok(assumedCancelled);
done();
});
promise.cancel();
return promise;
});
specify("then chain-fulfilled assumption", function(done) {
var assumedCancelled = false;
var assumed = pending().promise;
var assumedCancel = assumed.cancel.bind(assumed);
assumed.cancel = function() {
assumedCancelled = true;
assumedCancel();
};
var promise = fulfilled().then(function() {
return fulfilled();
}).then(function() {
return assumed;
}).then(assert.fail, function(reason) {
assert.ok(isCancellationError(reason));
assert.ok(assumedCancelled);
done();
});
promise.cancel();
return promise;
});
specify("then rejected assumption", function(done) {
var assumedCancelled = false;
var assumed = pending().promise;
assumed.then(null, function(reason) {
assert.ok(isCancellationError(reason));
assumedCancelled = true;
});
var promise = rejected().then(null, function() {
return assumed;
}).then(assert.fail, function(reason) {
assert.ok(isCancellationError(reason));
assert.ok(assumedCancelled);
done();
});
promise.cancel();
return promise;
});
specify("then chain-rejected assumption", function(done) {
var assumedCancelled = false;
var assumed = pending().promise;
var assumedCancel = assumed.cancel.bind(assumed);
assumed.cancel = function() {
assumedCancelled = true;
assumedCancel();
};
var promise = rejected().then(null, function() {
return rejected();
}).then(null, function() {
return assumed;
}).then(assert.fail, function(reason) {
assert.ok(isCancellationError(reason));
assert.ok(assumedCancelled);
done();
});
promise.cancel();
return promise;
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment