OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This file contains various mock objects for the chrome platform to make | 5 // This file contains various mock objects for the chrome platform to make |
6 // unit testing easier. | 6 // unit testing easier. |
7 | 7 |
8 Entry = function() {}; | 8 Entry = function() {}; |
9 | 9 |
10 var chromeMocks = {}; | 10 var chromeMocks = {}; |
11 | 11 |
12 (function(){ | 12 chromeMocks.reset = function() { |
13 | 13 |
14 /** | 14 /** |
15 * @constructor | 15 * @constructor |
16 */ | 16 */ |
17 chromeMocks.Event = function() { | 17 chrome.Event = function() { |
18 this.listeners_ = []; | 18 this.listeners_ = []; |
19 }; | 19 }; |
20 | 20 |
21 /** @param {Function} callback */ | 21 /** @param {Function} callback */ |
22 chromeMocks.Event.prototype.addListener = function(callback) { | 22 chrome.Event.prototype.addListener = function(callback) { |
23 this.listeners_.push(callback); | 23 this.listeners_.push(callback); |
24 }; | 24 }; |
25 | 25 |
26 /** @param {Function} callback */ | 26 /** @param {Function} callback */ |
27 chromeMocks.Event.prototype.removeListener = function(callback) { | 27 chrome.Event.prototype.removeListener = function(callback) { |
28 for (var i = 0; i < this.listeners_.length; i++) { | 28 for (var i = 0; i < this.listeners_.length; i++) { |
29 if (this.listeners_[i] === callback) { | 29 if (this.listeners_[i] === callback) { |
30 this.listeners_.splice(i, 1); | 30 this.listeners_.splice(i, 1); |
31 break; | 31 break; |
32 } | 32 } |
33 } | 33 } |
34 }; | 34 }; |
35 | 35 |
36 /** | 36 /** |
37 * @param {...*} var_args | 37 * @param {...*} var_args |
38 * @return {void} | 38 * @return {void} |
39 */ | 39 */ |
40 chromeMocks.Event.prototype.mock$fire = function(var_args) { | 40 chrome.Event.prototype.mock$fire = function(var_args) { |
41 var params = Array.prototype.slice.call(arguments); | 41 var params = Array.prototype.slice.call(arguments); |
42 this.listeners_.forEach( | 42 this.listeners_.forEach( |
43 /** @param {Function} listener */ | 43 /** @param {Function} listener */ |
44 function(listener){ | 44 function(listener){ |
45 listener.apply(null, params); | 45 listener.apply(null, params); |
46 }); | 46 }); |
47 }; | 47 }; |
48 | 48 |
49 /** @type {Object} */ | 49 /** @type {chrome.Event} */ |
50 chromeMocks.runtime = {}; | 50 chrome.runtime.onMessage = new chrome.Event(); |
51 | |
52 /** @constructor */ | |
53 chromeMocks.runtime.Port = function() { | |
54 this.onMessage = new chromeMocks.Event(); | |
55 this.onDisconnect = new chromeMocks.Event(); | |
56 | |
57 /** @type {string} */ | |
58 this.name = ''; | |
59 | |
60 /** @type {chrome.runtime.MessageSender} */ | |
61 this.sender = null; | |
62 }; | |
63 | |
64 chromeMocks.runtime.Port.prototype.disconnect = function() {}; | |
65 | 51 |
66 /** | 52 /** |
67 * @param {Object} message | 53 * TODO(garykac): Function signature doesn't match chrome.runtime.sendMessage |
68 */ | 54 * in chrome_proto. |
69 chromeMocks.runtime.Port.prototype.postMessage = function(message) {}; | 55 * |
70 | |
71 /** @type {chromeMocks.Event} */ | |
72 chromeMocks.runtime.onMessage = new chromeMocks.Event(); | |
73 | |
74 /** | |
75 * @param {string?} extensionId | 56 * @param {string?} extensionId |
76 * @param {*} message | 57 * @param {*} message |
77 * @param {function(*)=} responseCallback | 58 * @param {function(*)=} responseCallback |
78 */ | 59 */ |
79 chromeMocks.runtime.sendMessage = function(extensionId, message, | 60 chrome.runtime.sendMessage = function(extensionId, message, |
80 responseCallback) { | 61 responseCallback) { |
81 base.debug.assert( | 62 base.debug.assert( |
82 extensionId === null, | 63 extensionId === null, |
83 'The mock only supports sending messages to the same extension.'); | 64 'The mock only supports sending messages to the same extension.'); |
84 extensionId = chrome.runtime.id; | 65 extensionId = chrome.runtime.id; |
85 window.requestAnimationFrame(function() { | 66 window.requestAnimationFrame(function() { |
86 var message_copy = base.deepCopy(message); | 67 var message_copy = base.deepCopy(message); |
87 chromeMocks.runtime.onMessage.mock$fire( | 68 chrome.runtime.onMessage.mock$fire( |
88 message_copy, {id: extensionId}, responseCallback); | 69 message_copy, {id: extensionId}, responseCallback); |
89 }); | 70 }); |
90 }; | 71 }; |
91 | 72 |
92 /** @type {string} */ | 73 /** @type {string} */ |
93 chromeMocks.runtime.id = 'extensionId'; | 74 chrome.runtime.id = 'extensionId'; |
94 | |
95 /** @type {Object} */ | |
96 chromeMocks.storage = {}; | |
97 | 75 |
98 // Sample implementation of chrome.StorageArea according to | 76 // Sample implementation of chrome.StorageArea according to |
99 // https://developer.chrome.com/apps/storage#type-StorageArea | 77 // https://developer.chrome.com/apps/storage#type-StorageArea |
100 /** @constructor */ | 78 /** @constructor */ |
101 chromeMocks.StorageArea = function() { | 79 chrome.StorageArea = function() { |
102 /** @type {Object} */ | 80 /** @type {Object} */ |
103 this.storage_ = {}; | 81 this.storage_ = {}; |
104 }; | 82 }; |
105 | 83 |
106 /** | 84 /** |
107 * @param {!Object} keys | 85 * @param {!Object} keys |
108 * @return {Array<string>} | 86 * @return {Array<string>} |
109 */ | 87 */ |
110 function getKeys(keys) { | 88 function getKeys(keys) { |
111 if (typeof keys === 'string') { | 89 if (typeof keys === 'string') { |
112 return [keys]; | 90 return [keys]; |
113 } else if (typeof keys === 'object') { | 91 } else if (typeof keys === 'object') { |
114 return Object.keys(keys); | 92 return Object.keys(keys); |
115 } | 93 } |
116 return []; | 94 return []; |
117 } | 95 } |
118 | 96 |
119 /** | 97 /** |
120 * @param {!Object} keys | 98 * @param {!Object} keys |
121 * @param {Function} onDone | 99 * @param {Function} onDone |
122 */ | 100 */ |
123 chromeMocks.StorageArea.prototype.get = function(keys, onDone) { | 101 chrome.StorageArea.prototype.get = function(keys, onDone) { |
124 if (!keys) { | 102 if (!keys) { |
125 onDone(base.deepCopy(this.storage_)); | 103 onDone(base.deepCopy(this.storage_)); |
126 return; | 104 return; |
127 } | 105 } |
128 | 106 |
129 var result = (typeof keys === 'object') ? keys : {}; | 107 var result = (typeof keys === 'object') ? keys : {}; |
130 getKeys(keys).forEach( | 108 getKeys(keys).forEach( |
131 /** @param {string} key */ | 109 /** @param {string} key */ |
132 function(key) { | 110 function(key) { |
133 if (key in this.storage_) { | 111 if (key in this.storage_) { |
134 result[key] = base.deepCopy(this.storage_[key]); | 112 result[key] = base.deepCopy(this.storage_[key]); |
135 } | 113 } |
136 }, this); | 114 }, this); |
137 onDone(result); | 115 onDone(result); |
138 }; | 116 }; |
139 | 117 |
140 /** @param {Object} value */ | 118 /** @param {Object} value */ |
141 chromeMocks.StorageArea.prototype.set = function(value) { | 119 chrome.StorageArea.prototype.set = function(value) { |
142 for (var key in value) { | 120 for (var key in value) { |
143 this.storage_[key] = base.deepCopy(value[key]); | 121 this.storage_[key] = base.deepCopy(value[key]); |
144 } | 122 } |
145 }; | 123 }; |
146 | 124 |
147 /** | 125 /** |
148 * @param {!Object} keys | 126 * @param {!Object} keys |
149 */ | 127 */ |
150 chromeMocks.StorageArea.prototype.remove = function(keys) { | 128 chrome.StorageArea.prototype.remove = function(keys) { |
151 getKeys(keys).forEach( | 129 getKeys(keys).forEach( |
152 /** @param {string} key */ | 130 /** @param {string} key */ |
153 function(key) { | 131 function(key) { |
154 delete this.storage_[key]; | 132 delete this.storage_[key]; |
155 }, this); | 133 }, this); |
156 }; | 134 }; |
157 | 135 |
158 chromeMocks.StorageArea.prototype.clear = function() { | 136 chrome.StorageArea.prototype.clear = function() { |
159 this.storage_ = null; | 137 this.storage_ = null; |
160 }; | 138 }; |
161 | 139 |
162 /** @type {chromeMocks.StorageArea} */ | 140 /** @type {chrome.StorageArea} */ |
163 chromeMocks.storage.local = new chromeMocks.StorageArea(); | 141 chrome.storage.local = new chrome.StorageArea(); |
164 | 142 |
165 var originals_ = null; | |
166 | |
167 /** | |
168 * Activates a list of Chrome components to mock | |
169 * @param {Array<string>} components | |
170 */ | |
171 chromeMocks.activate = function(components) { | |
172 if (originals_) { | |
173 throw new Error('chromeMocks.activate() can only be called once.'); | |
174 } | |
175 originals_ = {}; | |
176 components.forEach(function(component) { | |
177 if (!chromeMocks[component]) { | |
178 throw new Error('No mocks defined for chrome.' + component); | |
179 } | |
180 originals_[component] = chrome[component]; | |
181 chrome[component] = chromeMocks[component]; | |
182 }); | |
183 }; | 143 }; |
184 | |
185 chromeMocks.restore = function() { | |
186 if (!originals_) { | |
187 throw new Error('You must call activate() before restore().'); | |
188 } | |
189 for (var components in originals_) { | |
190 chrome[components] = originals_[components]; | |
191 } | |
192 originals_ = null; | |
193 }; | |
194 | |
195 })(); | |
OLD | NEW |