Skip to content

Commit

Permalink
[#2834] module.initialize() now defers publish calls
Browse files Browse the repository at this point in the history
It will now wait until all modules have loaded before publishing
the events to ensure that all modules have a chance of receiving
them regardless of order.
  • Loading branch information
aron committed Aug 13, 2012
1 parent 42b3816 commit 092d257
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 0 deletions.
6 changes: 6 additions & 0 deletions ckan/public/base/javascript/module.js
Expand Up @@ -257,6 +257,9 @@ this.ckan = this.ckan || {};
module.initialize = function () {
var registry = module.registry;

// Start caching all calls to .publish() until all modules are loaded.
ckan.pubsub.enqueue();

jQuery('[data-module]', document.body).each(function (index, element) {
var names = jQuery.trim(this.getAttribute(MODULE_PREFIX)).split(' ');

Expand All @@ -269,6 +272,9 @@ this.ckan = this.ckan || {};
});
});

// Now trigger all .publish() calls so that all modules receive them.
ckan.pubsub.dequeue();

return module;
};

Expand Down
30 changes: 30 additions & 0 deletions ckan/public/base/test/spec/module.spec.js
Expand Up @@ -87,6 +87,36 @@ describe('ckan.module(id, properties|callback)', function () {
assert.calledWith(this.target, this.test1, this.element4[0]);
assert.calledWith(this.target, this.test2, this.element4[0]);
});

it('should defer all published events untill all modules have loaded', function () {
var pubsub = ckan.pubsub;
var callbacks = [];

// Ensure each module is loaded. Three in total.
ckan.module.registry = {
test1: function () {},
test2: function () {}
};

// Call a function to publish and subscribe to an event on each instance.
this.target.restore();
this.target = sinon.stub(ckan.module, 'createInstance', function () {
var callback = sinon.spy();

pubsub.publish('test');
pubsub.subscribe('test', callback);

callbacks.push(callback);
});

ckan.module.initialize();

// Ensure that all subscriptions received all messages.
assert.ok(callbacks.length, 'no callbacks were created');
jQuery.each(callbacks, function () {
assert.calledThrice(this);
});
});
});

describe('.createInstance(Module, element)', function () {
Expand Down
92 changes: 92 additions & 0 deletions ckan/public/base/test/spec/pubsub.spec.js
@@ -0,0 +1,92 @@
describe('ckan.pubsub', function () {
beforeEach(function () {
ckan.pubsub.events = jQuery({});
ckan.pubsub.queue = [];
});

describe('.enqueue()', function () {
beforeEach(function () {
this.target = sinon.spy();
});

it('should defer callbacks for published events until later', function () {
ckan.pubsub.subscribe('change', this.target);
ckan.pubsub.enqueue();
ckan.pubsub.publish('change');

assert.notCalled(this.target);
});

it('should add the published calls to the .queue', function () {
var queue = ckan.pubsub.queue;

ckan.pubsub.enqueue();

ckan.pubsub.publish('change');
assert.equal(queue.length, 1);

ckan.pubsub.publish('change');
assert.equal(queue.length, 2);

ckan.pubsub.publish('change');
assert.equal(queue.length, 3);
});
});

describe('.dequeue()', function () {
beforeEach(function () {
ckan.pubsub.queue = [
['change'],
['change', 'arg1', 'arg2'],
['update', 'arg1']
];

this.target1 = sinon.spy();
this.target2 = sinon.spy();
this.target3 = sinon.spy();

ckan.pubsub.subscribe('change', this.target1);
ckan.pubsub.subscribe('change', this.target2);
ckan.pubsub.subscribe('update', this.target3);
});

it('should publish all queued callbacks', function () {
ckan.pubsub.dequeue();

assert.calledTwice(this.target1);
assert.calledWith(this.target1, 'arg1', 'arg2');

assert.calledTwice(this.target2);
assert.calledWith(this.target2, 'arg1', 'arg2');

assert.calledOnce(this.target3);
});

it('should set the queue to null to allow new events to be published', function () {
ckan.pubsub.dequeue();
assert.isNull(ckan.pubsub.queue);
});

it('should not block new events from being published', function () {
var pubsub = ckan.pubsub;

var second = sinon.spy();
var third = sinon.spy();

pubsub.enqueue();
pubsub.subscribe('first', function () {
pubsub.publish('third');
});
pubsub.subscribe('second', second);
pubsub.subscribe('third', third);

pubsub.publish('first');
pubsub.publish('second');

pubsub.dequeue();

assert.called(second);
assert.called(third);
});
});
});

0 comments on commit 092d257

Please sign in to comment.