michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: const { Request } = require("sdk/request"); michael@0: const { pathFor } = require("sdk/system"); michael@0: const file = require("sdk/io/file"); michael@0: const { URL } = require("sdk/url"); michael@0: const { extend } = require("sdk/util/object"); michael@0: const { Loader } = require("sdk/test/loader"); michael@0: const options = require("@test/options"); michael@0: michael@0: const loader = Loader(module); michael@0: const httpd = loader.require("sdk/test/httpd"); michael@0: if (options.parseable || options.verbose) michael@0: loader.sandbox("sdk/test/httpd").DEBUG = true; michael@0: const { startServerAsync } = httpd; michael@0: michael@0: const { Cc, Ci, Cu } = require("chrome"); michael@0: const { Services } = Cu.import("resource://gre/modules/Services.jsm"); michael@0: michael@0: // Use the profile directory for the temporary files as that will be deleted michael@0: // when tests are complete michael@0: const basePath = pathFor("ProfD"); michael@0: const port = 8099; michael@0: michael@0: michael@0: exports.testOptionsValidator = function(assert) { michael@0: // First, a simple test to make sure we didn't break normal functionality. michael@0: assert.throws(function () { michael@0: Request({ michael@0: url: null michael@0: }); michael@0: }, /The option "url" is invalid./); michael@0: michael@0: // Next we'll have a Request that doesn't throw from c'tor, but from a setter. michael@0: let req = Request({ michael@0: url: "http://playground.zpao.com/jetpack/request/text.php", michael@0: onComplete: function () {} michael@0: }); michael@0: assert.throws(function () { michael@0: req.url = 'www.mozilla.org'; michael@0: }, /The option "url" is invalid/); michael@0: // The url shouldn't have changed, so check that michael@0: assert.equal(req.url, "http://playground.zpao.com/jetpack/request/text.php"); michael@0: }; michael@0: michael@0: exports.testContentValidator = function(assert, done) { michael@0: runMultipleURLs(null, assert, done, { michael@0: url: "data:text/html;charset=utf-8,response", michael@0: content: { 'key1' : null, 'key2' : 'some value' }, michael@0: onComplete: function(response) { michael@0: assert.equal(response.text, "response?key1=null&key2=some+value"); michael@0: } michael@0: }); michael@0: }; michael@0: michael@0: // This is a request to a file that exists. michael@0: exports.testStatus200 = function (assert, done) { michael@0: let srv = startServerAsync(port, basePath); michael@0: let content = "Look ma, no hands!\n"; michael@0: let basename = "test-request.txt" michael@0: prepareFile(basename, content); michael@0: michael@0: var req = Request({ michael@0: url: "http://localhost:" + port + "/" + basename, michael@0: onComplete: function (response) { michael@0: assert.equal(this, req, "`this` should be request"); michael@0: assert.equal(response.status, 200); michael@0: assert.equal(response.statusText, "OK"); michael@0: assert.equal(response.headers["Content-Type"], "text/plain"); michael@0: assert.equal(response.text, content); michael@0: srv.stop(done); michael@0: } michael@0: }).get(); michael@0: }; michael@0: michael@0: // This tries to get a file that doesn't exist michael@0: exports.testStatus404 = function (assert, done) { michael@0: var srv = startServerAsync(port, basePath); michael@0: michael@0: runMultipleURLs(srv, assert, done, { michael@0: // the following URL doesn't exist michael@0: url: "http://localhost:" + port + "/test-request-404.txt", michael@0: onComplete: function (response) { michael@0: assert.equal(response.status, 404); michael@0: assert.equal(response.statusText, "Not Found"); michael@0: } michael@0: }); michael@0: }; michael@0: michael@0: // a simple file with a known header michael@0: exports.testKnownHeader = function (assert, done) { michael@0: var srv = startServerAsync(port, basePath); michael@0: michael@0: // Create the file that will be requested with the associated headers file michael@0: let content = "This tests adding headers to the server's response.\n"; michael@0: let basename = "test-request-headers.txt"; michael@0: let headerContent = "x-jetpack-header: Jamba Juice\n"; michael@0: let headerBasename = "test-request-headers.txt^headers^"; michael@0: prepareFile(basename, content); michael@0: prepareFile(headerBasename, headerContent); michael@0: michael@0: runMultipleURLs(srv, assert, done, { michael@0: url: "http://localhost:" + port + "/test-request-headers.txt", michael@0: onComplete: function (response) { michael@0: assert.equal(response.headers["x-jetpack-header"], "Jamba Juice"); michael@0: } michael@0: }); michael@0: }; michael@0: michael@0: // complex headers michael@0: exports.testComplexHeader = function (assert, done) { michael@0: let srv = startServerAsync(port, basePath); michael@0: michael@0: let basename = "test-request-complex-headers.sjs"; michael@0: let content = handleRequest.toString(); michael@0: prepareFile(basename, content); michael@0: michael@0: let headers = { michael@0: "x-jetpack-header": "Jamba Juice is: delicious", michael@0: "x-jetpack-header-2": "foo,bar", michael@0: "x-jetpack-header-3": "sup dawg, i heard you like x, so we put a x in " + michael@0: "yo x so you can y while you y", michael@0: "Set-Cookie": "foo=bar\nbaz=foo" michael@0: }; michael@0: michael@0: runMultipleURLs(srv, assert, done, { michael@0: url: "http://localhost:" + port + "/test-request-complex-headers.sjs", michael@0: onComplete: function (response) { michael@0: for (k in headers) { michael@0: assert.equal(response.headers[k], headers[k]); michael@0: } michael@0: } michael@0: }); michael@0: }; michael@0: michael@0: // Force Allow Third Party cookies michael@0: exports.test3rdPartyCookies = function (assert, done) { michael@0: let srv = startServerAsync(port, basePath); michael@0: michael@0: let basename = "test-request-3rd-party-cookies.sjs"; michael@0: michael@0: // Function to handle the requests in the server michael@0: let content = function handleRequest(request, response) { michael@0: var cookiePresent = request.hasHeader("Cookie"); michael@0: // If no cookie, set it michael@0: if(!cookiePresent) { michael@0: response.setHeader("Set-Cookie", "cookie=monster;", "true"); michael@0: response.setHeader("x-jetpack-3rd-party", "false", "true"); michael@0: } else { michael@0: // We got the cookie, say so michael@0: response.setHeader("x-jetpack-3rd-party", "true", "true"); michael@0: } michael@0: michael@0: response.write("This tests 3rd party cookies."); michael@0: }.toString(); michael@0: michael@0: prepareFile(basename, content); michael@0: michael@0: // Disable the 3rd party cookies michael@0: Services.prefs.setIntPref("network.cookie.cookieBehavior", 1); michael@0: michael@0: Request({ michael@0: url: "http://localhost:" + port + "/test-request-3rd-party-cookies.sjs", michael@0: onComplete: function (response) { michael@0: // Check that the server created the cookie michael@0: assert.equal(response.headers['Set-Cookie'], 'cookie=monster;'); michael@0: michael@0: // Check it wasn't there before michael@0: assert.equal(response.headers['x-jetpack-3rd-party'], 'false'); michael@0: michael@0: // Make a second request, and check that the server this time michael@0: // got the cookie michael@0: Request({ michael@0: url: "http://localhost:" + port + "/test-request-3rd-party-cookies.sjs", michael@0: onComplete: function (response) { michael@0: assert.equal(response.headers['x-jetpack-3rd-party'], 'true'); michael@0: srv.stop(done); michael@0: } michael@0: }).get(); michael@0: } michael@0: }).get(); michael@0: }; michael@0: michael@0: exports.testSimpleJSON = function (assert, done) { michael@0: let srv = startServerAsync(port, basePath); michael@0: let json = { foo: "bar" }; michael@0: let basename = "test-request.json"; michael@0: prepareFile(basename, JSON.stringify(json)); michael@0: michael@0: runMultipleURLs(srv, assert, done, { michael@0: url: "http://localhost:" + port + "/" + basename, michael@0: onComplete: function (response) { michael@0: assert.deepEqual(response.json, json); michael@0: } michael@0: }); michael@0: }; michael@0: michael@0: exports.testInvalidJSON = function (assert, done) { michael@0: let srv = startServerAsync(port, basePath); michael@0: let basename = "test-request-invalid.json"; michael@0: prepareFile(basename, '"this": "isn\'t JSON"'); michael@0: michael@0: runMultipleURLs(srv, assert, done, { michael@0: url: "http://localhost:" + port + "/" + basename, michael@0: onComplete: function (response) { michael@0: assert.equal(response.json, null); michael@0: } michael@0: }); michael@0: }; michael@0: michael@0: exports.testDelete = function (assert, done) { michael@0: let srv = startServerAsync(port, basePath); michael@0: michael@0: srv.registerPathHandler("/test-delete", michael@0: function handle(request, response) { michael@0: response.setHeader("Content-Type", "text/plain", false); michael@0: }); michael@0: michael@0: Request({ michael@0: url: "http://localhost:" + port + "/test-delete", michael@0: onComplete: function (response) { michael@0: // We cannot access the METHOD of the request to verify it's set michael@0: // correctly. michael@0: assert.equal(response.text, ""); michael@0: assert.equal(response.statusText, "OK"); michael@0: assert.equal(response.headers["Content-Type"], "text/plain"); michael@0: srv.stop(done); michael@0: } michael@0: }).delete(); michael@0: }; michael@0: michael@0: exports.testHead = function (assert, done) { michael@0: let srv = startServerAsync(port, basePath); michael@0: michael@0: srv.registerPathHandler("/test-head", michael@0: function handle(request, response) { michael@0: response.setHeader("Content-Type", "text/plain", false); michael@0: }); michael@0: michael@0: Request({ michael@0: url: "http://localhost:" + port + "/test-head", michael@0: onComplete: function (response) { michael@0: assert.equal(response.text, ""); michael@0: assert.equal(response.statusText, "OK"); michael@0: assert.equal(response.headers["Content-Type"], "text/plain"); michael@0: srv.stop(done); michael@0: } michael@0: }).head(); michael@0: }; michael@0: michael@0: function runMultipleURLs (srv, assert, done, options) { michael@0: let urls = [options.url, URL(options.url)]; michael@0: let cb = options.onComplete; michael@0: let ran = 0; michael@0: let onComplete = function (res) { michael@0: cb(res); michael@0: if (++ran === urls.length) michael@0: srv ? srv.stop(done) : done(); michael@0: }; michael@0: urls.forEach(function (url) { michael@0: Request(extend(options, { url: url, onComplete: onComplete })).get(); michael@0: }); michael@0: } michael@0: michael@0: // All tests below here require a network connection. They will be commented out michael@0: // when checked in. If you'd like to run them, simply uncomment them. michael@0: // michael@0: // When we have the means, these tests will be converted so that they don't michael@0: // require an external server nor a network connection. michael@0: michael@0: /* michael@0: exports.testGetWithParamsNotContent = function (assert, done) { michael@0: Request({ michael@0: url: "http://playground.zpao.com/jetpack/request/getpost.php?foo=bar", michael@0: onComplete: function (response) { michael@0: let expected = { michael@0: "POST": [], michael@0: "GET" : { foo: "bar" } michael@0: }; michael@0: assert.deepEqual(response.json, expected); michael@0: done(); michael@0: } michael@0: }).get(); michael@0: } michael@0: michael@0: exports.testGetWithContent = function (assert, done) { michael@0: Request({ michael@0: url: "http://playground.zpao.com/jetpack/request/getpost.php", michael@0: content: { foo: "bar" }, michael@0: onComplete: function (response) { michael@0: let expected = { michael@0: "POST": [], michael@0: "GET" : { foo: "bar" } michael@0: }; michael@0: assert.deepEqual(response.json, expected); michael@0: done(); michael@0: } michael@0: }).get(); michael@0: } michael@0: michael@0: exports.testGetWithParamsAndContent = function (assert, done) { michael@0: Request({ michael@0: url: "http://playground.zpao.com/jetpack/request/getpost.php?foo=bar", michael@0: content: { baz: "foo" }, michael@0: onComplete: function (response) { michael@0: let expected = { michael@0: "POST": [], michael@0: "GET" : { foo: "bar", baz: "foo" } michael@0: }; michael@0: assert.deepEqual(response.json, expected); michael@0: done(); michael@0: } michael@0: }).get(); michael@0: } michael@0: michael@0: exports.testSimplePost = function (assert, done) { michael@0: Request({ michael@0: url: "http://playground.zpao.com/jetpack/request/getpost.php", michael@0: content: { foo: "bar" }, michael@0: onComplete: function (response) { michael@0: let expected = { michael@0: "POST": { foo: "bar" }, michael@0: "GET" : [] michael@0: }; michael@0: assert.deepEqual(response.json, expected); michael@0: done(); michael@0: } michael@0: }).post(); michael@0: } michael@0: michael@0: exports.testEncodedContent = function (assert, done) { michael@0: Request({ michael@0: url: "http://playground.zpao.com/jetpack/request/getpost.php", michael@0: content: "foo=bar&baz=foo", michael@0: onComplete: function (response) { michael@0: let expected = { michael@0: "POST": [], michael@0: "GET" : { foo: "bar", baz: "foo" } michael@0: }; michael@0: assert.deepEqual(response.json, expected); michael@0: done(); michael@0: } michael@0: }).get(); michael@0: } michael@0: michael@0: exports.testEncodedContentWithSpaces = function (assert, done) { michael@0: Request({ michael@0: url: "http://playground.zpao.com/jetpack/request/getpost.php", michael@0: content: "foo=bar+hop!&baz=foo", michael@0: onComplete: function (response) { michael@0: let expected = { michael@0: "POST": [], michael@0: "GET" : { foo: "bar hop!", baz: "foo" } michael@0: }; michael@0: assert.deepEqual(response.json, expected); michael@0: done(); michael@0: } michael@0: }).get(); michael@0: } michael@0: michael@0: exports.testGetWithArray = function (assert, done) { michael@0: Request({ michael@0: url: "http://playground.zpao.com/jetpack/request/getpost.php", michael@0: content: { foo: [1, 2], baz: "foo" }, michael@0: onComplete: function (response) { michael@0: let expected = { michael@0: "POST": [], michael@0: "GET" : { foo: [1, 2], baz: "foo" } michael@0: }; michael@0: assert.deepEqual(response.json, expected); michael@0: done(); michael@0: } michael@0: }).get(); michael@0: } michael@0: michael@0: exports.testGetWithNestedArray = function (assert, done) { michael@0: Request({ michael@0: url: "http://playground.zpao.com/jetpack/request/getpost.php", michael@0: content: { foo: [1, 2, [3, 4]], bar: "baz" }, michael@0: onComplete: function (response) { michael@0: let expected = { michael@0: "POST": [], michael@0: "GET" : this.content michael@0: }; michael@0: assert.deepEqual(response.json, expected); michael@0: done(); michael@0: } michael@0: }).get(); michael@0: } michael@0: michael@0: exports.testGetWithNestedArray = function (assert, done) { michael@0: let request = Request({ michael@0: url: "http://playground.zpao.com/jetpack/request/getpost.php", michael@0: content: { michael@0: foo: [1, 2, { michael@0: omg: "bbq", michael@0: "all your base!": "are belong to us" michael@0: }], michael@0: bar: "baz" michael@0: }, michael@0: onComplete: function (response) { michael@0: let expected = { michael@0: "POST": [], michael@0: "GET" : request.content michael@0: }; michael@0: assert.deepEqual(response.json, expected); michael@0: done(); michael@0: } michael@0: }).get(); michael@0: } michael@0: */ michael@0: michael@0: function prepareFile(basename, content) { michael@0: let filePath = file.join(basePath, basename); michael@0: let fileStream = file.open(filePath, 'w'); michael@0: fileStream.write(content); michael@0: fileStream.close(); michael@0: } michael@0: michael@0: // Helper function for testComplexHeaders michael@0: function handleRequest(request, response) { michael@0: // Test header with an extra colon michael@0: response.setHeader("x-jetpack-header", "Jamba Juice is: delicious", "true"); michael@0: michael@0: // Test that multiple headers with the same name coalesce michael@0: response.setHeader("x-jetpack-header-2", "foo", "true"); michael@0: response.setHeader("x-jetpack-header-2", "bar", "true"); michael@0: michael@0: // Test that headers with commas work michael@0: response.setHeader("x-jetpack-header-3", "sup dawg, i heard you like x, " + michael@0: "so we put a x in yo x so you can y while you y", "true"); michael@0: michael@0: // Test that multiple cookies work michael@0: response.setHeader("Set-Cookie", "foo=bar", "true"); michael@0: response.setHeader("Set-Cookie", "baz=foo", "true"); michael@0: michael@0: response.write("This file tests more complex headers."); michael@0: } michael@0: michael@0: require('sdk/test').run(exports);