mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-09 21:00:42 +02:00
291 lines
9.5 KiB
JavaScript
291 lines
9.5 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, hawk */
|
|
|
|
var expect = chai.expect;
|
|
|
|
describe("loop.shared.Client", function() {
|
|
"use strict";
|
|
|
|
var sandbox,
|
|
fakeXHR,
|
|
requests = [],
|
|
callback,
|
|
mozLoop,
|
|
fakeToken;
|
|
|
|
var fakeErrorRes = JSON.stringify({
|
|
status: "errors",
|
|
errors: [{
|
|
location: "url",
|
|
name: "token",
|
|
description: "invalid token"
|
|
}]
|
|
});
|
|
|
|
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.shared.Client", function() {
|
|
describe("#constructor", function() {
|
|
it("should require a baseServerUrl setting", function() {
|
|
expect(function() {
|
|
new loop.shared.Client();
|
|
}).to.Throw(Error, /required/);
|
|
});
|
|
});
|
|
|
|
describe("#requestCallUrl", function() {
|
|
var client;
|
|
|
|
beforeEach(function() {
|
|
window.navigator.mozLoop = {
|
|
ensureRegistered: sinon.stub().callsArgWith(0, null),
|
|
noteCallUrlExpiry: sinon.spy(),
|
|
getLoopCharPref: sandbox.stub()
|
|
.returns(null)
|
|
.withArgs("hawk-session-token")
|
|
.returns(fakeToken)
|
|
};
|
|
client = new loop.shared.Client(
|
|
{baseServerUrl: "http://fake.api", mozLoop: window.navigator.mozLoop}
|
|
);
|
|
});
|
|
|
|
it("should ensure loop is registered", function() {
|
|
client.requestCallUrl("foo", callback);
|
|
|
|
sinon.assert.calledOnce(navigator.mozLoop.ensureRegistered);
|
|
});
|
|
|
|
it("should send an error when registration fails", function() {
|
|
navigator.mozLoop.ensureRegistered.callsArgWith(0, "offline");
|
|
|
|
client.requestCallUrl("foo", callback);
|
|
|
|
sinon.assert.calledOnce(callback);
|
|
sinon.assert.calledWithExactly(callback, "offline");
|
|
});
|
|
|
|
it("should post to /call-url/", function() {
|
|
client.requestCallUrl("foo", callback);
|
|
|
|
expect(requests).to.have.length.of(1);
|
|
expect(requests[0].method).to.be.equal("POST");
|
|
expect(requests[0].url).to.be.equal("http://fake.api/call-url/");
|
|
expect(requests[0].requestBody).to.be.equal('callerId=foo');
|
|
});
|
|
|
|
it("should set the XHR Authorization header", function() {
|
|
sandbox.stub(hawk.client, "header").returns( {field: fakeToken} );
|
|
client._credentials = {
|
|
// XXX we probably really want to stub out external module calls
|
|
// eg deriveHawkCredentials, rather supplying them with valid arguments
|
|
// like we're doing here:
|
|
key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
|
|
algorithm: 'sha256',
|
|
user: 'Steve'
|
|
};
|
|
|
|
client.requestCallUrl("foo", callback);
|
|
|
|
expect(requests[0].requestHeaders.Authorization).to.equal(fakeToken);
|
|
});
|
|
|
|
it("should request a call url", function() {
|
|
var callUrlData = {
|
|
"call_url": "fakeCallUrl",
|
|
"expiresAt": 60
|
|
};
|
|
|
|
client.requestCallUrl("foo", callback);
|
|
requests[0].respond(200, {"Content-Type": "application/json"},
|
|
JSON.stringify(callUrlData));
|
|
|
|
sinon.assert.calledWithExactly(callback, null, callUrlData);
|
|
});
|
|
|
|
it("should note the call url expiry", function() {
|
|
var callUrlData = {
|
|
"call_url": "fakeCallUrl",
|
|
"expiresAt": 60
|
|
};
|
|
|
|
client.requestCallUrl("foo", callback);
|
|
requests[0].respond(200, {"Content-Type": "application/json"},
|
|
JSON.stringify(callUrlData));
|
|
|
|
// expiresAt is in hours, and noteCallUrlExpiry wants seconds.
|
|
sinon.assert.calledWithExactly(navigator.mozLoop.noteCallUrlExpiry,
|
|
60 * 60 * 60);
|
|
});
|
|
|
|
it("should send an error when the request fails", function() {
|
|
client.requestCallUrl("foo", callback);
|
|
|
|
expect(requests).to.have.length.of(1);
|
|
requests[0].respond(400, {"Content-Type": "application/json"},
|
|
fakeErrorRes);
|
|
|
|
sinon.assert.calledWithMatch(callback, sinon.match(function(err) {
|
|
return /400.*invalid token/.test(err.message);
|
|
}));
|
|
});
|
|
|
|
it("should send an error if the data is not valid", function() {
|
|
client.requestCallUrl("foo", callback);
|
|
requests[0].respond(200, {"Content-Type": "application/json"},
|
|
'{"bad": {}}');
|
|
|
|
sinon.assert.calledWithMatch(callback, sinon.match(function(err) {
|
|
return /Invalid data received/.test(err.message);
|
|
}));
|
|
});
|
|
});
|
|
|
|
describe("#requestCallsInfo", function() {
|
|
var client;
|
|
|
|
beforeEach(function() {
|
|
mozLoop = {
|
|
getLoopCharPref: sandbox.stub()
|
|
.returns(null)
|
|
.withArgs("hawk-session-token")
|
|
.returns(fakeToken)
|
|
};
|
|
client = new loop.shared.Client(
|
|
{baseServerUrl: "http://fake.api", mozLoop: mozLoop}
|
|
);
|
|
});
|
|
|
|
it("should prevent launching a conversation when version is missing",
|
|
function() {
|
|
expect(function() {
|
|
client.requestCallsInfo();
|
|
}).to.Throw(Error, /missing required parameter version/);
|
|
});
|
|
|
|
it("should request data for all calls", function() {
|
|
client.requestCallsInfo(42, callback);
|
|
|
|
expect(requests).to.have.length.of(1);
|
|
expect(requests[0].url).to.be.equal("http://fake.api/calls?version=42");
|
|
expect(requests[0].method).to.be.equal("GET");
|
|
|
|
requests[0].respond(200, {"Content-Type": "application/json"},
|
|
'{"calls": [{"apiKey": "fake"}]}');
|
|
sinon.assert.calledWithExactly(callback, null, [{apiKey: "fake"}]);
|
|
});
|
|
|
|
it("should set the XHR Authorization header", function() {
|
|
sandbox.stub(hawk.client, "header").returns( {field: fakeToken} );
|
|
// XXX we probably really want to stub out external module calls
|
|
// eg deriveHawkCredentials, rather supplying them with valid arguments
|
|
// like we're doing here:
|
|
client._credentials = {
|
|
key: 'werxhqb98rpaxn39848xrunpaw3489ruxnpa98w4rxn',
|
|
algorithm: 'sha256',
|
|
user: 'Steve'
|
|
};
|
|
|
|
client.requestCallsInfo("foo", callback);
|
|
|
|
expect(requests[0].requestHeaders.Authorization).to.equal(fakeToken);
|
|
});
|
|
|
|
it("should send an error when the request fails", function() {
|
|
client.requestCallsInfo(42, callback);
|
|
|
|
requests[0].respond(400, {"Content-Type": "application/json"},
|
|
fakeErrorRes);
|
|
sinon.assert.calledWithMatch(callback, sinon.match(function(err) {
|
|
return /400.*invalid token/.test(err.message);
|
|
}));
|
|
});
|
|
|
|
it("should send an error if the data is not valid", function() {
|
|
client.requestCallsInfo(42, callback);
|
|
|
|
requests[0].respond(200, {"Content-Type": "application/json"},
|
|
'{"bad": {}}');
|
|
sinon.assert.calledWithMatch(callback, sinon.match(function(err) {
|
|
return /Invalid data received/.test(err.message);
|
|
}));
|
|
});
|
|
});
|
|
|
|
describe("requestCallInfo", function() {
|
|
var client;
|
|
|
|
beforeEach(function() {
|
|
client = new loop.shared.Client(
|
|
{baseServerUrl: "http://fake.api", mozLoop: undefined}
|
|
);
|
|
});
|
|
|
|
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", 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");
|
|
});
|
|
|
|
it("should receive call data for the given call", function() {
|
|
client.requestCallInfo("fake", 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", callback);
|
|
|
|
requests[0].respond(400, {"Content-Type": "application/json"},
|
|
fakeErrorRes);
|
|
sinon.assert.calledWithMatch(callback, sinon.match(function(err) {
|
|
return /400.*invalid token/.test(err.message);
|
|
}));
|
|
});
|
|
|
|
it("should send an error if the data is not valid", function() {
|
|
client.requestCallInfo("fake", 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);
|
|
}));
|
|
});
|
|
});
|
|
});
|
|
});
|