/* 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, hawk */ var expect = chai.expect; describe("loop.StandaloneClient", function() { "use strict"; var sandbox, fakeXHR, requests = [], callback, fakeToken; beforeEach(function() { sandbox = sinon.sandbox.create(); fakeXHR = sandbox.useFakeXMLHttpRequest(); requests = []; // https://github.com/cjohansen/Sinon.JS/issues/393 fakeXHR.xhr.onCreate = function (xhr) { requests.push(xhr); }; callback = sinon.spy(); fakeToken = "fakeTokenText"; }); afterEach(function() { sandbox.restore(); }); describe("loop.StandaloneClient", function() { describe("#constructor", function() { it("should require a baseServerUrl setting", function() { expect(function() { new loop.StandaloneClient(); }).to.Throw(Error, /required/); }); }); describe("#requestCallUrlInfo", function() { var client, fakeServerErrorDescription; beforeEach(function() { client = new loop.StandaloneClient( {baseServerUrl: "http://fake.api"} ); }); describe("should make the requests to the server", function() { it("should throw if loopToken is missing", function() { expect(client.requestCallUrlInfo).to .throw(/Missing required parameter loopToken/); }); it("should make a GET request for the call url creation date", function() { client.requestCallUrlInfo("fakeCallUrlToken", function() {}); expect(requests).to.have.length.of(1); expect(requests[0].url) .to.eql("http://fake.api/calls/fakeCallUrlToken"); expect(requests[0].method).to.eql("GET"); }); it("should call the callback with (null, serverResponse)", function() { var successCallback = sandbox.spy(function() {}); var serverResponse = { calleeFriendlyName: "Andrei", urlCreationDate: 0 }; client.requestCallUrlInfo("fakeCallUrlToken", successCallback); requests[0].respond(200, {"Content-Type": "application/json"}, JSON.stringify(serverResponse)); sinon.assert.calledWithExactly(successCallback, null, serverResponse); }); it("should log the error if the requests fails", function() { sinon.stub(console, "error"); var serverResponse = {error: true}; var error = JSON.stringify(serverResponse); client.requestCallUrlInfo("fakeCallUrlToken", sandbox.stub()); requests[0].respond(404, {"Content-Type": "application/json"}, error); sinon.assert.calledOnce(console.error); sinon.assert.calledWithExactly(console.error, "Server error", "HTTP 404 Not Found", serverResponse); }); }) }); describe("requestCallInfo", function() { var client, fakeServerErrorDescription; beforeEach(function() { client = new loop.StandaloneClient( {baseServerUrl: "http://fake.api"} ); fakeServerErrorDescription = { code: 401, errno: 101, error: "error", message: "invalid token", info: "error info" }; }); it("should prevent launching a conversation when token is missing", function() { expect(function() { client.requestCallInfo(); }).to.Throw(Error, /missing.*[Tt]oken/); }); it("should post data for the given call", function() { client.requestCallInfo("fake", "audio", callback); expect(requests).to.have.length.of(1); expect(requests[0].url).to.be.equal("http://fake.api/calls/fake"); expect(requests[0].method).to.be.equal("POST"); expect(requests[0].requestBody).to.be.equal('{"callType":"audio","channel":"standalone"}'); }); it("should receive call data for the given call", function() { client.requestCallInfo("fake", "audio-video", callback); var sessionData = { sessionId: "one", sessionToken: "two", apiKey: "three" }; requests[0].respond(200, {"Content-Type": "application/json"}, JSON.stringify(sessionData)); sinon.assert.calledWithExactly(callback, null, sessionData); }); it("should send an error when the request fails", function() { client.requestCallInfo("fake", "audio", callback); requests[0].respond(401, {"Content-Type": "application/json"}, JSON.stringify(fakeServerErrorDescription)); sinon.assert.calledWithMatch(callback, sinon.match(function(err) { return /HTTP 401 Unauthorized/.test(err.message); })); }); it("should attach the server error description object to the error " + "passed to the callback", function() { client.requestCallInfo("fake", "audio", callback); requests[0].respond(401, {"Content-Type": "application/json"}, JSON.stringify(fakeServerErrorDescription)); sinon.assert.calledWithMatch(callback, sinon.match(function(err) { return err.errno === fakeServerErrorDescription.errno; })); }); it("should send an error if the data is not valid", function() { client.requestCallInfo("fake", "audio", callback); requests[0].respond(200, {"Content-Type": "application/json"}, '{"bad": "one"}'); sinon.assert.calledWithMatch(callback, sinon.match(function(err) { return /Invalid data received/.test(err.message); })); }); }); }); });