mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 17:55:50 +00:00
Bug 1210865 - Change how Loop's data channels are setup to cope with the newer SDK that doesn't allow setting them up until subscription is complete. r=dmose
This commit is contained in:
parent
b8b9d7e44d
commit
4b933355a4
@ -620,7 +620,7 @@ loop.OTSdkDriver = (function() {
|
||||
this.dispatcher.dispatch(new sharedActions.MediaConnected());
|
||||
}
|
||||
|
||||
this._setupDataChannelIfNeeded(sdkSubscriberObject.stream.connection);
|
||||
this._setupDataChannelIfNeeded(sdkSubscriberObject);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -655,61 +655,24 @@ loop.OTSdkDriver = (function() {
|
||||
* channel set-up routines. A data channel cannot be requested before this
|
||||
* time as the peer connection is not set up.
|
||||
*
|
||||
* @param {OT.Connection} connection The OT connection class object.paul
|
||||
* sched
|
||||
* @param {OT.Subscriber} sdkSubscriberObject The subscriber object for the stream.
|
||||
*
|
||||
*/
|
||||
_setupDataChannelIfNeeded: function(connection) {
|
||||
if (this._useDataChannels) {
|
||||
this.session.signal({
|
||||
type: "readyForDataChannel",
|
||||
to: connection
|
||||
}, function(signalError) {
|
||||
if (signalError) {
|
||||
console.error(signalError);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles receiving the signal that the other end of the connection
|
||||
* has subscribed to the stream and we're ready to setup the data channel.
|
||||
*
|
||||
* We get data channels for both the publisher and subscriber on reception
|
||||
* of the signal, as it means that a) the remote client is setup for data
|
||||
* channels, and b) that subscribing of streams has definitely completed
|
||||
* for both clients.
|
||||
*
|
||||
* @param {OT.SignalEvent} event Details of the signal received.
|
||||
*/
|
||||
_onReadyForDataChannel: function(event) {
|
||||
// If we don't want data channels, just ignore the message. We haven't
|
||||
// send the other side a message, so it won't display anything.
|
||||
_setupDataChannelIfNeeded: function(sdkSubscriberObject) {
|
||||
if (!this._useDataChannels) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This won't work until a subscriber exists for this publisher
|
||||
this.publisher._.getDataChannel("text", {}, function(err, channel) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
this.session.signal({
|
||||
type: "readyForDataChannel",
|
||||
to: sdkSubscriberObject.stream.connection
|
||||
}, function(signalError) {
|
||||
if (signalError) {
|
||||
console.error(signalError);
|
||||
}
|
||||
});
|
||||
|
||||
this._publisherChannel = channel;
|
||||
|
||||
channel.on({
|
||||
close: function(e) {
|
||||
// XXX We probably want to dispatch and handle this somehow.
|
||||
console.log("Published data channel closed!");
|
||||
}
|
||||
});
|
||||
|
||||
this._checkDataChannelsAvailable();
|
||||
}.bind(this));
|
||||
|
||||
this.subscriber._.getDataChannel("text", {}, function(err, channel) {
|
||||
sdkSubscriberObject._.getDataChannel("text", {}, function(err, channel) {
|
||||
// Sends will queue until the channel is fully open.
|
||||
if (err) {
|
||||
console.error(err);
|
||||
@ -741,6 +704,44 @@ loop.OTSdkDriver = (function() {
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles receiving the signal that the other end of the connection
|
||||
* has subscribed to the stream and we're ready to setup the data channel.
|
||||
*
|
||||
* We create the publisher data channel when we get the signal as it means
|
||||
* that the remote client is setup for data
|
||||
* channels. Getting the data channel for the subscriber is handled
|
||||
* separately when the subscription completes.
|
||||
*
|
||||
* @param {OT.SignalEvent} event Details of the signal received.
|
||||
*/
|
||||
_onReadyForDataChannel: function(event) {
|
||||
// If we don't want data channels, just ignore the message. We haven't
|
||||
// send the other side a message, so it won't display anything.
|
||||
if (!this._useDataChannels) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This won't work until a subscriber exists for this publisher
|
||||
this.publisher._.getDataChannel("text", {}, function(err, channel) {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
|
||||
this._publisherChannel = channel;
|
||||
|
||||
channel.on({
|
||||
close: function(e) {
|
||||
// XXX We probably want to dispatch and handle this somehow.
|
||||
console.log("Published data channel closed!");
|
||||
}
|
||||
});
|
||||
|
||||
this._checkDataChannelsAvailable();
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks to see if all channels have been obtained, and if so it dispatches
|
||||
* a notification to the stores to inform them.
|
||||
|
@ -142,6 +142,50 @@ class Test1BrowserCall(MarionetteTestCase):
|
||||
self.switch_to_chatbox()
|
||||
self.check_video(".remote-video")
|
||||
|
||||
def send_chat_message(self, text):
|
||||
"""
|
||||
Sends a chat message using the current context.
|
||||
|
||||
:param text: The text to send.
|
||||
"""
|
||||
chatbox = self.wait_for_element_displayed(By.CSS_SELECTOR,
|
||||
".text-chat-box > form > input")
|
||||
|
||||
chatbox.send_keys(text + "\n")
|
||||
|
||||
def check_received_message(self, expectedText):
|
||||
"""
|
||||
Checks a chat message has been received in the current context. The
|
||||
test assumes only one chat message will be received during the tests.
|
||||
|
||||
:param expectedText: The expected text of the chat message.
|
||||
"""
|
||||
text_entry = self.wait_for_element_displayed(By.CSS_SELECTOR,
|
||||
".text-chat-entry.received > p > span")
|
||||
|
||||
self.assertEqual(text_entry.text, expectedText,
|
||||
"should have received the correct message")
|
||||
|
||||
def check_text_messaging(self):
|
||||
"""
|
||||
Checks text messaging between the generator and clicker in a bi-directional
|
||||
fashion.
|
||||
"""
|
||||
# Send a message using the link generator.
|
||||
self.switch_to_chatbox()
|
||||
self.send_chat_message("test1")
|
||||
|
||||
# Now check the result on the link clicker.
|
||||
self.switch_to_standalone()
|
||||
self.check_received_message("test1")
|
||||
|
||||
# Then send a message using the standalone.
|
||||
self.send_chat_message("test2")
|
||||
|
||||
# Finally check the link generator got it.
|
||||
self.switch_to_chatbox()
|
||||
self.check_received_message("test2")
|
||||
|
||||
def local_enable_screenshare(self):
|
||||
self.switch_to_chatbox()
|
||||
button = self.marionette.find_element(By.CLASS_NAME, "btn-screen-share")
|
||||
@ -242,6 +286,9 @@ class Test1BrowserCall(MarionetteTestCase):
|
||||
self.standalone_check_remote_video()
|
||||
self.local_check_remote_video()
|
||||
|
||||
# Check text messaging
|
||||
self.check_text_messaging()
|
||||
|
||||
# since bi-directional media is connected, make sure we've set
|
||||
# the start time
|
||||
self.local_check_media_start_time_initialized()
|
||||
|
@ -752,6 +752,9 @@ describe("loop.OTSdkDriver", function() {
|
||||
};
|
||||
|
||||
fakeSubscriberObject = _.extend({
|
||||
"_": {
|
||||
getDataChannel: sinon.stub()
|
||||
},
|
||||
session: { connection: fakeConnection },
|
||||
stream: fakeStream
|
||||
}, Backbone.Events);
|
||||
@ -996,131 +999,196 @@ describe("loop.OTSdkDriver", function() {
|
||||
}));
|
||||
});
|
||||
|
||||
it("should subscribe to a camera stream", function() {
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
describe("Audio/Video streams", function() {
|
||||
beforeEach(function() {
|
||||
session.subscribe.yieldsOn(driver, null, fakeSubscriberObject,
|
||||
videoElement).returns(this.fakeSubscriberObject);
|
||||
});
|
||||
|
||||
sinon.assert.calledOnce(session.subscribe);
|
||||
sinon.assert.calledWithExactly(session.subscribe,
|
||||
fakeStream, sinon.match.instanceOf(HTMLDivElement), publisherConfig,
|
||||
sinon.match.func);
|
||||
});
|
||||
it("should subscribe to a camera stream", function() {
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
it("should dispatch MediaStreamCreated after subscribe is complete", function() {
|
||||
session.subscribe.yieldsOn(driver, null, fakeSubscriberObject,
|
||||
videoElement).returns(this.fakeSubscriberObject);
|
||||
driver.session = session;
|
||||
fakeStream.connection = fakeConnection;
|
||||
fakeStream.hasVideo = true;
|
||||
sinon.assert.calledOnce(session.subscribe);
|
||||
sinon.assert.calledWithExactly(session.subscribe,
|
||||
fakeStream, sinon.match.instanceOf(HTMLDivElement), publisherConfig,
|
||||
sinon.match.func);
|
||||
});
|
||||
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
it("should dispatch MediaStreamCreated after streamCreated is triggered on the session", function() {
|
||||
driver.session = session;
|
||||
fakeStream.connection = fakeConnection;
|
||||
fakeStream.hasVideo = true;
|
||||
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.MediaStreamCreated({
|
||||
hasVideo: true,
|
||||
isLocal: false,
|
||||
srcMediaElement: videoElement
|
||||
}));
|
||||
});
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
it("should dispatch MediaStreamCreated after subscribe with audio-only indication if hasVideo=false", function() {
|
||||
session.subscribe.yieldsOn(driver, null, fakeSubscriberObject,
|
||||
videoElement);
|
||||
fakeStream.connection = fakeConnection;
|
||||
fakeStream.hasVideo = false;
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.MediaStreamCreated({
|
||||
hasVideo: true,
|
||||
isLocal: false,
|
||||
srcMediaElement: videoElement
|
||||
}));
|
||||
});
|
||||
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
it("should dispatch MediaStreamCreated after streamCreated with audio-only indication if hasVideo=false", function() {
|
||||
fakeStream.connection = fakeConnection;
|
||||
fakeStream.hasVideo = false;
|
||||
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.MediaStreamCreated({
|
||||
hasVideo: false,
|
||||
isLocal: false,
|
||||
srcMediaElement: videoElement
|
||||
}));
|
||||
});
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
it("should trigger a readyForDataChannel signal after subscribe is complete", function() {
|
||||
session.subscribe.yieldsOn(driver, null, fakeSubscriberObject,
|
||||
document.createElement("video"));
|
||||
driver._useDataChannels = true;
|
||||
fakeStream.connection = fakeConnection;
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.MediaStreamCreated({
|
||||
hasVideo: false,
|
||||
isLocal: false,
|
||||
srcMediaElement: videoElement
|
||||
}));
|
||||
});
|
||||
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
it("should dispatch a mediaConnected action if both streams are up", function() {
|
||||
driver._publishedLocalStream = true;
|
||||
|
||||
sinon.assert.calledOnce(session.signal);
|
||||
sinon.assert.calledWith(session.signal, {
|
||||
type: "readyForDataChannel",
|
||||
to: fakeConnection
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
// Called twice due to the VideoDimensionsChanged above.
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithMatch(dispatcher.dispatch,
|
||||
new sharedActions.MediaConnected({}));
|
||||
});
|
||||
|
||||
it("should store the start time when both streams are up and" +
|
||||
" driver._sendTwoWayMediaTelemetry is true", function() {
|
||||
driver._sendTwoWayMediaTelemetry = true;
|
||||
driver._publishedLocalStream = true;
|
||||
var startTime = 1;
|
||||
sandbox.stub(performance, "now").returns(startTime);
|
||||
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
expect(driver._getTwoWayMediaStartTime()).to.eql(startTime);
|
||||
});
|
||||
|
||||
it("should not store the start time when both streams are up and" +
|
||||
" driver._isDesktop is false", function() {
|
||||
driver._isDesktop = false;
|
||||
driver._publishedLocalStream = true;
|
||||
var startTime = 73;
|
||||
sandbox.stub(performance, "now").returns(startTime);
|
||||
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
expect(driver._getTwoWayMediaStartTime()).to.not.eql(startTime);
|
||||
});
|
||||
|
||||
describe("Data channel setup", function() {
|
||||
var fakeChannel;
|
||||
|
||||
beforeEach(function() {
|
||||
fakeChannel = _.extend({}, Backbone.Events);
|
||||
fakeStream.connection = fakeConnection;
|
||||
driver._useDataChannels = true;
|
||||
});
|
||||
|
||||
it("should trigger a readyForDataChannel signal after subscribe is complete", function() {
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
sinon.assert.calledOnce(session.signal);
|
||||
sinon.assert.calledWith(session.signal, {
|
||||
type: "readyForDataChannel",
|
||||
to: fakeConnection
|
||||
});
|
||||
});
|
||||
|
||||
it("should not trigger readyForDataChannel signal if data channels are not wanted", function() {
|
||||
driver._useDataChannels = false;
|
||||
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
sinon.assert.notCalled(session.signal);
|
||||
});
|
||||
|
||||
it("should get the data channel after subscribe is complete", function() {
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
sinon.assert.calledOnce(fakeSubscriberObject._.getDataChannel);
|
||||
sinon.assert.calledWith(fakeSubscriberObject._.getDataChannel, "text", {});
|
||||
});
|
||||
|
||||
it("should not get the data channel if data channels are not wanted", function() {
|
||||
driver._useDataChannels = false;
|
||||
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
sinon.assert.notCalled(fakeSubscriberObject._.getDataChannel);
|
||||
});
|
||||
|
||||
it("should dispatch `DataChannelsAvailable` if the publisher channel is setup", function() {
|
||||
// Fake a publisher channel.
|
||||
driver._publisherChannel = {};
|
||||
|
||||
fakeSubscriberObject._.getDataChannel.callsArgWith(2, null, fakeChannel);
|
||||
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.DataChannelsAvailable({
|
||||
available: true
|
||||
}));
|
||||
});
|
||||
|
||||
it("should not dispatch `DataChannelsAvailable` if the publisher channel isn't setup", function() {
|
||||
fakeSubscriberObject._.getDataChannel.callsArgWith(2, null, fakeChannel);
|
||||
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
sinon.assert.neverCalledWith(dispatcher.dispatch,
|
||||
new sharedActions.DataChannelsAvailable({
|
||||
available: true
|
||||
}));
|
||||
});
|
||||
|
||||
it("should dispatch `ReceivedTextChatMessage` when a text message is received", function() {
|
||||
var data = '{"contentType":"' + CHAT_CONTENT_TYPES.TEXT +
|
||||
'","message":"Are you there?","receivedTimestamp": "2015-06-25T00:29:14.197Z"}';
|
||||
var clock = sinon.useFakeTimers();
|
||||
|
||||
fakeSubscriberObject._.getDataChannel.callsArgWith(2, null, fakeChannel);
|
||||
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
// Now send the message.
|
||||
fakeChannel.trigger("message", {
|
||||
data: data
|
||||
});
|
||||
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.ReceivedTextChatMessage({
|
||||
contentType: CHAT_CONTENT_TYPES.TEXT,
|
||||
message: "Are you there?",
|
||||
receivedTimestamp: "1970-01-01T00:00:00.000Z"
|
||||
}));
|
||||
|
||||
/* Restore the time. */
|
||||
clock.restore();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("should not trigger readyForDataChannel signal if data channels are not wanted", function() {
|
||||
session.subscribe.yieldsOn(driver, null, fakeSubscriberObject,
|
||||
document.createElement("video"));
|
||||
driver._useDataChannels = false;
|
||||
fakeStream.connection = fakeConnection;
|
||||
describe("screen sharing streams", function() {
|
||||
it("should subscribe to a screen sharing stream", function() {
|
||||
fakeStream.videoType = "screen";
|
||||
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
sinon.assert.notCalled(session.signal);
|
||||
});
|
||||
sinon.assert.calledOnce(session.subscribe);
|
||||
sinon.assert.calledWithExactly(session.subscribe,
|
||||
fakeStream, sinon.match.instanceOf(HTMLDivElement), publisherConfig,
|
||||
sinon.match.func);
|
||||
});
|
||||
|
||||
it("should subscribe to a screen sharing stream", function() {
|
||||
fakeStream.videoType = "screen";
|
||||
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
sinon.assert.calledOnce(session.subscribe);
|
||||
sinon.assert.calledWithExactly(session.subscribe,
|
||||
fakeStream, sinon.match.instanceOf(HTMLDivElement), publisherConfig,
|
||||
sinon.match.func);
|
||||
});
|
||||
|
||||
it("should dispatch a mediaConnected action if both streams are up", function() {
|
||||
session.subscribe.yieldsOn(driver, null, fakeSubscriberObject,
|
||||
videoElement);
|
||||
driver._publishedLocalStream = true;
|
||||
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
// Called twice due to the VideoDimensionsChanged above.
|
||||
sinon.assert.called(dispatcher.dispatch);
|
||||
sinon.assert.calledWithMatch(dispatcher.dispatch,
|
||||
new sharedActions.MediaConnected({}));
|
||||
});
|
||||
|
||||
it("should store the start time when both streams are up and" +
|
||||
" driver._sendTwoWayMediaTelemetry is true", function() {
|
||||
session.subscribe.yieldsOn(driver, null, fakeSubscriberObject,
|
||||
videoElement);
|
||||
driver._sendTwoWayMediaTelemetry = true;
|
||||
driver._publishedLocalStream = true;
|
||||
var startTime = 1;
|
||||
sandbox.stub(performance, "now").returns(startTime);
|
||||
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
expect(driver._getTwoWayMediaStartTime()).to.eql(startTime);
|
||||
});
|
||||
|
||||
it("should not store the start time when both streams are up and" +
|
||||
" driver._isDesktop is false", function() {
|
||||
session.subscribe.yieldsOn(driver, null, fakeSubscriberObject,
|
||||
videoElement);
|
||||
driver._isDesktop = false;
|
||||
driver._publishedLocalStream = true;
|
||||
var startTime = 73;
|
||||
sandbox.stub(performance, "now").returns(startTime);
|
||||
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
expect(driver._getTwoWayMediaStartTime()).to.not.eql(startTime);
|
||||
});
|
||||
|
||||
|
||||
it("should not dispatch a mediaConnected action for screen sharing streams",
|
||||
function() {
|
||||
it("should not dispatch a mediaConnected action for screen sharing streams", function() {
|
||||
driver._publishedLocalStream = true;
|
||||
fakeStream.videoType = "screen";
|
||||
|
||||
@ -1130,16 +1198,14 @@ describe("loop.OTSdkDriver", function() {
|
||||
sinon.match.hasOwn("name", "mediaConnected"));
|
||||
});
|
||||
|
||||
it("should not dispatch a ReceivingScreenShare action for camera streams",
|
||||
function() {
|
||||
it("should not dispatch a ReceivingScreenShare action for camera streams", function() {
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
|
||||
sinon.assert.neverCalledWithMatch(dispatcher.dispatch,
|
||||
new sharedActions.ReceivingScreenShare({ receiving: true }));
|
||||
});
|
||||
|
||||
it("should dispatch a ReceivingScreenShare action for screen" +
|
||||
" sharing streams", function() {
|
||||
it("should dispatch a ReceivingScreenShare action for screen sharing streams", function() {
|
||||
fakeStream.videoType = "screen";
|
||||
|
||||
session.trigger("streamCreated", { stream: fakeStream });
|
||||
@ -1149,6 +1215,7 @@ describe("loop.OTSdkDriver", function() {
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.ReceivingScreenShare({ receiving: true }));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("streamDestroyed: publisher/local", function() {
|
||||
@ -1499,16 +1566,11 @@ describe("loop.OTSdkDriver", function() {
|
||||
sinon.assert.calledOnce(publisher._.getDataChannel);
|
||||
});
|
||||
|
||||
it("should get the data channel for the subscriber", function() {
|
||||
session.trigger("signal:readyForDataChannel");
|
||||
|
||||
sinon.assert.calledOnce(subscriber._.getDataChannel);
|
||||
});
|
||||
|
||||
it("should dispatch `DataChannelsAvailable` once both data channels have been obtained", function() {
|
||||
it("should dispatch `DataChannelsAvailable` if the subscriber channel is setup", function() {
|
||||
var fakeChannel = _.extend({}, Backbone.Events);
|
||||
|
||||
subscriber._.getDataChannel.callsArgWith(2, null, fakeChannel);
|
||||
driver._subscriberChannel = fakeChannel;
|
||||
|
||||
publisher._.getDataChannel.callsArgWith(2, null, fakeChannel);
|
||||
|
||||
session.trigger("signal:readyForDataChannel");
|
||||
@ -1520,31 +1582,17 @@ describe("loop.OTSdkDriver", function() {
|
||||
}));
|
||||
});
|
||||
|
||||
it("should dispatch `ReceivedTextChatMessage` when a text message is received", function() {
|
||||
it("should not dispatch `DataChannelsAvailable` if the subscriber channel isn't setup", function() {
|
||||
var fakeChannel = _.extend({}, Backbone.Events);
|
||||
var data = '{"contentType":"' + CHAT_CONTENT_TYPES.TEXT +
|
||||
'","message":"Are you there?","receivedTimestamp": "2015-06-25T00:29:14.197Z"}';
|
||||
var clock = sinon.useFakeTimers();
|
||||
|
||||
subscriber._.getDataChannel.callsArgWith(2, null, fakeChannel);
|
||||
publisher._.getDataChannel.callsArgWith(2, null, fakeChannel);
|
||||
|
||||
session.trigger("signal:readyForDataChannel");
|
||||
|
||||
// Now send the message.
|
||||
fakeChannel.trigger("message", {
|
||||
data: data
|
||||
});
|
||||
|
||||
sinon.assert.calledOnce(dispatcher.dispatch);
|
||||
sinon.assert.calledWithExactly(dispatcher.dispatch,
|
||||
new sharedActions.ReceivedTextChatMessage({
|
||||
contentType: CHAT_CONTENT_TYPES.TEXT,
|
||||
message: "Are you there?",
|
||||
receivedTimestamp: "1970-01-01T00:00:00.000Z"
|
||||
sinon.assert.neverCalledWith(dispatcher.dispatch,
|
||||
new sharedActions.DataChannelsAvailable({
|
||||
available: true
|
||||
}));
|
||||
|
||||
/* Restore the time. */
|
||||
clock.restore();
|
||||
});
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user