tenfourfox/services/common/tests/unit/test_tokenserverclient.js
Cameron Kaiser c9b2922b70 hello FPR
2017-04-19 00:56:45 -07:00

467 lines
14 KiB
JavaScript

/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://services-common/async.js");
Cu.import("resource://services-common/tokenserverclient.js");
function run_test() {
initTestLogging("Trace");
run_next_test();
}
add_test(function test_working_bid_exchange() {
_("Ensure that working BrowserID token exchange works as expected.");
let service = "http://example.com/foo";
let duration = 300;
let server = httpd_setup({
"/1.0/foo/1.0": function(request, response) {
do_check_true(request.hasHeader("accept"));
do_check_false(request.hasHeader("x-conditions-accepted"));
do_check_eq("application/json", request.getHeader("accept"));
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Content-Type", "application/json");
let body = JSON.stringify({
id: "id",
key: "key",
api_endpoint: service,
uid: "uid",
duration: duration,
});
response.bodyOutputStream.write(body, body.length);
}
});
let client = new TokenServerClient();
let cb = Async.makeSpinningCallback();
let url = server.baseURI + "/1.0/foo/1.0";
client.getTokenFromBrowserIDAssertion(url, "assertion", cb);
let result = cb.wait();
do_check_eq("object", typeof(result));
do_check_attribute_count(result, 5);
do_check_eq(service, result.endpoint);
do_check_eq("id", result.id);
do_check_eq("key", result.key);
do_check_eq("uid", result.uid);
do_check_eq(duration, result.duration);
server.stop(run_next_test);
});
add_test(function test_invalid_arguments() {
_("Ensure invalid arguments to APIs are rejected.");
let args = [
[null, "assertion", function() {}],
["http://example.com/", null, function() {}],
["http://example.com/", "assertion", null]
];
for (let arg of args) {
try {
let client = new TokenServerClient();
client.getTokenFromBrowserIDAssertion(arg[0], arg[1], arg[2]);
do_throw("Should never get here.");
} catch (ex) {
do_check_true(ex instanceof TokenServerClientError);
}
}
run_next_test();
});
add_test(function test_conditions_required_response_handling() {
_("Ensure that a conditions required response is handled properly.");
let description = "Need to accept conditions";
let tosURL = "http://example.com/tos";
let server = httpd_setup({
"/1.0/foo/1.0": function(request, response) {
do_check_false(request.hasHeader("x-conditions-accepted"));
response.setStatusLine(request.httpVersion, 403, "Forbidden");
response.setHeader("Content-Type", "application/json");
let body = JSON.stringify({
errors: [{description: description, location: "body", name: ""}],
urls: {tos: tosURL}
});
response.bodyOutputStream.write(body, body.length);
}
});
let client = new TokenServerClient();
let url = server.baseURI + "/1.0/foo/1.0";
function onResponse(error, token) {
do_check_true(error instanceof TokenServerClientServerError);
do_check_eq(error.cause, "conditions-required");
// Check a JSON.stringify works on our errors as our logging will try and use it.
do_check_true(JSON.stringify(error), "JSON.stringify worked");
do_check_null(token);
do_check_eq(error.urls.tos, tosURL);
server.stop(run_next_test);
}
client.getTokenFromBrowserIDAssertion(url, "assertion", onResponse);
});
add_test(function test_invalid_403_no_content_type() {
_("Ensure that a 403 without content-type is handled properly.");
let server = httpd_setup({
"/1.0/foo/1.0": function(request, response) {
response.setStatusLine(request.httpVersion, 403, "Forbidden");
// No Content-Type header by design.
let body = JSON.stringify({
errors: [{description: "irrelevant", location: "body", name: ""}],
urls: {foo: "http://bar"}
});
response.bodyOutputStream.write(body, body.length);
}
});
let client = new TokenServerClient();
let url = server.baseURI + "/1.0/foo/1.0";
function onResponse(error, token) {
do_check_true(error instanceof TokenServerClientServerError);
do_check_eq(error.cause, "malformed-response");
do_check_null(token);
do_check_null(error.urls);
server.stop(run_next_test);
}
client.getTokenFromBrowserIDAssertion(url, "assertion", onResponse);
});
add_test(function test_invalid_403_bad_json() {
_("Ensure that a 403 with JSON that isn't proper is handled properly.");
let server = httpd_setup({
"/1.0/foo/1.0": function(request, response) {
response.setStatusLine(request.httpVersion, 403, "Forbidden");
response.setHeader("Content-Type", "application/json; charset=utf-8");
let body = JSON.stringify({
foo: "bar"
});
response.bodyOutputStream.write(body, body.length);
}
});
let client = new TokenServerClient();
let url = server.baseURI + "/1.0/foo/1.0";
function onResponse(error, token) {
do_check_true(error instanceof TokenServerClientServerError);
do_check_eq(error.cause, "malformed-response");
do_check_null(token);
do_check_null(error.urls);
server.stop(run_next_test);
}
client.getTokenFromBrowserIDAssertion(url, "assertion", onResponse);
});
add_test(function test_403_no_urls() {
_("Ensure that a 403 without a urls field is handled properly.");
let server = httpd_setup({
"/1.0/foo/1.0": function(request, response) {
response.setStatusLine(request.httpVersion, 403, "Forbidden");
response.setHeader("Content-Type", "application/json; charset=utf-8");
let body = "{}";
response.bodyOutputStream.write(body, body.length);
}
});
let client = new TokenServerClient();
let url = server.baseURI + "/1.0/foo/1.0";
client.getTokenFromBrowserIDAssertion(url, "assertion",
function onResponse(error, result) {
do_check_true(error instanceof TokenServerClientServerError);
do_check_eq(error.cause, "malformed-response");
do_check_null(result);
server.stop(run_next_test);
});
});
add_test(function test_send_extra_headers() {
_("Ensures that the condition acceptance header is sent when asked.");
let duration = 300;
let server = httpd_setup({
"/1.0/foo/1.0": function(request, response) {
do_check_true(request.hasHeader("x-foo"));
do_check_eq(request.getHeader("x-foo"), "42");
do_check_true(request.hasHeader("x-bar"));
do_check_eq(request.getHeader("x-bar"), "17");
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Content-Type", "application/json");
let body = JSON.stringify({
id: "id",
key: "key",
api_endpoint: "http://example.com/",
uid: "uid",
duration: duration,
});
response.bodyOutputStream.write(body, body.length);
}
});
let client = new TokenServerClient();
let url = server.baseURI + "/1.0/foo/1.0";
function onResponse(error, token) {
do_check_null(error);
// Other tests validate other things.
server.stop(run_next_test);
}
let extra = {
"X-Foo": 42,
"X-Bar": 17
};
client.getTokenFromBrowserIDAssertion(url, "assertion", onResponse, extra);
});
add_test(function test_error_404_empty() {
_("Ensure that 404 responses without proper response are handled properly.");
let server = httpd_setup();
let client = new TokenServerClient();
let url = server.baseURI + "/foo";
client.getTokenFromBrowserIDAssertion(url, "assertion", function(error, r) {
do_check_true(error instanceof TokenServerClientServerError);
do_check_eq(error.cause, "malformed-response");
do_check_neq(null, error.response);
do_check_null(r);
server.stop(run_next_test);
});
});
add_test(function test_error_404_proper_response() {
_("Ensure that a Cornice error report for 404 is handled properly.");
let server = httpd_setup({
"/1.0/foo/1.0": function(request, response) {
response.setStatusLine(request.httpVersion, 404, "Not Found");
response.setHeader("Content-Type", "application/json; charset=utf-8");
let body = JSON.stringify({
status: 404,
errors: [{description: "No service", location: "body", name: ""}],
});
response.bodyOutputStream.write(body, body.length);
}
});
function onResponse(error, token) {
do_check_true(error instanceof TokenServerClientServerError);
do_check_eq(error.cause, "unknown-service");
do_check_null(token);
server.stop(run_next_test);
}
let client = new TokenServerClient();
let url = server.baseURI + "/1.0/foo/1.0";
client.getTokenFromBrowserIDAssertion(url, "assertion", onResponse);
});
add_test(function test_bad_json() {
_("Ensure that malformed JSON is handled properly.");
let server = httpd_setup({
"/1.0/foo/1.0": function(request, response) {
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Content-Type", "application/json");
let body = '{"id": "id", baz}'
response.bodyOutputStream.write(body, body.length);
}
});
let client = new TokenServerClient();
let url = server.baseURI + "/1.0/foo/1.0";
client.getTokenFromBrowserIDAssertion(url, "assertion", function(error, r) {
do_check_neq(null, error);
do_check_eq("TokenServerClientServerError", error.name);
do_check_eq(error.cause, "malformed-response");
do_check_neq(null, error.response);
do_check_eq(null, r);
server.stop(run_next_test);
});
});
add_test(function test_400_response() {
_("Ensure HTTP 400 is converted to malformed-request.");
let server = httpd_setup({
"/1.0/foo/1.0": function(request, response) {
response.setStatusLine(request.httpVersion, 400, "Bad Request");
response.setHeader("Content-Type", "application/json; charset=utf-8");
let body = "{}"; // Actual content may not be used.
response.bodyOutputStream.write(body, body.length);
}
});
let client = new TokenServerClient();
let url = server.baseURI + "/1.0/foo/1.0";
client.getTokenFromBrowserIDAssertion(url, "assertion", function(error, r) {
do_check_neq(null, error);
do_check_eq("TokenServerClientServerError", error.name);
do_check_neq(null, error.response);
do_check_eq(error.cause, "malformed-request");
server.stop(run_next_test);
});
});
add_test(function test_401_with_error_cause() {
_("Ensure 401 cause is specified in body.status");
let server = httpd_setup({
"/1.0/foo/1.0": function(request, response) {
response.setStatusLine(request.httpVersion, 401, "Unauthorized");
response.setHeader("Content-Type", "application/json; charset=utf-8");
let body = JSON.stringify({status: "no-soup-for-you"});
response.bodyOutputStream.write(body, body.length);
}
});
let client = new TokenServerClient();
let url = server.baseURI + "/1.0/foo/1.0";
client.getTokenFromBrowserIDAssertion(url, "assertion", function(error, r) {
do_check_neq(null, error);
do_check_eq("TokenServerClientServerError", error.name);
do_check_neq(null, error.response);
do_check_eq(error.cause, "no-soup-for-you");
server.stop(run_next_test);
});
});
add_test(function test_unhandled_media_type() {
_("Ensure that unhandled media types throw an error.");
let server = httpd_setup({
"/1.0/foo/1.0": function(request, response) {
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Content-Type", "text/plain");
let body = "hello, world";
response.bodyOutputStream.write(body, body.length);
}
});
let url = server.baseURI + "/1.0/foo/1.0";
let client = new TokenServerClient();
client.getTokenFromBrowserIDAssertion(url, "assertion", function(error, r) {
do_check_neq(null, error);
do_check_eq("TokenServerClientServerError", error.name);
do_check_neq(null, error.response);
do_check_eq(null, r);
server.stop(run_next_test);
});
});
add_test(function test_rich_media_types() {
_("Ensure that extra tokens in the media type aren't rejected.");
let duration = 300;
let server = httpd_setup({
"/foo": function(request, response) {
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Content-Type", "application/json; foo=bar; bar=foo");
let body = JSON.stringify({
id: "id",
key: "key",
api_endpoint: "foo",
uid: "uid",
duration: duration,
});
response.bodyOutputStream.write(body, body.length);
}
});
let url = server.baseURI + "/foo";
let client = new TokenServerClient();
client.getTokenFromBrowserIDAssertion(url, "assertion", function(error, r) {
do_check_eq(null, error);
server.stop(run_next_test);
});
});
add_test(function test_exception_during_callback() {
_("Ensure that exceptions thrown during callback handling are handled.");
let duration = 300;
let server = httpd_setup({
"/foo": function(request, response) {
response.setStatusLine(request.httpVersion, 200, "OK");
response.setHeader("Content-Type", "application/json");
let body = JSON.stringify({
id: "id",
key: "key",
api_endpoint: "foo",
uid: "uid",
duration: duration,
});
response.bodyOutputStream.write(body, body.length);
}
});
let url = server.baseURI + "/foo";
let client = new TokenServerClient();
let cb = Async.makeSpinningCallback();
let callbackCount = 0;
client.getTokenFromBrowserIDAssertion(url, "assertion", function(error, r) {
do_check_eq(null, error);
cb();
callbackCount += 1;
throw new Error("I am a bad function!");
});
cb.wait();
// This relies on some heavy event loop magic. The error in the main
// callback should already have been raised at this point.
do_check_eq(callbackCount, 1);
server.stop(run_next_test);
});