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 // test_custom_bindings.js
6 // mini-framework for ExtensionApiTest browser tests
8 var binding
= require('binding').Binding
.create('test');
10 var environmentSpecificBindings
= require('test_environment_specific_bindings');
11 var GetExtensionAPIDefinitionsForTest
=
12 requireNative('apiDefinitions').GetExtensionAPIDefinitionsForTest
;
13 var GetAPIFeatures
= requireNative('test_features').GetAPIFeatures
;
14 var uncaughtExceptionHandler
= require('uncaught_exception_handler');
15 var userGestures
= requireNative('user_gestures');
17 var RunWithNativesEnabledModuleSystem
=
18 requireNative('v8_context').RunWithNativesEnabledModuleSystem
;
20 binding
.registerCustomHook(function(api
) {
21 var chromeTest
= api
.compiledApi
;
22 var apiFunctions
= api
.apiFunctions
;
24 chromeTest
.tests
= chromeTest
.tests
|| [];
26 var currentTest
= null;
30 var failureException
= 'chrome.test.failure';
32 // Helper function to get around the fact that function names in javascript
33 // are read-only, and you can't assign one to anonymous functions.
34 function testName(test
) {
35 return test
? (test
.name
|| test
.generatedName
) : "(no test)";
39 environmentSpecificBindings
.testDone(chromeTest
.runNextTest
);
42 function allTestsDone() {
43 if (testsFailed
== 0) {
44 chromeTest
.notifyPass();
46 chromeTest
.notifyFail('Failed ' + testsFailed
+ ' of ' +
47 testCount
+ ' tests');
51 var pendingCallbacks
= 0;
53 apiFunctions
.setHandleRequest('callbackAdded', function() {
59 var redundantPrefix
= 'Error\n';
61 'Callback has already been run. ' +
63 $String
.slice(called
, redundantPrefix
.length
) + '\n' +
65 $String
.slice(new Error().stack
, redundantPrefix
.length
));
67 called
= new Error().stack
;
70 if (pendingCallbacks
== 0) {
76 apiFunctions
.setHandleRequest('runNextTest', function() {
77 // There may have been callbacks which were interrupted by failure
81 lastTest
= currentTest
;
82 currentTest
= chromeTest
.tests
.shift();
90 chromeTest
.log("( RUN ) " + testName(currentTest
));
91 uncaughtExceptionHandler
.setHandler(function(message
, e
) {
92 if (e
!== failureException
)
93 chromeTest
.fail('uncaught exception: ' + message
);
97 uncaughtExceptionHandler
.handle(e
.message
, e
);
101 apiFunctions
.setHandleRequest('fail', function(message
) {
102 chromeTest
.log("( FAILED ) " + testName(currentTest
));
105 Error
.captureStackTrace(stack
, chromeTest
.fail
);
108 message
= "FAIL (no message)";
110 message
+= "\n" + stack
.stack
;
111 console
.log("[FAIL] " + testName(currentTest
) + ": " + message
);
115 // Interrupt the rest of the test.
116 throw failureException
;
119 apiFunctions
.setHandleRequest('succeed', function() {
120 console
.log("[SUCCESS] " + testName(currentTest
));
121 chromeTest
.log("( SUCCESS )");
125 apiFunctions
.setHandleRequest('runWithModuleSystem', function(callback
) {
126 RunWithNativesEnabledModuleSystem(callback
);
129 apiFunctions
.setHandleRequest('assertTrue', function(test
, message
) {
130 chromeTest
.assertBool(test
, true, message
);
133 apiFunctions
.setHandleRequest('assertFalse', function(test
, message
) {
134 chromeTest
.assertBool(test
, false, message
);
137 apiFunctions
.setHandleRequest('assertBool',
138 function(test
, expected
, message
) {
139 if (test
!== expected
) {
140 if (typeof(test
) == "string") {
142 message
= test
+ "\n" + message
;
146 chromeTest
.fail(message
);
150 apiFunctions
.setHandleRequest('checkDeepEq', function(expected
, actual
) {
151 if ((expected
=== null) != (actual
=== null))
154 if (expected
=== actual
)
157 if (typeof(expected
) !== typeof(actual
))
160 for (var p
in actual
) {
161 if ($Object
.hasOwnProperty(actual
, p
) &&
162 !$Object
.hasOwnProperty(expected
, p
)) {
166 for (var p
in expected
) {
167 if ($Object
.hasOwnProperty(expected
, p
) &&
168 !$Object
.hasOwnProperty(actual
, p
)) {
173 for (var p
in expected
) {
175 switch (typeof(expected
[p
])) {
177 eq
= chromeTest
.checkDeepEq(expected
[p
], actual
[p
]);
180 eq
= (typeof(actual
[p
]) != 'undefined' &&
181 expected
[p
].toString() == actual
[p
].toString());
184 eq
= (expected
[p
] == actual
[p
] &&
185 typeof(expected
[p
]) == typeof(actual
[p
]));
194 apiFunctions
.setHandleRequest('assertEq',
195 function(expected
, actual
, message
) {
196 var error_msg
= "API Test Error in " + testName(currentTest
);
198 error_msg
+= ": " + message
;
199 if (typeof(expected
) == 'object') {
200 if (!chromeTest
.checkDeepEq(expected
, actual
)) {
201 error_msg
+= "\nActual: " + $JSON
.stringify(actual
) +
202 "\nExpected: " + $JSON
.stringify(expected
);
203 chromeTest
.fail(error_msg
);
207 if (expected
!= actual
) {
208 chromeTest
.fail(error_msg
+
209 "\nActual: " + actual
+ "\nExpected: " + expected
);
211 if (typeof(expected
) != typeof(actual
)) {
212 chromeTest
.fail(error_msg
+
213 " (type mismatch)\nActual Type: " + typeof(actual
) +
214 "\nExpected Type:" + typeof(expected
));
218 apiFunctions
.setHandleRequest('assertNoLastError', function() {
219 if (chrome
.runtime
.lastError
!= undefined) {
220 chromeTest
.fail("lastError.message == " +
221 chrome
.runtime
.lastError
.message
);
225 apiFunctions
.setHandleRequest('assertLastError', function(expectedError
) {
226 chromeTest
.assertEq(typeof(expectedError
), 'string');
227 chromeTest
.assertTrue(chrome
.runtime
.lastError
!= undefined,
228 "No lastError, but expected " + expectedError
);
229 chromeTest
.assertEq(expectedError
, chrome
.runtime
.lastError
.message
);
232 apiFunctions
.setHandleRequest('assertThrows',
233 function(fn
, self
, args
, message
) {
234 chromeTest
.assertTrue(typeof fn
== 'function');
236 fn
.apply(self
, args
);
237 chromeTest
.fail('Did not throw error: ' + fn
);
239 if (e
!= failureException
&& message
!== undefined) {
240 if (message
instanceof RegExp
) {
241 chromeTest
.assertTrue(message
.test(e
.message
),
242 e
.message
+ ' should match ' + message
)
244 chromeTest
.assertEq(message
, e
.message
);
250 function safeFunctionApply(func
, args
) {
253 return $Function
.apply(func
, undefined, args
);
255 var msg
= "uncaught exception " + e
;
256 chromeTest
.fail(msg
);
260 // Wrapper for generating test functions, that takes care of calling
261 // assertNoLastError() and (optionally) succeed() for you.
262 apiFunctions
.setHandleRequest('callback', function(func
, expectedError
) {
264 chromeTest
.assertEq(typeof(func
), 'function');
266 var callbackCompleted
= chromeTest
.callbackAdded();
269 if (expectedError
== null) {
270 chromeTest
.assertNoLastError();
272 chromeTest
.assertLastError(expectedError
);
277 result
= safeFunctionApply(func
, arguments
);
285 apiFunctions
.setHandleRequest('listenOnce', function(event
, func
) {
286 var callbackCompleted
= chromeTest
.callbackAdded();
287 var listener = function() {
288 event
.removeListener(listener
);
289 safeFunctionApply(func
, arguments
);
292 event
.addListener(listener
);
295 apiFunctions
.setHandleRequest('listenForever', function(event
, func
) {
296 var callbackCompleted
= chromeTest
.callbackAdded();
298 var listener = function() {
299 safeFunctionApply(func
, arguments
);
302 var done = function() {
303 event
.removeListener(listener
);
307 event
.addListener(listener
);
311 apiFunctions
.setHandleRequest('callbackPass', function(func
) {
312 return chromeTest
.callback(func
);
315 apiFunctions
.setHandleRequest('callbackFail', function(expectedError
, func
) {
316 return chromeTest
.callback(func
, expectedError
);
319 apiFunctions
.setHandleRequest('runTests', function(tests
) {
320 chromeTest
.tests
= tests
;
321 testCount
= chromeTest
.tests
.length
;
322 chromeTest
.runNextTest();
325 apiFunctions
.setHandleRequest('getApiDefinitions', function() {
326 return GetExtensionAPIDefinitionsForTest();
329 apiFunctions
.setHandleRequest('getApiFeatures', function() {
330 return GetAPIFeatures();
333 apiFunctions
.setHandleRequest('isProcessingUserGesture', function() {
334 return userGestures
.IsProcessingUserGesture();
337 apiFunctions
.setHandleRequest('runWithUserGesture', function(callback
) {
338 chromeTest
.assertEq(typeof(callback
), 'function');
339 return userGestures
.RunWithUserGesture(callback
);
342 apiFunctions
.setHandleRequest('runWithoutUserGesture', function(callback
) {
343 chromeTest
.assertEq(typeof(callback
), 'function');
344 return userGestures
.RunWithoutUserGesture(callback
);
347 apiFunctions
.setHandleRequest('setExceptionHandler', function(callback
) {
348 chromeTest
.assertEq(typeof(callback
), 'function');
349 uncaughtExceptionHandler
.setHandler(callback
);
352 environmentSpecificBindings
.registerHooks(api
);
355 exports
.binding
= binding
.generate();