Chromium Code Reviews| Index: chrome/browser/resources/google_now/utility_unittest.gtestjs |
| diff --git a/chrome/browser/resources/google_now/utility_unittest.gtestjs b/chrome/browser/resources/google_now/utility_unittest.gtestjs |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..ea6b00aed4c3593d7e099b65237d8857a0c03c90 |
| --- /dev/null |
| +++ b/chrome/browser/resources/google_now/utility_unittest.gtestjs |
| @@ -0,0 +1,428 @@ |
| +// Copyright 2013 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. |
| + |
| +/** |
| + * Test fixture for utility.js. |
| + * @constructor |
| + * @extends {testing.Test} |
| + */ |
| +function GoogleNowUtilityUnitTest () { |
| + testing.Test.call(this); |
| +} |
| + |
| +GoogleNowUtilityUnitTest.prototype = { |
| + __proto__: testing.Test.prototype, |
| + |
| + /** @override */ |
| + extraLibraries: [ |
| + 'common_test_util.js', |
| + 'utility_test_util.js', |
| + 'utility.js' |
| + ] |
| +}; |
| + |
| +TEST_F('GoogleNowUtilityUnitTest', 'SendErrorReport1', function() { |
| + // Test sending report for an error with a message that can be sent to server. |
|
robliao
2013/08/28 22:05:29
Where is the test that checks for first line remov
vadimt
2013/08/28 22:29:35
Line 94.
|
| + |
| + // Setup and expectations. |
| + var testStack = 'Error: TEST ERROR MESSAGE\n ' + |
| + 'at buildErrorWithMessageForServer ' + |
| + '(chrome-extension://ext_id/utility.js:29:15)\n' + |
| + ' at <anonymous>:2:16\n ' + |
| + 'at Object.InjectedScript._evaluateOn (<anonymous>:580:39)\n ' + |
| + 'at Object.InjectedScript._evaluateAndWrap (<anonymous>:539:52)\n ' + |
| + 'at Object.InjectedScript.evaluate (<anonymous>:458:21)'; |
| + |
| + var testError = { |
| + canSendMessageToServer: true, |
| + stack: testStack, |
| + name: 'TEST ERROR NAME' |
| + }; |
| + |
| + this.makeAndRegisterMockGlobals(['buildServerRequest']); |
| + this.makeMockLocalFunctions(['sendRequest']); |
| + |
| + var mockRequest = {send: this.mockLocalFunctions.functions().sendRequest}; |
| + |
| + var expectedRequestParameters = 'error=TEST%20ERROR%20NAME&' + |
| + 'script=%2F%2Fext_id%2Futility.js&' + |
| + 'line=29&' + |
| + 'trace=Error%3A%20TEST%20ERROR%20MESSAGE%0A%20%20%20%20' + |
| + 'at%20buildErrorWithMessageForServer%20' + |
| + '(chrome-extension%3A%2F%2Fext_id%2Futility.js%3A29%3A15)%0A' + |
| + '%20%20%20%20at%20%3Canonymous%3E%3A2%3A16%0A%20%20%20%20' + |
| + 'at%20Object.InjectedScript._evaluateOn%20(%3Canonymous%3E%3A580%3A39)' + |
| + '%0A%20%20%20%20' + |
| + 'at%20Object.InjectedScript._evaluateAndWrap%20(%3Canonymous%3E%3A539' + |
| + '%3A52)%0A%20%20%20%20' + |
| + 'at%20Object.InjectedScript.evaluate%20(%3Canonymous%3E%3A458%3A21)'; |
| + |
| + this.mockGlobals.expects(once()). |
| + buildServerRequest('jserror', 'application/x-www-form-urlencoded'). |
| + will(returnValue(mockRequest)); |
| + this.mockLocalFunctions.expects(once()).sendRequest( |
| + expectedRequestParameters); |
| + |
| + // Invoking the tested function. |
| + sendErrorReport(testError); |
| +}); |
| + |
| +TEST_F('GoogleNowUtilityUnitTest', 'SendErrorReport2', function() { |
| + // Test sending report for an error with a message that cannot be sent to |
|
robliao
2013/08/28 22:42:31
cannot --> should not
vadimt
2013/08/28 23:02:19
Done.
|
| + // server, with an error generated in an anonymous function. |
| + |
| + // Setup and expectations. |
| + var testStack = 'TypeError: Property \'processPendingDismissals\' of ' + |
| + 'object [object Object] is not a function\n ' + |
| + 'at chrome-extension://ext_id/background.js:444:11\n ' + |
| + 'at chrome-extension://ext_id/utility.js:509:7'; |
| + |
| + var testError = { |
| + stack: testStack, |
| + name: 'TypeError' |
| + }; |
| + |
| + this.makeAndRegisterMockGlobals(['buildServerRequest']); |
| + this.makeMockLocalFunctions(['sendRequest']); |
| + |
| + var mockRequest = {send: this.mockLocalFunctions.functions().sendRequest}; |
| + |
| + var expectedRequestParameters = 'error=TypeError&' + |
| + 'script=%2F%2Fext_id%2Fbackground.js&' + |
| + 'line=444&' + |
| + 'trace=(message%20removed)%0A%20%20%20%20' + |
| + 'at%20chrome-extension%3A%2F%2Fext_id%2Fbackground.js%3A444%3A11' + |
| + '%0A%20%20%20%20' + |
| + 'at%20chrome-extension%3A%2F%2Fext_id%2Futility.js%3A509%3A7'; |
| + |
| + this.mockGlobals.expects(once()). |
| + buildServerRequest('jserror', 'application/x-www-form-urlencoded'). |
| + will(returnValue(mockRequest)); |
| + this.mockLocalFunctions.expects(once()).sendRequest( |
| + expectedRequestParameters); |
| + |
| + // Invoking the tested function. |
| + sendErrorReport(testError); |
| +}); |
| + |
| +TEST_F('GoogleNowUtilityUnitTest', 'WrapperCheckInWrappedCallback', function() { |
| + // Test generating an error when calling wrapper.checkInWrappedCallback from a |
| + // non-instrumented code. |
| + |
| + // Setup and expectations. |
| + var testError = { |
| + testField: 'TEST VALUE' |
| + }; |
| + |
| + this.makeAndRegisterMockGlobals([ |
| + 'buildErrorWithMessageForServer', |
| + 'reportError' |
| + ]); |
| + |
| + this.mockGlobals.expects(once()). |
| + buildErrorWithMessageForServer('Not in instrumented callback'). |
| + will(returnValue(testError)); |
| + this.mockGlobals.expects(once()). |
| + reportError(eqJSON(testError)); |
| + |
| + // Invoking the tested function. |
| + wrapper.checkInWrappedCallback(); |
| +}); |
| + |
| +TEST_F('GoogleNowUtilityUnitTest', 'WrapperWrapCallbackEvent', function() { |
| + // Tests wrapping event handler and that the handler code counts as an |
| + // instrumented callback. |
| + |
| + // Setup. |
| + var testError = { |
| + testField: 'TEST VALUE' |
| + }; |
| + |
| + this.makeAndRegisterMockGlobals([ |
| + 'buildErrorWithMessageForServer', |
| + 'reportError' |
| + ]); |
| + var onSuspendHandlerContainer = getMockHandlerContainer('runtime.onSuspend'); |
| + |
| + this.makeMockLocalFunctions(['callback']); |
| + |
| + // Step 1. Wrapping callback. |
| + var wrappedCallback = |
| + wrapper.wrapCallback(this.mockLocalFunctions.functions().callback, true); |
| + Mock4JS.verifyAllMocks(); |
| + |
| + // Step 2. Invoking wrapped callback. |
| + // Expectations. |
|
robliao
2013/08/28 22:05:29
Incomplete comment? (and all others)
vadimt
2013/08/28 22:29:35
No, simply Step 2 is divided into Expectations and
robliao
2013/08/28 22:42:31
No other comments that I've seen thus far do this.
vadimt
2013/08/28 23:02:19
Done.
|
| + this.mockLocalFunctions.expects(once()). |
| + callback('test string', 239). |
| + will(callFunction(function() { |
| + wrapper.checkInWrappedCallback(); // it should succeed |
| + })); |
| + |
| + // Invoking tested function. |
|
robliao
2013/08/28 22:05:29
Spacing. (and all others)
vadimt
2013/08/28 22:29:35
See above.
|
| + wrappedCallback('test string', 239); |
| + Mock4JS.verifyAllMocks(); |
| + |
| + // Step 3. Checking that after the callback we are again in non-instrumented |
|
robliao
2013/08/28 22:05:29
Let's not enumerate the steps. At the point you ne
vadimt
2013/08/28 22:29:35
Numbering really helps to read the code.
You want
robliao
2013/08/28 22:42:31
Your choice, as this is test code.
All further in
vadimt
2013/08/28 23:02:19
I feel that the current way is the best :)
Thanks!
|
| + // code. |
| + // Expectations. |
| + this.mockGlobals.expects(once()). |
| + buildErrorWithMessageForServer('Not in instrumented callback'). |
| + will(returnValue(testError)); |
| + this.mockGlobals.expects(once()). |
| + reportError(eqJSON(testError)); |
| + |
| + // Invocation. |
| + wrapper.checkInWrappedCallback(); |
| + |
| + // Step 4. Check that there won't be errors whe the page unloads. |
| + assertTrue(onSuspendHandlerContainer.length == 1, |
| + 'onSuspendHandlerContainer.length must be 1'); |
| + onSuspendHandlerContainer[0](); |
| +}); |
| + |
| +TEST_F('GoogleNowUtilityUnitTest', 'WrapperWrapCallbackPlugin', function() { |
| + // Tests calling plugin's prologue and epilogue. |
| + |
| + // Setup. |
| + this.makeMockLocalFunctions([ |
| + 'callback', |
| + 'pluginFactory', |
| + 'prologue', |
| + 'epilogue' |
| + ]); |
| + |
| + // Step 1. Registering plugin factory. |
| + wrapper.registerWrapperPluginFactory( |
| + this.mockLocalFunctions.functions().pluginFactory); |
| + Mock4JS.verifyAllMocks(); |
| + |
| + // Step 2. Wrapping callback. |
| + // Expectations. |
| + this.mockLocalFunctions.expects(once()). |
| + pluginFactory(). |
| + will(returnValue({ |
| + prologue: this.mockLocalFunctions.functions().prologue, |
| + epilogue: this.mockLocalFunctions.functions().epilogue |
| + })); |
| + |
| + // Invoking tested function. |
| + var wrappedCallback = |
| + wrapper.wrapCallback(this.mockLocalFunctions.functions().callback, true); |
| + Mock4JS.verifyAllMocks(); |
| + |
| + // Step 3. Calling the wrapped callback. |
| + // Expectations. |
| + this.mockLocalFunctions.expects(once()).prologue(); |
| + this.mockLocalFunctions.expects(once()).callback(); |
| + this.mockLocalFunctions.expects(once()).epilogue(); |
| + |
| + // Invoking wrapped callback. |
| + wrappedCallback(); |
| +}); |
| + |
| +TEST_F('GoogleNowUtilityUnitTest', 'WrapperWrapCallbackCatchError', function() { |
| + // Tests catching and sending errors by a wrapped callback. |
| + |
| + // Setup. |
| + this.makeAndRegisterMockGlobals([ |
| + 'reportError' |
| + ]); |
| + this.makeMockLocalFunctions(['callback']); |
| + |
| + // Step 1. Wrapping callback. |
| + var wrappedCallback = |
| + wrapper.wrapCallback(this.mockLocalFunctions.functions().callback, true); |
| + Mock4JS.verifyAllMocks(); |
| + |
| + // Step 2. Invoking wrapped callback. |
| + // Expectations. |
| + this.mockLocalFunctions.expects(once()). |
| + callback(). |
| + will(callFunction(function() { |
| + undefined.x = 5; |
| + })); |
| + this.mockGlobals.expects(once()). |
| + reportError( |
| + eqToString('TypeError: Cannot set property \'x\' of undefined')); |
| + |
| + // Invoking tested function. |
| + wrappedCallback(); |
| +}); |
| + |
| +TEST_F('GoogleNowUtilityUnitTest', |
| + 'WrapperInstrumentChromeApiFunction', |
| + function() { |
| + // Tests wrapper.instrumentChromeApiFunction(). |
| + |
| + // Setup. |
| + this.makeMockLocalFunctions([ |
| + 'apiFunction1', |
| + 'apiFunction2', |
| + 'callback1', |
| + 'callback2', |
| + 'pluginFactory', |
| + 'prologue', |
| + 'epilogue' |
| + ]); |
| + chrome.testApi = { |
| + addListener: this.mockLocalFunctions.functions().apiFunction1 |
| + }; |
| + |
| + // Step 1. Instrumenting the listener. |
| + wrapper.instrumentChromeApiFunction('testApi.addListener', 1); |
| + Mock4JS.verifyAllMocks(); |
| + |
| + // Step 2. Invoking the instrumented API call. |
| + // Expectations. |
| + var function1SavedArgs = new SaveMockArguments(); |
| + this.mockLocalFunctions.expects(once()). |
| + apiFunction1( |
| + function1SavedArgs.match(eq(239)), |
| + function1SavedArgs.match(ANYTHING)); |
| + |
| + // Invocation. |
| + instrumented.testApi.addListener( |
| + 239, this.mockLocalFunctions.functions().callback1); |
| + Mock4JS.verifyAllMocks(); |
| + |
| + // Step 3. Invoking the callback that was passed by the instrumented function |
| + // to the original one. |
| + // Expectations. |
| + this.mockLocalFunctions.expects(once()).callback1(237); |
| + |
| + // Invocation. |
| + function1SavedArgs.arguments[1](237); |
| + Mock4JS.verifyAllMocks(); |
| + |
| + // Step 4. Register plugin factory. |
| + wrapper.registerWrapperPluginFactory( |
| + this.mockLocalFunctions.functions().pluginFactory); |
| + Mock4JS.verifyAllMocks(); |
| + |
| + // Step 5. Binding the API to another function. |
| + chrome.testApi.addListener = this.mockLocalFunctions.functions().apiFunction2; |
| + |
| + // Step 6. Invoking the API with another callback. |
| + // Expectations. |
| + this.mockLocalFunctions.expects(once()). |
| + pluginFactory(). |
| + will(returnValue({ |
| + prologue: this.mockLocalFunctions.functions().prologue, |
| + epilogue: this.mockLocalFunctions.functions().epilogue |
| + })); |
| + var function2SavedArgs = new SaveMockArguments(); |
| + this.mockLocalFunctions.expects(once()). |
| + apiFunction2( |
| + function2SavedArgs.match(eq(239)), |
| + function2SavedArgs.match(ANYTHING)); |
| + |
| + // Invocation. |
| + instrumented.testApi.addListener( |
| + 239, this.mockLocalFunctions.functions().callback2); |
| + Mock4JS.verifyAllMocks(); |
| + |
| + // Step 7. Invoking the callback that was passed by the instrumented function |
| + // to the original one. |
| + // Expectations. |
| + this.mockLocalFunctions.expects(once()).prologue(); |
| + this.mockLocalFunctions.expects(once()).callback2(237); |
| + this.mockLocalFunctions.expects(once()).epilogue(); |
| + |
| + // Invocation. |
| + function2SavedArgs.arguments[1](237); |
| +}); |
| + |
| +TEST_F('GoogleNowUtilityUnitTest', 'WrapperOnSuspendListenerFail', function() { |
| + // Tests that upon unloading event page, we get an error if there are pending |
| + // required callbacks. |
| + |
| + // Setup. |
| + var testError = { |
| + testField: 'TEST VALUE' |
| + }; |
| + this.makeAndRegisterMockGlobals([ |
| + 'buildErrorWithMessageForServer', |
| + 'reportError' |
| + ]); |
| + this.makeMockLocalFunctions(['listener', 'callback']); |
| + var onSuspendHandlerContainer = getMockHandlerContainer('runtime.onSuspend'); |
| + |
| + // Step 1. Wrapping event listener. |
| + var wrappedListener = |
| + wrapper.wrapCallback(this.mockLocalFunctions.functions().listener, true); |
| + Mock4JS.verifyAllMocks(); |
| + |
| + // Step 2. Invoking event listener, which will wrap a required callback. |
| + // Setup and expectations. |
| + var wrappedCallback; |
| + var testFixture = this; |
| + this.mockLocalFunctions.expects(once()). |
| + listener(). |
| + will(callFunction(function() { |
| + wrappedCallback = wrapper.wrapCallback( |
| + testFixture.mockLocalFunctions.functions().callback); |
| + })); |
| + |
| + // Invocation. |
| + wrappedListener(); |
| + Mock4JS.verifyAllMocks(); |
| + |
| + // Step 3. Firing runtime.onSuspend event. |
| + // Expectations. |
| + this.mockGlobals.expects(once()). |
| + buildErrorWithMessageForServer(stringContains( |
| + 'ASSERT: Pending callbacks when unloading event page')). |
| + will(returnValue(testError)); |
| + this.mockGlobals.expects(once()). |
| + reportError(eqJSON(testError)); |
| + |
| + // Invocation. |
| + assertTrue(onSuspendHandlerContainer.length == 1, |
| + 'onSuspendHandlerContainer.length must be 1'); |
| + onSuspendHandlerContainer[0](); |
| +}); |
| + |
| +TEST_F('GoogleNowUtilityUnitTest', |
| + 'WrapperOnSuspendListenerSuccess', |
| + function() { |
| + // Tests that upon unloading event page, we don't get an error if there are no |
| + // pending required callbacks. |
| + |
| + // Setup. |
| + this.makeMockLocalFunctions(['listener', 'callback']); |
| + var onSuspendHandlerContainer = getMockHandlerContainer('runtime.onSuspend'); |
| + |
| + // Step 1. Wrapping event listener. |
| + var wrappedListener = |
| + wrapper.wrapCallback(this.mockLocalFunctions.functions().listener, true); |
| + Mock4JS.verifyAllMocks(); |
| + |
| + // Step 2. Invoking event listener, which will wrap a required callback. |
| + // Setup and expectations. |
| + var wrappedCallback; |
| + var testFixture = this; |
| + this.mockLocalFunctions.expects(once()). |
| + listener(). |
| + will(callFunction(function() { |
| + wrappedCallback = wrapper.wrapCallback( |
| + testFixture.mockLocalFunctions.functions().callback); |
| + })); |
| + |
| + // Invocation. |
| + wrappedListener(); |
| + Mock4JS.verifyAllMocks(); |
| + |
| + // Step 3. Calling wrapped callback. |
| + // Expectations. |
| + this.mockLocalFunctions.expects(once()).callback(); |
| + |
| + // Invocation. |
| + wrappedCallback(); |
| + |
| + // Step 4. Firing runtime.onSuspend event. |
| + assertTrue(onSuspendHandlerContainer.length == 1, |
| + 'onSuspendHandlerContainer.length must be 1'); |
| + onSuspendHandlerContainer[0](); |
| +}); |