From fab0b505c608d2a553c1ca74553e6a433e453a5d Mon Sep 17 00:00:00 2001 From: Carlo Zancanaro Date: Mon, 29 Sep 2014 01:32:38 +1000 Subject: Rename to Scorpion: sounds cooler --- scorpion-tests.js | 359 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 359 insertions(+) create mode 100644 scorpion-tests.js (limited to 'scorpion-tests.js') diff --git a/scorpion-tests.js b/scorpion-tests.js new file mode 100644 index 0000000..0bbe721 --- /dev/null +++ b/scorpion-tests.js @@ -0,0 +1,359 @@ +/*global describe,it,expect,beforeEach,Scorpion, setTimeout*/ + +describe("deferred", function() { + var deferred, promise; + beforeEach(function() { + deferred = Scorpion.defer(); + promise = deferred.promise; + }); + this.timeout(100); + + describe("promise", function() { + it("should have a 'then' method", function() { + expect(promise.then).not.to.equal(undefined); + }); + + it("should be able to chain 'then' methods", function() { + var promise1 = promise; + var promise2 = promise1.then(function(x) { + return x + 1; + }); + var promise3 = promise1.then(function(x) { + return x + 1; + }); + expect(promise1.then).not.to.equal(undefined); + expect(promise2.then).not.to.equal(undefined); + expect(promise3.then).not.to.equal(undefined); + }); + }); + + describe("resolution", function() { + + it("should resolve asynchronously", function(done) { + var hasRun = false; + promise.then(function(val) { + hasRun = true; + return val; + }); + deferred.resolve("value"); + expect(hasRun).to.equal(false); + setTimeout(function() { + expect(hasRun).to.equal(true); + done(); + }); + }); + + it("should propagate through multiple promises", function(done) { + var promise2 = promise.then(function(value) { + return value + 1; + }); + var promise3 = promise2.then(function(value) { + return value + 1; + }); + promise3.then(function(value) { + expect(value).to.equal(3); + done(); + }); + deferred.resolve(1); + }); + + it("should call all registered handlers", function(done) { + var called = 0; + promise.then(function() {called++;}); + promise.then(function() {called++;}); + promise.then(function() {called++;}); + expect(called).to.equal(0); + deferred.resolve(null); + setTimeout(function() { + expect(called).to.equal(3); + done(); + }); + }); + + it("should call handlers, even when added after resolution", function(done) { + deferred.resolve(null); + promise.then(function() { + done(); + }); + }); + + it("should not allow multiple resolution", function() { + deferred.resolve(1); + expect(function() { + deferred.resolve(2); + }).to.throw(); + }); + + it("should not allow rejecting after resolving", function() { + deferred.resolve(1); + expect(function() { + deferred.reject(2); + }).to.throw(); + }); + + it("should handle a returned promise by 'unwrapping' it", function(done) { + promise.then(function(value) { + var deferred = Scorpion.defer(); + deferred.resolve(value + 1); + return deferred.promise; + }).then(function(value) { + try { + expect(value).to.equal(2); + done(); + } catch (e) { + done(e); + } + }); + deferred.resolve(1); + }); + }); + + describe("rejection", function() { + it("should reject asynchronously", function(done) { + var hasRun = false; + promise.then(null, function(val) { + hasRun = true; + return val; + }); + deferred.reject("value"); + expect(hasRun).to.equal(false); + setTimeout(function() { + expect(hasRun).to.equal(true); + done(); + }); + }); + + + it("should be turned into resolution by a handler", function(done) { + var promise2 = promise.then(function(value) { + return value + 1; + }, function(value) { + return value + 100; + }); + promise2.then(function(value) { + try { + expect(value).to.equal(101); + done(); + } catch (e) { + done(e); + } + }); + deferred.reject(1); + }); + + it("should call all registered handlers", function(done) { + var called = 0; + promise.then(null, function() {called++;}); + promise.then(null, function() {called++;}); + promise.then(null, function() {called++;}); + expect(called).to.equal(0); + deferred.reject(null); + setTimeout(function() { + expect(called).to.equal(3); + done(); + }); + }); + + it("should not allow multiple rejection", function() { + deferred.reject(1); + expect(function() { + deferred.reject(2); + }).to.throw(); + }); + + it("should not allow resolving after rejecting", function() { + deferred.reject(1); + expect(function() { + deferred.resolve(2); + }).to.throw(); + }); + + it("should call handlers, even when added after resolution", function(done) { + deferred.reject(null); + promise.then(null, function() { + done(); + }); + }); + + it("should handle a returned promise by 'unwrapping' in the error case", function(done) { + promise.then(function(value) { + var deferred = Scorpion.defer(); + deferred.reject(value + 1); + return deferred.promise; + }).then(null, function(value) { + try { + expect(value).to.equal(2); + done(); + } catch (e) { + done(e); + } + }); + deferred.resolve(1); + }); + }); + + describe("waitForAll", function() { + it("should resolve with an array if all successful", function(done) { + var d1 = Scorpion.defer(), + d2 = Scorpion.defer(), + d3 = Scorpion.defer(); + Scorpion + .waitForAll([d1.promise, d2.promise, d3.promise]) + .then(function(values) { + if (values.length == 3 && + values[0] === 0 && + values[1] === 1 && + values[2] === 2) { + done(); + } else { + done(new Error("Error in resolved result: " + values)); + } + }, done); + d1.resolve(0); + d2.resolve(1); + d3.resolve(2); + }); + + it("should reject with an object of successes/errors if any fail", function(done) { + var d1 = Scorpion.defer(), + d2 = Scorpion.defer(), + d3 = Scorpion.defer(); + Scorpion + .waitForAll([d1.promise, d2.promise, d3.promise]) + .then(function(values) { + done(new Error("incorrectly resolved promise")); + }, function(e) { + if (e.errors && e.values && + e.values[0] === 0 && + e.values[1] === 1 && + e.errors[2] === 2) { + done(); + } else { + done(new Error("incorrect reject value")); + } + }); + d1.resolve(0); + d2.resolve(1); + d3.reject(2); + }); + }); +}); + +describe("injector", function() { + var injector, valuePlugin; + beforeEach(function() { + valuePlugin = new Scorpion.ValuePlugin(); + injector = new Scorpion([valuePlugin]); + }); + this.timeout(100); + + describe("value registration and retrieval", function() { + it("works", function(done) { + injector.register("a", function(){return "the value of a";}); + injector.get("a").then(function(value){ + if (value == "the value of a") + done(); + else + done(new Error("incorrect value for a (" + value + ")")); + }, done); + }); + + it("with dependencies works", function(done) { + injector + .register("a", function(){return "the value of a";}) + .register("b", ["a", function(a){return a.replace(/a/g, "b");}]); + injector.get("b").then(function(value){ + if (value == "the vblue of b") + done(); + else + done(new Error("incorrect value for b (" + value + ")")); + }, done); + }); + }); + + describe("destroy handlers", function() { + it("work with single gets", function(done) { + injector.register("a", function(){return "a";}); + expect("a" in valuePlugin.values).to.equal(false); + var result = injector.get("a"); + result.then(function() { + if ("a" in valuePlugin.values) { + result.destroy().then(function() { + if ("a" in valuePlugin.values) { + done(new Error("Value found for a after destruction")); + } else { + done(); + } + }); + } else { + done(new Error("No value found for a")); + } + }, done); + }); + + it("works with multiple gets", function(done) { + injector.register("a", function(){return "a";}); + expect("a" in valuePlugin.values).to.equal(false); + var result = [injector.get("a"), injector.get("a"), injector.get("a")]; + result[1].destroy(); + result[2].destroy(); + result[0].then(function() { + if ("a" in valuePlugin.values) { + result[0].destroy().then(function() { + if ("a" in valuePlugin.values) { + done(new Error("Value found for a after destruction")); + } else { + done(); + } + }); + } else { + done(new Error("No value found for a")); + } + }, done); + }); + + it("works through dependencies", function(done) { + injector + .register("a", function(){return "a";}) + .register("b", ["a", function(a){return a + "b";}]); + expect("a" in valuePlugin.values).to.equal(false); + var result = injector.get("b"); + result.then(function() { + if ("a" in valuePlugin.values) { + result.destroy().then(function() { + if ("a" in valuePlugin.values) { + done(new Error("Value found for a after destruction")); + } else { + done(); + } + }); + } else { + done(new Error("No value found for a")); + } + }, done); + }); + }); + + describe("cyclic dependency detection", function() { + it("detects simple cycles", function(done) { + injector.register("a", ["b", function(b) {return b;}]); + injector.register("b", ["a", function(a) {return a;}]); + injector.get("a").then(function() { + done(new Error("Promise should have been rejected")); + }, function(e) { + done(); + }); + }); + + it("detects cycles with intermediate nodes", function(done) { + injector.register("a", ["c", function(c) {return c;}]); + injector.register("b", ["a", function(a) {return a;}]); + injector.register("c", ["b", function(b) {return b;}]); + injector.get("a").then(function() { + done(new Error("Promise should have been rejected")); + }, function(e) { + done(); + }); + }); + }); +}); -- cgit v1.2.3