зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1097742 - Part 1 Handle access being denied to media, and prevent the sdk prompts from showing in Loop Rooms. r=nperriault
This commit is contained in:
Родитель
2b287ee41c
Коммит
cfa103ca14
|
@ -10,6 +10,15 @@ loop.store.ActiveRoomStore = (function() {
|
|||
"use strict";
|
||||
|
||||
var sharedActions = loop.shared.actions;
|
||||
var FAILURE_REASONS = loop.shared.utils.FAILURE_REASONS;
|
||||
|
||||
// Error numbers taken from
|
||||
// https://github.com/mozilla-services/loop-server/blob/master/loop/errno.json
|
||||
var SERVER_CODES = loop.store.SERVER_CODES = {
|
||||
INVALID_TOKEN: 105,
|
||||
EXPIRED: 111,
|
||||
ROOM_FULL: 202
|
||||
};
|
||||
|
||||
var ROOM_STATES = loop.store.ROOM_STATES = {
|
||||
// The initial state of the room
|
||||
|
@ -84,7 +93,8 @@ loop.store.ActiveRoomStore = (function() {
|
|||
this._storeState = {
|
||||
roomState: ROOM_STATES.INIT,
|
||||
audioMuted: false,
|
||||
videoMuted: false
|
||||
videoMuted: false,
|
||||
failureReason: undefined
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -112,13 +122,24 @@ loop.store.ActiveRoomStore = (function() {
|
|||
* @param {sharedActions.RoomFailure} actionData
|
||||
*/
|
||||
roomFailure: function(actionData) {
|
||||
function getReason(serverCode) {
|
||||
switch (serverCode) {
|
||||
case SERVER_CODES.INVALID_TOKEN:
|
||||
case SERVER_CODES.EXPIRED:
|
||||
return FAILURE_REASONS.EXPIRED_OR_INVALID;
|
||||
default:
|
||||
return FAILURE_REASONS.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
console.error("Error in state `" + this._storeState.roomState + "`:",
|
||||
actionData.error);
|
||||
|
||||
this.setStoreState({
|
||||
error: actionData.error,
|
||||
roomState: actionData.error.errno === 202 ? ROOM_STATES.FULL
|
||||
: ROOM_STATES.FAILED
|
||||
failureReason: getReason(actionData.error.errno),
|
||||
roomState: actionData.error.errno === SERVER_CODES.ROOM_FULL ?
|
||||
ROOM_STATES.FULL : ROOM_STATES.FAILED
|
||||
});
|
||||
},
|
||||
|
||||
|
@ -228,6 +249,11 @@ loop.store.ActiveRoomStore = (function() {
|
|||
* Handles the action to join to a room.
|
||||
*/
|
||||
joinRoom: function() {
|
||||
// Reset the failure reason if necessary.
|
||||
if (this.getStoreState().failureReason) {
|
||||
this.setStoreState({failureReason: undefined});
|
||||
}
|
||||
|
||||
this._mozLoop.rooms.join(this._storeState.roomToken,
|
||||
function(error, responseData) {
|
||||
if (error) {
|
||||
|
@ -275,11 +301,17 @@ loop.store.ActiveRoomStore = (function() {
|
|||
|
||||
/**
|
||||
* Handles disconnection of this local client from the sdk servers.
|
||||
*
|
||||
* @param {sharedActions.ConnectionFailure} actionData
|
||||
*/
|
||||
connectionFailure: function() {
|
||||
connectionFailure: function(actionData) {
|
||||
// Treat all reasons as something failed. In theory, clientDisconnected
|
||||
// could be a success case, but there's no way we should be intentionally
|
||||
// sending that and still have the window open.
|
||||
this.setStoreState({
|
||||
failureReason: actionData.reason
|
||||
});
|
||||
|
||||
this._leaveRoom(ROOM_STATES.FAILED);
|
||||
},
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ var loop = loop || {};
|
|||
loop.OTSdkDriver = (function() {
|
||||
|
||||
var sharedActions = loop.shared.actions;
|
||||
var FAILURE_REASONS = loop.shared.utils.FAILURE_REASONS;
|
||||
|
||||
/**
|
||||
* This is a wrapper for the OT sdk. It is used to translate the SDK events into
|
||||
|
@ -47,8 +48,11 @@ loop.OTSdkDriver = (function() {
|
|||
// the initial connect of the session. This saves time when setting up
|
||||
// the media.
|
||||
this.publisher = this.sdk.initPublisher(this.getLocalElement(),
|
||||
this.publisherConfig,
|
||||
this._onPublishComplete.bind(this));
|
||||
this.publisherConfig);
|
||||
this.publisher.on("accessAllowed", this._onPublishComplete.bind(this));
|
||||
this.publisher.on("accessDenied", this._onPublishDenied.bind(this));
|
||||
this.publisher.on("accessDialogOpened",
|
||||
this._onAccessDialogOpened.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -96,16 +100,12 @@ loop.OTSdkDriver = (function() {
|
|||
*/
|
||||
disconnectSession: function() {
|
||||
if (this.session) {
|
||||
this.session.off("streamCreated", this._onRemoteStreamCreated.bind(this));
|
||||
this.session.off("connectionDestroyed",
|
||||
this._onConnectionDestroyed.bind(this));
|
||||
this.session.off("sessionDisconnected",
|
||||
this._onSessionDisconnected.bind(this));
|
||||
|
||||
this.session.off("streamCreated connectionDestroyed sessionDisconnected");
|
||||
this.session.disconnect();
|
||||
delete this.session;
|
||||
}
|
||||
if (this.publisher) {
|
||||
this.publisher.off("accessAllowed accessDenied accessDialogOpened");
|
||||
this.publisher.destroy();
|
||||
delete this.publisher;
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ loop.OTSdkDriver = (function() {
|
|||
if (error) {
|
||||
console.error("Failed to complete connection", error);
|
||||
this.dispatcher.dispatch(new sharedActions.ConnectionFailure({
|
||||
reason: "couldNotConnect"
|
||||
reason: FAILURE_REASONS.COULD_NOT_CONNECT
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ loop.OTSdkDriver = (function() {
|
|||
// We only need to worry about the network disconnected reason here.
|
||||
if (event.reason === "networkDisconnected") {
|
||||
this.dispatcher.dispatch(new sharedActions.ConnectionFailure({
|
||||
reason: "networkDisconnected"
|
||||
reason: FAILURE_REASONS.NETWORK_DISCONNECTED
|
||||
}));
|
||||
}
|
||||
},
|
||||
|
@ -188,24 +188,42 @@ loop.OTSdkDriver = (function() {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called from the sdk when the media access dialog is opened.
|
||||
* Prevents the default action, to prevent the SDK's "allow access"
|
||||
* dialog from being shown.
|
||||
*
|
||||
* @param {OT.Event} event
|
||||
*/
|
||||
_onAccessDialogOpened: function(event) {
|
||||
event.preventDefault();
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the publishing being complete.
|
||||
*
|
||||
* @param {Error} error An OT error object, null if there was no error.
|
||||
* @param {OT.Event} event
|
||||
*/
|
||||
_onPublishComplete: function(error) {
|
||||
if (error) {
|
||||
console.error("Failed to initialize publisher", error);
|
||||
this.dispatcher.dispatch(new sharedActions.ConnectionFailure({
|
||||
reason: "noMedia"
|
||||
}));
|
||||
return;
|
||||
}
|
||||
|
||||
_onPublishComplete: function(event) {
|
||||
event.preventDefault();
|
||||
this._publisherReady = true;
|
||||
this._maybePublishLocalStream();
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles publishing of media being denied.
|
||||
*
|
||||
* @param {OT.Event} event
|
||||
*/
|
||||
_onPublishDenied: function(event) {
|
||||
// This prevents the SDK's "access denied" dialog showing.
|
||||
event.preventDefault();
|
||||
|
||||
this.dispatcher.dispatch(new sharedActions.ConnectionFailure({
|
||||
reason: FAILURE_REASONS.MEDIA_DENIED
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* Publishes the local stream if the session is connected
|
||||
* and the publisher is ready.
|
||||
|
|
|
@ -17,6 +17,14 @@ loop.shared.utils = (function(mozL10n) {
|
|||
AUDIO_ONLY: "audio"
|
||||
};
|
||||
|
||||
var FAILURE_REASONS = {
|
||||
MEDIA_DENIED: "reason-media-denied",
|
||||
COULD_NOT_CONNECT: "reason-could-not-connect",
|
||||
NETWORK_DISCONNECTED: "reason-network-disconnected",
|
||||
EXPIRED_OR_INVALID: "reason-expired-or-invalid",
|
||||
UNKNOWN: "reason-unknown"
|
||||
};
|
||||
|
||||
/**
|
||||
* Format a given date into an l10n-friendly string.
|
||||
*
|
||||
|
@ -110,6 +118,7 @@ loop.shared.utils = (function(mozL10n) {
|
|||
|
||||
return {
|
||||
CALL_TYPES: CALL_TYPES,
|
||||
FAILURE_REASONS: FAILURE_REASONS,
|
||||
Helper: Helper,
|
||||
composeCallUrlEmail: composeCallUrlEmail,
|
||||
formatDate: formatDate,
|
||||
|
|
|
@ -11,6 +11,7 @@ var loop = loop || {};
|
|||
loop.standaloneRoomViews = (function(mozL10n) {
|
||||
"use strict";
|
||||
|
||||
var FAILURE_REASONS = loop.shared.utils.FAILURE_REASONS;
|
||||
var ROOM_STATES = loop.store.ROOM_STATES;
|
||||
var sharedActions = loop.shared.actions;
|
||||
var sharedMixins = loop.shared.mixins;
|
||||
|
@ -40,6 +41,20 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
|||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* @return String An appropriate string according to the failureReason.
|
||||
*/
|
||||
_getFailureString: function() {
|
||||
switch(this.props.failureReason) {
|
||||
case FAILURE_REASONS.MEDIA_DENIED:
|
||||
return mozL10n.get("rooms_media_denied_message");
|
||||
case FAILURE_REASONS.EXPIRED_OR_INVALID:
|
||||
return mozL10n.get("rooms_unavailable_notification_message");
|
||||
default:
|
||||
return mozL10n.get("status_error");
|
||||
};
|
||||
},
|
||||
|
||||
_renderContent: function() {
|
||||
switch(this.props.roomState) {
|
||||
case ROOM_STATES.INIT:
|
||||
|
@ -68,6 +83,12 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
|||
React.DOM.p(null, this._renderCallToActionLink())
|
||||
)
|
||||
);
|
||||
case ROOM_STATES.FAILED:
|
||||
return (
|
||||
React.DOM.p({className: "failed-room-message"},
|
||||
this._getFailureString()
|
||||
)
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -252,6 +273,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
|||
React.DOM.div({className: "room-conversation-wrapper"},
|
||||
StandaloneRoomHeader(null),
|
||||
StandaloneRoomInfoArea({roomState: this.state.roomState,
|
||||
failureReason: this.state.failureReason,
|
||||
joinRoom: this.joinRoom,
|
||||
helper: this.props.helper}),
|
||||
React.DOM.div({className: "video-layout-wrapper"},
|
||||
|
|
|
@ -11,6 +11,7 @@ var loop = loop || {};
|
|||
loop.standaloneRoomViews = (function(mozL10n) {
|
||||
"use strict";
|
||||
|
||||
var FAILURE_REASONS = loop.shared.utils.FAILURE_REASONS;
|
||||
var ROOM_STATES = loop.store.ROOM_STATES;
|
||||
var sharedActions = loop.shared.actions;
|
||||
var sharedMixins = loop.shared.mixins;
|
||||
|
@ -40,6 +41,20 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
|||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* @return String An appropriate string according to the failureReason.
|
||||
*/
|
||||
_getFailureString: function() {
|
||||
switch(this.props.failureReason) {
|
||||
case FAILURE_REASONS.MEDIA_DENIED:
|
||||
return mozL10n.get("rooms_media_denied_message");
|
||||
case FAILURE_REASONS.EXPIRED_OR_INVALID:
|
||||
return mozL10n.get("rooms_unavailable_notification_message");
|
||||
default:
|
||||
return mozL10n.get("status_error");
|
||||
};
|
||||
},
|
||||
|
||||
_renderContent: function() {
|
||||
switch(this.props.roomState) {
|
||||
case ROOM_STATES.INIT:
|
||||
|
@ -68,6 +83,12 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
|||
<p>{this._renderCallToActionLink()}</p>
|
||||
</div>
|
||||
);
|
||||
case ROOM_STATES.FAILED:
|
||||
return (
|
||||
<p className="failed-room-message">
|
||||
{this._getFailureString()}
|
||||
</p>
|
||||
);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -252,6 +273,7 @@ loop.standaloneRoomViews = (function(mozL10n) {
|
|||
<div className="room-conversation-wrapper">
|
||||
<StandaloneRoomHeader />
|
||||
<StandaloneRoomInfoArea roomState={this.state.roomState}
|
||||
failureReason={this.state.failureReason}
|
||||
joinRoom={this.joinRoom}
|
||||
helper={this.props.helper} />
|
||||
<div className="video-layout-wrapper">
|
||||
|
|
|
@ -116,6 +116,8 @@ rooms_room_full_call_to_action_label=Learn more about {{clientShortname}} »
|
|||
rooms_room_joined_label=Someone has joined the conversation!
|
||||
rooms_room_join_label=Join the conversation
|
||||
rooms_display_name_guest=Guest
|
||||
rooms_unavailable_notification_message=Sorry, you cannot join this conversation. The link may be expired or invalid.
|
||||
rooms_media_denied_message=We could not get access to your microphone or camera. Please reload the page to try again.
|
||||
|
||||
## LOCALIZATION_NOTE(standalone_title_with_status): {{clientShortname}} will be
|
||||
## replaced by the brand name and {{currentStatus}} will be replaced
|
||||
|
|
|
@ -65,6 +65,7 @@ describe("loop.roomViews", function () {
|
|||
roomState: ROOM_STATES.INIT,
|
||||
audioMuted: false,
|
||||
videoMuted: false,
|
||||
failureReason: undefined
|
||||
foo: "bar"
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,7 +6,9 @@ var sharedActions = loop.shared.actions;
|
|||
describe("loop.store.ActiveRoomStore", function () {
|
||||
"use strict";
|
||||
|
||||
var SERVER_CODES = loop.store.SERVER_CODES;
|
||||
var ROOM_STATES = loop.store.ROOM_STATES;
|
||||
var FAILURE_REASONS = loop.shared.utils.FAILURE_REASONS;
|
||||
var sandbox, dispatcher, store, fakeMozLoop, fakeSdkDriver;
|
||||
var fakeMultiplexGum;
|
||||
|
||||
|
@ -91,8 +93,8 @@ describe("loop.store.ActiveRoomStore", function () {
|
|||
sinon.match(ROOM_STATES.READY), fakeError);
|
||||
});
|
||||
|
||||
it("should set the state to `FULL` on server errno 202", function() {
|
||||
fakeError.errno = 202;
|
||||
it("should set the state to `FULL` on server error room full", function() {
|
||||
fakeError.errno = SERVER_CODES.ROOM_FULL;
|
||||
|
||||
store.roomFailure({error: fakeError});
|
||||
|
||||
|
@ -103,7 +105,28 @@ describe("loop.store.ActiveRoomStore", function () {
|
|||
store.roomFailure({error: fakeError});
|
||||
|
||||
expect(store._storeState.roomState).eql(ROOM_STATES.FAILED);
|
||||
expect(store._storeState.failureReason).eql(FAILURE_REASONS.UNKNOWN);
|
||||
});
|
||||
|
||||
it("should set the failureReason to EXPIRED_OR_INVALID on server error: " +
|
||||
"invalid token", function() {
|
||||
fakeError.errno = SERVER_CODES.INVALID_TOKEN;
|
||||
|
||||
store.roomFailure({error: fakeError});
|
||||
|
||||
expect(store._storeState.roomState).eql(ROOM_STATES.FAILED);
|
||||
expect(store._storeState.failureReason).eql(FAILURE_REASONS.EXPIRED_OR_INVALID);
|
||||
});
|
||||
|
||||
it("should set the failureReason to EXPIRED_OR_INVALID on server error: " +
|
||||
"expired", function() {
|
||||
fakeError.errno = SERVER_CODES.EXPIRED;
|
||||
|
||||
store.roomFailure({error: fakeError});
|
||||
|
||||
expect(store._storeState.roomState).eql(ROOM_STATES.FAILED);
|
||||
expect(store._storeState.failureReason).eql(FAILURE_REASONS.EXPIRED_OR_INVALID);
|
||||
});
|
||||
});
|
||||
|
||||
describe("#setupWindowData", function() {
|
||||
|
@ -244,6 +267,14 @@ describe("loop.store.ActiveRoomStore", function () {
|
|||
store.setStoreState({roomToken: "tokenFake"});
|
||||
});
|
||||
|
||||
it("should reset failureReason", function() {
|
||||
store.setStoreState({failureReason: "Test"});
|
||||
|
||||
store.joinRoom();
|
||||
|
||||
expect(store.getStoreState().failureReason).eql(undefined);
|
||||
});
|
||||
|
||||
it("should call rooms.join on mozLoop", function() {
|
||||
store.joinRoom();
|
||||
|
||||
|
@ -380,22 +411,34 @@ describe("loop.store.ActiveRoomStore", function () {
|
|||
});
|
||||
|
||||
describe("#connectionFailure", function() {
|
||||
var connectionFailureAction;
|
||||
|
||||
beforeEach(function() {
|
||||
store.setStoreState({
|
||||
roomState: ROOM_STATES.JOINED,
|
||||
roomToken: "fakeToken",
|
||||
sessionToken: "1627384950"
|
||||
});
|
||||
|
||||
connectionFailureAction = new sharedActions.ConnectionFailure({
|
||||
reason: "FAIL"
|
||||
});
|
||||
});
|
||||
|
||||
it("should store the failure reason", function() {
|
||||
store.connectionFailure(connectionFailureAction);
|
||||
|
||||
expect(store.getStoreState().failureReason).eql("FAIL");
|
||||
});
|
||||
|
||||
it("should reset the multiplexGum", function() {
|
||||
store.leaveRoom();
|
||||
store.connectionFailure(connectionFailureAction);
|
||||
|
||||
sinon.assert.calledOnce(fakeMultiplexGum.reset);
|
||||
});
|
||||
|
||||
it("should disconnect from the servers via the sdk", function() {
|
||||
store.connectionFailure();
|
||||
store.connectionFailure(connectionFailureAction);
|
||||
|
||||
sinon.assert.calledOnce(fakeSdkDriver.disconnectSession);
|
||||
});
|
||||
|
@ -404,13 +447,13 @@ describe("loop.store.ActiveRoomStore", function () {
|
|||
sandbox.stub(window, "clearTimeout");
|
||||
store._timeout = {};
|
||||
|
||||
store.connectionFailure();
|
||||
store.connectionFailure(connectionFailureAction);
|
||||
|
||||
sinon.assert.calledOnce(clearTimeout);
|
||||
});
|
||||
|
||||
it("should call mozLoop.rooms.leave", function() {
|
||||
store.connectionFailure();
|
||||
store.connectionFailure(connectionFailureAction);
|
||||
|
||||
sinon.assert.calledOnce(fakeMozLoop.rooms.leave);
|
||||
sinon.assert.calledWithExactly(fakeMozLoop.rooms.leave,
|
||||
|
@ -418,7 +461,7 @@ describe("loop.store.ActiveRoomStore", function () {
|
|||
});
|
||||
|
||||
it("should set the state to `FAILED`", function() {
|
||||
store.connectionFailure();
|
||||
store.connectionFailure(connectionFailureAction);
|
||||
|
||||
expect(store.getStoreState().roomState).eql(ROOM_STATES.FAILED);
|
||||
});
|
||||
|
|
|
@ -7,16 +7,19 @@ describe("loop.OTSdkDriver", function () {
|
|||
"use strict";
|
||||
|
||||
var sharedActions = loop.shared.actions;
|
||||
|
||||
var FAILURE_REASONS = loop.shared.utils.FAILURE_REASONS;
|
||||
var sandbox;
|
||||
var dispatcher, driver, publisher, sdk, session, sessionData;
|
||||
var fakeLocalElement, fakeRemoteElement, publisherConfig;
|
||||
var fakeLocalElement, fakeRemoteElement, publisherConfig, fakeEvent;
|
||||
|
||||
beforeEach(function() {
|
||||
sandbox = sinon.sandbox.create();
|
||||
|
||||
fakeLocalElement = {fake: 1};
|
||||
fakeRemoteElement = {fake: 2};
|
||||
fakeEvent = {
|
||||
preventDefault: sinon.stub()
|
||||
};
|
||||
publisherConfig = {
|
||||
fake: "config"
|
||||
};
|
||||
|
@ -34,14 +37,14 @@ describe("loop.OTSdkDriver", function () {
|
|||
subscribe: sinon.stub()
|
||||
}, Backbone.Events);
|
||||
|
||||
publisher = {
|
||||
publisher = _.extend({
|
||||
destroy: sinon.stub(),
|
||||
publishAudio: sinon.stub(),
|
||||
publishVideo: sinon.stub()
|
||||
};
|
||||
}, Backbone.Events);
|
||||
|
||||
sdk = {
|
||||
initPublisher: sinon.stub(),
|
||||
initPublisher: sinon.stub().returns(publisher),
|
||||
initSession: sinon.stub().returns(session)
|
||||
};
|
||||
|
||||
|
@ -80,51 +83,6 @@ describe("loop.OTSdkDriver", function () {
|
|||
sinon.assert.calledOnce(sdk.initPublisher);
|
||||
sinon.assert.calledWith(sdk.initPublisher, fakeLocalElement, publisherConfig);
|
||||
});
|
||||
|
||||
describe("On Publisher Complete", function() {
|
||||
it("should publish the stream if the connection is ready", function() {
|
||||
sdk.initPublisher.callsArgWith(2, null);
|
||||
|
||||
driver.session = session;
|
||||
driver._sessionConnected = true;
|
||||
|
||||
dispatcher.dispatch(new sharedActions.SetupStreamElements({
|
||||
getLocalElementFunc: function() {return fakeLocalElement;},
|
||||
getRemoteElementFunc: function() {return fakeRemoteElement;},
|
||||
publisherConfig: publisherConfig
|
||||
}));
|
||||
|
||||
sinon.assert.calledOnce(session.publish);
|
||||
});
|
||||
|
||||
it("should dispatch connectionFailure if connecting failed", function() {
|
||||
sdk.initPublisher.callsArgWith(2, new Error("Failure"));
|
||||
|
||||
// Special stub, as we want to use the dispatcher, but also know that
|
||||
// we've been called correctly for the second dispatch.
|
||||
var dispatchStub = (function() {
|
||||
var originalDispatch = dispatcher.dispatch.bind(dispatcher);
|
||||
return sandbox.stub(dispatcher, "dispatch", function(action) {
|
||||
originalDispatch(action);
|
||||
});
|
||||
}());
|
||||
|
||||
driver.session = session;
|
||||
driver._sessionConnected = true;
|
||||
|
||||
dispatcher.dispatch(new sharedActions.SetupStreamElements({
|
||||
getLocalElementFunc: function() {return fakeLocalElement;},
|
||||
getRemoteElementFunc: function() {return fakeRemoteElement;},
|
||||
publisherConfig: publisherConfig
|
||||
}));
|
||||
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithMatch(dispatcher.dispatch,
|
||||
sinon.match.hasOwn("name", "connectionFailure"));
|
||||
sinon.assert.calledWithMatch(dispatcher.dispatch,
|
||||
sinon.match.hasOwn("reason", "noMedia"));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("#setMute", function() {
|
||||
|
@ -194,7 +152,7 @@ describe("loop.OTSdkDriver", function () {
|
|||
sinon.assert.calledWithMatch(dispatcher.dispatch,
|
||||
sinon.match.hasOwn("name", "connectionFailure"));
|
||||
sinon.assert.calledWithMatch(dispatcher.dispatch,
|
||||
sinon.match.hasOwn("reason", "couldNotConnect"));
|
||||
sinon.match.hasOwn("reason", FAILURE_REASONS.COULD_NOT_CONNECT));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -269,7 +227,7 @@ describe("loop.OTSdkDriver", function () {
|
|||
sinon.assert.calledWithMatch(dispatcher.dispatch,
|
||||
sinon.match.hasOwn("name", "connectionFailure"));
|
||||
sinon.assert.calledWithMatch(dispatcher.dispatch,
|
||||
sinon.match.hasOwn("reason", "networkDisconnected"));
|
||||
sinon.match.hasOwn("reason", FAILURE_REASONS.NETWORK_DISCONNECTED));
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -328,5 +286,41 @@ describe("loop.OTSdkDriver", function () {
|
|||
sinon.assert.notCalled(dispatcher.dispatch);
|
||||
});
|
||||
});
|
||||
|
||||
describe("accessAllowed", function() {
|
||||
it("should publish the stream if the connection is ready", function() {
|
||||
driver._sessionConnected = true;
|
||||
|
||||
publisher.trigger("accessAllowed", fakeEvent);
|
||||
|
||||
sinon.assert.calledOnce(session.publish);
|
||||
});
|
||||
});
|
||||
|
||||
describe("accessDenied", function() {
|
||||
it("should prevent the default event behavior", function() {
|
||||
publisher.trigger("accessDenied", fakeEvent);
|
||||
|
||||
sinon.assert.calledOnce(fakeEvent.preventDefault);
|
||||
});
|
||||
|
||||
it("should dispatch connectionFailure", function() {
|
||||
publisher.trigger("accessDenied", fakeEvent);
|
||||
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithMatch(dispatcher.dispatch,
|
||||
sinon.match.hasOwn("name", "connectionFailure"));
|
||||
sinon.assert.calledWithMatch(dispatcher.dispatch,
|
||||
sinon.match.hasOwn("reason", FAILURE_REASONS.MEDIA_DENIED));
|
||||
});
|
||||
});
|
||||
|
||||
describe("accessDialogOpened", function() {
|
||||
it("should prevent the default event behavior", function() {
|
||||
publisher.trigger("accessDialogOpened", fakeEvent);
|
||||
|
||||
sinon.assert.calledOnce(fakeEvent.preventDefault);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -139,6 +139,16 @@ describe("loop.standaloneRoomViews", function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe("Failed room message", function() {
|
||||
it("should display a failed room message on FAILED",
|
||||
function() {
|
||||
activeRoomStore.setStoreState({roomState: ROOM_STATES.FAILED});
|
||||
|
||||
expect(view.getDOMNode().querySelector(".failed-room-message"))
|
||||
.not.eql(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Join button", function() {
|
||||
function getJoinButton(view) {
|
||||
return view.getDOMNode().querySelector(".btn-join");
|
||||
|
|
|
@ -608,6 +608,16 @@
|
|||
roomState: ROOM_STATES.FULL,
|
||||
helper: {isFirefox: returnFalse}})
|
||||
)
|
||||
),
|
||||
|
||||
Example({summary: "Standalone room conversation (failed)"},
|
||||
React.DOM.div({className: "standalone"},
|
||||
StandaloneRoomView({
|
||||
dispatcher: dispatcher,
|
||||
activeRoomStore: activeRoomStore,
|
||||
roomState: ROOM_STATES.FAILED,
|
||||
helper: {isFirefox: returnFalse}})
|
||||
)
|
||||
)
|
||||
),
|
||||
|
||||
|
|
|
@ -609,6 +609,16 @@
|
|||
helper={{isFirefox: returnFalse}} />
|
||||
</div>
|
||||
</Example>
|
||||
|
||||
<Example summary="Standalone room conversation (failed)">
|
||||
<div className="standalone">
|
||||
<StandaloneRoomView
|
||||
dispatcher={dispatcher}
|
||||
activeRoomStore={activeRoomStore}
|
||||
roomState={ROOM_STATES.FAILED}
|
||||
helper={{isFirefox: returnFalse}} />
|
||||
</div>
|
||||
</Example>
|
||||
</Section>
|
||||
|
||||
<Section name="SVG icons preview">
|
||||
|
|
Загрузка…
Ссылка в новой задаче