mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-11 21:58:41 +02:00
341 lines
9.8 KiB
JavaScript
341 lines
9.8 KiB
JavaScript
/* 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, sinon, it, beforeEach, afterEach, describe */
|
|
|
|
var expect = chai.expect;
|
|
|
|
describe("loop.CallConnectionWebSocket", function() {
|
|
"use strict";
|
|
|
|
var sandbox,
|
|
dummySocket;
|
|
|
|
beforeEach(function() {
|
|
sandbox = sinon.sandbox.create();
|
|
sandbox.useFakeTimers();
|
|
|
|
dummySocket = {
|
|
close: sinon.spy(),
|
|
send: sinon.spy()
|
|
};
|
|
sandbox.stub(window, 'WebSocket').returns(dummySocket);
|
|
});
|
|
|
|
afterEach(function() {
|
|
sandbox.restore();
|
|
});
|
|
|
|
describe("#constructor", function() {
|
|
it("should require a url option", function() {
|
|
expect(function() {
|
|
return new loop.CallConnectionWebSocket();
|
|
}).to.Throw(/No url/);
|
|
});
|
|
|
|
it("should require a callId setting", function() {
|
|
expect(function() {
|
|
return new loop.CallConnectionWebSocket({url: "wss://fake/"});
|
|
}).to.Throw(/No callId/);
|
|
});
|
|
|
|
it("should require a websocketToken setting", function() {
|
|
expect(function() {
|
|
return new loop.CallConnectionWebSocket({
|
|
url: "http://fake/",
|
|
callId: "hello"
|
|
});
|
|
}).to.Throw(/No websocketToken/);
|
|
});
|
|
});
|
|
|
|
describe("constructed", function() {
|
|
var callWebSocket, fakeUrl, fakeCallId, fakeWebSocketToken;
|
|
|
|
beforeEach(function() {
|
|
fakeUrl = "wss://fake/";
|
|
fakeCallId = "callId";
|
|
fakeWebSocketToken = "7b";
|
|
|
|
callWebSocket = new loop.CallConnectionWebSocket({
|
|
url: fakeUrl,
|
|
callId: fakeCallId,
|
|
websocketToken: fakeWebSocketToken
|
|
});
|
|
});
|
|
|
|
describe("#promiseConnect", function() {
|
|
it("should create a new websocket connection", function() {
|
|
callWebSocket.promiseConnect();
|
|
|
|
sinon.assert.calledOnce(window.WebSocket);
|
|
sinon.assert.calledWithExactly(window.WebSocket, fakeUrl);
|
|
});
|
|
|
|
it("should reject the promise if connection is not completed in " +
|
|
"5 seconds", function(done) {
|
|
var promise = callWebSocket.promiseConnect();
|
|
|
|
sandbox.clock.tick(5101);
|
|
|
|
promise.then(function() {}, function(error) {
|
|
expect(error).to.be.equal("timeout");
|
|
done();
|
|
});
|
|
});
|
|
|
|
it("should reject the promise if the connection errors", function(done) {
|
|
var promise = callWebSocket.promiseConnect();
|
|
|
|
dummySocket.onerror("error");
|
|
|
|
promise.then(function() {}, function(error) {
|
|
expect(error).to.be.equal("error");
|
|
done();
|
|
});
|
|
});
|
|
|
|
it("should reject the promise if the connection closes", function(done) {
|
|
var promise = callWebSocket.promiseConnect();
|
|
|
|
dummySocket.onclose("close");
|
|
|
|
promise.then(function() {}, function(error) {
|
|
expect(error).to.be.equal("close");
|
|
done();
|
|
});
|
|
});
|
|
|
|
it("should send hello when the socket is opened", function() {
|
|
callWebSocket.promiseConnect();
|
|
|
|
dummySocket.onopen();
|
|
|
|
sinon.assert.calledOnce(dummySocket.send);
|
|
sinon.assert.calledWithExactly(dummySocket.send, JSON.stringify({
|
|
messageType: "hello",
|
|
callId: fakeCallId,
|
|
auth: fakeWebSocketToken
|
|
}));
|
|
});
|
|
|
|
it("should resolve the promise when the 'hello' is received",
|
|
function(done) {
|
|
var promise = callWebSocket.promiseConnect();
|
|
|
|
dummySocket.onmessage({
|
|
data: '{"messageType":"hello", "state":"init"}'
|
|
});
|
|
|
|
promise.then(function(state) {
|
|
expect(state).eql("init");
|
|
done();
|
|
}, function() {
|
|
done(new Error("shouldn't have rejected the promise"));
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("#close", function() {
|
|
it("should close the socket", function() {
|
|
callWebSocket.promiseConnect();
|
|
|
|
callWebSocket.close();
|
|
|
|
sinon.assert.calledOnce(dummySocket.close);
|
|
});
|
|
});
|
|
|
|
describe("#decline", function() {
|
|
it("should send a terminate message to the server", function() {
|
|
callWebSocket.promiseConnect();
|
|
|
|
callWebSocket.decline();
|
|
|
|
sinon.assert.calledOnce(dummySocket.send);
|
|
sinon.assert.calledWithExactly(dummySocket.send, JSON.stringify({
|
|
messageType: "action",
|
|
event: "terminate",
|
|
reason: "reject"
|
|
}));
|
|
});
|
|
});
|
|
|
|
describe("#accept", function() {
|
|
it("should send an accept message to the server", function() {
|
|
callWebSocket.promiseConnect();
|
|
|
|
callWebSocket.accept();
|
|
|
|
sinon.assert.calledOnce(dummySocket.send);
|
|
sinon.assert.calledWithExactly(dummySocket.send, JSON.stringify({
|
|
messageType: "action",
|
|
event: "accept"
|
|
}));
|
|
});
|
|
});
|
|
|
|
describe("#mediaUp", function() {
|
|
it("should send a media-up message to the server", function() {
|
|
callWebSocket.promiseConnect();
|
|
|
|
callWebSocket.mediaUp();
|
|
|
|
sinon.assert.calledOnce(dummySocket.send);
|
|
sinon.assert.calledWithExactly(dummySocket.send, JSON.stringify({
|
|
messageType: "action",
|
|
event: "media-up"
|
|
}));
|
|
});
|
|
});
|
|
|
|
describe("#cancel", function() {
|
|
it("should send a terminate message to the server with a reason of cancel",
|
|
function() {
|
|
callWebSocket.promiseConnect();
|
|
|
|
callWebSocket.cancel();
|
|
|
|
sinon.assert.calledOnce(dummySocket.send);
|
|
sinon.assert.calledWithExactly(dummySocket.send, JSON.stringify({
|
|
messageType: "action",
|
|
event: "terminate",
|
|
reason: "cancel"
|
|
}));
|
|
});
|
|
});
|
|
|
|
describe("#mediaFail", function() {
|
|
it("should send a terminate message to the server with a reason of media-fail",
|
|
function() {
|
|
callWebSocket.promiseConnect();
|
|
|
|
callWebSocket.mediaFail();
|
|
|
|
sinon.assert.calledOnce(dummySocket.send);
|
|
sinon.assert.calledWithExactly(dummySocket.send, JSON.stringify({
|
|
messageType: "action",
|
|
event: "terminate",
|
|
reason: "media-fail"
|
|
}));
|
|
});
|
|
});
|
|
|
|
describe("Events", function() {
|
|
beforeEach(function() {
|
|
sandbox.stub(callWebSocket, "trigger");
|
|
|
|
callWebSocket.promiseConnect();
|
|
});
|
|
|
|
describe("Progress", function() {
|
|
it("should trigger a progress event on the callWebSocket", function() {
|
|
var eventData = {
|
|
messageType: "progress",
|
|
state: "terminate",
|
|
reason: "reject"
|
|
};
|
|
|
|
dummySocket.onmessage({
|
|
data: JSON.stringify(eventData)
|
|
});
|
|
|
|
sinon.assert.called(callWebSocket.trigger);
|
|
sinon.assert.calledWithExactly(callWebSocket.trigger, "progress",
|
|
eventData, "init");
|
|
});
|
|
|
|
it("should trigger a progress event with the previous state", function() {
|
|
var previousEventData = {
|
|
messageType: "progress",
|
|
state: "alerting"
|
|
};
|
|
|
|
// This first call is to set the previous state of the object
|
|
// ready for the main test below.
|
|
dummySocket.onmessage({
|
|
data: JSON.stringify(previousEventData)
|
|
});
|
|
|
|
var currentEventData = {
|
|
messageType: "progress",
|
|
state: "terminate",
|
|
reason: "reject"
|
|
};
|
|
|
|
dummySocket.onmessage({
|
|
data: JSON.stringify(currentEventData)
|
|
});
|
|
|
|
sinon.assert.called(callWebSocket.trigger);
|
|
sinon.assert.calledWithExactly(callWebSocket.trigger, "progress",
|
|
currentEventData, "alerting");
|
|
});
|
|
|
|
it("should trigger a progress:<state> event on the callWebSocket", function() {
|
|
var eventData = {
|
|
messageType: "progress",
|
|
state: "terminate",
|
|
reason: "reject"
|
|
};
|
|
|
|
dummySocket.onmessage({
|
|
data: JSON.stringify(eventData)
|
|
});
|
|
|
|
sinon.assert.called(callWebSocket.trigger);
|
|
sinon.assert.calledWithExactly(callWebSocket.trigger, "progress:terminate");
|
|
});
|
|
});
|
|
|
|
describe("Error", function() {
|
|
// Handled in constructed -> #promiseConnect:
|
|
// should reject the promise if the connection errors
|
|
|
|
it("should trigger an error if state is not completed", function() {
|
|
callWebSocket._clearConnectionFlags();
|
|
|
|
dummySocket.onerror("Error");
|
|
|
|
sinon.assert.calledOnce(callWebSocket.trigger);
|
|
sinon.assert.calledWithExactly(callWebSocket.trigger,
|
|
"error", "Error");
|
|
});
|
|
|
|
it("should not trigger an error if state is completed", function() {
|
|
callWebSocket._clearConnectionFlags();
|
|
callWebSocket._lastServerState = "connected";
|
|
|
|
dummySocket.onerror("Error");
|
|
|
|
sinon.assert.notCalled(callWebSocket.trigger);
|
|
});
|
|
});
|
|
|
|
describe("Close", function() {
|
|
// Handled in constructed -> #promiseConnect:
|
|
// should reject the promise if the connection closes
|
|
|
|
it("should trigger a close event if state is not completed", function() {
|
|
callWebSocket._clearConnectionFlags();
|
|
|
|
dummySocket.onclose("Error");
|
|
|
|
sinon.assert.calledOnce(callWebSocket.trigger);
|
|
sinon.assert.calledWithExactly(callWebSocket.trigger,
|
|
"closed", "Error");
|
|
});
|
|
|
|
it("should not trigger an error if state is completed", function() {
|
|
callWebSocket._clearConnectionFlags();
|
|
callWebSocket._lastServerState = "terminated";
|
|
|
|
dummySocket.onclose("Error");
|
|
|
|
sinon.assert.notCalled(callWebSocket.trigger);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|