From 671f7c3fe4dac2ac8609e91f1b454b3514ce6649 Mon Sep 17 00:00:00 2001 From: Paolo Scanferla Date: Sun, 5 Oct 2014 01:55:50 +0200 Subject: [PATCH] Fixed bug in reEstablishSubscriptions method. --- bower.json | 2 +- dist/asteroid.browser.js | 38 ++++++++++---- dist/asteroid.chrome.js | 38 ++++++++++---- dist/asteroid.cordova.js | 38 ++++++++++---- dist/asteroid.node.js | 38 ++++++++++---- gulpfile.js | 14 +++--- package.json | 34 ++++--------- src/core/subscription.js | 38 ++++++++++---- test/asteroid.unit.js | 92 ++++++++++++++++++++++++++++++---- test/node.html | 2 +- test/unit/subscription.unit.js | 92 ++++++++++++++++++++++++++++++---- 11 files changed, 328 insertions(+), 98 deletions(-) diff --git a/bower.json b/bower.json index fc2c253..dd03f24 100644 --- a/bower.json +++ b/bower.json @@ -29,7 +29,7 @@ "gulpfile.js" ], "dependencies": { - "ddp.js": "~0.5.0", + "ddp.js": "~0.6.0", "q": "1.0.1" } } diff --git a/dist/asteroid.browser.js b/dist/asteroid.browser.js index a57d0af..9e8b961 100644 --- a/dist/asteroid.browser.js +++ b/dist/asteroid.browser.js @@ -1046,10 +1046,10 @@ Asteroid.Set = Set; // Subscription class // //////////////////////// -var Subscription = function (name, params, hash, asteroid) { +var Subscription = function (name, params, fingerprint, asteroid) { this._name = name; this._params = params; - this._hash = hash; + this._fingerprint = fingerprint; this._asteroid = asteroid; // Subscription promises this._ready = Q.defer(); @@ -1064,7 +1064,7 @@ Subscription.constructor = Subscription; Subscription.prototype.stop = function () { this._asteroid.ddp.unsub(this.id); - delete this._asteroid._subscriptionsCache[this._hash]; + delete this._asteroid._subscriptionsCache[this._fingerprint]; }; Subscription.prototype._onReady = function () { @@ -1073,6 +1073,7 @@ Subscription.prototype._onReady = function () { Subscription.prototype._onStop = function () { delete this._asteroid.subscriptions[this.id]; + delete this._asteroid._subscriptionsCache[this._fingerprint]; }; Subscription.prototype._onError = function (err) { @@ -1080,6 +1081,7 @@ Subscription.prototype._onError = function (err) { this._ready.reject(err); } delete this._asteroid.subscriptions[this.id]; + delete this._asteroid._subscriptionsCache[this._fingerprint]; }; @@ -1094,23 +1096,41 @@ Asteroid.prototype.subscribe = function (name /* , param1, param2, ... */) { // Collect arguments into array var args = Array.prototype.slice.call(arguments); // Hash the arguments to get a key for _subscriptionsCache - var hash = JSON.stringify(args); + var fingerprint = JSON.stringify(args); // Only subscribe if there is no cached subscription - if (!this._subscriptionsCache[hash]) { + if (!this._subscriptionsCache[fingerprint]) { // Get the parameters of the subscription var params = args.slice(1); - var sub = new Subscription(name, params, hash, this); - this._subscriptionsCache[hash] = sub; + // Subscribe + var sub = new Subscription( + name, + params, + fingerprint, + this + ); + this._subscriptionsCache[sub._fingerprint] = sub; this.subscriptions[sub.id] = sub; } - return this._subscriptionsCache[hash]; + return this._subscriptionsCache[fingerprint]; }; Asteroid.prototype._reEstablishSubscriptions = function () { var subs = this.subscriptions; + var oldSub; + var newSub; for (var id in subs) { if (subs.hasOwnProperty(id)) { - subs[id] = new Subscription(subs[id]._name, subs[id]._params, this); + oldSub = subs[id]; + newSub = new Subscription( + oldSub._name, + oldSub._params, + oldSub._fingerprint, + this + ); + delete this.subscriptions[oldSub.id]; + delete this._subscriptionsCache[oldSub._fingerprint]; + this.subscriptions[newSub.id] = newSub; + this._subscriptionsCache[newSub._fingerprint] = newSub; } } }; diff --git a/dist/asteroid.chrome.js b/dist/asteroid.chrome.js index f62028b..0bda7d0 100644 --- a/dist/asteroid.chrome.js +++ b/dist/asteroid.chrome.js @@ -1046,10 +1046,10 @@ Asteroid.Set = Set; // Subscription class // //////////////////////// -var Subscription = function (name, params, hash, asteroid) { +var Subscription = function (name, params, fingerprint, asteroid) { this._name = name; this._params = params; - this._hash = hash; + this._fingerprint = fingerprint; this._asteroid = asteroid; // Subscription promises this._ready = Q.defer(); @@ -1064,7 +1064,7 @@ Subscription.constructor = Subscription; Subscription.prototype.stop = function () { this._asteroid.ddp.unsub(this.id); - delete this._asteroid._subscriptionsCache[this._hash]; + delete this._asteroid._subscriptionsCache[this._fingerprint]; }; Subscription.prototype._onReady = function () { @@ -1073,6 +1073,7 @@ Subscription.prototype._onReady = function () { Subscription.prototype._onStop = function () { delete this._asteroid.subscriptions[this.id]; + delete this._asteroid._subscriptionsCache[this._fingerprint]; }; Subscription.prototype._onError = function (err) { @@ -1080,6 +1081,7 @@ Subscription.prototype._onError = function (err) { this._ready.reject(err); } delete this._asteroid.subscriptions[this.id]; + delete this._asteroid._subscriptionsCache[this._fingerprint]; }; @@ -1094,23 +1096,41 @@ Asteroid.prototype.subscribe = function (name /* , param1, param2, ... */) { // Collect arguments into array var args = Array.prototype.slice.call(arguments); // Hash the arguments to get a key for _subscriptionsCache - var hash = JSON.stringify(args); + var fingerprint = JSON.stringify(args); // Only subscribe if there is no cached subscription - if (!this._subscriptionsCache[hash]) { + if (!this._subscriptionsCache[fingerprint]) { // Get the parameters of the subscription var params = args.slice(1); - var sub = new Subscription(name, params, hash, this); - this._subscriptionsCache[hash] = sub; + // Subscribe + var sub = new Subscription( + name, + params, + fingerprint, + this + ); + this._subscriptionsCache[sub._fingerprint] = sub; this.subscriptions[sub.id] = sub; } - return this._subscriptionsCache[hash]; + return this._subscriptionsCache[fingerprint]; }; Asteroid.prototype._reEstablishSubscriptions = function () { var subs = this.subscriptions; + var oldSub; + var newSub; for (var id in subs) { if (subs.hasOwnProperty(id)) { - subs[id] = new Subscription(subs[id]._name, subs[id]._params, this); + oldSub = subs[id]; + newSub = new Subscription( + oldSub._name, + oldSub._params, + oldSub._fingerprint, + this + ); + delete this.subscriptions[oldSub.id]; + delete this._subscriptionsCache[oldSub._fingerprint]; + this.subscriptions[newSub.id] = newSub; + this._subscriptionsCache[newSub._fingerprint] = newSub; } } }; diff --git a/dist/asteroid.cordova.js b/dist/asteroid.cordova.js index 41e9114..fb7ba48 100644 --- a/dist/asteroid.cordova.js +++ b/dist/asteroid.cordova.js @@ -1046,10 +1046,10 @@ Asteroid.Set = Set; // Subscription class // //////////////////////// -var Subscription = function (name, params, hash, asteroid) { +var Subscription = function (name, params, fingerprint, asteroid) { this._name = name; this._params = params; - this._hash = hash; + this._fingerprint = fingerprint; this._asteroid = asteroid; // Subscription promises this._ready = Q.defer(); @@ -1064,7 +1064,7 @@ Subscription.constructor = Subscription; Subscription.prototype.stop = function () { this._asteroid.ddp.unsub(this.id); - delete this._asteroid._subscriptionsCache[this._hash]; + delete this._asteroid._subscriptionsCache[this._fingerprint]; }; Subscription.prototype._onReady = function () { @@ -1073,6 +1073,7 @@ Subscription.prototype._onReady = function () { Subscription.prototype._onStop = function () { delete this._asteroid.subscriptions[this.id]; + delete this._asteroid._subscriptionsCache[this._fingerprint]; }; Subscription.prototype._onError = function (err) { @@ -1080,6 +1081,7 @@ Subscription.prototype._onError = function (err) { this._ready.reject(err); } delete this._asteroid.subscriptions[this.id]; + delete this._asteroid._subscriptionsCache[this._fingerprint]; }; @@ -1094,23 +1096,41 @@ Asteroid.prototype.subscribe = function (name /* , param1, param2, ... */) { // Collect arguments into array var args = Array.prototype.slice.call(arguments); // Hash the arguments to get a key for _subscriptionsCache - var hash = JSON.stringify(args); + var fingerprint = JSON.stringify(args); // Only subscribe if there is no cached subscription - if (!this._subscriptionsCache[hash]) { + if (!this._subscriptionsCache[fingerprint]) { // Get the parameters of the subscription var params = args.slice(1); - var sub = new Subscription(name, params, hash, this); - this._subscriptionsCache[hash] = sub; + // Subscribe + var sub = new Subscription( + name, + params, + fingerprint, + this + ); + this._subscriptionsCache[sub._fingerprint] = sub; this.subscriptions[sub.id] = sub; } - return this._subscriptionsCache[hash]; + return this._subscriptionsCache[fingerprint]; }; Asteroid.prototype._reEstablishSubscriptions = function () { var subs = this.subscriptions; + var oldSub; + var newSub; for (var id in subs) { if (subs.hasOwnProperty(id)) { - subs[id] = new Subscription(subs[id]._name, subs[id]._params, this); + oldSub = subs[id]; + newSub = new Subscription( + oldSub._name, + oldSub._params, + oldSub._fingerprint, + this + ); + delete this.subscriptions[oldSub.id]; + delete this._subscriptionsCache[oldSub._fingerprint]; + this.subscriptions[newSub.id] = newSub; + this._subscriptionsCache[newSub._fingerprint] = newSub; } } }; diff --git a/dist/asteroid.node.js b/dist/asteroid.node.js index c7623b6..f0fb674 100644 --- a/dist/asteroid.node.js +++ b/dist/asteroid.node.js @@ -1040,10 +1040,10 @@ Asteroid.Set = Set; // Subscription class // //////////////////////// -var Subscription = function (name, params, hash, asteroid) { +var Subscription = function (name, params, fingerprint, asteroid) { this._name = name; this._params = params; - this._hash = hash; + this._fingerprint = fingerprint; this._asteroid = asteroid; // Subscription promises this._ready = Q.defer(); @@ -1058,7 +1058,7 @@ Subscription.constructor = Subscription; Subscription.prototype.stop = function () { this._asteroid.ddp.unsub(this.id); - delete this._asteroid._subscriptionsCache[this._hash]; + delete this._asteroid._subscriptionsCache[this._fingerprint]; }; Subscription.prototype._onReady = function () { @@ -1067,6 +1067,7 @@ Subscription.prototype._onReady = function () { Subscription.prototype._onStop = function () { delete this._asteroid.subscriptions[this.id]; + delete this._asteroid._subscriptionsCache[this._fingerprint]; }; Subscription.prototype._onError = function (err) { @@ -1074,6 +1075,7 @@ Subscription.prototype._onError = function (err) { this._ready.reject(err); } delete this._asteroid.subscriptions[this.id]; + delete this._asteroid._subscriptionsCache[this._fingerprint]; }; @@ -1088,23 +1090,41 @@ Asteroid.prototype.subscribe = function (name /* , param1, param2, ... */) { // Collect arguments into array var args = Array.prototype.slice.call(arguments); // Hash the arguments to get a key for _subscriptionsCache - var hash = JSON.stringify(args); + var fingerprint = JSON.stringify(args); // Only subscribe if there is no cached subscription - if (!this._subscriptionsCache[hash]) { + if (!this._subscriptionsCache[fingerprint]) { // Get the parameters of the subscription var params = args.slice(1); - var sub = new Subscription(name, params, hash, this); - this._subscriptionsCache[hash] = sub; + // Subscribe + var sub = new Subscription( + name, + params, + fingerprint, + this + ); + this._subscriptionsCache[sub._fingerprint] = sub; this.subscriptions[sub.id] = sub; } - return this._subscriptionsCache[hash]; + return this._subscriptionsCache[fingerprint]; }; Asteroid.prototype._reEstablishSubscriptions = function () { var subs = this.subscriptions; + var oldSub; + var newSub; for (var id in subs) { if (subs.hasOwnProperty(id)) { - subs[id] = new Subscription(subs[id]._name, subs[id]._params, this); + oldSub = subs[id]; + newSub = new Subscription( + oldSub._name, + oldSub._params, + oldSub._fingerprint, + this + ); + delete this.subscriptions[oldSub.id]; + delete this._subscriptionsCache[oldSub._fingerprint]; + this.subscriptions[newSub.id] = newSub; + this._subscriptionsCache[newSub._fingerprint] = newSub; } } }; diff --git a/gulpfile.js b/gulpfile.js index 2555b2e..a1e1a6e 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -5,7 +5,7 @@ var crypto = require("crypto"); var fs = require("fs"); var gulp = require("gulp"); -var plugins = require("gulp-load-plugins")(); +var concat = require("gulp-concat"); var http = require("http"); var _ = require("lodash"); var mkdirp = require("mkdirp"); @@ -36,7 +36,7 @@ var buildBrowser = function () { "src/platforms/browser/*.js", "src/platforms/browser/wrapper/tail.js" ]) - .pipe(plugins.concat("asteroid.browser.js")) + .pipe(concat("asteroid.browser.js")) .pipe(gulp.dest("dist/")) .on("end", function () { deferred.resolve(); @@ -59,7 +59,7 @@ var buildChrome = function () { "src/platforms/chrome/*.js", "src/platforms/chrome/wrapper/tail.js" ]) - .pipe(plugins.concat("asteroid.chrome.js")) + .pipe(concat("asteroid.chrome.js")) .pipe(gulp.dest("dist/")) .on("end", function () { deferred.resolve(); @@ -82,7 +82,7 @@ var buildCordova = function () { "src/platforms/cordova/*.js", "src/platforms/cordova/wrapper/tail.js" ]) - .pipe(plugins.concat("asteroid.cordova.js")) + .pipe(concat("asteroid.cordova.js")) .pipe(gulp.dest("dist/")) .on("end", function () { deferred.resolve(); @@ -105,7 +105,7 @@ var buildNode = function () { "src/platforms/node/*.js", "src/platforms/node/wrapper/tail.js" ]) - .pipe(plugins.concat("asteroid.node.js")) + .pipe(concat("asteroid.node.js")) .pipe(gulp.dest("dist/")) .on("end", function () { deferred.resolve(); @@ -144,7 +144,7 @@ var buildTests = function () { console.log("Building tests"); var deferred = Q.defer(); gulp.src("test/unit/**/*.unit.js") - .pipe(plugins.concat("asteroid.unit.js")) + .pipe(concat("asteroid.unit.js")) .pipe(gulp.dest("test/")) .on("end", function () { deferred.resolve(); @@ -155,7 +155,7 @@ var buildTests = function () { var runTests = function () { console.log("Running tests"); var deferred = Q.defer(); - exec("mocha test/asteroid.unit.js -R json", function (err, stdout) { + exec("node_modules/mocha/bin/mocha test/asteroid.unit.js -R json", function (err, stdout) { // Construct the html var res; try { diff --git a/package.json b/package.json index 6c8fdad..1931cbf 100644 --- a/package.json +++ b/package.json @@ -22,33 +22,19 @@ }, "homepage": "https://github.com/mondora/asteroid", "devDependencies": { - "coveralls": "^2.10.0", - "faye-websocket": "^0.7.2", - "gulp": "^3.5.6", - "gulp-concat": "^2.2.0", - "gulp-livereload": "^1.3.1", - "gulp-load-plugins": "^0.4.0", - "gulp-mocha": "^0.5.1", - "gulp-open": "^0.2.8", - "gulp-preprocess": "^1.0.1", - "gulp-rename": "^1.2.0", - "gulp-uglify": "^0.2.1", - "istanbul": "^0.2.10", - "karma": "^0.12.14", - "karma-chrome-launcher": "^0.1.3", - "karma-coverage": "^0.2.1", - "karma-firefox-launcher": "^0.1.3", - "karma-mocha": "^0.1.3", - "karma-safari-launcher": "^0.1.1", + "coveralls": "^2.11.2", + "faye-websocket": "^0.7.3", + "gulp": "^3.8.8", + "gulp-concat": "^2.4.1", "lodash": "^2.4.1", "mkdirp": "^0.5.0", - "mocha": "1.18.2", + "mocha": "git+https://github.com/visionmedia/mocha.git", "mocha-lcov-reporter": "0.0.1", - "node-static": "^0.7.3", - "rewire": "^2.0.1", - "should": "^3.2.0-beta1", - "sinon": "^1.9.0", - "tiny-lr": "0.0.5" + "node-static": "^0.7.6", + "q": "^1.0.1", + "rewire": "^2.1.0", + "should": "^4.0.4", + "sinon": "^1.10.3" }, "dependencies": { "ddp.js": "^0.5.0", diff --git a/src/core/subscription.js b/src/core/subscription.js index 54121c1..8bb23e2 100644 --- a/src/core/subscription.js +++ b/src/core/subscription.js @@ -2,10 +2,10 @@ // Subscription class // //////////////////////// -var Subscription = function (name, params, hash, asteroid) { +var Subscription = function (name, params, fingerprint, asteroid) { this._name = name; this._params = params; - this._hash = hash; + this._fingerprint = fingerprint; this._asteroid = asteroid; // Subscription promises this._ready = Q.defer(); @@ -20,7 +20,7 @@ Subscription.constructor = Subscription; Subscription.prototype.stop = function () { this._asteroid.ddp.unsub(this.id); - delete this._asteroid._subscriptionsCache[this._hash]; + delete this._asteroid._subscriptionsCache[this._fingerprint]; }; Subscription.prototype._onReady = function () { @@ -29,6 +29,7 @@ Subscription.prototype._onReady = function () { Subscription.prototype._onStop = function () { delete this._asteroid.subscriptions[this.id]; + delete this._asteroid._subscriptionsCache[this._fingerprint]; }; Subscription.prototype._onError = function (err) { @@ -36,6 +37,7 @@ Subscription.prototype._onError = function (err) { this._ready.reject(err); } delete this._asteroid.subscriptions[this.id]; + delete this._asteroid._subscriptionsCache[this._fingerprint]; }; @@ -50,23 +52,41 @@ Asteroid.prototype.subscribe = function (name /* , param1, param2, ... */) { // Collect arguments into array var args = Array.prototype.slice.call(arguments); // Hash the arguments to get a key for _subscriptionsCache - var hash = JSON.stringify(args); + var fingerprint = JSON.stringify(args); // Only subscribe if there is no cached subscription - if (!this._subscriptionsCache[hash]) { + if (!this._subscriptionsCache[fingerprint]) { // Get the parameters of the subscription var params = args.slice(1); - var sub = new Subscription(name, params, hash, this); - this._subscriptionsCache[hash] = sub; + // Subscribe + var sub = new Subscription( + name, + params, + fingerprint, + this + ); + this._subscriptionsCache[sub._fingerprint] = sub; this.subscriptions[sub.id] = sub; } - return this._subscriptionsCache[hash]; + return this._subscriptionsCache[fingerprint]; }; Asteroid.prototype._reEstablishSubscriptions = function () { var subs = this.subscriptions; + var oldSub; + var newSub; for (var id in subs) { if (subs.hasOwnProperty(id)) { - subs[id] = new Subscription(subs[id]._name, subs[id]._params, this); + oldSub = subs[id]; + newSub = new Subscription( + oldSub._name, + oldSub._params, + oldSub._fingerprint, + this + ); + delete this.subscriptions[oldSub.id]; + delete this._subscriptionsCache[oldSub._fingerprint]; + this.subscriptions[newSub.id] = newSub; + this._subscriptionsCache[newSub._fingerprint] = newSub; } } }; diff --git a/test/asteroid.unit.js b/test/asteroid.unit.js index d66b071..390a7ae 100644 --- a/test/asteroid.unit.js +++ b/test/asteroid.unit.js @@ -1427,13 +1427,16 @@ describe("The Asteroid.subscribe method", function () { if (e === "changed") ddp.emitChanged = f; if (e === "removed") ddp.emitRemoved = f; }; - ddp.sub = function (n, p, f, s, r) { - ddp.resolve = f; - ddp.stop = s; - ddp.reject = r; - ddp.params = p; - return 0; - }; + ddp.sub = (function () { + var i = 0; + return function (n, p, f, s, r) { + ddp.resolve = f; + ddp.stop = s; + ddp.reject = r; + ddp.params = p; + return i++; + }; + })(); ddp.unsub = sinon.spy(function () { ddp.stop(); }); @@ -1465,8 +1468,10 @@ describe("The Asteroid.subscribe method", function () { it("should save a reference to the subscription", function () { var ceres = new Asteroid("example.com"); - var sub = ceres.subscribe("sub"); - ceres.subscriptions[sub.id].should.equal(sub); + var sub0 = ceres.subscribe("sub0"); + var sub1 = ceres.subscribe("sub1"); + ceres.subscriptions[sub0.id].should.equal(sub0); + ceres.subscriptions[sub1.id].should.equal(sub1); }); describe("should return an object with a ready property, which", function () { @@ -1491,6 +1496,16 @@ describe("The Asteroid.subscribe method", function () { promise.isRejected().should.equal(true); }); + it("if rejected, should clean up all references of the subscription", function () { + var ceres = new Asteroid("example.com"); + var sub = ceres.subscribe("sub"); + var promise = sub.ready; + ceres.ddp.reject(); + promise.isRejected().should.equal(true); + _.isUndefined(ceres.subscriptions[sub.id]).should.equal(true); + _.isUndefined(ceres._subscriptionsCache[sub._fingerprint]).should.equal(true); + }); + }); describe("should return an object with a stop method, which", function () { @@ -1514,6 +1529,7 @@ describe("The Asteroid.subscribe method", function () { ceres.subscriptions[sub.id].should.equal(sub); sub.stop(); _.isUndefined(ceres.subscriptions[sub.id]).should.equal(true); + _.isUndefined(ceres._subscriptionsCache[sub._fingerprint]).should.equal(true); }); }); @@ -1541,7 +1557,7 @@ describe("The Asteroid.subscribe method", function () { sub0.should.equal(sub1); }); - it("should not cache non identical calls", function () { + it("should not cache non-identical calls", function () { var p = {}; var p0 = {a: 0}; var p1 = {a: 1}; @@ -1553,3 +1569,59 @@ describe("The Asteroid.subscribe method", function () { }); }); + +describe("The Asteroid._reEstablishSubscriptions method", function () { + + var tmp; + beforeEach(function () { + var ddpStub = function () { + ddp = {}; + ddp.on = function (e, f) { + if (e === "connected") ddp.emitConnected = f; + if (e === "added") ddp.emitAdded = f; + if (e === "changed") ddp.emitChanged = f; + if (e === "removed") ddp.emitRemoved = f; + }; + ddp.sub = (function () { + var i = 0; + return function (n, p, f, s, r) { + ddp.resolve = f; + ddp.stop = s; + ddp.reject = r; + ddp.params = p; + return i++; + }; + })(); + ddp.unsub = sinon.spy(function () { + ddp.stop(); + }); + return ddp; + }; + if (ENV === "node") { + tmp = glb.Asteroid.__get__("DDP"); + glb.Asteroid.__set__("DDP", ddpStub); + } else { + glb.DDP = ddpStub; + } + }); + + afterEach(function () { + if (ENV === "node") { + glb.Asteroid.__set__("DDP", tmp); + } else { + delete glb.DDP; + } + }); + + it("should replay all active subscriptions", function () { + var ceres = new Asteroid("example.com"); + var sub0 = ceres.subscribe("sub", 0, 1); + var sub1 = ceres.subscribe("sub", 1, 2); + _.keys(ceres.subscriptions).length.should.equal(2); + ceres._reEstablishSubscriptions(); + _.keys(ceres.subscriptions).length.should.equal(2); + _.isUndefined(ceres._subscriptionsCache[sub0._fingerprint]).should.equal(false); + _.isUndefined(ceres._subscriptionsCache[sub1._fingerprint]).should.equal(false); + }); + +}); diff --git a/test/node.html b/test/node.html index 323e646..298f2a7 100644 --- a/test/node.html +++ b/test/node.html @@ -35,5 +35,5 @@ })(); -

