Roll src/third_party/WebKit d9c6159:8139f33 (svn 201974:201975)
[chromium-blink-merge.git] / remoting / webapp / base / js / xhr_unittest.js
blob1fb7856f1193b34ed5e7b5f7757ad857d75e968d
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 /**
6 * @fileoverview
7 */
9 (function() {
11 'use strict';
13 /** @type {sinon.FakeXhrCtrl} */
14 var fakeXhrCtrl;
16 /** @type {sinon.FakeXhr} */
17 var fakeXhr;
19 QUnit.module('xhr', {
20 beforeEach: function() {
21 fakeXhr = null;
22 fakeXhrCtrl = sinon.useFakeXMLHttpRequest();
23 fakeXhrCtrl.onCreate =
24 function(/** sinon.FakeXhr */ xhr) {
25 fakeXhr = xhr;
27 remoting.identity = new remoting.Identity();
28 chromeMocks.identity.mock$setToken('my_token');
30 afterEach: function() {
31 remoting.identity = null;
32 fakeXhrCtrl.restore();
34 });
36 QUnit.test('urlencodeParamHash', function(assert) {
37 assert.equal(
38 remoting.Xhr.urlencodeParamHash({}),
39 '');
40 assert.equal(
41 remoting.Xhr.urlencodeParamHash({'key': 'value'}),
42 'key=value');
43 assert.equal(
44 remoting.Xhr.urlencodeParamHash({'key /?=&': 'value /?=&'}),
45 'key%20%2F%3F%3D%26=value%20%2F%3F%3D%26');
46 assert.equal(
47 remoting.Xhr.urlencodeParamHash({'k1': 'v1', 'k2': 'v2'}),
48 'k1=v1&k2=v2');
49 });
52 // Test for what happens when the parameters are specified
53 // incorrectly.
56 QUnit.test('invalid *content parameters', function(assert) {
57 assert.throws(function() {
58 new remoting.Xhr({
59 method: 'POST',
60 url: 'http://foo.com',
61 jsonContent: {},
62 formContent: {}
63 });
64 });
66 assert.throws(function() {
67 new remoting.Xhr({
68 method: 'POST',
69 url: 'http://foo.com',
70 textContent: '',
71 formContent: {}
72 });
73 });
75 assert.throws(function() {
76 new remoting.Xhr({
77 method: 'POST',
78 url: 'http://foo.com',
79 textContent: '',
80 jsonContent: {}
81 });
82 });
83 });
86 QUnit.test('invalid URL parameters', function(assert) {
87 assert.throws(function() {
88 new remoting.Xhr({
89 method: 'POST',
90 url: 'http://foo.com?',
91 urlParams: {}
92 });
93 });
95 assert.throws(function() {
96 new remoting.Xhr({
97 method: 'POST',
98 url: 'http://foo.com#',
99 urlParams: {}
104 QUnit.test('invalid auth parameters', function(assert) {
105 assert.throws(function() {
106 new remoting.Xhr({
107 method: 'POST',
108 url: 'http://foo.com',
109 useIdentity: false,
110 oauthToken: '',
111 headers: {
112 'Authorization': ''
117 assert.throws(function() {
118 new remoting.Xhr({
119 method: 'POST',
120 url: 'http://foo.com',
121 useIdentity: true,
122 headers: {
123 'Authorization': ''
128 assert.throws(function() {
129 new remoting.Xhr({
130 method: 'POST',
131 url: 'http://foo.com',
132 useIdentity: true,
133 oauthToken: '',
134 headers: {}
139 QUnit.test('invalid auth parameters', function(assert) {
140 assert.throws(function() {
141 new remoting.Xhr({
142 method: 'POST',
143 url: 'http://foo.com',
144 useIdentity: false,
145 oauthToken: '',
146 headers: {
147 'Authorization': ''
152 assert.throws(function() {
153 new remoting.Xhr({
154 method: 'POST',
155 url: 'http://foo.com',
156 useIdentity: true,
157 headers: {
158 'Authorization': ''
163 assert.throws(function() {
164 new remoting.Xhr({
165 method: 'POST',
166 url: 'http://foo.com',
167 useIdentity: true,
168 oauthToken: '',
169 headers: {}
175 QUnit.test('unexpected parameters', function(assert) {
176 assert.throws(function() {
177 new remoting.Xhr({
178 method: 'POST',
179 url: 'http://foo.com',
180 xyzzy: 'not a real parameter'
186 // The typical case.
189 QUnit.test('successful GET', function(assert) {
190 var promise = new remoting.Xhr({
191 method: 'GET',
192 url: 'http://foo.com'
193 }).start().then(function(response) {
194 assert.ok(!response.isError());
195 assert.equal(response.status, 200);
196 assert.equal(response.getText(), 'body');
198 assert.equal(fakeXhr.method, 'GET');
199 assert.equal(fakeXhr.url, 'http://foo.com');
200 assert.equal(fakeXhr.withCredentials, false);
201 assert.equal(fakeXhr.requestBody, null);
202 assert.ok(!('Content-type' in fakeXhr.requestHeaders));
203 fakeXhr.respond(200, {}, 'body');
204 return promise;
208 // Tests for the effect of acceptJson.
211 QUnit.test('acceptJson required', function(assert) {
212 var promise = new remoting.Xhr({
213 method: 'GET',
214 url: 'http://foo.com'
215 }).start().then(function(response) {
216 assert.throws(response.getJson);
218 fakeXhr.respond(200, {}, '{}');
219 return promise;
222 QUnit.test('JSON response', function(assert) {
223 var responseJson = {
224 'myJsonData': [true]
226 var responseText = JSON.stringify(responseJson);
227 var promise = new remoting.Xhr({
228 method: 'GET',
229 url: 'http://foo.com',
230 acceptJson: true
231 }).start().then(function(response) {
232 // Calling getText is still OK even when a JSON response is
233 // requested.
234 assert.equal(
235 response.getText(),
236 responseText);
237 // Check that getJson works as advertised.
238 assert.deepEqual(
239 response.getJson(),
240 responseJson);
241 // Calling getJson multiple times doesn't re-parse the response.
242 assert.strictEqual(
243 response.getJson(),
244 response.getJson());
246 fakeXhr.respond(200, {}, responseText);
247 return promise;
251 // Tests for various parameters that modify the HTTP request.
254 QUnit.test('GET with param string', function(assert) {
255 new remoting.Xhr({
256 method: 'GET',
257 url: 'http://foo.com',
258 urlParams: 'the_param_string'
259 }).start();
260 assert.equal(fakeXhr.url, 'http://foo.com?the_param_string');
263 QUnit.test('GET with param object', function(assert) {
264 new remoting.Xhr({
265 method: 'GET',
266 url: 'http://foo.com',
267 urlParams: {'a': 'b', 'c': 'd'}
268 }).start();
269 assert.equal(fakeXhr.url, 'http://foo.com?a=b&c=d');
272 QUnit.test('GET with headers', function(assert) {
273 new remoting.Xhr({
274 method: 'GET',
275 url: 'http://foo.com',
276 headers: {'Header1': 'headerValue1', 'Header2': 'headerValue2'}
277 }).start();
278 assert.equal(
279 fakeXhr.requestHeaders['Header1'],
280 'headerValue1');
281 assert.equal(
282 fakeXhr.requestHeaders['Header2'],
283 'headerValue2');
287 QUnit.test('GET with credentials', function(assert) {
288 new remoting.Xhr({
289 method: 'GET',
290 url: 'http://foo.com',
291 withCredentials: true
292 }).start();
293 assert.equal(fakeXhr.withCredentials, true);
297 // Checking that typical POST requests work.
300 QUnit.test('POST with text content', function(assert) {
301 var done = assert.async();
303 var promise = new remoting.Xhr({
304 method: 'POST',
305 url: 'http://foo.com',
306 textContent: 'the_content_string'
307 }).start().then(function(response) {
308 assert.equal(response.status, 200);
309 assert.equal(response.getText(), 'body');
310 done();
312 assert.equal(fakeXhr.method, 'POST');
313 assert.equal(fakeXhr.url, 'http://foo.com');
314 assert.equal(fakeXhr.withCredentials, false);
315 assert.equal(fakeXhr.requestBody, 'the_content_string');
316 assert.equal(fakeXhr.requestHeaders['Content-type'],
317 'text/plain; charset=UTF-8');
318 fakeXhr.respond(200, {}, 'body');
319 return promise;
322 QUnit.test('POST with form content', function(assert) {
323 new remoting.Xhr({
324 method: 'POST',
325 url: 'http://foo.com',
326 formContent: {'a': 'b', 'c': 'd'}
327 }).start();
328 assert.equal(fakeXhr.requestBody, 'a=b&c=d');
329 assert.equal(
330 fakeXhr.requestHeaders['Content-type'],
331 'application/x-www-form-urlencoded; charset=UTF-8');
335 // Tests for authentication-related options.
338 QUnit.test('GET with auth token', function(assert) {
339 new remoting.Xhr({
340 method: 'GET',
341 url: 'http://foo.com',
342 oauthToken: 'my_token'
343 }).start();
344 assert.equal(fakeXhr.requestHeaders['Authorization'],
345 'Bearer my_token');
348 QUnit.test('GET with useIdentity', function(assert) {
349 var xhr = new remoting.Xhr({
350 method: 'GET',
351 url: 'http://foo.com',
352 useIdentity: true
355 xhr.start();
356 var done = assert.async();
357 fakeXhr.addEventListener('loadstart', function() {
358 assert.equal(fakeXhr.requestHeaders['Authorization'],
359 'Bearer my_token');
360 done();
365 // Error responses.
367 QUnit.test('GET with error response', function(assert) {
368 var promise = new remoting.Xhr({
369 method: 'GET',
370 url: 'http://foo.com'
371 }).start().then(function(response) {
372 assert.ok(response.isError());
373 assert.equal(response.status, 500);
374 assert.equal(response.getText(), 'body');
376 fakeXhr.respond(500, {}, 'body');
377 return promise;
380 QUnit.test('204 is not an error', function(assert) {
381 var promise = new remoting.Xhr({
382 method: 'GET',
383 url: 'http://foo.com'
384 }).start().then(function(response) {
385 assert.ok(!response.isError());
386 assert.equal(response.status, 204);
387 assert.equal(response.getText(), '');
389 fakeXhr.respond(204, {}, null);
390 return promise;
393 QUnit.test('GET with non-HTTP response', function(assert) {
394 var promise = new remoting.Xhr({
395 method: 'GET',
396 url: 'http://foo.com'
397 }).start().then(function(response) {
398 assert.ok(response.isError());
400 fakeXhr.respond(0, {}, null);
401 return promise;
404 QUnit.module('AutoRetryXhr', {
405 beforeEach: function() {
406 fakeXhr = null;
407 fakeXhrCtrl = sinon.useFakeXMLHttpRequest();
408 fakeXhrCtrl.onCreate = function(/** sinon.FakeXhr */ xhr) {
409 fakeXhr = xhr;
412 afterEach: function() {
413 fakeXhrCtrl.restore();
418 * A class allows you to specify a sequence of canned responses, to be returned
419 * in order in response to XHRs.
421 * @param {Array<Array>} cannedResponses
422 * @constructor
424 var CannedXhrResponder = function(cannedResponses) {
425 /** @private */
426 this.mockXhr_ = sinon.useFakeXMLHttpRequest();
427 this.cannedResponses_ = cannedResponses;
428 this.mockXhr_.onCreate = this.onCreate_.bind(this);
431 /** @private */
432 CannedXhrResponder.prototype.onCreate_ = function(/** sinon.FakeXhr */ xhr) {
433 var that = this;
434 var response = that.cannedResponses_.shift();
435 Promise.resolve().then(function() {
436 xhr.respond.apply(xhr, response);
440 CannedXhrResponder.prototype.dispose = function() {
441 this.mockXhr_.restore();
444 QUnit.test('retries on status code equals 0',
446 * 'this' is not defined for jscompile, so it can't figure out the type of
447 * this.clock.
448 * @suppress {reportUnknownTypes|checkVars|checkTypes}
450 function(assert) {
451 this.clock.restore();
452 fakeXhrCtrl.restore();
453 var responder = new CannedXhrResponder([
454 [0, {}, null],
455 [0, {}, null],
456 [200, {}, 'body']
458 var promise = new remoting.AutoRetryXhr({
459 method: 'GET',
460 url: 'http://foo.com'
461 }).start().then(function(response) {
462 assert.ok(!response.isError());
463 }).catch(function(){
464 throw new Error('Expect retry to succeed.');
466 return promise;
469 QUnit.test('respects opt_maxRetryAttempts',
471 * 'this' is not defined for jscompile, so it can't figure out the type of
472 * this.clock.
473 * @suppress {reportUnknownTypes|checkVars|checkTypes}
475 function(assert) {
476 this.clock.restore();
477 fakeXhrCtrl.restore();
478 var responder = new CannedXhrResponder([
479 [0, {}, null],
480 [0, {}, null],
481 [0, {}, null],
482 [200, {}, 'body']
484 var promise = new remoting.AutoRetryXhr({
485 method: 'GET',
486 url: 'http://foo.com'
487 }, 2).start().then(function(response) {
488 throw new Error('Expect retry to fail.');
489 }).catch(function(){
490 assert.ok(true);
492 return promise;
495 QUnit.test('does not retry when offline', function(assert) {
496 var isOnlineStub = sinon.stub(base, 'isOnline');
497 isOnlineStub.returns(false);
499 var promise = new remoting.AutoRetryXhr({
500 method: 'GET',
501 url: 'http://foo.com'
502 }).start().then(function(response) {
503 assert.ok(false, 'Expect failure');
504 }).catch(function(/** remoting.Error */ error) {
505 assert.equal(error.getTag(), remoting.Error.Tag.NETWORK_FAILURE);
507 isOnlineStub.restore();
508 return promise;
511 QUnit.test('resolves with successful responses', function(assert) {
512 var promise = new remoting.AutoRetryXhr({
513 method: 'GET',
514 url: 'http://foo.com'
515 }).start().then(function(response) {
516 assert.ok(!response.isError());
517 assert.equal(response.getText(), 'body');
519 fakeXhr.respond(200, {}, 'body');
520 return promise;
523 QUnit.test('rejects with failed responses', function(assert) {
524 var promise = new remoting.AutoRetryXhr({
525 method: 'GET',
526 url: 'http://foo.com'
527 }).start().then(function(response) {
528 assert.ok(response.isError());
529 assert.equal(response.getText(), 'failure');
531 fakeXhr.respond(500, {}, 'failure');
532 return promise;
535 })();