1<!DOCTYPE html>
2<!--
3Copyright 2015 The Chromium Authors. All rights reserved.
4Use of this source code is governed by a BSD-style license that can be
5found in the LICENSE file.
6-->
7
8<script>
9'use strict';
10
11var testing_common = (function() {
12
13  var originalXMLHttpRequest = window.XMLHttpRequest;
14  var fixture = null;
15  var xhrMock = null;
16
17  var XMLHttpRequestMock = function() {
18    this.responseMap_ = {};
19    window.XMLHttpRequest = this.getMock();
20  };
21
22  XMLHttpRequestMock.prototype.getMock = function() {
23    // TODO(chrisphan): Add support for error state.
24    var self = this;
25    return function() {
26      this.status = 200;
27      this.onerror = function() {};
28      this.open = function(method, url, async) {
29        this.url = url;
30      };
31      this.abort = function() {};
32      this.setRequestHeader = function() {};
33      this.onload = function() {};
34      this.send = function(param) {
35        var requestStr = this.url + '?' + sortQueryPart(param);
36        if (requestStr in self.responseMap_) {
37          this.responseText = self.responseMap_[requestStr];
38          this.onload();
39        } else if ('*' in self.responseMap_) {
40          this.responseText = self.responseMap_['*'];
41          this.onload();
42        } else {
43          console.warn('XMLHttpRequest sent without a handler: ' + requestStr);
44        }
45      };
46    };
47  };
48
49  XMLHttpRequestMock.prototype.add = function(param, response) {
50    if (param != '*') {
51      param = sortQueryPart(param);
52    }
53    this.responseMap_[param] = response;
54  };
55
56  function addXhrMock(param, response) {
57    if (!xhrMock) {
58      xhrMock = new XMLHttpRequestMock();
59    }
60    xhrMock.add(param, response);
61  };
62
63  function clearXhrMock() {
64    window.XMLHttpRequest = originalXMLHttpRequest;
65    xhrMock = null;
66  };
67
68  /**
69   * Does a deep copy of the object.
70   * @param {*} obj Object to copy.
71   * @return {*} A copy of the object.
72   */
73  function deepCopy(obj) {
74    return JSON.parse(JSON.stringify(obj));
75  };
76
77  function addToFixture(node) {
78    if (!fixture) {
79      fixture = document.createElement('div');
80      document.body.appendChild(fixture);
81    }
82    fixture.appendChild(node);
83  };
84
85  function clearFixture() {
86    if (fixture) {
87      fixture.innerHTML = '';
88    }
89  };
90
91  var paramString = function(params) {
92    var keys = Object.keys(params).sort();
93    return keys.map(function(key) {
94      return key + '=' + encodeURIComponent(params[key]);
95    }).join('&');
96  };
97
98  var sortQueryPart = function(paramStr) {
99    var params = {};
100    var path = paramStr.substring(0, paramStr.indexOf('?') + 1);
101    var query = paramStr.substring(paramStr.indexOf('?') + 1);
102    var queryParts = query.split('&');
103    for (var i = 0; i < queryParts.length; i++) {
104      var pair = queryParts[i].split('=');
105      params[pair[0]] = pair.length == 1 ? '' : pair[1];
106    }
107    var keys = Object.keys(params).sort();
108    query = keys.map(function(key) {
109      return key + '=' + params[key];
110    }).join('&');
111    return path + query;
112  };
113
114  return {
115    addXhrMock: addXhrMock,
116    clearXhrMock: clearXhrMock,
117    deepCopy: deepCopy,
118    addToFixture: addToFixture,
119    clearFixture: clearFixture,
120    paramString: paramString,
121    sortQueryPart: sortQueryPart
122  };
123})();
124
125</script>
126