mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1140481 - Use the StoreMixin in some of the Loop conversation views. r=dmose
This commit is contained in:
parent
1dcd5b097c
commit
897951bc3a
@ -27,7 +27,11 @@ loop.conversation = (function(mozL10n) {
|
||||
* in progress, and hence, which view to display.
|
||||
*/
|
||||
var AppControllerView = React.createClass({displayName: "AppControllerView",
|
||||
mixins: [Backbone.Events, sharedMixins.WindowCloseMixin],
|
||||
mixins: [
|
||||
Backbone.Events,
|
||||
loop.store.StoreMixin("conversationAppStore"),
|
||||
sharedMixins.WindowCloseMixin
|
||||
],
|
||||
|
||||
propTypes: {
|
||||
// XXX Old types required for incoming call view.
|
||||
@ -37,26 +41,12 @@ loop.conversation = (function(mozL10n) {
|
||||
sdk: React.PropTypes.object.isRequired,
|
||||
|
||||
// XXX New types for flux style
|
||||
conversationAppStore: React.PropTypes.instanceOf(
|
||||
loop.store.ConversationAppStore).isRequired,
|
||||
conversationStore: React.PropTypes.instanceOf(loop.store.ConversationStore)
|
||||
.isRequired,
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
roomStore: React.PropTypes.instanceOf(loop.store.RoomStore)
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return this.props.conversationAppStore.getStoreState();
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this.listenTo(this.props.conversationAppStore, "change", function() {
|
||||
this.setState(this.props.conversationAppStore.getStoreState());
|
||||
}, this);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
this.stopListening(this.props.conversationAppStore);
|
||||
return this.getStoreState();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
@ -67,12 +57,11 @@ loop.conversation = (function(mozL10n) {
|
||||
conversation: this.props.conversation,
|
||||
sdk: this.props.sdk,
|
||||
isDesktop: true,
|
||||
conversationAppStore: this.props.conversationAppStore}
|
||||
conversationAppStore: this.getStore()}
|
||||
));
|
||||
}
|
||||
case "outgoing": {
|
||||
return (React.createElement(OutgoingConversationView, {
|
||||
store: this.props.conversationStore,
|
||||
dispatcher: this.props.dispatcher}
|
||||
));
|
||||
}
|
||||
@ -161,7 +150,11 @@ loop.conversation = (function(mozL10n) {
|
||||
feedbackClient: feedbackClient
|
||||
});
|
||||
|
||||
loop.store.StoreMixin.register({feedbackStore: feedbackStore});
|
||||
loop.store.StoreMixin.register({
|
||||
conversationAppStore: conversationAppStore,
|
||||
conversationStore: conversationStore,
|
||||
feedbackStore: feedbackStore,
|
||||
});
|
||||
|
||||
// XXX Old class creation for the incoming conversation view, whilst
|
||||
// we transition across (bug 1072323).
|
||||
@ -191,9 +184,7 @@ loop.conversation = (function(mozL10n) {
|
||||
});
|
||||
|
||||
React.render(React.createElement(AppControllerView, {
|
||||
conversationAppStore: conversationAppStore,
|
||||
roomStore: roomStore,
|
||||
conversationStore: conversationStore,
|
||||
client: client,
|
||||
conversation: conversation,
|
||||
dispatcher: dispatcher,
|
||||
|
@ -27,7 +27,11 @@ loop.conversation = (function(mozL10n) {
|
||||
* in progress, and hence, which view to display.
|
||||
*/
|
||||
var AppControllerView = React.createClass({
|
||||
mixins: [Backbone.Events, sharedMixins.WindowCloseMixin],
|
||||
mixins: [
|
||||
Backbone.Events,
|
||||
loop.store.StoreMixin("conversationAppStore"),
|
||||
sharedMixins.WindowCloseMixin
|
||||
],
|
||||
|
||||
propTypes: {
|
||||
// XXX Old types required for incoming call view.
|
||||
@ -37,26 +41,12 @@ loop.conversation = (function(mozL10n) {
|
||||
sdk: React.PropTypes.object.isRequired,
|
||||
|
||||
// XXX New types for flux style
|
||||
conversationAppStore: React.PropTypes.instanceOf(
|
||||
loop.store.ConversationAppStore).isRequired,
|
||||
conversationStore: React.PropTypes.instanceOf(loop.store.ConversationStore)
|
||||
.isRequired,
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
roomStore: React.PropTypes.instanceOf(loop.store.RoomStore)
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return this.props.conversationAppStore.getStoreState();
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this.listenTo(this.props.conversationAppStore, "change", function() {
|
||||
this.setState(this.props.conversationAppStore.getStoreState());
|
||||
}, this);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
this.stopListening(this.props.conversationAppStore);
|
||||
return this.getStoreState();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
@ -67,12 +57,11 @@ loop.conversation = (function(mozL10n) {
|
||||
conversation={this.props.conversation}
|
||||
sdk={this.props.sdk}
|
||||
isDesktop={true}
|
||||
conversationAppStore={this.props.conversationAppStore}
|
||||
conversationAppStore={this.getStore()}
|
||||
/>);
|
||||
}
|
||||
case "outgoing": {
|
||||
return (<OutgoingConversationView
|
||||
store={this.props.conversationStore}
|
||||
dispatcher={this.props.dispatcher}
|
||||
/>);
|
||||
}
|
||||
@ -161,7 +150,11 @@ loop.conversation = (function(mozL10n) {
|
||||
feedbackClient: feedbackClient
|
||||
});
|
||||
|
||||
loop.store.StoreMixin.register({feedbackStore: feedbackStore});
|
||||
loop.store.StoreMixin.register({
|
||||
conversationAppStore: conversationAppStore,
|
||||
conversationStore: conversationStore,
|
||||
feedbackStore: feedbackStore,
|
||||
});
|
||||
|
||||
// XXX Old class creation for the incoming conversation view, whilst
|
||||
// we transition across (bug 1072323).
|
||||
@ -191,9 +184,7 @@ loop.conversation = (function(mozL10n) {
|
||||
});
|
||||
|
||||
React.render(<AppControllerView
|
||||
conversationAppStore={conversationAppStore}
|
||||
roomStore={roomStore}
|
||||
conversationStore={conversationStore}
|
||||
client={client}
|
||||
conversation={conversation}
|
||||
dispatcher={dispatcher}
|
||||
|
@ -720,14 +720,13 @@ loop.conversationViews = (function(mozL10n) {
|
||||
var CallFailedView = React.createClass({displayName: "CallFailedView",
|
||||
mixins: [
|
||||
Backbone.Events,
|
||||
loop.store.StoreMixin("conversationStore"),
|
||||
sharedMixins.AudioMixin,
|
||||
sharedMixins.WindowCloseMixin
|
||||
],
|
||||
|
||||
propTypes: {
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
store: React.PropTypes.instanceOf(
|
||||
loop.store.ConversationStore).isRequired,
|
||||
contact: React.PropTypes.object.isRequired,
|
||||
// This is used by the UI showcase.
|
||||
emailLinkError: React.PropTypes.bool,
|
||||
@ -742,18 +741,18 @@ loop.conversationViews = (function(mozL10n) {
|
||||
|
||||
componentDidMount: function() {
|
||||
this.play("failure");
|
||||
this.listenTo(this.props.store, "change:emailLink",
|
||||
this.listenTo(this.getStore(), "change:emailLink",
|
||||
this._onEmailLinkReceived);
|
||||
this.listenTo(this.props.store, "error:emailLink",
|
||||
this.listenTo(this.getStore(), "error:emailLink",
|
||||
this._onEmailLinkError);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
this.stopListening(this.props.store);
|
||||
this.stopListening(this.getStore());
|
||||
},
|
||||
|
||||
_onEmailLinkReceived: function() {
|
||||
var emailLink = this.props.store.getStoreState("emailLink");
|
||||
var emailLink = this.getStoreState().emailLink;
|
||||
var contactEmail = _getPreferredEmail(this.props.contact).value;
|
||||
sharedUtils.composeCallUrlEmail(emailLink, contactEmail);
|
||||
this.closeWindow();
|
||||
@ -775,7 +774,7 @@ loop.conversationViews = (function(mozL10n) {
|
||||
|
||||
_getTitleMessage: function() {
|
||||
var callStateReason =
|
||||
this.props.store.getStoreState("callStateReason");
|
||||
this.getStoreState().callStateReason;
|
||||
|
||||
if (callStateReason === WEBSOCKET_REASONS.REJECT || callStateReason === WEBSOCKET_REASONS.BUSY ||
|
||||
callStateReason === REST_ERRNOS.USER_UNAVAILABLE) {
|
||||
@ -928,29 +927,16 @@ loop.conversationViews = (function(mozL10n) {
|
||||
var OutgoingConversationView = React.createClass({displayName: "OutgoingConversationView",
|
||||
mixins: [
|
||||
sharedMixins.AudioMixin,
|
||||
loop.store.StoreMixin("conversationStore"),
|
||||
Backbone.Events
|
||||
],
|
||||
|
||||
propTypes: {
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
store: React.PropTypes.instanceOf(
|
||||
loop.store.ConversationStore).isRequired
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return this.props.store.getStoreState();
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this.listenTo(this.props.store, "change", function() {
|
||||
this.setState(this.props.store.getStoreState());
|
||||
}, this);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
this.stopListening(this.props.store, "change", function() {
|
||||
this.setState(this.props.store.getStoreState());
|
||||
}, this);
|
||||
return this.getStoreState();
|
||||
},
|
||||
|
||||
_closeWindow: function() {
|
||||
@ -987,7 +973,6 @@ loop.conversationViews = (function(mozL10n) {
|
||||
case CALL_STATES.TERMINATED: {
|
||||
return (React.createElement(CallFailedView, {
|
||||
dispatcher: this.props.dispatcher,
|
||||
store: this.props.store,
|
||||
contact: this.state.contact}
|
||||
));
|
||||
}
|
||||
|
@ -720,14 +720,13 @@ loop.conversationViews = (function(mozL10n) {
|
||||
var CallFailedView = React.createClass({
|
||||
mixins: [
|
||||
Backbone.Events,
|
||||
loop.store.StoreMixin("conversationStore"),
|
||||
sharedMixins.AudioMixin,
|
||||
sharedMixins.WindowCloseMixin
|
||||
],
|
||||
|
||||
propTypes: {
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
store: React.PropTypes.instanceOf(
|
||||
loop.store.ConversationStore).isRequired,
|
||||
contact: React.PropTypes.object.isRequired,
|
||||
// This is used by the UI showcase.
|
||||
emailLinkError: React.PropTypes.bool,
|
||||
@ -742,18 +741,18 @@ loop.conversationViews = (function(mozL10n) {
|
||||
|
||||
componentDidMount: function() {
|
||||
this.play("failure");
|
||||
this.listenTo(this.props.store, "change:emailLink",
|
||||
this.listenTo(this.getStore(), "change:emailLink",
|
||||
this._onEmailLinkReceived);
|
||||
this.listenTo(this.props.store, "error:emailLink",
|
||||
this.listenTo(this.getStore(), "error:emailLink",
|
||||
this._onEmailLinkError);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
this.stopListening(this.props.store);
|
||||
this.stopListening(this.getStore());
|
||||
},
|
||||
|
||||
_onEmailLinkReceived: function() {
|
||||
var emailLink = this.props.store.getStoreState("emailLink");
|
||||
var emailLink = this.getStoreState().emailLink;
|
||||
var contactEmail = _getPreferredEmail(this.props.contact).value;
|
||||
sharedUtils.composeCallUrlEmail(emailLink, contactEmail);
|
||||
this.closeWindow();
|
||||
@ -775,7 +774,7 @@ loop.conversationViews = (function(mozL10n) {
|
||||
|
||||
_getTitleMessage: function() {
|
||||
var callStateReason =
|
||||
this.props.store.getStoreState("callStateReason");
|
||||
this.getStoreState().callStateReason;
|
||||
|
||||
if (callStateReason === WEBSOCKET_REASONS.REJECT || callStateReason === WEBSOCKET_REASONS.BUSY ||
|
||||
callStateReason === REST_ERRNOS.USER_UNAVAILABLE) {
|
||||
@ -928,29 +927,16 @@ loop.conversationViews = (function(mozL10n) {
|
||||
var OutgoingConversationView = React.createClass({
|
||||
mixins: [
|
||||
sharedMixins.AudioMixin,
|
||||
loop.store.StoreMixin("conversationStore"),
|
||||
Backbone.Events
|
||||
],
|
||||
|
||||
propTypes: {
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
|
||||
store: React.PropTypes.instanceOf(
|
||||
loop.store.ConversationStore).isRequired
|
||||
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return this.props.store.getStoreState();
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this.listenTo(this.props.store, "change", function() {
|
||||
this.setState(this.props.store.getStoreState());
|
||||
}, this);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
this.stopListening(this.props.store, "change", function() {
|
||||
this.setState(this.props.store.getStoreState());
|
||||
}, this);
|
||||
return this.getStoreState();
|
||||
},
|
||||
|
||||
_closeWindow: function() {
|
||||
@ -987,7 +973,6 @@ loop.conversationViews = (function(mozL10n) {
|
||||
case CALL_STATES.TERMINATED: {
|
||||
return (<CallFailedView
|
||||
dispatcher={this.props.dispatcher}
|
||||
store={this.props.store}
|
||||
contact={this.state.contact}
|
||||
/>);
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ loop.store.StoreMixin = (function() {
|
||||
}, this);
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
this.getStore().off("change");
|
||||
this.getStore().off("change", null, this);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -283,7 +283,6 @@ describe("loop.conversationViews", function () {
|
||||
return TestUtils.renderIntoDocument(
|
||||
React.createElement(loop.conversationViews.CallFailedView, {
|
||||
dispatcher: dispatcher,
|
||||
store: store,
|
||||
contact: options.contact
|
||||
}));
|
||||
}
|
||||
@ -294,6 +293,10 @@ describe("loop.conversationViews", function () {
|
||||
mozLoop: navigator.mozLoop,
|
||||
sdkDriver: {}
|
||||
});
|
||||
loop.store.StoreMixin.register({
|
||||
conversationStore: store
|
||||
});
|
||||
|
||||
fakeAudio = {
|
||||
play: sinon.spy(),
|
||||
pause: sinon.spy(),
|
||||
@ -582,7 +585,6 @@ describe("loop.conversationViews", function () {
|
||||
return TestUtils.renderIntoDocument(
|
||||
React.createElement(loop.conversationViews.OutgoingConversationView, {
|
||||
dispatcher: dispatcher,
|
||||
store: store
|
||||
}));
|
||||
}
|
||||
|
||||
@ -592,6 +594,10 @@ describe("loop.conversationViews", function () {
|
||||
mozLoop: fakeMozLoop,
|
||||
sdkDriver: {}
|
||||
});
|
||||
loop.store.StoreMixin.register({
|
||||
conversationStore: store
|
||||
});
|
||||
|
||||
feedbackStore = new loop.store.FeedbackStore(dispatcher, {
|
||||
feedbackClient: {}
|
||||
});
|
||||
|
@ -139,8 +139,6 @@ describe("loop.conversation", function() {
|
||||
conversation: conversation,
|
||||
roomStore: roomStore,
|
||||
sdk: {},
|
||||
conversationStore: conversationStore,
|
||||
conversationAppStore: conversationAppStore,
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: navigator.mozLoop
|
||||
}));
|
||||
@ -176,6 +174,11 @@ describe("loop.conversation", function() {
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: navigator.mozLoop
|
||||
});
|
||||
|
||||
loop.store.StoreMixin.register({
|
||||
conversationAppStore: conversationAppStore,
|
||||
conversationStore: conversationStore
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
|
@ -4,157 +4,202 @@
|
||||
|
||||
var expect = chai.expect;
|
||||
|
||||
describe("loop.store.createStore", function () {
|
||||
describe("loop.store", function () {
|
||||
"use strict";
|
||||
|
||||
var dispatcher;
|
||||
var sandbox;
|
||||
var sharedActions = loop.shared.actions;
|
||||
|
||||
beforeEach(function() {
|
||||
sandbox = sinon.sandbox.create();
|
||||
dispatcher = new loop.Dispatcher();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
it("should create a store constructor", function() {
|
||||
expect(loop.store.createStore({})).to.be.a("function");
|
||||
describe("loop.store.createStore", function() {
|
||||
it("should create a store constructor", function() {
|
||||
expect(loop.store.createStore({})).to.be.a("function");
|
||||
});
|
||||
|
||||
it("should implement Backbone.Events", function() {
|
||||
expect(loop.store.createStore({}).prototype).to.include.keys(["on", "off"]);
|
||||
});
|
||||
|
||||
describe("Store API", function() {
|
||||
describe("#constructor", function() {
|
||||
it("should require a dispatcher", function() {
|
||||
var TestStore = loop.store.createStore({});
|
||||
expect(function() {
|
||||
new TestStore();
|
||||
}).to.Throw(/required dispatcher/);
|
||||
});
|
||||
|
||||
it("should call initialize() when constructed, if defined", function() {
|
||||
var initialize = sandbox.spy();
|
||||
var TestStore = loop.store.createStore({initialize: initialize});
|
||||
var options = {fake: true};
|
||||
|
||||
new TestStore(dispatcher, options);
|
||||
|
||||
sinon.assert.calledOnce(initialize);
|
||||
sinon.assert.calledWithExactly(initialize, options);
|
||||
});
|
||||
|
||||
it("should register actions", function() {
|
||||
sandbox.stub(dispatcher, "register");
|
||||
var TestStore = loop.store.createStore({
|
||||
actions: ["a", "b"],
|
||||
a: function() {},
|
||||
b: function() {}
|
||||
});
|
||||
|
||||
var store = new TestStore(dispatcher);
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.register);
|
||||
sinon.assert.calledWithExactly(dispatcher.register, store, ["a", "b"]);
|
||||
});
|
||||
|
||||
it("should throw if a registered action isn't implemented", function() {
|
||||
var TestStore = loop.store.createStore({
|
||||
actions: ["a", "b"],
|
||||
a: function() {} // missing b
|
||||
});
|
||||
|
||||
expect(function() {
|
||||
new TestStore(dispatcher);
|
||||
}).to.Throw(/should implement an action handler for b/);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#getInitialStoreState", function() {
|
||||
it("should set initial store state if provided", function() {
|
||||
var TestStore = loop.store.createStore({
|
||||
getInitialStoreState: function() {
|
||||
return {foo: "bar"};
|
||||
}
|
||||
});
|
||||
|
||||
var store = new TestStore(dispatcher);
|
||||
|
||||
expect(store.getStoreState()).eql({foo: "bar"});
|
||||
});
|
||||
});
|
||||
|
||||
describe("#dispatchAction", function() {
|
||||
it("should dispatch an action", function() {
|
||||
sandbox.stub(dispatcher, "dispatch");
|
||||
var TestStore = loop.store.createStore({});
|
||||
var TestAction = sharedActions.Action.define("TestAction", {});
|
||||
var action = new TestAction({});
|
||||
var store = new TestStore(dispatcher);
|
||||
|
||||
store.dispatchAction(action);
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch, action);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#getStoreState", function() {
|
||||
var TestStore = loop.store.createStore({});
|
||||
var store;
|
||||
|
||||
beforeEach(function() {
|
||||
store = new TestStore(dispatcher);
|
||||
store.setStoreState({foo: "bar", bar: "baz"});
|
||||
});
|
||||
|
||||
it("should retrieve the whole state by default", function() {
|
||||
expect(store.getStoreState()).eql({foo: "bar", bar: "baz"});
|
||||
});
|
||||
|
||||
it("should retrieve a given property state", function() {
|
||||
expect(store.getStoreState("bar")).eql("baz");
|
||||
});
|
||||
});
|
||||
|
||||
describe("#setStoreState", function() {
|
||||
var TestStore = loop.store.createStore({});
|
||||
var store;
|
||||
|
||||
beforeEach(function() {
|
||||
store = new TestStore(dispatcher);
|
||||
store.setStoreState({foo: "bar"});
|
||||
});
|
||||
|
||||
it("should update store state data", function() {
|
||||
store.setStoreState({foo: "baz"});
|
||||
|
||||
expect(store.getStoreState("foo")).eql("baz");
|
||||
});
|
||||
|
||||
it("should trigger a `change` event", function(done) {
|
||||
store.once("change", function() {
|
||||
done();
|
||||
});
|
||||
|
||||
store.setStoreState({foo: "baz"});
|
||||
});
|
||||
|
||||
it("should trigger a `change:<prop>` event", function(done) {
|
||||
store.once("change:foo", function() {
|
||||
done();
|
||||
});
|
||||
|
||||
store.setStoreState({foo: "baz"});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should implement Backbone.Events", function() {
|
||||
expect(loop.store.createStore({}).prototype).to.include.keys(["on", "off"])
|
||||
});
|
||||
|
||||
describe("Store API", function() {
|
||||
var dispatcher;
|
||||
describe("loop.store.StoreMixin", function() {
|
||||
var view1, view2, store, storeClass, testComp;
|
||||
|
||||
beforeEach(function() {
|
||||
dispatcher = new loop.Dispatcher();
|
||||
storeClass = loop.store.createStore({});
|
||||
|
||||
store = new storeClass(dispatcher);
|
||||
|
||||
loop.store.StoreMixin.register({store: store});
|
||||
|
||||
testComp = React.createClass({
|
||||
mixins: [loop.store.StoreMixin("store")],
|
||||
render: function() {
|
||||
return React.DOM.div();
|
||||
}
|
||||
});
|
||||
|
||||
view1 = TestUtils.renderIntoDocument(React.createElement(testComp));
|
||||
});
|
||||
|
||||
describe("#constructor", function() {
|
||||
it("should require a dispatcher", function() {
|
||||
var TestStore = loop.store.createStore({});
|
||||
expect(function() {
|
||||
new TestStore();
|
||||
}).to.Throw(/required dispatcher/);
|
||||
});
|
||||
it("should update the state when the store changes", function() {
|
||||
store.setStoreState({test: true});
|
||||
|
||||
it("should call initialize() when constructed, if defined", function() {
|
||||
var initialize = sandbox.spy();
|
||||
var TestStore = loop.store.createStore({initialize: initialize});
|
||||
var options = {fake: true};
|
||||
|
||||
new TestStore(dispatcher, options);
|
||||
|
||||
sinon.assert.calledOnce(initialize);
|
||||
sinon.assert.calledWithExactly(initialize, options);
|
||||
});
|
||||
|
||||
it("should register actions", function() {
|
||||
sandbox.stub(dispatcher, "register");
|
||||
var TestStore = loop.store.createStore({
|
||||
actions: ["a", "b"],
|
||||
a: function() {},
|
||||
b: function() {}
|
||||
});
|
||||
|
||||
var store = new TestStore(dispatcher);
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.register);
|
||||
sinon.assert.calledWithExactly(dispatcher.register, store, ["a", "b"]);
|
||||
});
|
||||
|
||||
it("should throw if a registered action isn't implemented", function() {
|
||||
var TestStore = loop.store.createStore({
|
||||
actions: ["a", "b"],
|
||||
a: function() {} // missing b
|
||||
});
|
||||
|
||||
expect(function() {
|
||||
new TestStore(dispatcher);
|
||||
}).to.Throw(/should implement an action handler for b/);
|
||||
});
|
||||
expect(view1.state).eql({test: true});
|
||||
});
|
||||
|
||||
describe("#getInitialStoreState", function() {
|
||||
it("should set initial store state if provided", function() {
|
||||
var TestStore = loop.store.createStore({
|
||||
getInitialStoreState: function() {
|
||||
return {foo: "bar"};
|
||||
}
|
||||
});
|
||||
it("should stop listening to state changes", function() {
|
||||
// There's no easy way in TestUtils to unmount, so simulate it.
|
||||
view1.componentWillUnmount();
|
||||
|
||||
var store = new TestStore(dispatcher);
|
||||
store.setStoreState({test2: true});
|
||||
|
||||
expect(store.getStoreState()).eql({foo: "bar"});
|
||||
});
|
||||
expect(view1.state).eql(null);
|
||||
});
|
||||
|
||||
describe("#dispatchAction", function() {
|
||||
it("should dispatch an action", function() {
|
||||
sandbox.stub(dispatcher, "dispatch");
|
||||
var TestStore = loop.store.createStore({});
|
||||
var TestAction = sharedActions.Action.define("TestAction", {});
|
||||
var action = new TestAction({});
|
||||
var store = new TestStore(dispatcher);
|
||||
it("should not stop listening to state changes on other components", function() {
|
||||
view2 = TestUtils.renderIntoDocument(React.createElement(testComp));
|
||||
|
||||
store.dispatchAction(action);
|
||||
// There's no easy way in TestUtils to unmount, so simulate it.
|
||||
view1.componentWillUnmount();
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch, action);
|
||||
});
|
||||
});
|
||||
store.setStoreState({test3: true});
|
||||
|
||||
describe("#getStoreState", function() {
|
||||
var TestStore = loop.store.createStore({});
|
||||
var store;
|
||||
|
||||
beforeEach(function() {
|
||||
store = new TestStore(dispatcher);
|
||||
store.setStoreState({foo: "bar", bar: "baz"});
|
||||
});
|
||||
|
||||
it("should retrieve the whole state by default", function() {
|
||||
expect(store.getStoreState()).eql({foo: "bar", bar: "baz"});
|
||||
});
|
||||
|
||||
it("should retrieve a given property state", function() {
|
||||
expect(store.getStoreState("bar")).eql("baz");
|
||||
});
|
||||
});
|
||||
|
||||
describe("#setStoreState", function() {
|
||||
var TestStore = loop.store.createStore({});
|
||||
var store;
|
||||
|
||||
beforeEach(function() {
|
||||
store = new TestStore(dispatcher);
|
||||
store.setStoreState({foo: "bar"});
|
||||
});
|
||||
|
||||
it("should update store state data", function() {
|
||||
store.setStoreState({foo: "baz"});
|
||||
|
||||
expect(store.getStoreState("foo")).eql("baz");
|
||||
});
|
||||
|
||||
it("should trigger a `change` event", function(done) {
|
||||
store.once("change", function() {
|
||||
done();
|
||||
});
|
||||
|
||||
store.setStoreState({foo: "baz"});
|
||||
});
|
||||
|
||||
it("should trigger a `change:<prop>` event", function(done) {
|
||||
store.once("change:foo", function() {
|
||||
done();
|
||||
});
|
||||
|
||||
store.setStoreState({foo: "baz"});
|
||||
});
|
||||
expect(view2.state).eql({test3: true});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user