1 // Copyright 2013 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 // Common test utilities.
8 * Allows console.log output.
10 var showConsoleLogOutput = false;
13 * Conditionally allow console.log output based off of showConsoleLogOutput.
15 console.log = function() {
16 var originalConsoleLog = console.log;
18 if (showConsoleLogOutput) {
19 originalConsoleLog.apply(console, arguments);
24 function emptyMock() {}
26 // Container for event handlers added by mocked 'addListener' functions.
27 var mockEventHandlers = {};
30 * Mocks 'addListener' function of an API event. The mocked function will keep
32 * @param {Object} topLevelContainer Top-level container of the original
33 * function. Can be either 'chrome' or 'instrumented'.
34 * @param {string} eventIdentifier Event identifier, such as
35 * 'runtime.onSuspend'.
37 function mockChromeEvent(topLevelContainer, eventIdentifier) {
38 var eventIdentifierParts = eventIdentifier.split('.');
39 var eventName = eventIdentifierParts.pop();
40 var originalMethodContainer = topLevelContainer;
41 var mockEventContainer = mockEventHandlers;
42 eventIdentifierParts.forEach(function(fragment) {
43 originalMethodContainer =
44 originalMethodContainer[fragment] =
45 originalMethodContainer[fragment] || {};
47 mockEventContainer[fragment] =
48 mockEventContainer[fragment] || {};
51 mockEventContainer[eventName] = [];
52 originalMethodContainer[eventName] = {
53 addListener: function(callback) {
54 mockEventContainer[eventName].push(callback);
60 * Gets the array of event handlers added by a mocked 'addListener' function.
61 * @param {string} eventIdentifier Event identifier, such as
62 * 'runtime.onSuspend'.
63 * @return {Array<Function>} Array of handlers.
65 function getMockHandlerContainer(eventIdentifier) {
66 var eventIdentifierParts = eventIdentifier.split('.');
67 var mockEventContainer = mockEventHandlers;
68 eventIdentifierParts.forEach(function(fragment) {
69 mockEventContainer = mockEventContainer[fragment];
72 return mockEventContainer;
77 * The JS test harness expects all calls to complete synchronously.
78 * As a result, we can't use built-in JS promises since they run asynchronously.
79 * Instead of mocking all possible calls to promises, a skeleton
80 * implementation is provided to get the tests to pass.
82 * This functionality and logic originates from ECMAScript 6's spec of promises.
84 var Promise = function() {
85 function PromisePrototypeObject(asyncTask) {
86 function isThenable(value) {
87 return (typeof value === 'object') && isCallable(value.then);
90 function isCallable(value) {
91 return typeof value === 'function';
94 function callResolveRejectFunc(func) {
96 var funcResolved = false;
98 function(resolveResult) {
99 funcResult = resolveResult;
102 function(rejectResult) {
103 funcResult = rejectResult;
104 funcResolved = false;
106 return { result: funcResult, resolved: funcResolved };
109 function then(onResolve, onReject) {
110 var resolutionHandler =
111 isCallable(onResolve) ? onResolve : function() { return result; };
112 var rejectionHandler =
113 isCallable(onReject) ? onReject : function() { return result; };
115 resolved ? resolutionHandler(result) : rejectionHandler(result);
116 var promiseResolved = resolved;
117 if (isThenable(handlerResult)) {
118 var resolveReject = callResolveRejectFunc(handlerResult.then);
119 handlerResult = resolveReject.result;
120 promiseResolved = resolveReject.resolved;
123 if (promiseResolved) {
124 return Promise.resolve(handlerResult);
126 return Promise.reject(handlerResult);
130 // Promises use the function name "catch" to call back error handlers.
131 // We can't use "catch" since function or variable names cannot use the word
133 function catchFunc(onRejected) {
134 return this.then(undefined, onRejected);
137 var resolveReject = callResolveRejectFunc(asyncTask);
138 var result = resolveReject.result;
139 var resolved = resolveReject.resolved;
141 if (isThenable(result)) {
142 var thenResolveReject = callResolveRejectFunc(result.then);
143 result = thenResolveReject.result;
144 resolved = thenResolveReject.resolved;
147 return {then: then, catch: catchFunc, isPromise: true};
150 function all(arrayOfPromises) {
152 for (i = 0; i < arrayOfPromises.length; i++) {
153 if (arrayOfPromises[i].isPromise) {
154 arrayOfPromises[i].then(function(result) {
158 results[i] = arrayOfPromises[i];
161 var promise = new PromisePrototypeObject(function(resolve) {
167 function resolve(value) {
168 var promise = new PromisePrototypeObject(function(resolve) {
174 function reject(value) {
175 var promise = new PromisePrototypeObject(function(resolve, reject) {
181 PromisePrototypeObject.all = all;
182 PromisePrototypeObject.resolve = resolve;
183 PromisePrototypeObject.reject = reject;
184 return PromisePrototypeObject;
188 * Sets up the test to expect a Chrome Local Storage call.
189 * @param {Object} fixture Mock JS Test Object.
190 * @param {Object} defaultObject Storage request default object.
191 * @param {Object} result Storage result.
192 * @param {boolean=} opt_AllowRejection Allow Promise Rejection
194 function expectChromeLocalStorageGet(
195 fixture, defaultObject, result, opt_AllowRejection) {
196 if (opt_AllowRejection === undefined) {
197 fixture.mockApis.expects(once()).
198 fillFromChromeLocalStorage(eqJSON(defaultObject)).
199 will(returnValue(Promise.resolve(result)));
201 fixture.mockApis.expects(once()).
202 fillFromChromeLocalStorage(eqJSON(defaultObject), opt_AllowRejection).
203 will(returnValue(Promise.resolve(result)));