Bug 1106474 - Drop conversationStore's use of Backbone.Model for Loop. r=nperriault

This commit is contained in:
Mark Banner 2014-12-02 13:50:37 -08:00
parent d4b9453ca0
commit 43e7a4852c
9 changed files with 238 additions and 212 deletions

View File

@ -656,9 +656,9 @@ loop.conversation = (function(mozL10n) {
dispatcher: dispatcher,
mozLoop: navigator.mozLoop
});
var conversationStore = new loop.store.ConversationStore({}, {
var conversationStore = new loop.store.ConversationStore(dispatcher, {
client: client,
dispatcher: dispatcher,
mozLoop: navigator.mozLoop,
sdkDriver: sdkDriver
});
var activeRoomStore = new loop.store.ActiveRoomStore(dispatcher, {

View File

@ -656,9 +656,9 @@ loop.conversation = (function(mozL10n) {
dispatcher: dispatcher,
mozLoop: navigator.mozLoop
});
var conversationStore = new loop.store.ConversationStore({}, {
var conversationStore = new loop.store.ConversationStore(dispatcher, {
client: client,
dispatcher: dispatcher,
mozLoop: navigator.mozLoop,
sdkDriver: sdkDriver
});
var activeRoomStore = new loop.store.ActiveRoomStore(dispatcher, {

View File

@ -224,7 +224,7 @@ loop.conversationViews = (function(mozL10n) {
},
_onEmailLinkReceived: function() {
var emailLink = this.props.store.get("emailLink");
var emailLink = this.props.store.getStoreState("emailLink");
var contactEmail = _getPreferredEmail(this.props.contact).value;
sharedUtils.composeCallUrlEmail(emailLink, contactEmail);
window.close();
@ -428,7 +428,10 @@ loop.conversationViews = (function(mozL10n) {
* the different views that need displaying.
*/
var OutgoingConversationView = React.createClass({displayName: 'OutgoingConversationView',
mixins: [sharedMixins.AudioMixin],
mixins: [
sharedMixins.AudioMixin,
Backbone.Events
],
propTypes: {
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
@ -438,12 +441,18 @@ loop.conversationViews = (function(mozL10n) {
},
getInitialState: function() {
return this.props.store.attributes;
return this.props.store.getStoreState();
},
componentWillMount: function() {
this.props.store.on("change", function() {
this.setState(this.props.store.attributes);
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);
},

View File

@ -224,7 +224,7 @@ loop.conversationViews = (function(mozL10n) {
},
_onEmailLinkReceived: function() {
var emailLink = this.props.store.get("emailLink");
var emailLink = this.props.store.getStoreState("emailLink");
var contactEmail = _getPreferredEmail(this.props.contact).value;
sharedUtils.composeCallUrlEmail(emailLink, contactEmail);
window.close();
@ -428,7 +428,10 @@ loop.conversationViews = (function(mozL10n) {
* the different views that need displaying.
*/
var OutgoingConversationView = React.createClass({
mixins: [sharedMixins.AudioMixin],
mixins: [
sharedMixins.AudioMixin,
Backbone.Events
],
propTypes: {
dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
@ -438,12 +441,18 @@ loop.conversationViews = (function(mozL10n) {
},
getInitialState: function() {
return this.props.store.attributes;
return this.props.store.getStoreState();
},
componentWillMount: function() {
this.props.store.on("change", function() {
this.setState(this.props.store.attributes);
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);
},

View File

@ -7,7 +7,7 @@
var loop = loop || {};
loop.store = loop.store || {};
loop.store.ConversationStore = (function() {
(function() {
var sharedActions = loop.shared.actions;
var CALL_TYPES = loop.shared.utils.CALL_TYPES;
@ -53,81 +53,84 @@ loop.store.ConversationStore = (function() {
TERMINATED: "cs-terminated"
};
// XXX this needs to migrate to use loop.store.createStore
var ConversationStore = Backbone.Model.extend({
defaults: {
// The id of the window. Currently used for getting the window id.
windowId: undefined,
// The current state of the call
callState: CALL_STATES.INIT,
// The reason if a call was terminated
callStateReason: undefined,
// The error information, if there was a failure
error: undefined,
// True if the call is outgoing, false if not, undefined if unknown
outgoing: undefined,
// The contact being called for outgoing calls
contact: undefined,
// The call type for the call.
// XXX Don't hard-code, this comes from the data in bug 1072323
callType: CALL_TYPES.AUDIO_VIDEO,
/**
* Conversation store.
*
* @param {loop.Dispatcher} dispatcher The dispatcher for dispatching actions
* and registering to consume actions.
* @param {Object} options Options object:
* - {client} client The client object.
* - {mozLoop} mozLoop The MozLoop API object.
* - {loop.OTSdkDriver} loop.OTSdkDriver The SDK Driver
*/
loop.store.ConversationStore = loop.store.createStore({
// Further actions are registered in setupWindowData when
// we know what window type this is.
actions: [
"setupWindowData"
],
// Call Connection information
// The call id from the loop-server
callId: undefined,
// The caller id of the contacting side
callerId: undefined,
// The connection progress url to connect the websocket
progressURL: undefined,
// The websocket token that allows connection to the progress url
websocketToken: undefined,
// SDK API key
apiKey: undefined,
// SDK session ID
sessionId: undefined,
// SDK session token
sessionToken: undefined,
// If the audio is muted
audioMuted: false,
// If the video is muted
videoMuted: false
getInitialStoreState: function() {
return {
// The id of the window. Currently used for getting the window id.
windowId: undefined,
// The current state of the call
callState: CALL_STATES.INIT,
// The reason if a call was terminated
callStateReason: undefined,
// True if the call is outgoing, false if not, undefined if unknown
outgoing: undefined,
// The contact being called for outgoing calls
contact: undefined,
// The call type for the call.
// XXX Don't hard-code, this comes from the data in bug 1072323
callType: CALL_TYPES.AUDIO_VIDEO,
// A link for emailing once obtained from the server
emailLink: undefined,
// Call Connection information
// The call id from the loop-server
callId: undefined,
// The caller id of the contacting side
callerId: undefined,
// The connection progress url to connect the websocket
progressURL: undefined,
// The websocket token that allows connection to the progress url
websocketToken: undefined,
// SDK API key
apiKey: undefined,
// SDK session ID
sessionId: undefined,
// SDK session token
sessionToken: undefined,
// If the audio is muted
audioMuted: false,
// If the video is muted
videoMuted: false
};
},
/**
* Constructor
* Handles initialisation of the store.
*
* Options:
* - {loop.Dispatcher} dispatcher The dispatcher for dispatching actions and
* registering to consume actions.
* - {Object} client A client object for communicating with the server.
*
* @param {Object} attributes Attributes object.
* @param {Object} options Options object.
*/
initialize: function(attributes, options) {
initialize: function(options) {
options = options || {};
if (!options.dispatcher) {
throw new Error("Missing option dispatcher");
}
if (!options.client) {
throw new Error("Missing option client");
}
if (!options.sdkDriver) {
throw new Error("Missing option sdkDriver");
}
if (!options.mozLoop) {
throw new Error("Missing option mozLoop");
}
this.client = options.client;
this.dispatcher = options.dispatcher;
this.sdkDriver = options.sdkDriver;
// XXX Further actions are registered in setupWindowData when
// we know what window type this is. At some stage, we might want to
// consider store mixins or some alternative which means the stores
// would only be created when we want them.
this.dispatcher.register(this, [
"setupWindowData"
]);
this.mozLoop = options.mozLoop;
},
/**
@ -138,7 +141,7 @@ loop.store.ConversationStore = (function() {
*/
connectionFailure: function(actionData) {
this._endSession();
this.set({
this.setStoreState({
callState: CALL_STATES.TERMINATED,
callStateReason: actionData.reason
});
@ -151,34 +154,35 @@ loop.store.ConversationStore = (function() {
* @param {sharedActions.ConnectionProgress} actionData The action data.
*/
connectionProgress: function(actionData) {
var callState = this.get("callState");
var state = this.getStoreState();
switch(actionData.wsState) {
case WS_STATES.INIT: {
if (callState === CALL_STATES.GATHER) {
this.set({callState: CALL_STATES.CONNECTING});
if (state.callState === CALL_STATES.GATHER) {
this.setStoreState({callState: CALL_STATES.CONNECTING});
}
break;
}
case WS_STATES.ALERTING: {
this.set({callState: CALL_STATES.ALERTING});
this.setStoreState({callState: CALL_STATES.ALERTING});
break;
}
case WS_STATES.CONNECTING: {
this.sdkDriver.connectSession({
apiKey: this.get("apiKey"),
sessionId: this.get("sessionId"),
sessionToken: this.get("sessionToken")
apiKey: state.apiKey,
sessionId: state.sessionId,
sessionToken: state.sessionToken
});
navigator.mozLoop.addConversationContext(this.get("windowId"),
this.get("sessionId"),
this.get("callId"));
this.set({callState: CALL_STATES.ONGOING});
this.mozLoop.addConversationContext(
state.windowId,
state.sessionId,
state.callId);
this.setStoreState({callState: CALL_STATES.ONGOING});
break;
}
case WS_STATES.HALF_CONNECTED:
case WS_STATES.CONNECTED: {
this.set({callState: CALL_STATES.ONGOING});
this.setStoreState({callState: CALL_STATES.ONGOING});
break;
}
default: {
@ -209,7 +213,7 @@ loop.store.ConversationStore = (function() {
"fetchEmailLink"
]);
this.set({
this.setStoreState({
contact: actionData.contact,
outgoing: windowType === "outgoing",
windowId: actionData.windowId,
@ -218,7 +222,7 @@ loop.store.ConversationStore = (function() {
videoMuted: actionData.callType === CALL_TYPES.AUDIO_ONLY
});
if (this.get("outgoing")) {
if (this.getStoreState("outgoing")) {
this._setupOutgoingCall();
} // XXX Else, other types aren't supported yet.
},
@ -231,7 +235,7 @@ loop.store.ConversationStore = (function() {
* @param {sharedActions.ConnectCall} actionData The action data.
*/
connectCall: function(actionData) {
this.set(actionData.sessionData);
this.setStoreState(actionData.sessionData);
this._connectWebSocket();
},
@ -245,7 +249,7 @@ loop.store.ConversationStore = (function() {
}
this._endSession();
this.set({callState: CALL_STATES.FINISHED});
this.setStoreState({callState: CALL_STATES.FINISHED});
},
/**
@ -259,9 +263,9 @@ loop.store.ConversationStore = (function() {
// If the peer hungup, we end normally, otherwise
// we treat this as a call failure.
if (actionData.peerHungup) {
this.set({callState: CALL_STATES.FINISHED});
this.setStoreState({callState: CALL_STATES.FINISHED});
} else {
this.set({
this.setStoreState({
callState: CALL_STATES.TERMINATED,
callStateReason: "peerNetworkDisconnected"
});
@ -272,7 +276,7 @@ loop.store.ConversationStore = (function() {
* Cancels a call
*/
cancelCall: function() {
var callState = this.get("callState");
var callState = this.getStoreState("callState");
if (this._websocket &&
(callState === CALL_STATES.CONNECTING ||
callState === CALL_STATES.ALERTING)) {
@ -281,21 +285,21 @@ loop.store.ConversationStore = (function() {
}
this._endSession();
this.set({callState: CALL_STATES.CLOSE});
this.setStoreState({callState: CALL_STATES.CLOSE});
},
/**
* Retries a call
*/
retryCall: function() {
var callState = this.get("callState");
var callState = this.getStoreState("callState");
if (callState !== CALL_STATES.TERMINATED) {
console.error("Unexpected retry in state", callState);
return;
}
this.set({callState: CALL_STATES.GATHER});
if (this.get("outgoing")) {
this.setStoreState({callState: CALL_STATES.GATHER});
if (this.getStoreState("outgoing")) {
this._setupOutgoingCall();
}
},
@ -313,8 +317,9 @@ loop.store.ConversationStore = (function() {
* @param {sharedActions.setMute} actionData The mute state for the stream type.
*/
setMute: function(actionData) {
var muteType = actionData.type + "Muted";
this.set(muteType, !actionData.enabled);
var newState = {};
newState[actionData.type + "Muted"] = !actionData.enabled;
this.setStoreState(newState);
},
/**
@ -329,7 +334,7 @@ loop.store.ConversationStore = (function() {
this.trigger("error:emailLink");
return;
}
this.set("emailLink", callUrlData.callUrl);
this.setStoreState({"emailLink": callUrlData.callUrl});
}.bind(this));
},
@ -339,9 +344,9 @@ loop.store.ConversationStore = (function() {
*/
_setupOutgoingCall: function() {
var contactAddresses = [];
var contact = this.get("contact");
var contact = this.getStoreState("contact");
navigator.mozLoop.calls.setCallInProgress(this.get("windowId"));
this.mozLoop.calls.setCallInProgress(this.getStoreState("windowId"));
function appendContactValues(property, strip) {
if (contact.hasOwnProperty(property)) {
@ -362,7 +367,7 @@ loop.store.ConversationStore = (function() {
appendContactValues("tel", true);
this.client.setupOutgoingCall(contactAddresses,
this.get("callType"),
this.getStoreState("callType"),
function(err, result) {
if (err) {
console.error("Failed to get outgoing call data", err);
@ -385,9 +390,9 @@ loop.store.ConversationStore = (function() {
*/
_connectWebSocket: function() {
this._websocket = new loop.CallConnectionWebSocket({
url: this.get("progressURL"),
callId: this.get("callId"),
websocketToken: this.get("websocketToken")
url: this.getStoreState("progressURL"),
callId: this.getStoreState("callId"),
websocketToken: this.getStoreState("websocketToken")
});
this._websocket.promiseConnect().then(
@ -422,7 +427,8 @@ loop.store.ConversationStore = (function() {
delete this._websocket;
}
navigator.mozLoop.calls.clearCallInProgress(this.get("windowId"));
this.mozLoop.calls.clearCallInProgress(
this.getStoreState("windowId"));
},
/**
@ -450,6 +456,4 @@ loop.store.ConversationStore = (function() {
this.dispatcher.dispatch(action);
}
});
return ConversationStore;
})();

View File

@ -8,6 +8,7 @@ describe("loop.conversationViews", function () {
var sharedUtils = loop.shared.utils;
var sandbox, oldTitle, view, dispatcher, contact, fakeAudioXHR;
var fakeMozLoop;
var CALL_STATES = loop.store.CALL_STATES;
@ -43,7 +44,7 @@ describe("loop.conversationViews", function () {
onload: null
};
navigator.mozLoop = {
fakeMozLoop = navigator.mozLoop = {
getLoopPref: sinon.stub().returns("http://fakeurl"),
composeEmail: sinon.spy(),
get appVersionInfo() {
@ -242,9 +243,9 @@ describe("loop.conversationViews", function () {
}
beforeEach(function() {
store = new loop.store.ConversationStore({}, {
dispatcher: dispatcher,
store = new loop.store.ConversationStore(dispatcher, {
client: {},
mozLoop: navigator.mozLoop,
sdkDriver: {}
});
fakeAudio = {
@ -306,7 +307,7 @@ describe("loop.conversationViews", function () {
it("should compose an email once the email link is received", function() {
var composeCallUrlEmail = sandbox.stub(sharedUtils, "composeCallUrlEmail");
view = mountTestComponent();
store.set("emailLink", "http://fake.invalid/");
store.setStoreState({emailLink: "http://fake.invalid/"});
sinon.assert.calledOnce(composeCallUrlEmail);
sinon.assert.calledWithExactly(composeCallUrlEmail,
@ -318,7 +319,7 @@ describe("loop.conversationViews", function () {
sandbox.stub(window, "close");
view = mountTestComponent();
store.set("emailLink", "http://fake.invalid/");
store.setStoreState({emailLink: "http://fake.invalid/"});
sinon.assert.calledOnce(window.close);
});
@ -457,9 +458,9 @@ describe("loop.conversationViews", function () {
}
beforeEach(function() {
store = new loop.store.ConversationStore({}, {
dispatcher: dispatcher,
store = new loop.store.ConversationStore(dispatcher, {
client: {},
mozLoop: fakeMozLoop,
sdkDriver: {}
});
feedbackStore = new loop.store.FeedbackStore(dispatcher, {
@ -469,7 +470,7 @@ describe("loop.conversationViews", function () {
it("should render the CallFailedView when the call state is 'terminated'",
function() {
store.set({callState: CALL_STATES.TERMINATED});
store.setStoreState({callState: CALL_STATES.TERMINATED});
view = mountTestComponent();
@ -479,7 +480,7 @@ describe("loop.conversationViews", function () {
it("should render the PendingConversationView when the call state is 'gather'",
function() {
store.set({
store.setStoreState({
callState: CALL_STATES.GATHER,
contact: contact
});
@ -492,7 +493,7 @@ describe("loop.conversationViews", function () {
it("should render the OngoingConversationView when the call state is 'ongoing'",
function() {
store.set({callState: CALL_STATES.ONGOING});
store.setStoreState({callState: CALL_STATES.ONGOING});
view = mountTestComponent();
@ -502,7 +503,7 @@ describe("loop.conversationViews", function () {
it("should render the FeedbackView when the call state is 'finished'",
function() {
store.set({callState: CALL_STATES.FINISHED});
store.setStoreState({callState: CALL_STATES.FINISHED});
view = mountTestComponent();
@ -519,7 +520,7 @@ describe("loop.conversationViews", function () {
};
sandbox.stub(window, "Audio").returns(fakeAudio);
store.set({callState: CALL_STATES.FINISHED});
store.setStoreState({callState: CALL_STATES.FINISHED});
view = mountTestComponent();
@ -528,7 +529,7 @@ describe("loop.conversationViews", function () {
it("should update the rendered views when the state is changed.",
function() {
store.set({
store.setStoreState({
callState: CALL_STATES.GATHER,
contact: contact
});
@ -538,7 +539,7 @@ describe("loop.conversationViews", function () {
TestUtils.findRenderedComponentWithType(view,
loop.conversationViews.PendingConversationView);
store.set({callState: CALL_STATES.TERMINATED});
store.setStoreState({callState: CALL_STATES.TERMINATED});
TestUtils.findRenderedComponentWithType(view,
loop.conversationViews.CallFailedView);

View File

@ -160,20 +160,22 @@ describe("loop.conversation", function() {
sdk: {}
});
dispatcher = new loop.Dispatcher();
conversationStore = new loop.store.ConversationStore({
contact: {
name: [ "Mr Smith" ],
email: [{
type: "home",
value: "fakeEmail",
pref: true
}]
}
}, {
client: client,
dispatcher: dispatcher,
sdkDriver: {}
});
conversationStore = new loop.store.ConversationStore(
dispatcher, {
client: client,
mozLoop: navigator.mozLoop,
sdkDriver: {}
});
conversationStore.setStoreState({contact: {
name: [ "Mr Smith" ],
email: [{
type: "home",
value: "fakeEmail",
pref: true
}]
}});
roomStore = new loop.store.RoomStore(dispatcher, {
mozLoop: navigator.mozLoop,
});

View File

@ -41,7 +41,6 @@
<!-- App scripts -->
<script src="../../content/shared/js/utils.js"></script>
<script src="../../content/shared/js/feedbackApiClient.js"></script>
<script src="../../content/shared/js/conversationStore.js"></script>
<script src="../../content/shared/js/models.js"></script>
<script src="../../content/shared/js/mixins.js"></script>
<script src="../../content/shared/js/views.js"></script>
@ -51,6 +50,7 @@
<script src="../../content/shared/js/dispatcher.js"></script>
<script src="../../content/shared/js/otSdkDriver.js"></script>
<script src="../../content/shared/js/store.js"></script>
<script src="../../content/shared/js/conversationStore.js"></script>
<script src="../../content/shared/js/roomStore.js"></script>
<script src="../../content/shared/js/activeRoomStore.js"></script>
<script src="../../content/shared/js/feedbackStore.js"></script>

View File

@ -11,7 +11,7 @@ describe("loop.store.ConversationStore", function () {
var sharedActions = loop.shared.actions;
var sharedUtils = loop.shared.utils;
var sandbox, dispatcher, client, store, fakeSessionData, sdkDriver;
var contact;
var contact, fakeMozLoop;
var connectPromise, resolveConnectPromise, rejectConnectPromise;
var wsCancelSpy, wsCloseSpy, wsMediaUpSpy, fakeWebsocket;
@ -36,7 +36,7 @@ describe("loop.store.ConversationStore", function () {
}]
};
navigator.mozLoop = {
fakeMozLoop = {
getLoopPref: sandbox.stub(),
addConversationContext: sandbox.stub(),
calls: {
@ -65,9 +65,9 @@ describe("loop.store.ConversationStore", function () {
mediaUp: wsMediaUpSpy
};
store = new loop.store.ConversationStore({}, {
store = new loop.store.ConversationStore(dispatcher, {
client: client,
dispatcher: dispatcher,
mozLoop: fakeMozLoop,
sdkDriver: sdkDriver
});
fakeSessionData = {
@ -99,19 +99,9 @@ describe("loop.store.ConversationStore", function () {
});
describe("#initialize", function() {
it("should throw an error if the dispatcher is missing", function() {
expect(function() {
new loop.store.ConversationStore({}, {
client: client,
sdkDriver: sdkDriver
});
}).to.Throw(/dispatcher/);
});
it("should throw an error if the client is missing", function() {
expect(function() {
new loop.store.ConversationStore({}, {
dispatcher: dispatcher,
new loop.store.ConversationStore(dispatcher, {
sdkDriver: sdkDriver
});
}).to.Throw(/client/);
@ -119,18 +109,26 @@ describe("loop.store.ConversationStore", function () {
it("should throw an error if the sdkDriver is missing", function() {
expect(function() {
new loop.store.ConversationStore({}, {
client: client,
dispatcher: dispatcher
new loop.store.ConversationStore(dispatcher, {
client: client
});
}).to.Throw(/sdkDriver/);
});
it("should throw an error if mozLoop is missing", function() {
expect(function() {
new loop.store.ConversationStore(dispatcher, {
sdkDriver: sdkDriver,
client: client
});
}).to.Throw(/mozLoop/);
});
});
describe("#connectionFailure", function() {
beforeEach(function() {
store._websocket = fakeWebsocket;
store.set({windowId: "42"});
store.setStoreState({windowId: "42"});
});
it("should disconnect the session", function() {
@ -148,71 +146,71 @@ describe("loop.store.ConversationStore", function () {
});
it("should set the state to 'terminated'", function() {
store.set({callState: CALL_STATES.ALERTING});
store.setStoreState({callState: CALL_STATES.ALERTING});
store.connectionFailure(
new sharedActions.ConnectionFailure({reason: "fake"}));
expect(store.get("callState")).eql(CALL_STATES.TERMINATED);
expect(store.get("callStateReason")).eql("fake");
expect(store.getStoreState("callState")).eql(CALL_STATES.TERMINATED);
expect(store.getStoreState("callStateReason")).eql("fake");
});
it("should release mozLoop callsData", function() {
store.connectionFailure(
new sharedActions.ConnectionFailure({reason: "fake"}));
sinon.assert.calledOnce(navigator.mozLoop.calls.clearCallInProgress);
sinon.assert.calledOnce(fakeMozLoop.calls.clearCallInProgress);
sinon.assert.calledWithExactly(
navigator.mozLoop.calls.clearCallInProgress, "42");
fakeMozLoop.calls.clearCallInProgress, "42");
});
});
describe("#connectionProgress", function() {
describe("progress: init", function() {
it("should change the state from 'gather' to 'connecting'", function() {
store.set({callState: CALL_STATES.GATHER});
store.setStoreState({callState: CALL_STATES.GATHER});
store.connectionProgress(
new sharedActions.ConnectionProgress({wsState: WS_STATES.INIT}));
expect(store.get("callState")).eql(CALL_STATES.CONNECTING);
expect(store.getStoreState("callState")).eql(CALL_STATES.CONNECTING);
});
});
describe("progress: alerting", function() {
it("should change the state from 'gather' to 'alerting'", function() {
store.set({callState: CALL_STATES.GATHER});
store.setStoreState({callState: CALL_STATES.GATHER});
store.connectionProgress(
new sharedActions.ConnectionProgress({wsState: WS_STATES.ALERTING}));
expect(store.get("callState")).eql(CALL_STATES.ALERTING);
expect(store.getStoreState("callState")).eql(CALL_STATES.ALERTING);
});
it("should change the state from 'init' to 'alerting'", function() {
store.set({callState: CALL_STATES.INIT});
store.setStoreState({callState: CALL_STATES.INIT});
store.connectionProgress(
new sharedActions.ConnectionProgress({wsState: WS_STATES.ALERTING}));
expect(store.get("callState")).eql(CALL_STATES.ALERTING);
expect(store.getStoreState("callState")).eql(CALL_STATES.ALERTING);
});
});
describe("progress: connecting", function() {
beforeEach(function() {
store.set({callState: CALL_STATES.ALERTING});
store.setStoreState({callState: CALL_STATES.ALERTING});
});
it("should change the state to 'ongoing'", function() {
store.connectionProgress(
new sharedActions.ConnectionProgress({wsState: WS_STATES.CONNECTING}));
expect(store.get("callState")).eql(CALL_STATES.ONGOING);
expect(store.getStoreState("callState")).eql(CALL_STATES.ONGOING);
});
it("should connect the session", function() {
store.set(fakeSessionData);
store.setStoreState(fakeSessionData);
store.connectionProgress(
new sharedActions.ConnectionProgress({wsState: WS_STATES.CONNECTING}));
@ -226,13 +224,13 @@ describe("loop.store.ConversationStore", function () {
});
it("should call mozLoop.addConversationContext", function() {
store.set(fakeSessionData);
store.setStoreState(fakeSessionData);
store.connectionProgress(
new sharedActions.ConnectionProgress({wsState: WS_STATES.CONNECTING}));
sinon.assert.calledOnce(navigator.mozLoop.addConversationContext);
sinon.assert.calledWithExactly(navigator.mozLoop.addConversationContext,
sinon.assert.calledOnce(fakeMozLoop.addConversationContext);
sinon.assert.calledWithExactly(fakeMozLoop.addConversationContext,
"28", "321456", "142536");
});
});
@ -242,7 +240,7 @@ describe("loop.store.ConversationStore", function () {
var fakeSetupWindowData;
beforeEach(function() {
store.set({callState: CALL_STATES.INIT});
store.setStoreState({callState: CALL_STATES.INIT});
fakeSetupWindowData = {
windowId: "123456",
type: "outgoing",
@ -255,23 +253,24 @@ describe("loop.store.ConversationStore", function () {
dispatcher.dispatch(
new sharedActions.SetupWindowData(fakeSetupWindowData));
expect(store.get("callState")).eql(CALL_STATES.GATHER);
expect(store.getStoreState("callState")).eql(CALL_STATES.GATHER);
});
it("should save the basic call information", function() {
dispatcher.dispatch(
new sharedActions.SetupWindowData(fakeSetupWindowData));
expect(store.get("windowId")).eql("123456");
expect(store.get("outgoing")).eql(true);
expect(store.getStoreState("windowId")).eql("123456");
expect(store.getStoreState("outgoing")).eql(true);
});
it("should save the basic information from the mozLoop api", function() {
dispatcher.dispatch(
new sharedActions.SetupWindowData(fakeSetupWindowData));
expect(store.get("contact")).eql(contact);
expect(store.get("callType")).eql(sharedUtils.CALL_TYPES.AUDIO_VIDEO);
expect(store.getStoreState("contact")).eql(contact);
expect(store.getStoreState("callType"))
.eql(sharedUtils.CALL_TYPES.AUDIO_VIDEO);
});
describe("outgoing calls", function() {
@ -402,12 +401,12 @@ describe("loop.store.ConversationStore", function () {
store.connectCall(
new sharedActions.ConnectCall({sessionData: fakeSessionData}));
expect(store.get("apiKey")).eql("fakeKey");
expect(store.get("callId")).eql("142536");
expect(store.get("sessionId")).eql("321456");
expect(store.get("sessionToken")).eql("341256");
expect(store.get("websocketToken")).eql("543216");
expect(store.get("progressURL")).eql("fakeURL");
expect(store.getStoreState("apiKey")).eql("fakeKey");
expect(store.getStoreState("callId")).eql("142536");
expect(store.getStoreState("sessionId")).eql("321456");
expect(store.getStoreState("sessionToken")).eql("341256");
expect(store.getStoreState("websocketToken")).eql("543216");
expect(store.getStoreState("progressURL")).eql("fakeURL");
});
it("should initialize the websocket", function() {
@ -488,8 +487,8 @@ describe("loop.store.ConversationStore", function () {
mediaFail: wsMediaFailSpy,
close: wsCloseSpy
};
store.set({callState: CALL_STATES.ONGOING});
store.set({windowId: "42"});
store.setStoreState({callState: CALL_STATES.ONGOING});
store.setStoreState({windowId: "42"});
});
it("should disconnect the session", function() {
@ -513,15 +512,15 @@ describe("loop.store.ConversationStore", function () {
it("should set the callState to finished", function() {
store.hangupCall(new sharedActions.HangupCall());
expect(store.get("callState")).eql(CALL_STATES.FINISHED);
expect(store.getStoreState("callState")).eql(CALL_STATES.FINISHED);
});
it("should release mozLoop callsData", function() {
store.hangupCall(new sharedActions.HangupCall());
sinon.assert.calledOnce(navigator.mozLoop.calls.clearCallInProgress);
sinon.assert.calledOnce(fakeMozLoop.calls.clearCallInProgress);
sinon.assert.calledWithExactly(
navigator.mozLoop.calls.clearCallInProgress, "42");
fakeMozLoop.calls.clearCallInProgress, "42");
});
});
@ -535,8 +534,8 @@ describe("loop.store.ConversationStore", function () {
mediaFail: wsMediaFailSpy,
close: wsCloseSpy
};
store.set({callState: CALL_STATES.ONGOING});
store.set({windowId: "42"});
store.setStoreState({callState: CALL_STATES.ONGOING});
store.setStoreState({windowId: "42"});
});
it("should disconnect the session", function() {
@ -560,9 +559,9 @@ describe("loop.store.ConversationStore", function () {
peerHungup: true
}));
sinon.assert.calledOnce(navigator.mozLoop.calls.clearCallInProgress);
sinon.assert.calledOnce(fakeMozLoop.calls.clearCallInProgress);
sinon.assert.calledWithExactly(
navigator.mozLoop.calls.clearCallInProgress, "42");
fakeMozLoop.calls.clearCallInProgress, "42");
});
it("should set the callState to finished if the peer hungup", function() {
@ -570,7 +569,7 @@ describe("loop.store.ConversationStore", function () {
peerHungup: true
}));
expect(store.get("callState")).eql(CALL_STATES.FINISHED);
expect(store.getStoreState("callState")).eql(CALL_STATES.FINISHED);
});
it("should set the callState to terminated if the peer was disconnected" +
@ -579,7 +578,7 @@ describe("loop.store.ConversationStore", function () {
peerHungup: false
}));
expect(store.get("callState")).eql(CALL_STATES.TERMINATED);
expect(store.getStoreState("callState")).eql(CALL_STATES.TERMINATED);
});
it("should set the reason to peerNetworkDisconnected if the peer was" +
@ -588,7 +587,8 @@ describe("loop.store.ConversationStore", function () {
peerHungup: false
}));
expect(store.get("callStateReason")).eql("peerNetworkDisconnected");
expect(store.getStoreState("callStateReason"))
.eql("peerNetworkDisconnected");
});
});
@ -596,8 +596,8 @@ describe("loop.store.ConversationStore", function () {
beforeEach(function() {
store._websocket = fakeWebsocket;
store.set({callState: CALL_STATES.CONNECTING});
store.set({windowId: "42"});
store.setStoreState({callState: CALL_STATES.CONNECTING});
store.setStoreState({windowId: "42"});
});
it("should disconnect the session", function() {
@ -621,37 +621,38 @@ describe("loop.store.ConversationStore", function () {
it("should set the state to close if the call is connecting", function() {
store.cancelCall(new sharedActions.CancelCall());
expect(store.get("callState")).eql(CALL_STATES.CLOSE);
expect(store.getStoreState("callState")).eql(CALL_STATES.CLOSE);
});
it("should set the state to close if the call has terminated already", function() {
store.set({callState: CALL_STATES.TERMINATED});
store.setStoreState({callState: CALL_STATES.TERMINATED});
store.cancelCall(new sharedActions.CancelCall());
expect(store.get("callState")).eql(CALL_STATES.CLOSE);
expect(store.getStoreState("callState")).eql(CALL_STATES.CLOSE);
});
it("should release mozLoop callsData", function() {
store.cancelCall(new sharedActions.CancelCall());
sinon.assert.calledOnce(navigator.mozLoop.calls.clearCallInProgress);
sinon.assert.calledOnce(fakeMozLoop.calls.clearCallInProgress);
sinon.assert.calledWithExactly(
navigator.mozLoop.calls.clearCallInProgress, "42");
fakeMozLoop.calls.clearCallInProgress, "42");
});
});
describe("#retryCall", function() {
it("should set the state to gather", function() {
store.set({callState: CALL_STATES.TERMINATED});
store.setStoreState({callState: CALL_STATES.TERMINATED});
store.retryCall(new sharedActions.RetryCall());
expect(store.get("callState")).eql(CALL_STATES.GATHER);
expect(store.getStoreState("callState"))
.eql(CALL_STATES.GATHER);
});
it("should request the outgoing call data", function() {
store.set({
store.setStoreState({
callState: CALL_STATES.TERMINATED,
outgoing: true,
callType: sharedUtils.CALL_TYPES.AUDIO_VIDEO,
@ -678,25 +679,25 @@ describe("loop.store.ConversationStore", function () {
describe("#setMute", function() {
it("should save the mute state for the audio stream", function() {
store.set({"audioMuted": false});
store.setStoreState({"audioMuted": false});
dispatcher.dispatch(new sharedActions.SetMute({
type: "audio",
enabled: true
}));
expect(store.get("audioMuted")).eql(false);
expect(store.getStoreState("audioMuted")).eql(false);
});
it("should save the mute state for the video stream", function() {
store.set({"videoMuted": true});
store.setStoreState({"videoMuted": true});
dispatcher.dispatch(new sharedActions.SetMute({
type: "video",
enabled: false
}));
expect(store.get("videoMuted")).eql(true);
expect(store.getStoreState("videoMuted")).eql(true);
});
});
@ -715,7 +716,7 @@ describe("loop.store.ConversationStore", function () {
};
store.fetchEmailLink(new sharedActions.FetchEmailLink());
expect(store.get("emailLink")).eql("http://fake.invalid/");
expect(store.getStoreState("emailLink")).eql("http://fake.invalid/");
});
it("should trigger an error:emailLink event in case of failure",