Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get default data #49

Merged
merged 6 commits into from
Aug 20, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/ListenerMixin.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
var _ = require('./utils');
module.exports = {

/**
Expand All @@ -16,10 +17,13 @@ module.exports = {
* @param {Action|Store} listenable An Action or Store that should be
* listened to.
* @param {Function} callback The callback to register as event handler
* @param {Function} defaultCallback The callback to register as default handler
*/
listenTo: function(listenable, callback) {
listenTo: function(listenable, callback, defaultCallback) {
var unsubscribe = listenable.listen(callback, this);
this.subscriptions.push(unsubscribe);

_.handleDefaultCallback(this, listenable, defaultCallback);
},

componentWillUnmount: function() {
Expand Down
3 changes: 2 additions & 1 deletion src/createStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module.exports = function(definition) {
}
}
_.extend(Store.prototype, definition);
Store.prototype.listenTo = function(listenable, callback) {
Store.prototype.listenTo = function(listenable, callback, defaultCallback) {
if (listenable === this) {
throw Error("Store is not able to listen to itself");
}
Expand All @@ -26,6 +26,7 @@ module.exports = function(definition) {
if (this.hasListener(listenable)) {
throw Error("Store cannot listen to this listenable because of circular loop");
}
_.handleDefaultCallback(this, listenable, defaultCallback);
this.registered.push(listenable);
return listenable.listen(callback, this);
};
Expand Down
23 changes: 18 additions & 5 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
* order to remove the dependency
*/

var isObject = module.exports.isObject = function(obj) {
var isObject = exports.isObject = function(obj) {
var type = typeof obj;
return type === 'function' || type === 'object' && !!obj;
};

module.exports.extend = function(obj) {
exports.extend = function(obj) {
if (!isObject(obj)) {
return obj;
}
Expand All @@ -22,11 +22,24 @@ module.exports.extend = function(obj) {
return obj;
};

module.exports.isFunction = function(value) {
var isFunction = exports.isFunction = function(value) {
return typeof value === 'function';
};

module.exports.EventEmitter = require('eventemitter3');
module.exports.nextTick = function(callback) {
exports.EventEmitter = require('eventemitter3');
exports.nextTick = function(callback) {
setTimeout(callback, 0);
};

exports.handleDefaultCallback = function (listener, listenable, defaultCallback) {
if (defaultCallback && isFunction(defaultCallback)) {
if (listenable.getDefaultData && isFunction(listenable.getDefaultData)) {
data = listenable.getDefaultData();
if (data && data.then && isFunction(data.then)) {
data.then(defaultCallback.bind(listener));
} else {
defaultCallback.bind(listener)(data);
}
}
}
};
44 changes: 41 additions & 3 deletions test/ListenerMixin.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ chai.use(require('chai-as-promised'));
describe('Managing subscriptions via ListenerMixin', function() {
var component,
action,
promise;
promise,
store;

beforeEach(function() {
// simulate ReactJS component instantiation and mounting
Expand Down Expand Up @@ -51,10 +52,47 @@ describe('Managing subscriptions via ListenerMixin', function() {
action(1337, 'ninja');

setTimeout(function() {
assert.equal(resolved, false);
done();
assert.equal(resolved, false);
done();
}, 200);
});
});

describe('get default data', function () {
beforeEach(function() {
component.componentWillUnmount();
});
function mountComponent() {
component.componentWillMount();
promise = Q.Promise(function(resolve) {
var setData = function () {
resolve(Array.prototype.slice.call(arguments, 0));
};
component.listenTo(store, setData, setData);
});
}
it('should get default data from getDefaultData()', function () {
store = Reflux.createStore({
getDefaultData: function () {
return 'default data';
}
});
mountComponent();
return assert.eventually.equal(promise, 'default data');
});
it('should get default data from getDefaultData() returned promise', function () {
store = Reflux.createStore({
getDefaultData: function () {
return Q.Promise(function (resolve) {
setTimeout(function () {
resolve('default data');
}, 20);
});
}
});
mountComponent();
return assert.eventually.equal(promise, 'default data');
});
});

});
74 changes: 74 additions & 0 deletions test/creatingStores.spec.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
var chai = require('chai'),
assert = chai.assert,
Reflux = require('../src'),
_ = require('../src/utils'),
Q = require('q');

chai.use(require('chai-as-promised'));
Expand Down Expand Up @@ -108,4 +109,77 @@ describe('Creating stores', function() {
});
});

describe('with one store listening to another store', function() {
var action,
baseDefinition;

beforeEach(function () {
action = Reflux.createAction();
baseDefinition = {
init: function() {
this.listenTo(action, this.actionCalled);
},
actionCalled: function() {
var args = Array.prototype.slice.call(arguments, 0);
this.trigger(args);
}
};
});

function createPromiseForTest(store) {
return Q.Promise(function(resolve) {
var storeTriggered = function (args) {
args = args.map(function (arg) {
return '[...] ' + arg;
});
this.trigger(args);
resolve(args);
};
Reflux.createStore({
init: function() {
this.listenTo(store, this.storeTriggered, storeTriggered);
},
storeTriggered: storeTriggered
});
});
}

it('should be triggered with argument from upstream store', function() {
var promise = createPromiseForTest(Reflux.createStore(baseDefinition));
action('my argument');
return assert.eventually.equal(promise, '[...] my argument');
});

it('should be triggered with arbitrary arguments from upstream store', function() {
var promise = createPromiseForTest(Reflux.createStore(baseDefinition));
action(1337, 'ninja');
return assert.eventually.deepEqual(promise, ['[...] 1337', '[...] ninja']);
});

it('should get default data from getDefaultData()', function() {
var store = Reflux.createStore(_.extend(baseDefinition, {
getDefaultData: function () {
return ['default data'];
}
}));
var promise = createPromiseForTest(store);
return assert.eventually.equal(promise, '[...] default data');
});

it('should get default data from getDefaultData() returned promise', function() {
var store = Reflux.createStore(_.extend(baseDefinition, {
getDefaultData: function () {
return Q.Promise(function (resolve) {
setTimeout(function () {
resolve(['default data']);
}, 20);
});
}
}));
var promise = createPromiseForTest(store);
return assert.eventually.equal(promise, '[...] default data');
});

});

});