// extension_apitest.js // mini-framework for ExtensionApiTest browser tests var chrome = chrome || {}; (function() { chrome.test = chrome.test || {}; chrome.test.tests = chrome.test.tests || []; var completed = false; var currentTest = null; var lastTest = null; function complete() { completed = true; // Try to get the script to stop running immediately. // This isn't an error, just an attempt at saying "done". throw "completed"; } chrome.test.fail = function(message) { if (completed) throw "completed"; chrome.test.log("( FAILED ) " + currentTest.name); var stack; try { crash.me += 0; // An intentional exception to get the stack trace. } catch (e) { stack = e.stack.split("\n"); stack = stack.slice(2); // Remove title and fail() lines. stack = stack.join("\n"); } if (!message) { message = "FAIL (no message)"; } message += "\n" + stack; console.log("[FAIL] " + currentTest.name + ": " + message); chrome.test.notifyFail(message); complete(); }; function allTestsSucceeded() { console.log("All tests succeeded"); if (completed) throw "completed"; chrome.test.notifyPass(); complete(); } var pendingCallbacks = 0; chrome.test.callbackAdded = function () { pendingCallbacks++; return function() { pendingCallbacks--; if (pendingCallbacks == 0) { chrome.test.succeed(); } } }; chrome.test.runNextTest = function() { chrome.test.assertEq(pendingCallbacks, 0); lastTest = currentTest; currentTest = chrome.test.tests.shift(); if (!currentTest) { allTestsSucceeded(); return; } try { chrome.test.log("( RUN ) " + currentTest.name); currentTest.call(); } catch (e) { var message = e.stack; console.log("[FAIL] " + currentTest.name + ": " + message); chrome.test.notifyFail(message); complete(); } }; chrome.test.succeed = function() { console.log("[SUCCESS] " + currentTest.name); chrome.test.log("( SUCCESS )"); // Use setTimeout here to allow previous test contexts to be // eligible for garbage collection. setTimeout(chrome.test.runNextTest, 0); }; chrome.test.assertTrue = function(test, message) { if (test !== true) { if (typeof(test) == "string") { if (message) { message = test + "\n" + message; } else { message = test; } } chrome.test.fail(message); } }; chrome.test.assertEq = function(expected, actual) { if (expected != actual) { chrome.test.fail("API Test Error in " + currentTest.name + "\nActual: " + actual + "\nExpected: " + expected); } if (typeof(expected) != typeof(actual)) { chrome.test.fail("API Test Error in " + currentTest.name + " (type mismatch)\nActual Type: " + typeof(actual) + "\nExpected Type:" + typeof(expected)); } }; chrome.test.assertNoLastError = function() { if (chrome.extension.lastError != undefined) { chrome.test.fail("lastError.message == " + chrome.extension.lastError.message); } }; function safeFunctionApply(func, arguments) { try { if (func) { func.apply(null, arguments); } } catch (e) { var stack = null; if (typeof(e.stack) != "undefined") { stack = e.stack.toString(); } var msg = "Exception during execution of callback in " + currentTest.name; if (stack) { msg += "\n" + stack; } else { msg += "\n(no stack available)"; } chrome.test.fail(msg); } }; // Wrapper for generating test functions, that takes care of calling // assertNoLastError() and (optionally) succeed() for you. chrome.test.callback = function(func, expectedError) { if (func) { chrome.test.assertEq(typeof(func), 'function'); } var callbackCompleted = chrome.test.callbackAdded(); return function() { if (expectedError == null) { chrome.test.assertNoLastError(); } else { chrome.test.assertEq(typeof(expectedError), 'string'); chrome.test.assertEq(expectedError, chrome.extension.lastError.message); } if (func) { safeFunctionApply(func, arguments); } callbackCompleted(); }; }; chrome.test.listenOnce = function(event, func) { var callbackCompleted = chrome.test.callbackAdded(); var listener = function() { event.removeListener(listener); safeFunctionApply(func, arguments); callbackCompleted(); }; event.addListener(listener); }; chrome.test.listenForever = function(event, func) { var callbackCompleted = chrome.test.callbackAdded(); var listener = function() { safeFunctionApply(func, arguments); }; var done = function() { event.removeListener(listener); callbackCompleted(); }; event.addListener(listener); return done; }; chrome.test.callbackPass = function(func) { return chrome.test.callback(func); }; chrome.test.callbackFail = function(expectedError) { return chrome.test.callback(null, expectedError); }; chrome.test.runTests = function(tests) { chrome.test.tests = tests; chrome.test.runNextTest(); }; })();