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 // This file contains various mock objects for the chrome platform to make
6 // unit testing easier.
16 * @extends {ChromeEvent}
18 chromeMocks
.Event = function() {
22 /** @param {Function} callback */
23 chromeMocks
.Event
.prototype.addListener = function(callback
) {
24 this.listeners_
.push(callback
);
27 /** @param {Function} callback */
28 chromeMocks
.Event
.prototype.removeListener = function(callback
) {
29 for (var i
= 0; i
< this.listeners_
.length
; i
++) {
30 if (this.listeners_
[i
] === callback
) {
31 this.listeners_
.splice(i
, 1);
38 * @param {...*} var_args
40 * @suppress {reportUnknownTypes}
42 chromeMocks
.Event
.prototype.mock
$fire = function(var_args
) {
43 var params
= Array
.prototype.slice
.call(arguments
);
44 this.listeners_
.forEach(
45 /** @param {Function} listener */
47 listener
.apply(null, params
);
52 chromeMocks
.runtime
= {};
55 chromeMocks
.runtime
.Port = function() {
57 this.onMessage
= new chromeMocks
.Event();
60 this.onDisconnect
= new chromeMocks
.Event();
65 /** @type {MessageSender} */
69 chromeMocks
.runtime
.Port
.prototype.disconnect = function() {};
72 * @param {Object} message
74 chromeMocks
.runtime
.Port
.prototype.postMessage = function(message
) {};
76 /** @type {chromeMocks.Event} */
77 chromeMocks
.runtime
.onMessage
= new chromeMocks
.Event();
80 /** @type {chromeMocks.Event} */
81 chromeMocks
.runtime
.onSuspend
= new chromeMocks
.Event();
84 * @param {string?} extensionId
86 * @param {function(*)=} responseCallback
88 chromeMocks
.runtime
.sendMessage = function(extensionId
, message
,
92 'The mock only supports sending messages to the same extension.');
93 extensionId
= chrome
.runtime
.id
;
94 Promise
.resolve().then(function() {
95 var message_copy
= base
.deepCopy(message
);
96 chromeMocks
.runtime
.onMessage
.mock
$fire(
97 message_copy
, {id
: extensionId
}, responseCallback
);
102 * Always returns the same mock port for given application name.
103 * @param {string} application
104 * @return {chromeMocks.runtime.Port}
106 chromeMocks
.runtime
.connectNative = function(application
) {
107 var port
= nativePorts
[application
];
108 if (port
=== undefined) {
109 port
= new chromeMocks
.runtime
.Port();
110 port
.name
= application
;
111 nativePorts
[application
] = port
;
116 /** @const {Object<!chromeMocks.runtime.Port>} */
117 var nativePorts
= null;
119 /** @type {string} */
120 chromeMocks
.runtime
.id
= 'extensionId';
122 /** @type {Object} */
123 chromeMocks
.runtime
.lastError
= {
124 /** @type {string|undefined} */
128 chromeMocks
.runtime
.getManifest = function() {
137 // Sample implementation of chrome.StorageArea according to
138 // https://developer.chrome.com/apps/storage#type-StorageArea
141 * @extends {StorageArea}
143 chromeMocks
.StorageArea = function() {
144 /** @type {!Object} */
149 * @param {Object|string} keys
150 * @return {Array<string>}
152 function getKeys(keys
) {
153 if (typeof keys
=== 'string') {
155 } else if (typeof keys
=== 'object') {
156 var objectKeys
= /** @type {!Object} */ (keys
);
157 return Object
.keys(objectKeys
);
162 chromeMocks
.StorageArea
.prototype.get = function(keys
, onDone
) {
164 // No keys are specified, returns the entire storage.
165 var storageCopy
= base
.deepCopy(this.storage_
);
166 onDone(/** @type {Object} */ (storageCopy
));
170 var result
= (typeof keys
=== 'object') ? keys
: {};
171 getKeys(keys
).forEach(
172 /** @param {string} key */
174 if (key
in this.storage_
) {
175 result
[key
] = base
.deepCopy(this.storage_
[key
]);
181 chromeMocks
.StorageArea
.prototype.set = function(value
, opt_onDone
) {
182 for (var key
in value
) {
183 this.storage_
[key
] = base
.deepCopy(value
[key
]);
190 chromeMocks
.StorageArea
.prototype.remove = function(keys
, opt_onDone
) {
191 getKeys(keys
).forEach(
192 /** @param {string} key */
194 delete this.storage_
[key
];
201 /** @return {!Object} */
202 chromeMocks
.StorageArea
.prototype.mock
$getStorage = function() {
203 return this.storage_
;
206 chromeMocks
.StorageArea
.prototype.clear = function() {
210 /** @type {Object} */
211 chromeMocks
.storage
= {};
213 /** @type {chromeMocks.StorageArea} */
214 chromeMocks
.storage
.local
= new chromeMocks
.StorageArea();
218 chromeMocks
.Identity = function() {
219 /** @private {string|undefined} */
220 this.token_
= undefined;
224 * @param {Object} options
225 * @param {function(string=):void} callback
227 chromeMocks
.Identity
.prototype.getAuthToken = function(options
, callback
) {
228 // Append the 'scopes' array, if present, to the dummy token.
229 var token
= this.token_
;
230 if (token
!== undefined && options
['scopes'] !== undefined) {
231 token
+= JSON
.stringify(options
['scopes']);
233 // Don't use setTimeout because sinon mocks it.
234 Promise
.resolve().then(callback
.bind(null, token
));
237 /** @param {string} token */
238 chromeMocks
.Identity
.prototype.mock
$setToken = function(token
) {
242 chromeMocks
.Identity
.prototype.mock
$clearToken = function() {
243 this.token_
= undefined;
246 /** @type {chromeMocks.Identity} */
247 chromeMocks
.identity
;
250 chromeMocks
.MetricsPrivate = function() {};
252 chromeMocks
.MetricsPrivate
.prototype.recordValue = function() {};
254 /** @type {chromeMocks.MetricsPrivate} */
255 chromeMocks
.metricsPrivate
;
258 chromeMocks
.I18n = function() {};
261 * @param {string} messageName
262 * @param {(string|Array<string>)=} opt_args
265 chromeMocks
.I18n
.prototype.getMessage = function(messageName
, opt_args
) {};
270 chromeMocks
.I18n
.prototype.getUILanguage = function() {};
273 chromeMocks
.WindowManager = function() {
274 this.current_
= new chromeMocks
.AppWindow();
277 chromeMocks
.WindowManager
.prototype.current = function() {
278 return this.current_
;
282 chromeMocks
.AppWindow = function() {};
284 var originals_
= null;
287 * Activates a list of Chrome components to mock
289 chromeMocks
.activate = function() {
291 throw new Error('chromeMocks.activate() can only be called once.');
296 chromeMocks
.i18n
= new chromeMocks
.I18n();
297 chromeMocks
.identity
= new chromeMocks
.Identity();
298 chromeMocks
.metricsPrivate
= new chromeMocks
.MetricsPrivate();
300 ['identity', 'i18n', 'runtime', 'storage', 'metricsPrivate'].forEach(
301 function(/** string */ component
) {
302 if (!chromeMocks
[component
]) {
303 throw new Error('No mocks defined for chrome.' + component
);
305 originals_
[component
] = chrome
[component
];
306 chrome
[component
] = chromeMocks
[component
];
309 chrome
.app
['window'] = new chromeMocks
.WindowManager();
312 chromeMocks
.restore = function() {
314 throw new Error('You must call activate() before restore().');
316 for (var components
in originals_
) {
317 chrome
[components
] = originals_
[components
];