diff options
Diffstat (limited to 'services/common/tests/unit/test_tokenserverclient.js')
-rw-r--r-- | services/common/tests/unit/test_tokenserverclient.js | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/services/common/tests/unit/test_tokenserverclient.js b/services/common/tests/unit/test_tokenserverclient.js new file mode 100644 index 0000000000..c923393742 --- /dev/null +++ b/services/common/tests/unit/test_tokenserverclient.js @@ -0,0 +1,380 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +const { + TokenServerClient, + TokenServerClientError, + TokenServerClientServerError, +} = ChromeUtils.import("resource://services-common/tokenserverclient.js"); + +initTestLogging("Trace"); + +add_task(async function test_working_token_exchange() { + _("Ensure that working OAuth 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) { + Assert.ok(request.hasHeader("accept")); + Assert.equal("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, + }); + response.bodyOutputStream.write(body, body.length); + }, + }); + + let client = new TokenServerClient(); + let url = server.baseURI + "/1.0/foo/1.0"; + let result = await client.getTokenUsingOAuth(url, "access_token"); + Assert.equal("object", typeof result); + do_check_attribute_count(result, 7); + Assert.equal(service, result.endpoint); + Assert.equal("id", result.id); + Assert.equal("key", result.key); + Assert.equal("uid", result.uid); + Assert.equal(duration, result.duration); + Assert.deepEqual(undefined, result.node_type); + await promiseStopServer(server); +}); + +add_task(async function test_working_token_exchange_with_nodetype() { + _("Ensure that a token response with a node type as expected."); + + let service = "http://example.com/foo"; + let duration = 300; + let nodeType = "the-node-type"; + + let server = httpd_setup({ + "/1.0/foo/1.0": function(request, response) { + Assert.ok(request.hasHeader("accept")); + Assert.equal("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, + node_type: nodeType, + }); + response.bodyOutputStream.write(body, body.length); + }, + }); + + let client = new TokenServerClient(); + let url = server.baseURI + "/1.0/foo/1.0"; + let result = await client.getTokenUsingOAuth(url, "access_token"); + Assert.equal("object", typeof result); + do_check_attribute_count(result, 7); + Assert.equal(service, result.endpoint); + Assert.equal("id", result.id); + Assert.equal("key", result.key); + Assert.equal("uid", result.uid); + Assert.equal(duration, result.duration); + Assert.equal(nodeType, result.node_type); + await promiseStopServer(server); +}); + +add_task(async function test_invalid_arguments() { + _("Ensure invalid arguments to APIs are rejected."); + + let args = [ + [null, "access_token"], + ["http://example.com/", null], + ]; + + for (let arg of args) { + let client = new TokenServerClient(); + await Assert.rejects(client.getTokenUsingOAuth(arg[0], arg[1]), ex => { + Assert.ok(ex instanceof TokenServerClientError); + return true; + }); + } +}); + +add_task(async 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"; + + await Assert.rejects( + client.getTokenUsingOAuth(url, "access_token"), + error => { + Assert.ok(error instanceof TokenServerClientServerError); + Assert.equal(error.cause, "malformed-response"); + + Assert.equal(null, error.urls); + return true; + } + ); + + await promiseStopServer(server); +}); + +add_task(async 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) { + Assert.ok(request.hasHeader("x-foo")); + Assert.equal(request.getHeader("x-foo"), "42"); + + Assert.ok(request.hasHeader("x-bar")); + Assert.equal(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, + }); + response.bodyOutputStream.write(body, body.length); + }, + }); + + let client = new TokenServerClient(); + let url = server.baseURI + "/1.0/foo/1.0"; + + let extra = { + "X-Foo": 42, + "X-Bar": 17, + }; + + await client.getTokenUsingOAuth(url, "access_token", extra); + // Other tests validate other things. + + await promiseStopServer(server); +}); + +add_task(async 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"; + + await Assert.rejects( + client.getTokenUsingOAuth(url, "access_token"), + error => { + Assert.ok(error instanceof TokenServerClientServerError); + Assert.equal(error.cause, "malformed-response"); + + Assert.notEqual(null, error.response); + return true; + } + ); + + await promiseStopServer(server); +}); + +add_task(async 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); + }, + }); + + let client = new TokenServerClient(); + let url = server.baseURI + "/1.0/foo/1.0"; + + await Assert.rejects( + client.getTokenUsingOAuth(url, "access_token"), + error => { + Assert.ok(error instanceof TokenServerClientServerError); + Assert.equal(error.cause, "unknown-service"); + return true; + } + ); + + await promiseStopServer(server); +}); + +add_task(async 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"; + + await Assert.rejects( + client.getTokenUsingOAuth(url, "access_token"), + error => { + Assert.notEqual(null, error); + Assert.equal("TokenServerClientServerError", error.name); + Assert.equal(error.cause, "malformed-response"); + Assert.notEqual(null, error.response); + return true; + } + ); + + await promiseStopServer(server); +}); + +add_task(async 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"; + + await Assert.rejects( + client.getTokenUsingOAuth(url, "access_token"), + error => { + Assert.notEqual(null, error); + Assert.equal("TokenServerClientServerError", error.name); + Assert.notEqual(null, error.response); + Assert.equal(error.cause, "malformed-request"); + return true; + } + ); + + await promiseStopServer(server); +}); + +add_task(async 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"; + + await Assert.rejects( + client.getTokenUsingOAuth(url, "access_token"), + error => { + Assert.notEqual(null, error); + Assert.equal("TokenServerClientServerError", error.name); + Assert.notEqual(null, error.response); + Assert.equal(error.cause, "no-soup-for-you"); + return true; + } + ); + + await promiseStopServer(server); +}); + +add_task(async 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(); + + await Assert.rejects( + client.getTokenUsingOAuth(url, "access_token"), + error => { + Assert.notEqual(null, error); + Assert.equal("TokenServerClientServerError", error.name); + Assert.notEqual(null, error.response); + return true; + } + ); + + await promiseStopServer(server); +}); + +add_task(async 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, + }); + response.bodyOutputStream.write(body, body.length); + }, + }); + + let url = server.baseURI + "/foo"; + let client = new TokenServerClient(); + + await client.getTokenUsingOAuth(url, "access_token"); + await promiseStopServer(server); +}); |