mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1090209 - Part 1 Drop the window type from the url that opens a Loop conversation window, and pass it in the call data instead. r=nperriault
Also creates a ConversationAppStore for managing the overall window data and selection of the type of window it is for the views.
This commit is contained in:
parent
2dd6bd5c87
commit
6292d8459f
@ -252,7 +252,8 @@ let LoopCallsInternal = {
|
||||
callData.sessionType = sessionType;
|
||||
// XXX Bug 1090209 will transiton into a better window id.
|
||||
callData.windowId = callData.callId;
|
||||
this._startCall(callData, "incoming");
|
||||
callData.type = "incoming";
|
||||
this._startCall(callData);
|
||||
} else {
|
||||
this._returnBusy(callData);
|
||||
}
|
||||
@ -269,17 +270,17 @@ let LoopCallsInternal = {
|
||||
* Starts a call, saves the call data, and opens a chat window.
|
||||
*
|
||||
* @param {Object} callData The data associated with the call including an id.
|
||||
* @param {Boolean} conversationType Whether or not the call is "incoming"
|
||||
* or "outgoing"
|
||||
* The data should include the type - "incoming" or
|
||||
* "outgoing".
|
||||
*/
|
||||
_startCall: function(callData, conversationType) {
|
||||
_startCall: function(callData) {
|
||||
this.callsData.inUse = true;
|
||||
this.callsData.data = callData;
|
||||
MozLoopService.openChatWindow(
|
||||
null,
|
||||
// No title, let the page set that, to avoid flickering.
|
||||
"",
|
||||
"about:loopconversation#" + conversationType + "/" + callData.windowId);
|
||||
"about:loopconversation#" + callData.windowId);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -296,11 +297,12 @@ let LoopCallsInternal = {
|
||||
var callData = {
|
||||
contact: contact,
|
||||
callType: callType,
|
||||
type: "outgoing",
|
||||
// XXX Really we shouldn't be using random numbers, bug 1090209 will fix this.
|
||||
windowId: Math.floor((Math.random() * 100000000))
|
||||
};
|
||||
|
||||
this._startCall(callData, "outgoing");
|
||||
this._startCall(callData);
|
||||
return true;
|
||||
},
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
<script type="text/javascript" src="loop/shared/js/localRoomStore.js"></script>
|
||||
<script type="text/javascript" src="loop/js/conversationViews.js"></script>
|
||||
<script type="text/javascript" src="loop/shared/js/websocket.js"></script>
|
||||
<script type="text/javascript" src="loop/js/conversationAppStore.js"></script>
|
||||
<script type="text/javascript" src="loop/js/client.js"></script>
|
||||
<script type="text/javascript" src="loop/js/conversationViews.js"></script>
|
||||
<script type="text/javascript" src="loop/js/roomViews.js"></script>
|
||||
|
@ -179,12 +179,12 @@ loop.conversation = (function(mozL10n) {
|
||||
});
|
||||
|
||||
/**
|
||||
* Incoming Call failed view. Displayed when a call fails.
|
||||
* Something went wrong view. Displayed when there's a big problem.
|
||||
*
|
||||
* XXX Based on CallFailedView, but built specially until we flux-ify the
|
||||
* incoming call views (bug 1088672).
|
||||
*/
|
||||
var IncomingCallFailedView = React.createClass({displayName: 'IncomingCallFailedView',
|
||||
var GenericFailureView = React.createClass({displayName: 'GenericFailureView',
|
||||
propTypes: {
|
||||
cancelCall: React.PropTypes.func.isRequired
|
||||
},
|
||||
@ -283,7 +283,7 @@ loop.conversation = (function(mozL10n) {
|
||||
case "end": {
|
||||
// XXX To be handled with the "failed" view state when bug 1047410 lands
|
||||
if (this.state.callFailed) {
|
||||
return IncomingCallFailedView({
|
||||
return GenericFailureView({
|
||||
cancelCall: this.closeWindow.bind(this)}
|
||||
)
|
||||
}
|
||||
@ -523,6 +523,8 @@ loop.conversation = (function(mozL10n) {
|
||||
* in progress, and hence, which view to display.
|
||||
*/
|
||||
var AppControllerView = React.createClass({displayName: 'AppControllerView',
|
||||
mixins: [Backbone.Events],
|
||||
|
||||
propTypes: {
|
||||
// XXX Old types required for incoming call view.
|
||||
client: React.PropTypes.instanceOf(loop.Client).isRequired,
|
||||
@ -530,51 +532,65 @@ loop.conversation = (function(mozL10n) {
|
||||
.isRequired,
|
||||
sdk: React.PropTypes.object.isRequired,
|
||||
|
||||
// XXX New types for OutgoingConversationView
|
||||
store: React.PropTypes.instanceOf(loop.store.ConversationStore).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,
|
||||
|
||||
// if not passed, this is not a room view
|
||||
localRoomStore: React.PropTypes.instanceOf(loop.store.LocalRoomStore)
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return this.props.store.attributes;
|
||||
return this.props.conversationAppStore.getStoreState();
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this.props.store.on("change:outgoing", function() {
|
||||
this.setState(this.props.store.attributes);
|
||||
this.listenTo(this.props.conversationAppStore, "change", function() {
|
||||
this.setState(this.props.conversationAppStore.getStoreState());
|
||||
}, this);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
this.stopListening(this.props.conversationAppStore);
|
||||
},
|
||||
|
||||
closeWindow: function() {
|
||||
window.close();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
if (this.props.localRoomStore) {
|
||||
return (
|
||||
EmptyRoomView({
|
||||
switch(this.state.windowType) {
|
||||
case "incoming": {
|
||||
return (IncomingConversationView({
|
||||
client: this.props.client,
|
||||
conversation: this.props.conversation,
|
||||
sdk: this.props.sdk}
|
||||
));
|
||||
}
|
||||
case "outgoing": {
|
||||
return (OutgoingConversationView({
|
||||
store: this.props.conversationStore,
|
||||
dispatcher: this.props.dispatcher}
|
||||
));
|
||||
}
|
||||
case "room": {
|
||||
return (EmptyRoomView({
|
||||
mozLoop: navigator.mozLoop,
|
||||
localRoomStore: this.props.localRoomStore}
|
||||
)
|
||||
);
|
||||
));
|
||||
}
|
||||
case "failed": {
|
||||
return (GenericFailureView({
|
||||
cancelCall: this.closeWindow.bind(this)}
|
||||
));
|
||||
}
|
||||
default: {
|
||||
// If we don't have a windowType, we don't know what we are yet,
|
||||
// so don't display anything.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't display anything, until we know what type of call we are.
|
||||
if (this.state.outgoing === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.state.outgoing) {
|
||||
return (OutgoingConversationView({
|
||||
store: this.props.store,
|
||||
dispatcher: this.props.dispatcher}
|
||||
));
|
||||
}
|
||||
|
||||
return (IncomingConversationView({
|
||||
client: this.props.client,
|
||||
conversation: this.props.conversation,
|
||||
sdk: this.props.sdk}
|
||||
));
|
||||
}
|
||||
});
|
||||
|
||||
@ -605,11 +621,20 @@ loop.conversation = (function(mozL10n) {
|
||||
sdk: OT
|
||||
});
|
||||
|
||||
// Create the stores.
|
||||
var conversationAppStore = new loop.store.ConversationAppStore({
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: navigator.mozLoop
|
||||
});
|
||||
var conversationStore = new loop.store.ConversationStore({}, {
|
||||
client: client,
|
||||
dispatcher: dispatcher,
|
||||
sdkDriver: sdkDriver
|
||||
});
|
||||
var localRoomStore = new loop.store.LocalRoomStore({
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: navigator.mozLoop
|
||||
});;
|
||||
|
||||
// XXX Old class creation for the incoming conversation view, whilst
|
||||
// we transition across (bug 1072323).
|
||||
@ -622,30 +647,10 @@ loop.conversation = (function(mozL10n) {
|
||||
var helper = new loop.shared.utils.Helper();
|
||||
var locationHash = helper.locationData().hash;
|
||||
var windowId;
|
||||
var outgoing;
|
||||
var localRoomStore;
|
||||
|
||||
// XXX removeMe, along with noisy comment at the beginning of
|
||||
// conversation_test.js "when locationHash begins with #room".
|
||||
if (navigator.mozLoop.getLoopBoolPref("test.alwaysUseRooms")) {
|
||||
locationHash = "#room/32";
|
||||
}
|
||||
|
||||
var hash = locationHash.match(/#incoming\/(.*)/);
|
||||
var hash = locationHash.match(/#(.*)/);
|
||||
if (hash) {
|
||||
windowId = hash[1];
|
||||
outgoing = false;
|
||||
} else if (hash = locationHash.match(/#room\/(.*)/)) {
|
||||
localRoomStore = new loop.store.LocalRoomStore({
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: navigator.mozLoop
|
||||
});
|
||||
} else {
|
||||
hash = locationHash.match(/#outgoing\/(.*)/);
|
||||
if (hash) {
|
||||
windowId = hash[1];
|
||||
outgoing = true;
|
||||
}
|
||||
}
|
||||
|
||||
conversation.set({windowId: windowId});
|
||||
@ -656,23 +661,17 @@ loop.conversation = (function(mozL10n) {
|
||||
});
|
||||
|
||||
React.renderComponent(AppControllerView({
|
||||
conversationAppStore: conversationAppStore,
|
||||
localRoomStore: localRoomStore,
|
||||
store: conversationStore,
|
||||
conversationStore: conversationStore,
|
||||
client: client,
|
||||
conversation: conversation,
|
||||
dispatcher: dispatcher,
|
||||
sdk: window.OT}
|
||||
), document.querySelector('#main'));
|
||||
|
||||
if (localRoomStore) {
|
||||
dispatcher.dispatch(
|
||||
new sharedActions.SetupEmptyRoom({localRoomId: hash[1]}));
|
||||
return;
|
||||
}
|
||||
|
||||
dispatcher.dispatch(new loop.shared.actions.GatherCallData({
|
||||
windowId: windowId,
|
||||
outgoing: outgoing
|
||||
dispatcher.dispatch(new sharedActions.GetWindowData({
|
||||
windowId: windowId
|
||||
}));
|
||||
}
|
||||
|
||||
@ -680,7 +679,7 @@ loop.conversation = (function(mozL10n) {
|
||||
AppControllerView: AppControllerView,
|
||||
IncomingConversationView: IncomingConversationView,
|
||||
IncomingCallView: IncomingCallView,
|
||||
IncomingCallFailedView: IncomingCallFailedView,
|
||||
GenericFailureView: GenericFailureView,
|
||||
init: init
|
||||
};
|
||||
})(document.mozL10n);
|
||||
|
@ -179,12 +179,12 @@ loop.conversation = (function(mozL10n) {
|
||||
});
|
||||
|
||||
/**
|
||||
* Incoming Call failed view. Displayed when a call fails.
|
||||
* Something went wrong view. Displayed when there's a big problem.
|
||||
*
|
||||
* XXX Based on CallFailedView, but built specially until we flux-ify the
|
||||
* incoming call views (bug 1088672).
|
||||
*/
|
||||
var IncomingCallFailedView = React.createClass({
|
||||
var GenericFailureView = React.createClass({
|
||||
propTypes: {
|
||||
cancelCall: React.PropTypes.func.isRequired
|
||||
},
|
||||
@ -283,7 +283,7 @@ loop.conversation = (function(mozL10n) {
|
||||
case "end": {
|
||||
// XXX To be handled with the "failed" view state when bug 1047410 lands
|
||||
if (this.state.callFailed) {
|
||||
return <IncomingCallFailedView
|
||||
return <GenericFailureView
|
||||
cancelCall={this.closeWindow.bind(this)}
|
||||
/>
|
||||
}
|
||||
@ -523,6 +523,8 @@ loop.conversation = (function(mozL10n) {
|
||||
* in progress, and hence, which view to display.
|
||||
*/
|
||||
var AppControllerView = React.createClass({
|
||||
mixins: [Backbone.Events],
|
||||
|
||||
propTypes: {
|
||||
// XXX Old types required for incoming call view.
|
||||
client: React.PropTypes.instanceOf(loop.Client).isRequired,
|
||||
@ -530,51 +532,65 @@ loop.conversation = (function(mozL10n) {
|
||||
.isRequired,
|
||||
sdk: React.PropTypes.object.isRequired,
|
||||
|
||||
// XXX New types for OutgoingConversationView
|
||||
store: React.PropTypes.instanceOf(loop.store.ConversationStore).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,
|
||||
|
||||
// if not passed, this is not a room view
|
||||
localRoomStore: React.PropTypes.instanceOf(loop.store.LocalRoomStore)
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return this.props.store.attributes;
|
||||
return this.props.conversationAppStore.getStoreState();
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this.props.store.on("change:outgoing", function() {
|
||||
this.setState(this.props.store.attributes);
|
||||
this.listenTo(this.props.conversationAppStore, "change", function() {
|
||||
this.setState(this.props.conversationAppStore.getStoreState());
|
||||
}, this);
|
||||
},
|
||||
|
||||
componentWillUnmount: function() {
|
||||
this.stopListening(this.props.conversationAppStore);
|
||||
},
|
||||
|
||||
closeWindow: function() {
|
||||
window.close();
|
||||
},
|
||||
|
||||
render: function() {
|
||||
if (this.props.localRoomStore) {
|
||||
return (
|
||||
<EmptyRoomView
|
||||
switch(this.state.windowType) {
|
||||
case "incoming": {
|
||||
return (<IncomingConversationView
|
||||
client={this.props.client}
|
||||
conversation={this.props.conversation}
|
||||
sdk={this.props.sdk}
|
||||
/>);
|
||||
}
|
||||
case "outgoing": {
|
||||
return (<OutgoingConversationView
|
||||
store={this.props.conversationStore}
|
||||
dispatcher={this.props.dispatcher}
|
||||
/>);
|
||||
}
|
||||
case "room": {
|
||||
return (<EmptyRoomView
|
||||
mozLoop={navigator.mozLoop}
|
||||
localRoomStore={this.props.localRoomStore}
|
||||
/>
|
||||
);
|
||||
/>);
|
||||
}
|
||||
case "failed": {
|
||||
return (<GenericFailureView
|
||||
cancelCall={this.closeWindow.bind(this)}
|
||||
/>);
|
||||
}
|
||||
default: {
|
||||
// If we don't have a windowType, we don't know what we are yet,
|
||||
// so don't display anything.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't display anything, until we know what type of call we are.
|
||||
if (this.state.outgoing === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.state.outgoing) {
|
||||
return (<OutgoingConversationView
|
||||
store={this.props.store}
|
||||
dispatcher={this.props.dispatcher}
|
||||
/>);
|
||||
}
|
||||
|
||||
return (<IncomingConversationView
|
||||
client={this.props.client}
|
||||
conversation={this.props.conversation}
|
||||
sdk={this.props.sdk}
|
||||
/>);
|
||||
}
|
||||
});
|
||||
|
||||
@ -605,11 +621,20 @@ loop.conversation = (function(mozL10n) {
|
||||
sdk: OT
|
||||
});
|
||||
|
||||
// Create the stores.
|
||||
var conversationAppStore = new loop.store.ConversationAppStore({
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: navigator.mozLoop
|
||||
});
|
||||
var conversationStore = new loop.store.ConversationStore({}, {
|
||||
client: client,
|
||||
dispatcher: dispatcher,
|
||||
sdkDriver: sdkDriver
|
||||
});
|
||||
var localRoomStore = new loop.store.LocalRoomStore({
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: navigator.mozLoop
|
||||
});;
|
||||
|
||||
// XXX Old class creation for the incoming conversation view, whilst
|
||||
// we transition across (bug 1072323).
|
||||
@ -622,30 +647,10 @@ loop.conversation = (function(mozL10n) {
|
||||
var helper = new loop.shared.utils.Helper();
|
||||
var locationHash = helper.locationData().hash;
|
||||
var windowId;
|
||||
var outgoing;
|
||||
var localRoomStore;
|
||||
|
||||
// XXX removeMe, along with noisy comment at the beginning of
|
||||
// conversation_test.js "when locationHash begins with #room".
|
||||
if (navigator.mozLoop.getLoopBoolPref("test.alwaysUseRooms")) {
|
||||
locationHash = "#room/32";
|
||||
}
|
||||
|
||||
var hash = locationHash.match(/#incoming\/(.*)/);
|
||||
var hash = locationHash.match(/#(.*)/);
|
||||
if (hash) {
|
||||
windowId = hash[1];
|
||||
outgoing = false;
|
||||
} else if (hash = locationHash.match(/#room\/(.*)/)) {
|
||||
localRoomStore = new loop.store.LocalRoomStore({
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: navigator.mozLoop
|
||||
});
|
||||
} else {
|
||||
hash = locationHash.match(/#outgoing\/(.*)/);
|
||||
if (hash) {
|
||||
windowId = hash[1];
|
||||
outgoing = true;
|
||||
}
|
||||
}
|
||||
|
||||
conversation.set({windowId: windowId});
|
||||
@ -656,23 +661,17 @@ loop.conversation = (function(mozL10n) {
|
||||
});
|
||||
|
||||
React.renderComponent(<AppControllerView
|
||||
conversationAppStore={conversationAppStore}
|
||||
localRoomStore={localRoomStore}
|
||||
store={conversationStore}
|
||||
conversationStore={conversationStore}
|
||||
client={client}
|
||||
conversation={conversation}
|
||||
dispatcher={dispatcher}
|
||||
sdk={window.OT}
|
||||
/>, document.querySelector('#main'));
|
||||
|
||||
if (localRoomStore) {
|
||||
dispatcher.dispatch(
|
||||
new sharedActions.SetupEmptyRoom({localRoomId: hash[1]}));
|
||||
return;
|
||||
}
|
||||
|
||||
dispatcher.dispatch(new loop.shared.actions.GatherCallData({
|
||||
windowId: windowId,
|
||||
outgoing: outgoing
|
||||
dispatcher.dispatch(new sharedActions.GetWindowData({
|
||||
windowId: windowId
|
||||
}));
|
||||
}
|
||||
|
||||
@ -680,7 +679,7 @@ loop.conversation = (function(mozL10n) {
|
||||
AppControllerView: AppControllerView,
|
||||
IncomingConversationView: IncomingConversationView,
|
||||
IncomingCallView: IncomingCallView,
|
||||
IncomingCallFailedView: IncomingCallFailedView,
|
||||
GenericFailureView: GenericFailureView,
|
||||
init: init
|
||||
};
|
||||
})(document.mozL10n);
|
||||
|
88
browser/components/loop/content/js/conversationAppStore.js
Normal file
88
browser/components/loop/content/js/conversationAppStore.js
Normal file
@ -0,0 +1,88 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* global loop:true */
|
||||
|
||||
var loop = loop || {};
|
||||
loop.store = loop.store || {};
|
||||
|
||||
/**
|
||||
* Manages the conversation window app controller view. Used to get
|
||||
* the window data and store the window type.
|
||||
*/
|
||||
loop.store.ConversationAppStore = (function() {
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param {Object} options Options for the store. Should contain the dispatcher.
|
||||
*/
|
||||
var ConversationAppStore = function(options) {
|
||||
if (!options.dispatcher) {
|
||||
throw new Error("Missing option dispatcher");
|
||||
}
|
||||
if (!options.mozLoop) {
|
||||
throw new Error("Missing option mozLoop");
|
||||
}
|
||||
|
||||
this._dispatcher = options.dispatcher;
|
||||
this._mozLoop = options.mozLoop;
|
||||
this._storeState = {};
|
||||
|
||||
this._dispatcher.register(this, [
|
||||
"getWindowData"
|
||||
]);
|
||||
};
|
||||
|
||||
ConversationAppStore.prototype = _.extend({
|
||||
/**
|
||||
* Retrieves current store state.
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
getStoreState: function() {
|
||||
return this._storeState;
|
||||
},
|
||||
|
||||
/**
|
||||
* Updates store states and trigger a "change" event.
|
||||
*
|
||||
* @param {Object} state The new store state.
|
||||
*/
|
||||
setStoreState: function(state) {
|
||||
this._storeState = state;
|
||||
this.trigger("change");
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the get window data action - obtains the window data,
|
||||
* updates the store and notifies interested components.
|
||||
*
|
||||
* @param {sharedActions.GetWindowData} actionData The action data
|
||||
*/
|
||||
getWindowData: function(actionData) {
|
||||
var windowData;
|
||||
// XXX Remove me in bug 1074678
|
||||
if (this._mozLoop.getLoopBoolPref("test.alwaysUseRooms")) {
|
||||
windowData = {type: "room", localRoomId: "42"};
|
||||
} else {
|
||||
windowData = this._mozLoop.getCallData(actionData.windowId);
|
||||
}
|
||||
|
||||
if (!windowData) {
|
||||
console.error("Failed to get the window data");
|
||||
this.setStoreState({windowType: "failed"});
|
||||
return;
|
||||
}
|
||||
|
||||
this.setStoreState({windowType: windowData.type});
|
||||
|
||||
this._dispatcher.dispatch(new loop.shared.actions.SetupWindowData({
|
||||
windowData: windowData
|
||||
}));
|
||||
}
|
||||
}, Backbone.Events);
|
||||
|
||||
return ConversationAppStore;
|
||||
|
||||
})();
|
@ -499,6 +499,10 @@ loop.conversationViews = (function(mozL10n) {
|
||||
case CALL_STATES.FINISHED: {
|
||||
return this._renderFeedbackView();
|
||||
}
|
||||
case CALL_STATES.INIT: {
|
||||
// We know what we are, but we haven't got the data yet.
|
||||
return null;
|
||||
}
|
||||
default: {
|
||||
return (PendingConversationView({
|
||||
dispatcher: this.props.dispatcher,
|
||||
|
@ -499,6 +499,10 @@ loop.conversationViews = (function(mozL10n) {
|
||||
case CALL_STATES.FINISHED: {
|
||||
return this._renderFeedbackView();
|
||||
}
|
||||
case CALL_STATES.INIT: {
|
||||
// We know what we are, but we haven't got the data yet.
|
||||
return null;
|
||||
}
|
||||
default: {
|
||||
return (<PendingConversationView
|
||||
dispatcher={this.props.dispatcher}
|
||||
|
@ -30,6 +30,21 @@ loop.shared.actions = (function() {
|
||||
};
|
||||
|
||||
return {
|
||||
/**
|
||||
* Get the window data for the provided window id
|
||||
*/
|
||||
GetWindowData: Action.define("getWindowData", {
|
||||
windowId: String
|
||||
}),
|
||||
|
||||
/**
|
||||
* Used to pass round the window data so that stores can
|
||||
* record the appropriate data.
|
||||
*/
|
||||
SetupWindowData: Action.define("setupWindowData", {
|
||||
windowData: Object
|
||||
}),
|
||||
|
||||
/**
|
||||
* Fetch a new call url from the server, intended to be sent over email when
|
||||
* a contact can't be reached.
|
||||
@ -37,15 +52,6 @@ loop.shared.actions = (function() {
|
||||
FetchEmailLink: Action.define("fetchEmailLink", {
|
||||
}),
|
||||
|
||||
/**
|
||||
* Used to trigger gathering of initial call data.
|
||||
*/
|
||||
GatherCallData: Action.define("gatherCallData", {
|
||||
// Specify the callId for an incoming call.
|
||||
windowId: [String, null],
|
||||
outgoing: Boolean
|
||||
}),
|
||||
|
||||
/**
|
||||
* Used to cancel call setup.
|
||||
*/
|
||||
@ -167,16 +173,6 @@ loop.shared.actions = (function() {
|
||||
*/
|
||||
UpdateRoomList: Action.define("updateRoomList", {
|
||||
roomList: Array
|
||||
}),
|
||||
|
||||
/**
|
||||
* Primes localRoomStore with roomLocalId, which triggers the EmptyRoomView
|
||||
* to do any necessary setup.
|
||||
*
|
||||
* XXX should move to localRoomActions module
|
||||
*/
|
||||
SetupEmptyRoom: Action.define("setupEmptyRoom", {
|
||||
localRoomId: String
|
||||
})
|
||||
};
|
||||
})();
|
||||
|
@ -121,7 +121,7 @@ loop.store.ConversationStore = (function() {
|
||||
this.dispatcher.register(this, [
|
||||
"connectionFailure",
|
||||
"connectionProgress",
|
||||
"gatherCallData",
|
||||
"setupWindowData",
|
||||
"connectCall",
|
||||
"hangupCall",
|
||||
"peerHungupCall",
|
||||
@ -188,37 +188,24 @@ loop.store.ConversationStore = (function() {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the gather call data action, setting the state
|
||||
* and starting to get the appropriate data for the type of call.
|
||||
*
|
||||
* @param {sharedActions.GatherCallData} actionData The action data.
|
||||
*/
|
||||
gatherCallData: function(actionData) {
|
||||
if (!actionData.outgoing) {
|
||||
// XXX Other types aren't supported yet, but set the state for the
|
||||
// view selection.
|
||||
this.set({outgoing: false});
|
||||
return;
|
||||
}
|
||||
|
||||
var callData = navigator.mozLoop.getCallData(actionData.windowId);
|
||||
if (!callData) {
|
||||
console.error("Failed to get the call data");
|
||||
this.set({callState: CALL_STATES.TERMINATED});
|
||||
setupWindowData: function(actionData) {
|
||||
var windowData = actionData.windowData;
|
||||
var windowType = windowData.type;
|
||||
if (windowType !== "outgoing" &&
|
||||
windowType !== "incoming") {
|
||||
// Not for this store, don't do anything.
|
||||
return;
|
||||
}
|
||||
|
||||
this.set({
|
||||
contact: callData.contact,
|
||||
outgoing: actionData.outgoing,
|
||||
windowId: actionData.windowId,
|
||||
callType: callData.callType,
|
||||
callState: CALL_STATES.GATHER
|
||||
contact: windowData.contact,
|
||||
outgoing: windowType === "outgoing",
|
||||
windowId: windowData.windowId,
|
||||
callType: windowData.callType,
|
||||
callState: CALL_STATES.GATHER,
|
||||
videoMuted: windowData.callType === CALL_TYPES.AUDIO_ONLY
|
||||
});
|
||||
|
||||
this.set({videoMuted: this.get("callType") === CALL_TYPES.AUDIO_ONLY});
|
||||
|
||||
if (this.get("outgoing")) {
|
||||
this._setupOutgoingCall();
|
||||
} // XXX Else, other types aren't supported yet.
|
||||
|
@ -36,7 +36,9 @@ loop.store.LocalRoomStore = (function() {
|
||||
}
|
||||
this.mozLoop = options.mozLoop;
|
||||
|
||||
this.dispatcher.register(this, ["setupEmptyRoom"]);
|
||||
this.dispatcher.register(this, [
|
||||
"setupWindowData"
|
||||
]);
|
||||
}
|
||||
|
||||
LocalRoomStore.prototype = _.extend({
|
||||
@ -73,12 +75,13 @@ loop.store.LocalRoomStore = (function() {
|
||||
*
|
||||
* XXXremoveMe Can probably be removed when bug 1074664 lands.
|
||||
*
|
||||
* @param {sharedActions.setupEmptyRoom} actionData
|
||||
* @param {Integer} roomId The id of the room.
|
||||
* @param {Function} cb Callback(error, roomData)
|
||||
*/
|
||||
_fetchRoomData: function(actionData, cb) {
|
||||
if (this.mozLoop.rooms && this.mozLoop.rooms.getRoomData) {
|
||||
this.mozLoop.rooms.getRoomData(actionData.localRoomId, cb);
|
||||
_fetchRoomData: function(roomId, cb) {
|
||||
// XXX Remove me in bug 1074678
|
||||
if (!this.mozLoop.getLoopBoolPref("test.alwaysUseRooms")) {
|
||||
this.mozLoop.rooms.getRoomData(roomId, cb);
|
||||
} else {
|
||||
cb(null, {roomName: "Donkeys"});
|
||||
}
|
||||
@ -94,16 +97,22 @@ loop.store.LocalRoomStore = (function() {
|
||||
* When the room name gets set, that will trigger the view to display
|
||||
* that name.
|
||||
*
|
||||
* @param {sharedActions.setupEmptyRoom} actionData
|
||||
* @param {sharedActions.SetupWindowData} actionData
|
||||
*/
|
||||
setupEmptyRoom: function(actionData) {
|
||||
this._fetchRoomData(actionData, function(error, roomData) {
|
||||
this.setStoreState({
|
||||
error: error,
|
||||
localRoomId: actionData.localRoomId,
|
||||
serverData: roomData
|
||||
});
|
||||
}.bind(this));
|
||||
setupWindowData: function(actionData) {
|
||||
if (actionData.windowData.type !== "room") {
|
||||
// Nothing for us to do here, leave it to other stores.
|
||||
return;
|
||||
}
|
||||
|
||||
this._fetchRoomData(actionData.windowData.localRoomId,
|
||||
function(error, roomData) {
|
||||
this.setStoreState({
|
||||
error: error,
|
||||
localRoomId: actionData.windowData.localRoomId,
|
||||
serverData: roomData
|
||||
});
|
||||
}.bind(this));
|
||||
}
|
||||
|
||||
}, Backbone.Events);
|
||||
|
@ -13,6 +13,7 @@ browser.jar:
|
||||
# Desktop script
|
||||
content/browser/loop/js/client.js (content/js/client.js)
|
||||
content/browser/loop/js/conversation.js (content/js/conversation.js)
|
||||
content/browser/loop/js/conversationAppStore.js (content/js/conversationAppStore.js)
|
||||
content/browser/loop/js/otconfig.js (content/js/otconfig.js)
|
||||
content/browser/loop/js/panel.js (content/js/panel.js)
|
||||
content/browser/loop/js/contacts.js (content/js/contacts.js)
|
||||
|
@ -0,0 +1,84 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var expect = chai.expect;
|
||||
|
||||
describe("loop.store.ConversationAppStore", function () {
|
||||
|
||||
var sharedActions = loop.shared.actions;
|
||||
var sandbox, dispatcher;
|
||||
|
||||
beforeEach(function() {
|
||||
sandbox = sinon.sandbox.create();
|
||||
dispatcher = new loop.Dispatcher();
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
describe("#constructor", function() {
|
||||
it("should throw an error if the dispatcher is missing", function() {
|
||||
expect(function() {
|
||||
new loop.store.ConversationAppStore({mozLoop: {}});
|
||||
}).to.Throw(/dispatcher/);
|
||||
});
|
||||
|
||||
it("should throw an error if mozLoop is missing", function() {
|
||||
expect(function() {
|
||||
new loop.store.ConversationAppStore({dispatcher: dispatcher});
|
||||
}).to.Throw(/mozLoop/);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#getWindowData", function() {
|
||||
var fakeCallData, fakeGetWindowData, fakeMozLoop, store;
|
||||
|
||||
beforeEach(function() {
|
||||
fakeCallData = {
|
||||
type: "incoming",
|
||||
callId: "123456"
|
||||
};
|
||||
|
||||
fakeGetWindowData = {
|
||||
windowId: "42"
|
||||
};
|
||||
|
||||
fakeMozLoop = {
|
||||
// XXX Remove me in bug 1074678
|
||||
getLoopBoolPref: function() { return false; },
|
||||
getCallData: function(windowId) {
|
||||
if (windowId === "42") {
|
||||
return fakeCallData;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
store = new loop.store.ConversationAppStore({
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: fakeMozLoop
|
||||
});
|
||||
});
|
||||
|
||||
it("should fetch the window type from the mozLoop API", function() {
|
||||
dispatcher.dispatch(new sharedActions.GetWindowData(fakeGetWindowData));
|
||||
|
||||
expect(store.getStoreState()).eql({windowType: "incoming"});
|
||||
});
|
||||
|
||||
it("should dispatch a SetupWindowData action with the data from the mozLoop API",
|
||||
function() {
|
||||
sandbox.stub(dispatcher, "dispatch");
|
||||
|
||||
store.getWindowData(new sharedActions.GetWindowData(fakeGetWindowData));
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.SetupWindowData({
|
||||
windowData: fakeCallData
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
@ -438,10 +438,10 @@ describe("loop.conversationViews", function () {
|
||||
loop.conversationViews.CallFailedView);
|
||||
});
|
||||
|
||||
it("should render the PendingConversationView when the call state is 'init'",
|
||||
it("should render the PendingConversationView when the call state is 'gather'",
|
||||
function() {
|
||||
store.set({
|
||||
callState: CALL_STATES.INIT,
|
||||
callState: CALL_STATES.GATHER,
|
||||
contact: contact
|
||||
});
|
||||
|
||||
@ -474,7 +474,7 @@ describe("loop.conversationViews", function () {
|
||||
it("should update the rendered views when the state is changed.",
|
||||
function() {
|
||||
store.set({
|
||||
callState: CALL_STATES.INIT,
|
||||
callState: CALL_STATES.GATHER,
|
||||
contact: contact
|
||||
});
|
||||
|
||||
|
@ -80,7 +80,7 @@ describe("loop.conversation", function() {
|
||||
|
||||
sandbox.stub(loop.shared.utils.Helper.prototype,
|
||||
"locationData").returns({
|
||||
hash: "#incoming/42",
|
||||
hash: "#42",
|
||||
pathname: "/"
|
||||
});
|
||||
|
||||
@ -112,86 +112,30 @@ describe("loop.conversation", function() {
|
||||
}));
|
||||
});
|
||||
|
||||
describe("when locationHash begins with #room", function () {
|
||||
// XXX must stay in sync with "test.alwaysUseRooms" pref check
|
||||
// in conversation.jsx:init until we remove that code, which should
|
||||
// happen in the second patch in bug 1074686, at which time this comment
|
||||
// can go away as well.
|
||||
var fakeRoomID = "32";
|
||||
|
||||
beforeEach(function() {
|
||||
loop.shared.utils.Helper.prototype.locationData
|
||||
.returns({
|
||||
hash: "#room/" + fakeRoomID,
|
||||
pathname: ""
|
||||
});
|
||||
|
||||
sandbox.stub(loop.store, "LocalRoomStore");
|
||||
});
|
||||
|
||||
it("should create a localRoomStore", function() {
|
||||
loop.conversation.init();
|
||||
|
||||
sinon.assert.calledOnce(loop.store.LocalRoomStore);
|
||||
sinon.assert.calledWithNew(loop.store.LocalRoomStore);
|
||||
sinon.assert.calledWithExactly(loop.store.LocalRoomStore,
|
||||
sinon.match({
|
||||
dispatcher: sinon.match.instanceOf(loop.Dispatcher),
|
||||
mozLoop: sinon.match.same(navigator.mozLoop)
|
||||
}));
|
||||
});
|
||||
|
||||
it("should dispatch SetupEmptyRoom with localRoomId from locationHash",
|
||||
function() {
|
||||
|
||||
loop.conversation.init();
|
||||
|
||||
sinon.assert.calledOnce(loop.Dispatcher.prototype.dispatch);
|
||||
sinon.assert.calledWithExactly(loop.Dispatcher.prototype.dispatch,
|
||||
new loop.shared.actions.SetupEmptyRoom({localRoomId: fakeRoomID}));
|
||||
});
|
||||
});
|
||||
|
||||
it("should trigger a gatherCallData action", function() {
|
||||
it("should trigger a getWindowData action", function() {
|
||||
loop.conversation.init();
|
||||
|
||||
sinon.assert.calledOnce(loop.Dispatcher.prototype.dispatch);
|
||||
sinon.assert.calledWithExactly(loop.Dispatcher.prototype.dispatch,
|
||||
new loop.shared.actions.GatherCallData({
|
||||
windowId: "42",
|
||||
outgoing: false
|
||||
new loop.shared.actions.GetWindowData({
|
||||
windowId: "42"
|
||||
}));
|
||||
});
|
||||
|
||||
it("should trigger an outgoing gatherCallData action for outgoing calls",
|
||||
function() {
|
||||
loop.shared.utils.Helper.prototype.locationData.returns({
|
||||
hash: "#outgoing/24",
|
||||
pathname: "/"
|
||||
});
|
||||
|
||||
loop.conversation.init();
|
||||
|
||||
sinon.assert.calledOnce(loop.Dispatcher.prototype.dispatch);
|
||||
sinon.assert.calledWithExactly(loop.Dispatcher.prototype.dispatch,
|
||||
new loop.shared.actions.GatherCallData({
|
||||
windowId: "24",
|
||||
outgoing: true
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe("ConversationControllerView", function() {
|
||||
var store, conversation, client, ccView, oldTitle, dispatcher;
|
||||
describe("AppControllerView", function() {
|
||||
var conversationStore, conversation, client, ccView, oldTitle, dispatcher;
|
||||
var conversationAppStore, localRoomStore;
|
||||
|
||||
function mountTestComponent(localRoomStore) {
|
||||
function mountTestComponent() {
|
||||
return TestUtils.renderIntoDocument(
|
||||
loop.conversation.AppControllerView({
|
||||
client: client,
|
||||
conversation: conversation,
|
||||
localRoomStore: localRoomStore,
|
||||
sdk: {},
|
||||
store: store
|
||||
conversationStore: conversationStore,
|
||||
conversationAppStore: conversationAppStore
|
||||
}));
|
||||
}
|
||||
|
||||
@ -202,7 +146,7 @@ describe("loop.conversation", function() {
|
||||
sdk: {}
|
||||
});
|
||||
dispatcher = new loop.Dispatcher();
|
||||
store = new loop.store.ConversationStore({
|
||||
conversationStore = new loop.store.ConversationStore({
|
||||
contact: {
|
||||
name: [ "Mr Smith" ],
|
||||
email: [{
|
||||
@ -216,6 +160,14 @@ describe("loop.conversation", function() {
|
||||
dispatcher: dispatcher,
|
||||
sdkDriver: {}
|
||||
});
|
||||
localRoomStore = new loop.store.LocalRoomStore({
|
||||
mozLoop: navigator.mozLoop,
|
||||
dispatcher: dispatcher
|
||||
});
|
||||
conversationAppStore = new loop.store.ConversationAppStore({
|
||||
dispatcher: dispatcher,
|
||||
mozLoop: navigator.mozLoop
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
@ -224,7 +176,7 @@ describe("loop.conversation", function() {
|
||||
});
|
||||
|
||||
it("should display the OutgoingConversationView for outgoing calls", function() {
|
||||
store.set({outgoing: true});
|
||||
conversationAppStore.setStoreState({windowType: "outgoing"});
|
||||
|
||||
ccView = mountTestComponent();
|
||||
|
||||
@ -233,7 +185,7 @@ describe("loop.conversation", function() {
|
||||
});
|
||||
|
||||
it("should display the IncomingConversationView for incoming calls", function() {
|
||||
store.set({outgoing: false});
|
||||
conversationAppStore.setStoreState({windowType: "incoming"});
|
||||
|
||||
ccView = mountTestComponent();
|
||||
|
||||
@ -242,20 +194,22 @@ describe("loop.conversation", function() {
|
||||
});
|
||||
|
||||
it("should display the EmptyRoomView for rooms", function() {
|
||||
navigator.mozLoop.rooms = {
|
||||
addCallback: function() {},
|
||||
removeCallback: function() {}
|
||||
};
|
||||
var localRoomStore = new loop.store.LocalRoomStore({
|
||||
mozLoop: navigator.mozLoop,
|
||||
dispatcher: dispatcher
|
||||
});
|
||||
conversationAppStore.setStoreState({windowType: "room"});
|
||||
|
||||
ccView = mountTestComponent(localRoomStore);
|
||||
ccView = mountTestComponent();
|
||||
|
||||
TestUtils.findRenderedComponentWithType(ccView,
|
||||
loop.roomViews.EmptyRoomView);
|
||||
});
|
||||
|
||||
it("should display the GenericFailureView for failures", function() {
|
||||
conversationAppStore.setStoreState({windowType: "failed"});
|
||||
|
||||
ccView = mountTestComponent();
|
||||
|
||||
TestUtils.findRenderedComponentWithType(ccView,
|
||||
loop.conversation.GenericFailureView);
|
||||
});
|
||||
});
|
||||
|
||||
describe("IncomingConversationView", function() {
|
||||
@ -700,7 +654,7 @@ describe("loop.conversation", function() {
|
||||
conversation.trigger("session:network-disconnected");
|
||||
|
||||
TestUtils.findRenderedComponentWithType(icView,
|
||||
loop.conversation.IncomingCallFailedView);
|
||||
loop.conversation.GenericFailureView);
|
||||
});
|
||||
|
||||
it("should update the conversation window toolbar title",
|
||||
|
@ -46,6 +46,7 @@
|
||||
<script src="../../content/shared/js/roomListStore.js"></script>
|
||||
<script src="../../content/js/client.js"></script>
|
||||
<script src="../../content/shared/js/localRoomStore.js"></script>
|
||||
<script src="../../content/js/conversationAppStore.js"></script>
|
||||
<script src="../../content/js/roomViews.js"></script>
|
||||
<script src="../../content/js/conversationViews.js"></script>
|
||||
<script src="../../content/js/conversation.js"></script>
|
||||
@ -53,6 +54,7 @@
|
||||
<script src="../../content/js/panel.js"></script>
|
||||
|
||||
<!-- Test scripts -->
|
||||
<script src="conversationAppStore_test.js"></script>
|
||||
<script src="client_test.js"></script>
|
||||
<script src="conversation_test.js"></script>
|
||||
<script src="panel_test.js"></script>
|
||||
|
@ -221,40 +221,31 @@ describe("loop.store.ConversationStore", function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe("#gatherCallData", function() {
|
||||
describe("#setupWindowData", function() {
|
||||
var fakeSetupWindowData;
|
||||
|
||||
beforeEach(function() {
|
||||
store.set({callState: CALL_STATES.INIT});
|
||||
|
||||
navigator.mozLoop = {
|
||||
getCallData: function() {
|
||||
return {
|
||||
contact: contact,
|
||||
callType: sharedUtils.CALL_TYPES.AUDIO_VIDEO
|
||||
};
|
||||
fakeSetupWindowData = {
|
||||
windowData: {
|
||||
type: "outgoing",
|
||||
contact: contact,
|
||||
windowId: "123456",
|
||||
callType: sharedUtils.CALL_TYPES.AUDIO_VIDEO
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
delete navigator.mozLoop;
|
||||
});
|
||||
|
||||
it("should set the state to 'gather'", function() {
|
||||
dispatcher.dispatch(
|
||||
new sharedActions.GatherCallData({
|
||||
windowId: "76543218",
|
||||
outgoing: true
|
||||
}));
|
||||
new sharedActions.SetupWindowData(fakeSetupWindowData));
|
||||
|
||||
expect(store.get("callState")).eql(CALL_STATES.GATHER);
|
||||
});
|
||||
|
||||
it("should save the basic call information", function() {
|
||||
dispatcher.dispatch(
|
||||
new sharedActions.GatherCallData({
|
||||
windowId: "123456",
|
||||
outgoing: true
|
||||
}));
|
||||
new sharedActions.SetupWindowData(fakeSetupWindowData));
|
||||
|
||||
expect(store.get("windowId")).eql("123456");
|
||||
expect(store.get("outgoing")).eql(true);
|
||||
@ -262,28 +253,16 @@ describe("loop.store.ConversationStore", function () {
|
||||
|
||||
it("should save the basic information from the mozLoop api", function() {
|
||||
dispatcher.dispatch(
|
||||
new sharedActions.GatherCallData({
|
||||
windowId: "123456",
|
||||
outgoing: true
|
||||
}));
|
||||
new sharedActions.SetupWindowData(fakeSetupWindowData));
|
||||
|
||||
expect(store.get("contact")).eql(contact);
|
||||
expect(store.get("callType")).eql(sharedUtils.CALL_TYPES.AUDIO_VIDEO);
|
||||
});
|
||||
|
||||
describe("outgoing calls", function() {
|
||||
var outgoingCallData;
|
||||
|
||||
beforeEach(function() {
|
||||
outgoingCallData = {
|
||||
windowId: "123456",
|
||||
outgoing: true
|
||||
};
|
||||
});
|
||||
|
||||
it("should request the outgoing call data", function() {
|
||||
dispatcher.dispatch(
|
||||
new sharedActions.GatherCallData(outgoingCallData));
|
||||
new sharedActions.SetupWindowData(fakeSetupWindowData));
|
||||
|
||||
sinon.assert.calledOnce(client.setupOutgoingCall);
|
||||
sinon.assert.calledWith(client.setupOutgoingCall,
|
||||
@ -291,7 +270,7 @@ describe("loop.store.ConversationStore", function () {
|
||||
});
|
||||
|
||||
it("should include all email addresses in the call data", function() {
|
||||
contact = {
|
||||
fakeSetupWindowData.windowData.contact = {
|
||||
name: [ "Mr Smith" ],
|
||||
email: [{
|
||||
type: "home",
|
||||
@ -306,7 +285,7 @@ describe("loop.store.ConversationStore", function () {
|
||||
};
|
||||
|
||||
dispatcher.dispatch(
|
||||
new sharedActions.GatherCallData(outgoingCallData));
|
||||
new sharedActions.SetupWindowData(fakeSetupWindowData));
|
||||
|
||||
sinon.assert.calledOnce(client.setupOutgoingCall);
|
||||
sinon.assert.calledWith(client.setupOutgoingCall,
|
||||
@ -314,7 +293,7 @@ describe("loop.store.ConversationStore", function () {
|
||||
});
|
||||
|
||||
it("should include trim phone numbers for the call data", function() {
|
||||
contact = {
|
||||
fakeSetupWindowData.windowData.contact = {
|
||||
name: [ "Mr Smith" ],
|
||||
tel: [{
|
||||
type: "home",
|
||||
@ -324,7 +303,7 @@ describe("loop.store.ConversationStore", function () {
|
||||
};
|
||||
|
||||
dispatcher.dispatch(
|
||||
new sharedActions.GatherCallData(outgoingCallData));
|
||||
new sharedActions.SetupWindowData(fakeSetupWindowData));
|
||||
|
||||
sinon.assert.calledOnce(client.setupOutgoingCall);
|
||||
sinon.assert.calledWith(client.setupOutgoingCall,
|
||||
@ -332,7 +311,7 @@ describe("loop.store.ConversationStore", function () {
|
||||
});
|
||||
|
||||
it("should include all email and telephone values in the call data", function() {
|
||||
contact = {
|
||||
fakeSetupWindowData.windowData.contact = {
|
||||
name: [ "Mr Smith" ],
|
||||
email: [{
|
||||
type: "home",
|
||||
@ -355,7 +334,7 @@ describe("loop.store.ConversationStore", function () {
|
||||
};
|
||||
|
||||
dispatcher.dispatch(
|
||||
new sharedActions.GatherCallData(outgoingCallData));
|
||||
new sharedActions.SetupWindowData(fakeSetupWindowData));
|
||||
|
||||
sinon.assert.calledOnce(client.setupOutgoingCall);
|
||||
sinon.assert.calledWith(client.setupOutgoingCall,
|
||||
@ -375,8 +354,8 @@ describe("loop.store.ConversationStore", function () {
|
||||
|
||||
client.setupOutgoingCall.callsArgWith(2, null, callData);
|
||||
|
||||
store.gatherCallData(
|
||||
new sharedActions.GatherCallData(outgoingCallData));
|
||||
store.setupWindowData(
|
||||
new sharedActions.SetupWindowData(fakeSetupWindowData));
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
// Can't use instanceof here, as that matches any action
|
||||
@ -389,8 +368,8 @@ describe("loop.store.ConversationStore", function () {
|
||||
it("should dispatch a connection failure action on failure", function() {
|
||||
client.setupOutgoingCall.callsArgWith(2, {});
|
||||
|
||||
store.gatherCallData(
|
||||
new sharedActions.GatherCallData(outgoingCallData));
|
||||
store.setupWindowData(
|
||||
new sharedActions.SetupWindowData(fakeSetupWindowData));
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
// Can't use instanceof here, as that matches any action
|
||||
|
@ -22,31 +22,30 @@ describe("loop.Dispatcher", function () {
|
||||
it("should register a store against an action name", function() {
|
||||
var object = { fake: true };
|
||||
|
||||
dispatcher.register(object, ["gatherCallData"]);
|
||||
dispatcher.register(object, ["getWindowData"]);
|
||||
|
||||
expect(dispatcher._eventData["gatherCallData"][0]).eql(object);
|
||||
expect(dispatcher._eventData["getWindowData"][0]).eql(object);
|
||||
});
|
||||
|
||||
it("should register multiple store against an action name", function() {
|
||||
var object1 = { fake: true };
|
||||
var object2 = { fake2: true };
|
||||
|
||||
dispatcher.register(object1, ["gatherCallData"]);
|
||||
dispatcher.register(object2, ["gatherCallData"]);
|
||||
dispatcher.register(object1, ["getWindowData"]);
|
||||
dispatcher.register(object2, ["getWindowData"]);
|
||||
|
||||
expect(dispatcher._eventData["gatherCallData"][0]).eql(object1);
|
||||
expect(dispatcher._eventData["gatherCallData"][1]).eql(object2);
|
||||
expect(dispatcher._eventData["getWindowData"][0]).eql(object1);
|
||||
expect(dispatcher._eventData["getWindowData"][1]).eql(object2);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#dispatch", function() {
|
||||
var gatherStore1, gatherStore2, cancelStore1, connectStore1;
|
||||
var gatherAction, cancelAction, connectAction, resolveCancelStore1;
|
||||
var getDataStore1, getDataStore2, cancelStore1, connectStore1;
|
||||
var getDataAction, cancelAction, connectAction, resolveCancelStore1;
|
||||
|
||||
beforeEach(function() {
|
||||
gatherAction = new sharedActions.GatherCallData({
|
||||
windowId: "42",
|
||||
outgoing: false
|
||||
getDataAction = new sharedActions.GetWindowData({
|
||||
windowId: "42"
|
||||
});
|
||||
|
||||
cancelAction = new sharedActions.CancelCall();
|
||||
@ -54,11 +53,11 @@ describe("loop.Dispatcher", function () {
|
||||
sessionData: {}
|
||||
});
|
||||
|
||||
gatherStore1 = {
|
||||
gatherCallData: sinon.stub()
|
||||
getDataStore1 = {
|
||||
getWindowData: sinon.stub()
|
||||
};
|
||||
gatherStore2 = {
|
||||
gatherCallData: sinon.stub()
|
||||
getDataStore2 = {
|
||||
getWindowData: sinon.stub()
|
||||
};
|
||||
cancelStore1 = {
|
||||
cancelCall: sinon.stub()
|
||||
@ -67,8 +66,8 @@ describe("loop.Dispatcher", function () {
|
||||
connectCall: function() {}
|
||||
};
|
||||
|
||||
dispatcher.register(gatherStore1, ["gatherCallData"]);
|
||||
dispatcher.register(gatherStore2, ["gatherCallData"]);
|
||||
dispatcher.register(getDataStore1, ["getWindowData"]);
|
||||
dispatcher.register(getDataStore2, ["getWindowData"]);
|
||||
dispatcher.register(cancelStore1, ["cancelCall"]);
|
||||
dispatcher.register(connectStore1, ["connectCall"]);
|
||||
});
|
||||
@ -76,33 +75,33 @@ describe("loop.Dispatcher", function () {
|
||||
it("should dispatch an action to the required object", function() {
|
||||
dispatcher.dispatch(cancelAction);
|
||||
|
||||
sinon.assert.notCalled(gatherStore1.gatherCallData);
|
||||
sinon.assert.notCalled(getDataStore1.getWindowData);
|
||||
|
||||
sinon.assert.calledOnce(cancelStore1.cancelCall);
|
||||
sinon.assert.calledWithExactly(cancelStore1.cancelCall, cancelAction);
|
||||
|
||||
sinon.assert.notCalled(gatherStore2.gatherCallData);
|
||||
sinon.assert.notCalled(getDataStore2.getWindowData);
|
||||
});
|
||||
|
||||
it("should dispatch actions to multiple objects", function() {
|
||||
dispatcher.dispatch(gatherAction);
|
||||
dispatcher.dispatch(getDataAction);
|
||||
|
||||
sinon.assert.calledOnce(gatherStore1.gatherCallData);
|
||||
sinon.assert.calledWithExactly(gatherStore1.gatherCallData, gatherAction);
|
||||
sinon.assert.calledOnce(getDataStore1.getWindowData);
|
||||
sinon.assert.calledWithExactly(getDataStore1.getWindowData, getDataAction);
|
||||
|
||||
sinon.assert.notCalled(cancelStore1.cancelCall);
|
||||
|
||||
sinon.assert.calledOnce(gatherStore2.gatherCallData);
|
||||
sinon.assert.calledWithExactly(gatherStore2.gatherCallData, gatherAction);
|
||||
sinon.assert.calledOnce(getDataStore2.getWindowData);
|
||||
sinon.assert.calledWithExactly(getDataStore2.getWindowData, getDataAction);
|
||||
});
|
||||
|
||||
it("should dispatch multiple actions", function() {
|
||||
dispatcher.dispatch(cancelAction);
|
||||
dispatcher.dispatch(gatherAction);
|
||||
dispatcher.dispatch(getDataAction);
|
||||
|
||||
sinon.assert.calledOnce(cancelStore1.cancelCall);
|
||||
sinon.assert.calledOnce(gatherStore1.gatherCallData);
|
||||
sinon.assert.calledOnce(gatherStore2.gatherCallData);
|
||||
sinon.assert.calledOnce(getDataStore1.getWindowData);
|
||||
sinon.assert.calledOnce(getDataStore2.getWindowData);
|
||||
});
|
||||
|
||||
describe("Queued actions", function() {
|
||||
@ -110,10 +109,10 @@ describe("loop.Dispatcher", function () {
|
||||
// Restore the stub, so that we can easily add a function to be
|
||||
// returned. Unfortunately, sinon doesn't make this easy.
|
||||
sandbox.stub(connectStore1, "connectCall", function() {
|
||||
dispatcher.dispatch(gatherAction);
|
||||
dispatcher.dispatch(getDataAction);
|
||||
|
||||
sinon.assert.notCalled(gatherStore1.gatherCallData);
|
||||
sinon.assert.notCalled(gatherStore2.gatherCallData);
|
||||
sinon.assert.notCalled(getDataStore1.getWindowData);
|
||||
sinon.assert.notCalled(getDataStore2.getWindowData);
|
||||
});
|
||||
});
|
||||
|
||||
@ -132,8 +131,8 @@ describe("loop.Dispatcher", function () {
|
||||
|
||||
sinon.assert.calledOnce(connectStore1.connectCall);
|
||||
// These should be called, because the dispatcher synchronously queues actions.
|
||||
sinon.assert.calledOnce(gatherStore1.gatherCallData);
|
||||
sinon.assert.calledOnce(gatherStore2.gatherCallData);
|
||||
sinon.assert.calledOnce(getDataStore1.getWindowData);
|
||||
sinon.assert.calledOnce(getDataStore2.getWindowData);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -31,14 +31,15 @@ describe("loop.store.LocalRoomStore", function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe("#setupEmptyRoom", function() {
|
||||
describe("#setupWindowData", function() {
|
||||
var store, fakeMozLoop, fakeRoomId, fakeRoomName;
|
||||
|
||||
beforeEach(function() {
|
||||
fakeRoomId = "337-ff-54";
|
||||
fakeRoomName = "Monkeys";
|
||||
fakeMozLoop = {
|
||||
rooms: { getRoomData: sandbox.stub() }
|
||||
rooms: { getRoomData: sandbox.stub() },
|
||||
getLoopBoolPref: function () { return false; }
|
||||
};
|
||||
|
||||
store = new loop.store.LocalRoomStore(
|
||||
@ -57,8 +58,12 @@ describe("loop.store.LocalRoomStore", function () {
|
||||
done();
|
||||
});
|
||||
|
||||
dispatcher.dispatch(new sharedActions.SetupEmptyRoom(
|
||||
{localRoomId: fakeRoomId}));
|
||||
dispatcher.dispatch(new sharedActions.SetupWindowData({
|
||||
windowData: {
|
||||
type: "room",
|
||||
localRoomId: fakeRoomId
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
it("should set localRoomId on the store from the action data",
|
||||
@ -70,9 +75,13 @@ describe("loop.store.LocalRoomStore", function () {
|
||||
done();
|
||||
});
|
||||
|
||||
dispatcher.dispatch(
|
||||
new sharedActions.SetupEmptyRoom({localRoomId: fakeRoomId}));
|
||||
});
|
||||
dispatcher.dispatch(new sharedActions.SetupWindowData({
|
||||
windowData: {
|
||||
type: "room",
|
||||
localRoomId: fakeRoomId
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
it("should set serverData.roomName from the getRoomData callback",
|
||||
function(done) {
|
||||
@ -83,8 +92,12 @@ describe("loop.store.LocalRoomStore", function () {
|
||||
done();
|
||||
});
|
||||
|
||||
dispatcher.dispatch(
|
||||
new sharedActions.SetupEmptyRoom({localRoomId: fakeRoomId}));
|
||||
dispatcher.dispatch(new sharedActions.SetupWindowData({
|
||||
windowData: {
|
||||
type: "room",
|
||||
localRoomId: fakeRoomId
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
it("should set error on the store when getRoomData calls back an error",
|
||||
@ -102,8 +115,12 @@ describe("loop.store.LocalRoomStore", function () {
|
||||
done();
|
||||
});
|
||||
|
||||
dispatcher.dispatch(
|
||||
new sharedActions.SetupEmptyRoom({localRoomId: fakeRoomId}));
|
||||
dispatcher.dispatch(new sharedActions.SetupWindowData({
|
||||
windowData: {
|
||||
type: "room",
|
||||
localRoomId: fakeRoomId
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -26,7 +26,7 @@ add_task(function test_startDirectCall_opens_window() {
|
||||
do_check_true(!!openedUrl, "should open a chat window");
|
||||
|
||||
// Stop the busy kicking in for following tests.
|
||||
let callId = openedUrl.match(/about:loopconversation\#outgoing\/(.*)/)[1];
|
||||
let callId = openedUrl.match(/about:loopconversation\#(\d+)$/)[1];
|
||||
LoopCalls.releaseCallData(callId);
|
||||
});
|
||||
|
||||
@ -38,7 +38,7 @@ add_task(function test_startDirectCall_getCallData() {
|
||||
|
||||
LoopCalls.startDirectCall(contact, "audio-video");
|
||||
|
||||
let callId = openedUrl.match(/about:loopconversation\#outgoing\/(.*)/)[1];
|
||||
let callId = openedUrl.match(/about:loopconversation\#(\d+)$/)[1];
|
||||
|
||||
let callData = LoopCalls.getCallData(callId);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user