<!DOCTYPE HTML> <html> <head> <title>Test for XMLHttpRequest</title> <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> </head> <body onload="gen.next();"> <p id="display"></p> <div id="content" style="display: none"> </div> <pre id="test"> <script class="testbody" type="application/javascript;version=1.7"> "use strict"; SimpleTest.waitForExplicitFinish(); var gen = runTests(); function continueTest() { gen.next(); } function runTests() { var path = "/tests/dom/xhr/tests/"; var passFiles = [['file_XHR_pass1.xml', 'GET', 200, 'OK', 'text/xml'], ['file_XHR_pass2.txt', 'GET', 200, 'OK', 'text/plain'], ['file_XHR_pass3.txt', 'GET', 200, 'OK', 'text/plain'], ['data:text/xml,%3Cres%3Ehello%3C/res%3E%0A', 'GET', 200, 'OK', 'text/xml'], ['data:text/plain,hello%20pass%0A', 'GET', 200, 'OK', 'text/plain'], ['data:,foo', 'GET', 200, 'OK', 'text/plain;charset=US-ASCII', 'foo'], ['data:text/plain;base64,Zm9v', 'GET', 200, 'OK', 'text/plain', 'foo'], ['data:text/plain,foo#bar', 'GET', 200, 'OK', 'text/plain', 'foo'], ['data:text/plain,foo%23bar', 'GET', 200, 'OK', 'text/plain', 'foo#bar'], ]; var blob = new Blob(["foo"], { type: "text/plain" }); var blobURL = URL.createObjectURL(blob); passFiles.push([blobURL, 'GET', 200, 'OK', 'text/plain', 'foo']); var failFiles = [['//example.com' + path + 'file_XHR_pass1.xml', 'GET'], ['ftp://localhost' + path + 'file_XHR_pass1.xml', 'GET'], ['file_XHR_fail1.txt', 'GET'], ]; for (i = 0; i < passFiles.length; ++i) { // Function to give our hacked is() a scope (function(oldIs) { function is(actual, expected, message) { oldIs(actual, expected, message + " for " + passFiles[i][0]); } xhr = new XMLHttpRequest(); is(xhr.getResponseHeader("Content-Type"), null, "should be null"); is(xhr.getAllResponseHeaders(), "", "should be empty string"); is(xhr.responseType, "", "wrong initial responseType"); xhr.open(passFiles[i][1], passFiles[i][0], false); xhr.send(null); is(xhr.status, passFiles[i][2], "wrong status"); is(xhr.statusText, passFiles[i][3], "wrong statusText"); is(xhr.getResponseHeader("Content-Type"), passFiles[i][4], "wrong content type"); var headers = xhr.getAllResponseHeaders(); ok(/(?:^|\n)Content-Type:\s*([^\r\n]*)\r\n/i.test(headers) && RegExp.$1 === passFiles[i][4], "wrong response headers"); if (xhr.responseXML) { is((new XMLSerializer()).serializeToString(xhr.responseXML.documentElement), passFiles[i][5] || "<res>hello</res>", "wrong responseXML"); is(xhr.response, passFiles[i][5] || "<res>hello</res>\n", "wrong response"); } else { is(xhr.responseText, passFiles[i][5] || "hello pass\n", "wrong responseText"); is(xhr.response, passFiles[i][5] || "hello pass\n", "wrong response"); } })(is); } URL.revokeObjectURL(blobURL); for (i = 0; i < failFiles.length; ++i) { xhr = new XMLHttpRequest(); var didthrow = false; try { xhr.open(failFiles[i][1], failFiles[i][0], false); xhr.send(null); } catch (e) { didthrow = true; } if (!didthrow) { is(xhr.status, 301, "wrong status"); is(xhr.responseText, "redirect file\n", "wrong response"); } else { ok(1, "should have thrown or given incorrect result"); } } function checkResponseTextAccessThrows(xhr) { var didthrow = false; try { xhr.responseText } catch (e) { didthrow = true; } ok(didthrow, "should have thrown when accessing responseText"); } function checkResponseXMLAccessThrows(xhr) { var didthrow = false; try { xhr.responseXML } catch (e) { didthrow = true; } ok(didthrow, "should have thrown when accessing responseXML"); } function checkSetResponseType(xhr, type) { var didthrow = false; try { xhr.responseType = type; } catch (e) { didthrow = true; } is(xhr.responseType, type, "responseType should be " + type); ok(!didthrow, "should not have thrown when setting responseType"); } function checkSetResponseTypeThrows(xhr, type) { var didthrow = false; try { xhr.responseType = type; } catch (e) { didthrow = true; } ok(didthrow, "should have thrown when setting responseType"); } function checkOpenThrows(xhr, method, url, async) { var didthrow = false; try { xhr.open(method, url, async); } catch (e) { didthrow = true; } ok(didthrow, "should have thrown when open is called"); } // test if setting responseType before calling open() works xhr = new XMLHttpRequest(); checkSetResponseType(xhr, ""); checkSetResponseType(xhr, "text"); checkSetResponseType(xhr, "document"); checkSetResponseType(xhr, "arraybuffer"); checkSetResponseType(xhr, "blob"); checkSetResponseType(xhr, "json"); checkSetResponseType(xhr, "moz-chunked-text"); checkSetResponseType(xhr, "moz-chunked-arraybuffer"); checkOpenThrows(xhr, "GET", "file_XHR_pass2.txt", false); // test response (sync, responseType is not changeable) xhr = new XMLHttpRequest(); xhr.open("GET", 'file_XHR_pass2.txt', false); checkSetResponseTypeThrows(xhr, ""); checkSetResponseTypeThrows(xhr, "text"); checkSetResponseTypeThrows(xhr, "document"); checkSetResponseTypeThrows(xhr, "arraybuffer"); checkSetResponseTypeThrows(xhr, "blob"); checkSetResponseTypeThrows(xhr, "json"); checkSetResponseTypeThrows(xhr, "moz-chunked-text"); checkSetResponseTypeThrows(xhr, "moz-chunked-arraybuffer"); xhr.send(null); checkSetResponseTypeThrows(xhr, "document"); is(xhr.status, 200, "wrong status"); is(xhr.response, "hello pass\n", "wrong response"); // test response (responseType='document') xhr = new XMLHttpRequest(); xhr.open("GET", 'file_XHR_pass1.xml'); xhr.responseType = 'document'; xhr.onloadend = continueTest; xhr.send(null); yield undefined; checkSetResponseTypeThrows(xhr, "document"); is(xhr.status, 200, "wrong status"); checkResponseTextAccessThrows(xhr); is((new XMLSerializer()).serializeToString(xhr.response.documentElement), "<res>hello</res>", "wrong response"); // test response (responseType='text') xhr = new XMLHttpRequest(); xhr.open("GET", 'file_XHR_pass2.txt'); xhr.responseType = 'text'; xhr.onloadend = continueTest; xhr.send(null); yield undefined; is(xhr.status, 200, "wrong status"); checkResponseXMLAccessThrows(xhr); is(xhr.response, "hello pass\n", "wrong response"); // test response (responseType='arraybuffer') function arraybuffer_equals_to(ab, s) { is(ab.byteLength, s.length, "wrong arraybuffer byteLength"); var u8v = new Uint8Array(ab); is(String.fromCharCode.apply(String, u8v), s, "wrong values"); } // with a simple text file xhr = new XMLHttpRequest(); xhr.open("GET", 'file_XHR_pass2.txt'); xhr.responseType = 'arraybuffer'; xhr.onloadend = continueTest; xhr.send(null); yield undefined; is(xhr.status, 200, "wrong status"); checkResponseTextAccessThrows(xhr); checkResponseXMLAccessThrows(xhr); var ab = xhr.response; ok(ab != null, "should have a non-null arraybuffer"); arraybuffer_equals_to(ab, "hello pass\n"); // test reusing the same XHR (Bug 680816) xhr.open("GET", 'file_XHR_binary1.bin'); xhr.responseType = 'arraybuffer'; xhr.onloadend = continueTest; xhr.send(null); yield undefined; is(xhr.status, 200, "wrong status"); var ab2 = xhr.response; ok(ab2 != null, "should have a non-null arraybuffer"); ok(ab2 != ab, "arraybuffer on XHR reuse should be distinct"); arraybuffer_equals_to(ab, "hello pass\n"); arraybuffer_equals_to(ab2, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb"); // with a binary file xhr = new XMLHttpRequest(); xhr.open("GET", 'file_XHR_binary1.bin'); xhr.responseType = 'arraybuffer'; xhr.onloadend = continueTest; xhr.send(null); yield undefined; is(xhr.status, 200, "wrong status"); checkResponseTextAccessThrows(xhr); checkResponseXMLAccessThrows(xhr); ab = xhr.response; ok(ab != null, "should have a non-null arraybuffer"); arraybuffer_equals_to(ab, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb"); is(xhr.response, xhr.response, "returns the same ArrayBuffer"); // test response (responseType='json') var xhr = new XMLHttpRequest(); xhr.open("POST", 'responseIdentical.sjs'); xhr.responseType = 'json'; var jsonObjStr = JSON.stringify({title: "aBook", author: "john"}); xhr.onloadend = continueTest; xhr.send(jsonObjStr); yield undefined; is(xhr.status, 200, "wrong status"); checkResponseTextAccessThrows(xhr); checkResponseXMLAccessThrows(xhr); is(JSON.stringify(xhr.response), jsonObjStr, "correct result"); is(xhr.response, xhr.response, "returning the same object on each access"); // with invalid json var xhr = new XMLHttpRequest(); xhr.open("POST", 'responseIdentical.sjs'); xhr.responseType = 'json'; xhr.onloadend = continueTest; xhr.send("{"); yield undefined; is(xhr.status, 200, "wrong status"); checkResponseTextAccessThrows(xhr); checkResponseXMLAccessThrows(xhr); is(xhr.response, null, "Bad JSON should result in null response."); is(xhr.response, null, "Bad JSON should result in null response even 2nd time."); // Test status/statusText in all readyStates xhr = new XMLHttpRequest(); function checkXHRStatus() { if (xhr.readyState == xhr.UNSENT || xhr.readyState == xhr.OPENED) { is(xhr.status, 0, "should be 0 before getting data"); is(xhr.statusText, "", "should be empty before getting data"); } else { is(xhr.status, 200, "should be 200 when we have data"); is(xhr.statusText, "OK", "should be OK when we have data"); } } checkXHRStatus(); xhr.open("GET", 'file_XHR_binary1.bin'); checkXHRStatus(); xhr.responseType = 'arraybuffer'; xhr.send(null); xhr.onreadystatechange = continueTest; while (xhr.readyState != 4) { checkXHRStatus(); yield undefined; } checkXHRStatus(); // test response (responseType='blob') var responseTypes = ['blob', 'moz-blob']; for (var i = 0; i < responseTypes.length; i++) { var t = responseTypes[i]; // with a simple text file xhr = new XMLHttpRequest(); xhr.open("GET", 'file_XHR_pass2.txt'); xhr.responseType = t; xhr.onloadend = continueTest; xhr.send(null); yield undefined; is(xhr.status, 200, "wrong status"); checkResponseTextAccessThrows(xhr); checkResponseXMLAccessThrows(xhr); var b = xhr.response; ok(b, "should have a non-null blob"); ok(b instanceof Blob, "should be a Blob"); ok(!(b instanceof File), "should not be a File"); is(b.size, "hello pass\n".length, "wrong blob size"); var fr = new FileReader(); fr.onload = continueTest; fr.readAsBinaryString(b); yield undefined; ok(fr.result, "hello pass\n", "wrong values"); // with a binary file xhr = new XMLHttpRequest(); xhr.open("GET", 'file_XHR_binary1.bin', true); xhr.send(null); xhr.onreadystatechange = continueTest; while(xhr.readyState != 2) yield undefined; is(xhr.status, 200, "wrong status"); xhr.responseType = t; while(xhr.readyState != 4) yield undefined; xhr.onreadystatechange = null; b = xhr.response; ok(b != null, "should have a non-null blob"); is(b.size, 12, "wrong blob size"); fr = new FileReader(); fr.readAsBinaryString(b); xhr = null; // kill the XHR object b = null; SpecialPowers.gc(); fr.onload = continueTest; yield undefined; is(fr.result, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb", "wrong values"); // with a larger binary file xhr = new XMLHttpRequest(); xhr.open("GET", 'file_XHR_binary2.bin', true); xhr.responseType = t; xhr.send(null); xhr.onreadystatechange = continueTest; while (xhr.readyState != 4) yield undefined; xhr.onreadystatechange = null; var b = xhr.response; ok(b != null, "should have a non-null blob"); is(b.size, 65536, "wrong blob size"); fr = new FileReader(); fr.readAsArrayBuffer(b); fr.onload = continueTest; xhr = null; // kill the XHR object b = null; SpecialPowers.gc(); yield undefined; var u8 = new Uint8Array(fr.result); for (var i = 0; i < 65536; i++) { if (u8[i] !== (i & 255)) { break; } } is(i, 65536, "wrong value at offset " + i); } var client = new XMLHttpRequest(); client.open("GET", "file_XHR_pass1.xml", true); client.send(); client.onreadystatechange = function() { if(client.readyState == 4) { try { is(client.responseXML, null, "responseXML should be null."); is(client.responseText, "", "responseText should be empty string."); is(client.response, "", "response should be empty string."); is(client.status, 0, "status should be 0."); is(client.statusText, "", "statusText should be empty string."); is(client.getAllResponseHeaders(), "", "getAllResponseHeaders() should return empty string."); } catch(ex) { ok(false, "Shouldn't throw! [" + ex + "]"); } } } client.abort(); SimpleTest.finish(); yield undefined; } /* runTests */ </script> </pre> </body> </html>