Stats

Suites:25

Tests:90

Passes:90

Failures:0

Duration:100


+

Stats

Suites:26

Tests:92

Passes:92

Failures:0

Duration:104


diff --git a/test/unit/subscription.unit.js b/test/unit/subscription.unit.js index 9a63930..a1ee7e4 100644 --- a/test/unit/subscription.unit.js +++ b/test/unit/subscription.unit.js @@ -10,13 +10,16 @@ describe("The Asteroid.subscribe method", function () { if (e === "changed") ddp.emitChanged = f; if (e === "removed") ddp.emitRemoved = f; }; - ddp.sub = function (n, p, f, s, r) { - ddp.resolve = f; - ddp.stop = s; - ddp.reject = r; - ddp.params = p; - return 0; - }; + ddp.sub = (function () { + var i = 0; + return function (n, p, f, s, r) { + ddp.resolve = f; + ddp.stop = s; + ddp.reject = r; + ddp.params = p; + return i++; + }; + })(); ddp.unsub = sinon.spy(function () { ddp.stop(); }); @@ -48,8 +51,10 @@ describe("The Asteroid.subscribe method", function () { it("should save a reference to the subscription", function () { var ceres = new Asteroid("example.com"); - var sub = ceres.subscribe("sub"); - ceres.subscriptions[sub.id].should.equal(sub); + var sub0 = ceres.subscribe("sub0"); + var sub1 = ceres.subscribe("sub1"); + ceres.subscriptions[sub0.id].should.equal(sub0); + ceres.subscriptions[sub1.id].should.equal(sub1); }); describe("should return an object with a ready property, which", function () { @@ -74,6 +79,16 @@ describe("The Asteroid.subscribe method", function () { promise.isRejected().should.equal(true); }); + it("if rejected, should clean up all references of the subscription", function () { + var ceres = new Asteroid("example.com"); + var sub = ceres.subscribe("sub"); + var promise = sub.ready; + ceres.ddp.reject(); + promise.isRejected().should.equal(true); + _.isUndefined(ceres.subscriptions[sub.id]).should.equal(true); + _.isUndefined(ceres._subscriptionsCache[sub._fingerprint]).should.equal(true); + }); + }); describe("should return an object with a stop method, which", function () { @@ -97,6 +112,7 @@ describe("The Asteroid.subscribe method", function () { ceres.subscriptions[sub.id].should.equal(sub); sub.stop(); _.isUndefined(ceres.subscriptions[sub.id]).should.equal(true); + _.isUndefined(ceres._subscriptionsCache[sub._fingerprint]).should.equal(true); }); }); @@ -124,7 +140,7 @@ describe("The Asteroid.subscribe method", function () { sub0.should.equal(sub1); }); - it("should not cache non identical calls", function () { + it("should not cache non-identical calls", function () { var p = {}; var p0 = {a: 0}; var p1 = {a: 1}; @@ -136,3 +152,59 @@ describe("The Asteroid.subscribe method", function () { }); }); + +describe("The Asteroid._reEstablishSubscriptions method", function () { + + var tmp; + beforeEach(function () { + var ddpStub = function () { + ddp = {}; + ddp.on = function (e, f) { + if (e === "connected") ddp.emitConnected = f; + if (e === "added") ddp.emitAdded = f; + if (e === "changed") ddp.emitChanged = f; + if (e === "removed") ddp.emitRemoved = f; + }; + ddp.sub = (function () { + var i = 0; + return function (n, p, f, s, r) { + ddp.resolve = f; + ddp.stop = s; + ddp.reject = r; + ddp.params = p; + return i++; + }; + })(); + ddp.unsub = sinon.spy(function () { + ddp.stop(); + }); + return ddp; + }; + if (ENV === "node") { + tmp = glb.Asteroid.__get__("DDP"); + glb.Asteroid.__set__("DDP", ddpStub); + } else { + glb.DDP = ddpStub; + } + }); + + afterEach(function () { + if (ENV === "node") { + glb.Asteroid.__set__("DDP", tmp); + } else { + delete glb.DDP; + } + }); + + it("should replay all active subscriptions", function () { + var ceres = new Asteroid("example.com"); + var sub0 = ceres.subscribe("sub", 0, 1); + var sub1 = ceres.subscribe("sub", 1, 2); + _.keys(ceres.subscriptions).length.should.equal(2); + ceres._reEstablishSubscriptions(); + _.keys(ceres.subscriptions).length.should.equal(2); + _.isUndefined(ceres._subscriptionsCache[sub0._fingerprint]).should.equal(false); + _.isUndefined(ceres._subscriptionsCache[sub1._fingerprint]).should.equal(false); + }); + +});