|
1 <!DOCTYPE HTML> |
|
2 <html> |
|
3 <head> |
|
4 <title>Test for XMLHttpRequest</title> |
|
5 <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> |
|
6 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> |
|
7 </head> |
|
8 <body onload="gen.next();"> |
|
9 <p id="display"></p> |
|
10 <div id="content" style="display: none"> |
|
11 |
|
12 </div> |
|
13 <pre id="test"> |
|
14 <script class="testbody" type="application/javascript;version=1.7"> |
|
15 "use strict"; |
|
16 SimpleTest.waitForExplicitFinish(); |
|
17 |
|
18 var gen = runTests(); |
|
19 function continueTest() { gen.next(); } |
|
20 |
|
21 function runTests() { |
|
22 |
|
23 var path = "/tests/content/base/test/"; |
|
24 |
|
25 var passFiles = [['file_XHR_pass1.xml', 'GET', 200, 'text/xml'], |
|
26 ['file_XHR_pass2.txt', 'GET', 200, 'text/plain'], |
|
27 ['file_XHR_pass3.txt', 'GET', 200, 'text/plain'], |
|
28 ['data:text/xml,%3Cres%3Ehello%3C/res%3E%0A', 'GET', 0, 'text/xml'], |
|
29 ['data:text/plain,hello%20pass%0A', 'GET', 0, 'text/plain'], |
|
30 ['data:,foo', 'GET', 0, 'text/plain;charset=US-ASCII', 'foo'], |
|
31 ['data:text/plain;base64,Zm9v', 'GET', 0, 'text/plain', 'foo'], |
|
32 ['data:text/plain,foo#bar', 'GET', 0, 'text/plain', 'foo'], |
|
33 ['data:text/plain,foo%23bar', 'GET', 0, 'text/plain', 'foo#bar'], |
|
34 ]; |
|
35 |
|
36 var failFiles = [['//example.com' + path + 'file_XHR_pass1.xml', 'GET'], |
|
37 ['ftp://localhost' + path + 'file_XHR_pass1.xml', 'GET'], |
|
38 ['file_XHR_fail1.txt', 'GET'], |
|
39 ]; |
|
40 |
|
41 for (i = 0; i < passFiles.length; ++i) { |
|
42 xhr = new XMLHttpRequest(); |
|
43 is(xhr.getResponseHeader("Content-Type"), null, "should be null"); |
|
44 is(xhr.getAllResponseHeaders(), "", "should be empty string"); |
|
45 is(xhr.responseType, "", "wrong initial responseType"); |
|
46 xhr.open(passFiles[i][1], passFiles[i][0], false); |
|
47 xhr.send(null); |
|
48 is(xhr.status, passFiles[i][2], "wrong status"); |
|
49 is(xhr.getResponseHeader("Content-Type"), passFiles[i][3], "wrong content type"); |
|
50 var headers = xhr.getAllResponseHeaders(); |
|
51 ok(/(?:^|\n)Content-Type:\s*([^\r\n]*)\r\n/i.test(headers) && |
|
52 RegExp.$1 === passFiles[i][3], "wrong response headers"); |
|
53 if (xhr.responseXML) { |
|
54 is((new XMLSerializer()).serializeToString(xhr.responseXML.documentElement), |
|
55 passFiles[i][4] || "<res>hello</res>", "wrong responseXML"); |
|
56 is(xhr.response, passFiles[i][4] || "<res>hello</res>\n", "wrong response"); |
|
57 } |
|
58 else { |
|
59 is(xhr.responseText, passFiles[i][4] || "hello pass\n", "wrong responseText"); |
|
60 is(xhr.response, passFiles[i][4] || "hello pass\n", "wrong response"); |
|
61 } |
|
62 } |
|
63 |
|
64 for (i = 0; i < failFiles.length; ++i) { |
|
65 xhr = new XMLHttpRequest(); |
|
66 var didthrow = false; |
|
67 try { |
|
68 xhr.open(failFiles[i][1], failFiles[i][0], false); |
|
69 xhr.send(null); |
|
70 } |
|
71 catch (e) { |
|
72 didthrow = true; |
|
73 } |
|
74 if (!didthrow) { |
|
75 is(xhr.status, 301, "wrong status"); |
|
76 is(xhr.responseText, "redirect file\n", "wrong response"); |
|
77 } |
|
78 else { |
|
79 ok(1, "should have thrown or given incorrect result"); |
|
80 } |
|
81 } |
|
82 |
|
83 function checkResponseTextAccessThrows(xhr) { |
|
84 var didthrow = false; |
|
85 try { xhr.responseText } catch (e) { didthrow = true; } |
|
86 ok(didthrow, "should have thrown when accessing responseText"); |
|
87 } |
|
88 function checkResponseXMLAccessThrows(xhr) { |
|
89 var didthrow = false; |
|
90 try { xhr.responseXML } catch (e) { didthrow = true; } |
|
91 ok(didthrow, "should have thrown when accessing responseXML"); |
|
92 } |
|
93 function checkSetResponseTypeThrows(xhr, type) { |
|
94 var didthrow = false; |
|
95 try { xhr.responseType = type; } catch (e) { didthrow = true; } |
|
96 ok(didthrow, "should have thrown when setting responseType"); |
|
97 } |
|
98 function checkOpenThrows(xhr, method, url, async) { |
|
99 var didthrow = false; |
|
100 try { xhr.open(method, url, async); } catch (e) { didthrow = true; } |
|
101 ok(didthrow, "should have thrown when open is called"); |
|
102 } |
|
103 |
|
104 // test response (sync, responseType is not changeable) |
|
105 xhr = new XMLHttpRequest(); |
|
106 xhr.open("GET", 'file_XHR_pass2.txt', false); |
|
107 checkSetResponseTypeThrows(xhr, ""); |
|
108 checkSetResponseTypeThrows(xhr, "text"); |
|
109 checkSetResponseTypeThrows(xhr, "document"); |
|
110 checkSetResponseTypeThrows(xhr, "arraybuffer"); |
|
111 checkSetResponseTypeThrows(xhr, "blob"); |
|
112 checkSetResponseTypeThrows(xhr, "json"); |
|
113 checkSetResponseTypeThrows(xhr, "moz-chunked-text"); |
|
114 checkSetResponseTypeThrows(xhr, "moz-chunked-arraybuffer"); |
|
115 xhr.send(null); |
|
116 checkSetResponseTypeThrows(xhr, "document"); |
|
117 is(xhr.status, 200, "wrong status"); |
|
118 is(xhr.response, "hello pass\n", "wrong response"); |
|
119 |
|
120 // test response (responseType='document') |
|
121 xhr = new XMLHttpRequest(); |
|
122 xhr.open("GET", 'file_XHR_pass1.xml'); |
|
123 xhr.responseType = 'document'; |
|
124 xhr.onloadend = continueTest; |
|
125 xhr.send(null); |
|
126 yield undefined; |
|
127 checkSetResponseTypeThrows(xhr, "document"); |
|
128 is(xhr.status, 200, "wrong status"); |
|
129 checkResponseTextAccessThrows(xhr); |
|
130 is((new XMLSerializer()).serializeToString(xhr.response.documentElement), |
|
131 "<res>hello</res>", |
|
132 "wrong response"); |
|
133 |
|
134 // test response (responseType='text') |
|
135 xhr = new XMLHttpRequest(); |
|
136 xhr.open("GET", 'file_XHR_pass2.txt'); |
|
137 xhr.responseType = 'text'; |
|
138 xhr.onloadend = continueTest; |
|
139 xhr.send(null); |
|
140 yield undefined; |
|
141 is(xhr.status, 200, "wrong status"); |
|
142 checkResponseXMLAccessThrows(xhr); |
|
143 is(xhr.response, "hello pass\n", "wrong response"); |
|
144 |
|
145 // test response (responseType='arraybuffer') |
|
146 function arraybuffer_equals_to(ab, s) { |
|
147 is(ab.byteLength, s.length, "wrong arraybuffer byteLength"); |
|
148 |
|
149 var u8v = new Uint8Array(ab); |
|
150 is(String.fromCharCode.apply(String, u8v), s, "wrong values"); |
|
151 } |
|
152 |
|
153 // with a simple text file |
|
154 xhr = new XMLHttpRequest(); |
|
155 xhr.open("GET", 'file_XHR_pass2.txt'); |
|
156 xhr.responseType = 'arraybuffer'; |
|
157 xhr.onloadend = continueTest; |
|
158 xhr.send(null); |
|
159 yield undefined; |
|
160 is(xhr.status, 200, "wrong status"); |
|
161 checkResponseTextAccessThrows(xhr); |
|
162 checkResponseXMLAccessThrows(xhr); |
|
163 var ab = xhr.response; |
|
164 ok(ab != null, "should have a non-null arraybuffer"); |
|
165 arraybuffer_equals_to(ab, "hello pass\n"); |
|
166 |
|
167 // test reusing the same XHR (Bug 680816) |
|
168 xhr.open("GET", 'file_XHR_binary1.bin'); |
|
169 xhr.responseType = 'arraybuffer'; |
|
170 xhr.onloadend = continueTest; |
|
171 xhr.send(null); |
|
172 yield undefined; |
|
173 is(xhr.status, 200, "wrong status"); |
|
174 var ab2 = xhr.response; |
|
175 ok(ab2 != null, "should have a non-null arraybuffer"); |
|
176 ok(ab2 != ab, "arraybuffer on XHR reuse should be distinct"); |
|
177 arraybuffer_equals_to(ab, "hello pass\n"); |
|
178 arraybuffer_equals_to(ab2, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb"); |
|
179 |
|
180 // with a binary file |
|
181 xhr = new XMLHttpRequest(); |
|
182 xhr.open("GET", 'file_XHR_binary1.bin'); |
|
183 xhr.responseType = 'arraybuffer'; |
|
184 xhr.onloadend = continueTest; |
|
185 xhr.send(null); |
|
186 yield undefined; |
|
187 is(xhr.status, 200, "wrong status"); |
|
188 checkResponseTextAccessThrows(xhr); |
|
189 checkResponseXMLAccessThrows(xhr); |
|
190 ab = xhr.response; |
|
191 ok(ab != null, "should have a non-null arraybuffer"); |
|
192 arraybuffer_equals_to(ab, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb"); |
|
193 is(xhr.response, xhr.response, "returns the same ArrayBuffer"); |
|
194 |
|
195 // test response (responseType='json') |
|
196 var xhr = new XMLHttpRequest(); |
|
197 xhr.open("POST", 'responseIdentical.sjs'); |
|
198 xhr.responseType = 'json'; |
|
199 var jsonObjStr = JSON.stringify({title: "aBook", author: "john"}); |
|
200 xhr.onloadend = continueTest; |
|
201 xhr.send(jsonObjStr); |
|
202 yield undefined; |
|
203 is(xhr.status, 200, "wrong status"); |
|
204 checkResponseTextAccessThrows(xhr); |
|
205 checkResponseXMLAccessThrows(xhr); |
|
206 is(JSON.stringify(xhr.response), jsonObjStr, "correct result"); |
|
207 is(xhr.response, xhr.response, "returning the same object on each access"); |
|
208 |
|
209 // with invalid json |
|
210 var xhr = new XMLHttpRequest(); |
|
211 xhr.open("POST", 'responseIdentical.sjs'); |
|
212 xhr.responseType = 'json'; |
|
213 xhr.onloadend = continueTest; |
|
214 xhr.send("{"); |
|
215 yield undefined; |
|
216 is(xhr.status, 200, "wrong status"); |
|
217 checkResponseTextAccessThrows(xhr); |
|
218 checkResponseXMLAccessThrows(xhr); |
|
219 is(xhr.response, null, "Bad JSON should result in null response."); |
|
220 is(xhr.response, null, "Bad JSON should result in null response even 2nd time."); |
|
221 |
|
222 // Test status/statusText in all readyStates |
|
223 xhr = new XMLHttpRequest(); |
|
224 function checkXHRStatus() { |
|
225 if (xhr.readyState == xhr.UNSENT || xhr.readyState == xhr.OPENED) { |
|
226 is(xhr.status, 0, "should be 0 before getting data"); |
|
227 is(xhr.statusText, "", "should be empty before getting data"); |
|
228 } |
|
229 else { |
|
230 is(xhr.status, 200, "should be 200 when we have data"); |
|
231 is(xhr.statusText, "OK", "should be OK when we have data"); |
|
232 } |
|
233 } |
|
234 checkXHRStatus(); |
|
235 xhr.open("GET", 'file_XHR_binary1.bin'); |
|
236 checkXHRStatus(); |
|
237 xhr.responseType = 'arraybuffer'; |
|
238 xhr.send(null); |
|
239 xhr.onreadystatechange = continueTest; |
|
240 while (xhr.readyState != 4) { |
|
241 checkXHRStatus(); |
|
242 yield undefined; |
|
243 } |
|
244 checkXHRStatus(); |
|
245 |
|
246 // test response (responseType='blob') |
|
247 var responseTypes = ['blob', 'moz-blob']; |
|
248 for (var i = 0; i < responseTypes.length; i++) { |
|
249 var t = responseTypes[i]; |
|
250 // with a simple text file |
|
251 xhr = new XMLHttpRequest(); |
|
252 xhr.open("GET", 'file_XHR_pass2.txt'); |
|
253 xhr.responseType = t; |
|
254 xhr.onloadend = continueTest; |
|
255 xhr.send(null); |
|
256 yield undefined; |
|
257 is(xhr.status, 200, "wrong status"); |
|
258 checkResponseTextAccessThrows(xhr); |
|
259 checkResponseXMLAccessThrows(xhr); |
|
260 var b = xhr.response; |
|
261 ok(b, "should have a non-null blob"); |
|
262 ok(b instanceof Blob, "should be a Blob"); |
|
263 ok(!(b instanceof File), "should not be a File"); |
|
264 is(b.size, "hello pass\n".length, "wrong blob size"); |
|
265 |
|
266 var fr = new FileReader(); |
|
267 fr.onload = continueTest; |
|
268 fr.readAsBinaryString(b); |
|
269 yield undefined; |
|
270 ok(fr.result, "hello pass\n", "wrong values"); |
|
271 |
|
272 // with a binary file |
|
273 xhr = new XMLHttpRequest(); |
|
274 xhr.open("GET", 'file_XHR_binary1.bin', true); |
|
275 xhr.send(null); |
|
276 xhr.onreadystatechange = continueTest; |
|
277 while(xhr.readyState != 2) |
|
278 yield undefined; |
|
279 |
|
280 is(xhr.status, 200, "wrong status"); |
|
281 xhr.responseType = t; |
|
282 |
|
283 while(xhr.readyState != 4) |
|
284 yield undefined; |
|
285 |
|
286 xhr.onreadystatechange = null; |
|
287 |
|
288 b = xhr.response; |
|
289 ok(b != null, "should have a non-null blob"); |
|
290 is(b.size, 12, "wrong blob size"); |
|
291 |
|
292 fr = new FileReader(); |
|
293 fr.readAsBinaryString(b); |
|
294 xhr = null; // kill the XHR object |
|
295 b = null; |
|
296 SpecialPowers.gc(); |
|
297 fr.onload = continueTest; |
|
298 yield undefined; |
|
299 is(fr.result, "\xaa\xee\0\x03\xff\xff\xff\xff\xbb\xbb\xbb\xbb", "wrong values"); |
|
300 |
|
301 // with a larger binary file |
|
302 xhr = new XMLHttpRequest(); |
|
303 xhr.open("GET", 'file_XHR_binary2.bin', true); |
|
304 xhr.responseType = t; |
|
305 xhr.send(null); |
|
306 xhr.onreadystatechange = continueTest; |
|
307 |
|
308 while (xhr.readyState != 4) |
|
309 yield undefined; |
|
310 |
|
311 xhr.onreadystatechange = null; |
|
312 |
|
313 var b = xhr.response; |
|
314 ok(b != null, "should have a non-null blob"); |
|
315 is(b.size, 65536, "wrong blob size"); |
|
316 |
|
317 fr = new FileReader(); |
|
318 fr.readAsArrayBuffer(b); |
|
319 fr.onload = continueTest; |
|
320 xhr = null; // kill the XHR object |
|
321 b = null; |
|
322 SpecialPowers.gc(); |
|
323 yield undefined; |
|
324 |
|
325 var u8 = new Uint8Array(fr.result); |
|
326 for (var i = 0; i < 65536; i++) { |
|
327 if (u8[i] !== (i & 255)) { |
|
328 break; |
|
329 } |
|
330 } |
|
331 is(i, 65536, "wrong value at offset " + i); |
|
332 } |
|
333 |
|
334 var client = new XMLHttpRequest(); |
|
335 client.open("GET", "file_XHR_pass1.xml", true); |
|
336 client.send(); |
|
337 client.onreadystatechange = function() { |
|
338 if(client.readyState == 4) { |
|
339 try { |
|
340 is(client.responseXML, null, "responseXML should be null."); |
|
341 is(client.responseText, "", "responseText should be empty string."); |
|
342 is(client.response, "", "response should be empty string."); |
|
343 is(client.status, 0, "status should be 0."); |
|
344 is(client.statusText, "", "statusText should be empty string."); |
|
345 is(client.getAllResponseHeaders(), "", |
|
346 "getAllResponseHeaders() should return empty string."); |
|
347 } catch(ex) { |
|
348 ok(false, "Shouldn't throw! [" + ex + "]"); |
|
349 } |
|
350 } |
|
351 } |
|
352 client.abort(); |
|
353 |
|
354 SimpleTest.finish(); |
|
355 yield undefined; |
|
356 |
|
357 } /* runTests */ |
|
358 </script> |
|
359 </pre> |
|
360 </body> |
|
361 </html> |