summaryrefslogtreecommitdiffstats
path: root/dom/tests/unit/test_Fetch.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/tests/unit/test_Fetch.js')
-rw-r--r--dom/tests/unit/test_Fetch.js367
1 files changed, 367 insertions, 0 deletions
diff --git a/dom/tests/unit/test_Fetch.js b/dom/tests/unit/test_Fetch.js
new file mode 100644
index 0000000000..768cf671dd
--- /dev/null
+++ b/dom/tests/unit/test_Fetch.js
@@ -0,0 +1,367 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const { HttpServer } = ChromeUtils.importESModule(
+ "resource://testing-common/httpd.sys.mjs"
+);
+
+const BinaryInputStream = Components.Constructor(
+ "@mozilla.org/binaryinputstream;1",
+ "nsIBinaryInputStream",
+ "setInputStream"
+);
+
+var server;
+
+function getBaseUrl() {
+ return "http://localhost:" + server.identity.primaryPort;
+}
+
+// a way to create some test defaults
+function createTestData(testPath) {
+ return {
+ testPath,
+ request: {
+ headers: {},
+ contentType: "application/json",
+ },
+ response: {
+ headers: {},
+ contentType: "application/json",
+ body: '{"Look": "Success!"}',
+ status: 200,
+ statusText: "OK",
+ },
+ };
+}
+
+// read body and content type information from a request
+function readDataFromRequest(aRequest) {
+ let requestData = {};
+ if (aRequest.method == "POST" || aRequest.method == "PUT") {
+ if (aRequest.bodyInputStream) {
+ let inputStream = new BinaryInputStream(aRequest.bodyInputStream);
+ let bytes = [];
+ let available;
+
+ while ((available = inputStream.available()) > 0) {
+ Array.prototype.push.apply(bytes, inputStream.readByteArray(available));
+ }
+
+ requestData.body = String.fromCharCode.apply(null, bytes);
+ requestData.contentType = aRequest.getHeader("Content-Type");
+ }
+ }
+ return requestData;
+}
+
+// write status information, content type information and body to a response
+function writeDataToResponse(aData, aResponse) {
+ aResponse.setStatusLine(null, aData.status, aData.statusText);
+ aResponse.setHeader("Content-Type", aData.contentType);
+ for (let header in aData.headers) {
+ aResponse.setHeader(header, aData.headers[header]);
+ }
+ aResponse.write(aData.body);
+}
+
+// test some GET functionality
+add_test(function test_GetData() {
+ do_test_pending();
+
+ let testData = createTestData("/getData");
+
+ // set up some headers to test
+ let headerNames = ["x-test-header", "x-other-test-header"];
+ for (let headerName of headerNames) {
+ testData.request.headers[headerName] = "test-value-for-" + headerName;
+ }
+
+ server.registerPathHandler(testData.testPath, function (aRequest, aResponse) {
+ try {
+ // check our request headers made it OK
+ for (let headerName of headerNames) {
+ Assert.equal(
+ testData.request.headers[headerName],
+ aRequest.getHeader(headerName)
+ );
+ }
+
+ // send a response
+ writeDataToResponse(testData.response, aResponse);
+ } catch (e) {
+ do_report_unexpected_exception(e);
+ }
+ });
+
+ // fetch, via GET, with some request headers set
+ fetch(getBaseUrl() + testData.testPath, { headers: testData.request.headers })
+ .then(function (response) {
+ // check response looks as expected
+ Assert.ok(response.ok);
+ Assert.equal(response.status, testData.response.status);
+ Assert.equal(response.statusText, testData.response.statusText);
+
+ // check a response header looks OK:
+ Assert.equal(
+ response.headers.get("Content-Type"),
+ testData.response.contentType
+ );
+
+ // ... and again to check header names are case insensitive
+ Assert.equal(
+ response.headers.get("content-type"),
+ testData.response.contentType
+ );
+
+ // ensure response.text() returns a promise that resolves appropriately
+ response.text().then(function (text) {
+ Assert.equal(text, testData.response.body);
+ do_test_finished();
+ run_next_test();
+ });
+ })
+ .catch(function (e) {
+ do_report_unexpected_exception(e);
+ do_test_finished();
+ run_next_test();
+ });
+});
+
+// test a GET with no init
+add_test(function test_GetDataNoInit() {
+ do_test_pending();
+
+ let testData = createTestData("/getData");
+
+ server.registerPathHandler(testData.testPath, function (aRequest, aResponse) {
+ try {
+ // send a response
+ writeDataToResponse(testData.response, aResponse);
+ } catch (e) {
+ do_report_unexpected_exception(e);
+ }
+ });
+
+ fetch(getBaseUrl() + testData.testPath, { headers: testData.request.headers })
+ .then(function (response) {
+ // check response looks as expected
+ Assert.ok(response.ok);
+ Assert.equal(response.status, testData.response.status);
+
+ // ensure response.text() returns a promise that resolves appropriately
+ response.text().then(function (text) {
+ Assert.equal(text, testData.response.body);
+ do_test_finished();
+ run_next_test();
+ });
+ })
+ .catch(function (e) {
+ do_report_unexpected_exception(e);
+ do_test_finished();
+ run_next_test();
+ });
+});
+
+// test some error responses
+add_test(function test_get40x() {
+ do_test_pending();
+
+ // prepare a response with some 40x error - a 404 will do
+ let notFoundData = createTestData("/getNotFound");
+ notFoundData.response.status = 404;
+ notFoundData.response.statusText = "Not found";
+ notFoundData.response.body = null;
+
+ // No need to register a path handler - httpd will return 404 anyway.
+ // Fetch, via GET, the resource that doesn't exist
+ fetch(getBaseUrl() + notFoundData.testPath).then(function (response) {
+ Assert.equal(response.status, 404);
+ do_test_finished();
+ run_next_test();
+ });
+});
+
+add_test(function test_get50x() {
+ do_test_pending();
+
+ // prepare a response with some server error - a 500 will do
+ let serverErrorData = createTestData("/serverError");
+ serverErrorData.response.status = 500;
+ serverErrorData.response.statusText = "The server broke";
+ serverErrorData.response.body = null;
+
+ server.registerPathHandler(
+ serverErrorData.testPath,
+ function (aRequest, aResponse) {
+ try {
+ // send the error response
+ writeDataToResponse(serverErrorData.response, aResponse);
+ } catch (e) {
+ do_report_unexpected_exception(e);
+ }
+ }
+ );
+
+ // fetch, via GET, the resource that creates a server error
+ fetch(getBaseUrl() + serverErrorData.testPath).then(function (response) {
+ Assert.equal(response.status, 500);
+ do_test_finished();
+ run_next_test();
+ });
+});
+
+// test a failure to connect
+add_test(function test_getTestFailedConnect() {
+ do_test_pending();
+ // try a server that's not there
+ fetch("http://localhost:4/should/fail")
+ .then(response => {
+ do_throw("Request should not succeed");
+ })
+ .catch(err => {
+ Assert.equal(true, err instanceof TypeError);
+ do_test_finished();
+ run_next_test();
+ });
+});
+
+add_test(function test_mozError() {
+ do_test_pending();
+ // try a server that's not there
+ fetch("http://localhost:4/should/fail", { mozErrors: true })
+ .then(response => {
+ do_throw("Request should not succeed");
+ })
+ .catch(err => {
+ Assert.equal(err.result, Cr.NS_ERROR_CONNECTION_REFUSED);
+ do_test_finished();
+ run_next_test();
+ });
+});
+
+add_test(function test_request_mozError() {
+ do_test_pending();
+ // try a server that's not there
+ const r = new Request("http://localhost:4/should/fail", { mozErrors: true });
+ fetch(r)
+ .then(response => {
+ do_throw("Request should not succeed");
+ })
+ .catch(err => {
+ Assert.equal(err.result, Cr.NS_ERROR_CONNECTION_REFUSED);
+ do_test_finished();
+ run_next_test();
+ });
+});
+
+// test POSTing some JSON data
+add_test(function test_PostJSONData() {
+ do_test_pending();
+
+ let testData = createTestData("/postJSONData");
+ testData.request.body = '{"foo": "bar"}';
+
+ server.registerPathHandler(testData.testPath, function (aRequest, aResponse) {
+ try {
+ let requestData = readDataFromRequest(aRequest);
+
+ // Check the request body is OK
+ Assert.equal(requestData.body, testData.request.body);
+
+ // Check the content type is as expected
+ Assert.equal(requestData.contentType, testData.request.contentType);
+
+ writeDataToResponse(testData.response, aResponse);
+ } catch (e) {
+ Assert.ok(false);
+ }
+ });
+
+ fetch(getBaseUrl() + testData.testPath, {
+ method: "POST",
+ body: testData.request.body,
+ headers: {
+ "Content-Type": "application/json",
+ },
+ })
+ .then(function (aResponse) {
+ Assert.ok(aResponse.ok);
+ Assert.equal(aResponse.status, testData.response.status);
+ Assert.equal(aResponse.statusText, testData.response.statusText);
+
+ do_test_finished();
+ run_next_test();
+ })
+ .catch(function (e) {
+ do_report_unexpected_exception(e);
+ do_test_finished();
+ run_next_test();
+ });
+});
+
+// test POSTing some text
+add_test(function test_PostTextData() {
+ do_test_pending();
+
+ let testData = createTestData("/postTextData");
+ testData.request.body = "A plain text body";
+ testData.request.contentType = "text/plain";
+ let responseHeaderName = "some-response-header";
+ testData.response.headers[responseHeaderName] = "some header value";
+
+ server.registerPathHandler(testData.testPath, function (aRequest, aResponse) {
+ try {
+ let requestData = readDataFromRequest(aRequest);
+
+ // Check the request body is OK
+ Assert.equal(requestData.body, testData.request.body);
+
+ // Check the content type is as expected
+ Assert.equal(requestData.contentType, testData.request.contentType);
+
+ writeDataToResponse(testData.response, aResponse);
+ } catch (e) {
+ Assert.ok(false);
+ }
+ });
+
+ fetch(getBaseUrl() + testData.testPath, {
+ method: "POST",
+ body: testData.request.body,
+ headers: {
+ "Content-Type": testData.request.contentType,
+ },
+ })
+ .then(function (aResponse) {
+ Assert.ok(aResponse.ok);
+ Assert.equal(aResponse.status, testData.response.status);
+ Assert.equal(aResponse.statusText, testData.response.statusText);
+
+ // check the response header is set OK
+ Assert.equal(
+ aResponse.headers.get(responseHeaderName),
+ testData.response.headers[responseHeaderName]
+ );
+
+ do_test_finished();
+ run_next_test();
+ })
+ .catch(function (e) {
+ do_report_unexpected_exception(e);
+ do_test_finished();
+ run_next_test();
+ });
+});
+
+function run_test() {
+ // Set up an HTTP Server
+ server = new HttpServer();
+ server.start(-1);
+
+ run_next_test();
+
+ registerCleanupFunction(function () {
+ server.stop(function () {});
+ });
+}