diff options
-rw-r--r-- | chrome/chrome_tests.gypi | 3 | ||||
-rw-r--r-- | chrome/test/data/webui/chrome_send_browsertest-inl.h | 61 | ||||
-rw-r--r-- | chrome/test/data/webui/chrome_send_browsertest.js | 80 | ||||
-rw-r--r-- | chrome/test/data/webui/mock4js_browsertest.js | 76 | ||||
-rw-r--r-- | chrome/test/data/webui/test_api.js | 65 |
5 files changed, 272 insertions, 13 deletions
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 401c64c..c4f7616 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -2670,6 +2670,9 @@ 'test/data/webui/async_gen.js', 'test/data/webui/certificate_viewer_dialog_test.js', 'test/data/webui/certificate_viewer_ui_test-inl.h', + 'test/data/webui/chrome_send_browsertest-inl.h', + 'test/data/webui/chrome_send_browsertest.js', + 'test/data/webui/mock4js_browsertest.js', 'test/data/webui/ntp4.js', 'test/data/webui/print_preview.js', # TODO(craig): Rename this and run from base_unittests when the test diff --git a/chrome/test/data/webui/chrome_send_browsertest-inl.h b/chrome/test/data/webui/chrome_send_browsertest-inl.h new file mode 100644 index 0000000..7d238f7 --- /dev/null +++ b/chrome/test/data/webui/chrome_send_browsertest-inl.h @@ -0,0 +1,61 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/values.h" +#include "chrome/browser/ui/webui/web_ui_browsertest.h" +#include "testing/gmock/include/gmock/gmock.h" + +// Test fixture for testing chrome.send. This class registers the "checkSend" +// message, but should NOT receive it. +class ChromeSendWebUITest : public WebUIBrowserTest { + public: + ChromeSendWebUITest(); + virtual ~ChromeSendWebUITest(); + + // Mocked message handler class to register expects using gmock framework. + class ChromeSendWebUIMessageHandler : public WebUIMessageHandler { + public: + ChromeSendWebUIMessageHandler(); + ~ChromeSendWebUIMessageHandler(); + + MOCK_METHOD1(HandleCheckSend, void(const base::ListValue*)); + + private: + virtual void RegisterMessages() OVERRIDE { + web_ui_->RegisterMessageCallback( + "checkSend", + base::Bind(&ChromeSendWebUIMessageHandler::HandleCheckSend, + base::Unretained(this))); + } + }; + + protected: + // Strict mock will fail when unexpected chrome.send messages are received. + ::testing::StrictMock<ChromeSendWebUIMessageHandler> message_handler_; + + private: + virtual WebUIMessageHandler* GetMockMessageHandler() OVERRIDE { + return &message_handler_; + } + + DISALLOW_COPY_AND_ASSIGN(ChromeSendWebUITest); +}; + +// Test fixture for verifying chrome.send messages are passed through. This +// class DOES expect to receive the "checkSend" message. +class ChromeSendPassthroughWebUITest : public ChromeSendWebUITest { + public: + ChromeSendPassthroughWebUITest(); + virtual ~ChromeSendPassthroughWebUITest(); + + virtual void SetUpOnMainThread() OVERRIDE { + ChromeSendWebUITest::SetUpOnMainThread(); + EXPECT_CALL(message_handler_, HandleCheckSend(::testing::_)); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ChromeSendPassthroughWebUITest); +}; diff --git a/chrome/test/data/webui/chrome_send_browsertest.js b/chrome/test/data/webui/chrome_send_browsertest.js new file mode 100644 index 0000000..52a30e8 --- /dev/null +++ b/chrome/test/data/webui/chrome_send_browsertest.js @@ -0,0 +1,80 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Tests to ensure that chrome.send mocking works as expected. + * @author scr@chromium.org (Sheridan Rawlins) + * @see test_api.js + */ + +GEN('#include "chrome/test/data/webui/chrome_send_browsertest-inl.h"'); + +// Code that must be in a C++ file to pass clang rules. +GEN('ChromeSendWebUITest::ChromeSendWebUITest() {}'); +GEN('ChromeSendWebUITest::~ChromeSendWebUITest() {}'); +GEN('ChromeSendWebUITest::ChromeSendWebUIMessageHandler::'); +GEN(' ChromeSendWebUIMessageHandler() {}'); +GEN('ChromeSendWebUITest::ChromeSendWebUIMessageHandler::'); +GEN(' ~ChromeSendWebUIMessageHandler() {}'); +GEN('ChromeSendPassthroughWebUITest::ChromeSendPassthroughWebUITest() {}'); +GEN('ChromeSendPassthroughWebUITest::~ChromeSendPassthroughWebUITest() {}'); + +/** + * Test fixture for chrome send WebUI testing. + * @constructor + * @extends {testing.Test} + */ +function ChromeSendWebUITest() {} + +ChromeSendWebUITest.prototype = { + __proto__: testing.Test.prototype, + + /** + * Generate a real C++ class; don't typedef. + * @type {?string} + * @override + */ + typedefCppFixture: null, + + /** @inheritDoc */ + browsePreload: DUMMY_URL, + + /** @inheritDoc */ + setUp: function() { + // Set up a mock handler class to catch the 'checkSend' message. + function MockHandler() {} + MockHandler.prototype = { + checkSend: function() {}, + }; + this.mockHandler = mock(MockHandler); + registerMockMessageCallbacks(this.mockHandler, MockHandler); + } +}; + +// Test that chrome.send can be mocked outside the preLoad method. +TEST_F('ChromeSendWebUITest', 'NotInPreload', function() { + this.mockHandler.expects(once()).checkSend(); + chrome.send('checkSend'); +}); + +/** + * Test fixture for chrome send WebUI testing with passthrough. + * @constructor + * @extends {ChromeSendWebUITest} + */ +function ChromeSendPassthroughWebUITest() {} + +ChromeSendPassthroughWebUITest.prototype = { + __proto__: ChromeSendWebUITest.prototype, +}; + +// Test that the mocked chrome.send can call the original. +TEST_F('ChromeSendPassthroughWebUITest', 'CanCallOriginal', function() { + chrome.send('expectCheckSend'); + this.mockHandler.expects(once()).checkSend(). + will(callFunction(function() { + chrome.originalSend('checkSend'); + })); + chrome.send('checkSend'); +}); diff --git a/chrome/test/data/webui/mock4js_browsertest.js b/chrome/test/data/webui/mock4js_browsertest.js new file mode 100644 index 0000000..1fd0cfe --- /dev/null +++ b/chrome/test/data/webui/mock4js_browsertest.js @@ -0,0 +1,76 @@ +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Tests for Mock4JS to ensure that expectations pass or fail as + * expected using the test framework. + * @author scr@chromium.org (Sheridan Rawlins) + * @see test_api.js + */ + +/** + * Test fixture for Mock4JS testing. + * @constructor + * @extends {testing.Test} + */ +function Mock4JSWebUITest() {} + +Mock4JSWebUITest.prototype = { + __proto__: testing.Test.prototype, + + /** @inheritDoc */ + browsePreload: DUMMY_URL, + + /** @inheritDoc */ + setUp: function() { + function MockHandler() {} + MockHandler.prototype = { + callMe: function() {}, + }; + this.mockHandler = mock(MockHandler); + }, +}; + +TEST_F('Mock4JSWebUITest', 'CalledExpectPasses', function() { + this.mockHandler.expects(once()).callMe(); + this.mockHandler.proxy().callMe(); +}); + +TEST_F('Mock4JSWebUITest', 'CalledTwiceExpectTwice', function() { + this.mockHandler.expects(exactly(2)).callMe(); + var proxy = this.mockHandler.proxy(); + proxy.callMe(); + proxy.callMe(); +}); + +/** + * Test fixture for Mock4JS testing which is expected to fail. + * @constructor + * @extends {Mock4JSWebUITest} + */ +function Mock4JSWebUITestFails() {} + +Mock4JSWebUITestFails.prototype = { + __proto__: Mock4JSWebUITest.prototype, + + /** @inheritDoc */ + testShouldFail: true, +}; + +TEST_F('Mock4JSWebUITestFails', 'NotCalledExpectFails', function() { + this.mockHandler.expects(once()).callMe(); +}); + +TEST_F('Mock4JSWebUITestFails', 'CalledTwiceExpectOnceFails', function() { + this.mockHandler.expects(once()).callMe(); + var proxy = this.mockHandler.proxy(); + proxy.callMe(); + proxy.callMe(); +}); + +TEST_F('Mock4JSWebUITestFails', 'CalledOnceExpectTwiceFails', function() { + this.mockHandler.expects(exactly(2)).callMe(); + var proxy = this.mockHandler.proxy(); + proxy.callMe(); +}); diff --git a/chrome/test/data/webui/test_api.js b/chrome/test/data/webui/test_api.js index c9f2313..baf629a 100644 --- a/chrome/test/data/webui/test_api.js +++ b/chrome/test/data/webui/test_api.js @@ -13,6 +13,11 @@ var testing = {}; (function(exports) { /** + * Holds the original version of the |chrome| object. + */ + var originalChrome = null; + + /** * Hold the currentTestCase across between preLoad and run. * @type {TestCase} */ @@ -338,8 +343,11 @@ var testing = {}; * @param {Mock4JS.Mock} mockObject The mock to register callbacks against. * @param {function(new:Object)} mockClAss Constructor for the mocked class. * @see registerMessageCallback + * @see overrideChrome */ function registerMockMessageCallbacks(mockObject, mockClass) { + if (!deferGlobalOverrides && !originalChrome) + overrideChrome(); var mockProxy = mockObject.proxy(); for (var func in mockClass.prototype) { if (typeof mockClass.prototype[func] === 'function') { @@ -556,7 +564,11 @@ var testing = {}; try { currentTestCase.tearDown(); } catch (e) { + // Caught an exception in tearDown; Register the error and recreate + // the result if it is passed in. errors.push(e); + if (result) + result = [false, errorsToMessage([e], result[1])]; } currentTestCase = null; } @@ -568,6 +580,26 @@ var testing = {}; } /** + * Converts each Error in |errors| to a suitable message, adding them to + * |message|, and returns the message string. + * @param {Array.<Error>} errors Array of errors to add to |message|. + * @param {string?} message When supplied, error messages are appended to it. + * @return {string} |message| + messages of all |errors|. + */ + function errorsToMessage(errors, message) { + for (var i = 0; i < errors.length; ++i) { + var errorMessage = errors[i].stack || errors[i].message; + if (message) + message += '\n'; + + message += 'Failed: ' + currentTestFunction + '(' + + currentTestArguments.map(JSON.stringify) + + ')\n' + errorMessage; + } + return message; + } + + /** * Returns [success, message] & clears |errors|. * @param {boolean} errorsOk When true, errors are ok. * @return {Array.<boolean, string>} @@ -575,13 +607,7 @@ var testing = {}; function testResult(errorsOk) { var result = [true, '']; if (errors.length) { - var message = ''; - for (var i = 0; i < errors.length; ++i) { - message += 'Failed: ' + currentTestFunction + '(' + - currentTestArguments.map(JSON.stringify) + - ')\n' + errors[i].stack; - } - result = [!!errorsOk, message]; + result = [!!errorsOk, errorsToMessage(errors)]; } return result; } @@ -821,6 +847,23 @@ var testing = {}; } /** + * Overrides the |chrome| object to enable mocking calls to chrome.send(). + */ + function overrideChrome() { + if (originalChrome) { + console.error('chrome object already overridden'); + return; + } + + originalChrome = chrome; + chrome = { + __proto__: originalChrome, + send: send, + originalSend: originalChrome.send.bind(originalChrome), + }; + } + + /** * Used by WebUIBrowserTest to preload the javascript libraries at the * appropriate time for javascript injection into the current page. This * creates a test case and calls its preLoad for any early initialization such @@ -835,12 +878,8 @@ var testing = {}; function preloadJavascriptLibraries(testFixture, testName) { deferGlobalOverrides = true; - exports.addEventListener('DOMContentLoaded', function() { - var oldChrome = chrome; - chrome = { - __proto__: oldChrome, - send: send, - }; + window.addEventListener('DOMContentLoaded', function() { + overrideChrome(); // Override globals at load time so they will be defined. assertTrue(deferGlobalOverrides); |