// 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. // TODO(robliao,vadimt): Determine the granularity of testing to perform. /** * Test fixture for background.js. * @constructor * @extends {testing.Test} */ function GoogleNowBackgroundUnitTest () { testing.Test.call(this); } GoogleNowBackgroundUnitTest.prototype = { __proto__: testing.Test.prototype, /** @override */ extraLibraries: [ 'common_test_util.js', 'background_test_util.js', 'background.js' ] }; TEST_F('GoogleNowBackgroundUnitTest', 'AreTasksConflicting', function() { function testTaskPair(newTaskName, scheduledTaskName, expected) { assertTrue(areTasksConflicting(newTaskName, scheduledTaskName) == expected, '(' + newTaskName + ', ' + scheduledTaskName + ')'); } testTaskPair(UPDATE_CARDS_TASK_NAME, UPDATE_CARDS_TASK_NAME, true); testTaskPair(UPDATE_CARDS_TASK_NAME, DISMISS_CARD_TASK_NAME, false); testTaskPair(UPDATE_CARDS_TASK_NAME, RETRY_DISMISS_TASK_NAME, false); testTaskPair(UPDATE_CARDS_TASK_NAME, STATE_CHANGED_TASK_NAME, false); testTaskPair(DISMISS_CARD_TASK_NAME, UPDATE_CARDS_TASK_NAME, false); testTaskPair(DISMISS_CARD_TASK_NAME, DISMISS_CARD_TASK_NAME, false); testTaskPair(DISMISS_CARD_TASK_NAME, RETRY_DISMISS_TASK_NAME, false); testTaskPair(DISMISS_CARD_TASK_NAME, STATE_CHANGED_TASK_NAME, false); testTaskPair(RETRY_DISMISS_TASK_NAME, UPDATE_CARDS_TASK_NAME, true); testTaskPair(RETRY_DISMISS_TASK_NAME, DISMISS_CARD_TASK_NAME, true); testTaskPair(RETRY_DISMISS_TASK_NAME, RETRY_DISMISS_TASK_NAME, true); testTaskPair(RETRY_DISMISS_TASK_NAME, STATE_CHANGED_TASK_NAME, false); testTaskPair(STATE_CHANGED_TASK_NAME, UPDATE_CARDS_TASK_NAME, false); testTaskPair(STATE_CHANGED_TASK_NAME, DISMISS_CARD_TASK_NAME, false); testTaskPair(STATE_CHANGED_TASK_NAME, RETRY_DISMISS_TASK_NAME, false); testTaskPair(STATE_CHANGED_TASK_NAME, STATE_CHANGED_TASK_NAME, false); }); /** * Mocks global functions and APIs that initialize() depends upon. * @param {Test} fixture Test fixture. */ function mockInitializeDependencies(fixture) { fixture.makeAndRegisterMockGlobals([ 'recordEvent', 'setBackgroundEnable', 'startPollingCards' ]); fixture.makeAndRegisterMockApis([ 'authenticationManager.isSignedIn', 'chrome.location.clearWatch', 'chrome.storage.local.remove', 'instrumented.metricsPrivate.getVariationParams', 'instrumented.notifications.getAll', 'instrumented.notifications.getPermissionLevel', 'instrumented.preferencesPrivate.googleGeolocationAccessEnabled.get', 'instrumented.storage.local.get', 'tasks.add', 'updateCardsAttempts.isRunning', 'updateCardsAttempts.stop' ]); } /** * Sets up the test to expect the state machine calls and send * the specified state machine state. Currently used to test initialize(). * Note that this CAN NOT be used if any of the methods below are called * outside of this context with the same argument matchers. * expects() calls cannot be chained with the same argument matchers. * @param {object} fixture Test fixture. * @param {string} testIdentityToken getAuthToken callback token. * @param {boolean} testGeolocationPref Geolocation Preference callback value. * @param {object} testExperimentVariationParams Response of * metricsPrivate.getVariationParams. * @param {string} testExperimentVariationParams Response of * notifications.getPermissionLevel. * @param {boolean} testGoogleNowEnabled True if the user is opted in to Google * Now. */ function expectStateMachineCalls( fixture, testIdentityToken, testGeolocationPref, testExperimentVariationParams, testNotificationPermissionLevel, testGoogleNowEnabled) { var authenticationManagerIsSignedInSavedArgs = new SaveMockArguments(); fixture.mockApis.expects(once()). authenticationManager_isSignedIn( authenticationManagerIsSignedInSavedArgs.match(ANYTHING)). will(invokeCallback( authenticationManagerIsSignedInSavedArgs, 0, testIdentityToken)); var getVariationParamsSavedArgs = new SaveMockArguments(); fixture.mockApis.expects(once()). instrumented_metricsPrivate_getVariationParams( getVariationParamsSavedArgs.match(ANYTHING), getVariationParamsSavedArgs.match(ANYTHING)). will(invokeCallback( getVariationParamsSavedArgs, 1, testExperimentVariationParams)); var googleGeolocationPrefGetSavedArgs = new SaveMockArguments(); fixture.mockApis.expects(once()). instrumented_preferencesPrivate_googleGeolocationAccessEnabled_get( googleGeolocationPrefGetSavedArgs.match(eqJSON({})), googleGeolocationPrefGetSavedArgs.match(ANYTHING)). will(invokeCallback( googleGeolocationPrefGetSavedArgs, 1, {value: testGeolocationPref})); var notificationGetPermissionLevelSavedArgs = new SaveMockArguments(); fixture.mockApis.expects(once()). instrumented_notifications_getPermissionLevel( notificationGetPermissionLevelSavedArgs.match(ANYTHING)). will(invokeCallback( notificationGetPermissionLevelSavedArgs, 0, testNotificationPermissionLevel)) var storageGetSavedArgs = new SaveMockArguments(); fixture.mockApis.expects(once()). instrumented_storage_local_get( storageGetSavedArgs.match(eq('googleNowEnabled')), storageGetSavedArgs.match(ANYTHING)). will(invokeCallback( storageGetSavedArgs, 1, {googleNowEnabled: testGoogleNowEnabled})); fixture.mockGlobals.expects(once()). setBackgroundEnable(ANYTHING); } /** * Sets up the test to expect the initialization calls that * initialize() invokes. * Note that this CAN NOT be used if any of the methods below are called * outside of this context with the same argument matchers. * expects() calls cannot be chained with the same argument matchers. */ function expectInitialization(mockApisObj) { var tasksAddSavedArgs = new SaveMockArguments(); mockApisObj.expects(once()). tasks_add( tasksAddSavedArgs.match(ANYTHING), tasksAddSavedArgs.match(ANYTHING)). will(invokeCallback(tasksAddSavedArgs, 1, function() {})); var updateCardsAttemptsIsRunningSavedArgs = new SaveMockArguments(); mockApisObj.expects(once()). updateCardsAttempts_isRunning( updateCardsAttemptsIsRunningSavedArgs.match(ANYTHING)). will( invokeCallback( updateCardsAttemptsIsRunningSavedArgs, 0, false)); } TEST_F( 'GoogleNowBackgroundUnitTest', 'Initialize_ToastStateEmpty', function() { // Tests the case when getAuthToken fails most likely because the user is // not signed in. In this case, the function should quietly exit after // finding out that getAuthToken fails. // Setup and expectations. var testIdentityToken = undefined; var testGeolocationPref = false; var testExperimentVariationParams = {}; var testNotificationPermissionLevel = 'denied'; var testGoogleNowEnabled = undefined; mockInitializeDependencies(this); this.mockGlobals.expects(once()).recordEvent( GoogleNowEvent.EXTENSION_START); this.mockGlobals.expects(once()).recordEvent( GoogleNowEvent.STOPPED); expectInitialization(this.mockApis); expectStateMachineCalls( this, testIdentityToken, testGeolocationPref, testExperimentVariationParams, testNotificationPermissionLevel, testGoogleNowEnabled); // Invoking the tested function. initialize(); }); TEST_F( 'GoogleNowBackgroundUnitTest', 'DISABLED_Initialize_ToastStateEmpty2', function() { // Tests the case when getAuthToken succeeds, and the user has never // responded to the toast. // In this case, the function should invoke showWelcomeToast(). // Setup and expectations. var testIdentityToken = 'some identity token'; var testGeolocationPref = false; var testExperimentVariationParams = {}; var testNotificationPermissionLevel = 'denied'; var testGoogleNowEnabled = undefined; mockInitializeDependencies(this); this.mockGlobals.expects(once()).recordEvent( GoogleNowEvent.EXTENSION_START); expectInitialization(this.mockApis); expectStateMachineCalls( this, testIdentityToken, testGeolocationPref, testExperimentVariationParams, testNotificationPermissionLevel, testGoogleNowEnabled); var chromeNotificationGetAllSavedArgs = new SaveMockArguments(); this.mockApis.expects(exactly(1)). instrumented_notifications_getAll( chromeNotificationGetAllSavedArgs.match(ANYTHING)). will( invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}), invokeCallback(chromeNotificationGetAllSavedArgs, 0, {})); // Invoking the tested function. initialize(); }); TEST_F('GoogleNowBackgroundUnitTest', 'Initialize_RunGoogleNow', function() { // Tests if Google Now will invoke startPollingCards when all // of the required state is fulfilled. // Setup and expectations. var testIdentityToken = 'some identity token'; var testGeolocationPref = true; var testExperimentVariationParams = {}; var testNotificationPermissionLevel = 'granted'; var testGoogleNowEnabled = true; mockInitializeDependencies(this); this.mockGlobals.expects(once()).recordEvent( GoogleNowEvent.EXTENSION_START); expectInitialization(this.mockApis); expectStateMachineCalls( this, testIdentityToken, testGeolocationPref, testExperimentVariationParams, testNotificationPermissionLevel, testGoogleNowEnabled); this.mockGlobals.expects(once()).startPollingCards(); // Invoking the tested function. initialize(); }); TEST_F( 'GoogleNowBackgroundUnitTest', 'DISABLED_Initialize_NoGeolocation', function() { // Tests the case where everything is in place except for the // Geolocation Preference after the user responded to the toast. // Setup and expectations. var testIdentityToken = 'some identity token'; var testGeolocationPref = false; var testExperimentVariationParams = {}; var testNotificationPermissionLevel = 'denied'; var testGoogleNowEnabled = undefined; mockInitializeDependencies(this); this.mockGlobals.expects(once()).recordEvent( GoogleNowEvent.EXTENSION_START); this.mockGlobals.expects(once()).recordEvent( GoogleNowEvent.USER_SUPPRESSED); expectInitialization(this.mockApis); expectStateMachineCalls( this, testIdentityToken, testGeolocationPref, testExperimentVariationParams, testNotificationPermissionLevel, testNotificationPermissionLevel, testGoogleNowEnabled); var chromeNotificationGetAllSavedArgs = new SaveMockArguments(); this.mockApis.expects(exactly(2)). instrumented_notifications_getAll( chromeNotificationGetAllSavedArgs.match(ANYTHING)). will( invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}), invokeCallback(chromeNotificationGetAllSavedArgs, 0, {})); // Invoking the tested function. initialize(); }); /** * Mocks global functions and APIs that onNotificationClicked() depends upon. * @param {Test} fixture Test fixture. */ function mockOnNotificationClickedDependencies(fixture) { fixture.makeAndRegisterMockApis([ 'chrome.windows.create', 'chrome.windows.update', 'instrumented.storage.local.get', 'instrumented.tabs.create']); } TEST_F( 'GoogleNowBackgroundUnitTest', 'OnNotificationClicked_NoData', function() { // Tests the case when there is no data associated with notification id. // In this case, the function should do nothing. // Setup and expectations. var testNotificationId = 'TEST_ID'; var testNotificationData = {}; mockOnNotificationClickedDependencies(this); this.makeMockLocalFunctions(['selector']); var storageGetSavedArgs = new SaveMockArguments(); this.mockApis.expects(once()). instrumented_storage_local_get( storageGetSavedArgs.match(eq('notificationsData')), storageGetSavedArgs.match(ANYTHING)). will(invokeCallback(storageGetSavedArgs, 1, testNotificationData)); // Invoking the tested function. onNotificationClicked( testNotificationId, this.mockLocalFunctions.functions().selector); }); TEST_F( 'GoogleNowBackgroundUnitTest', 'OnNotificationClicked_ActionUrlsUndefined', function() { // Tests the case when the data associated with notification id is // 'undefined'. // In this case, the function should do nothing. // Setup and expectations. var testActionUrls = undefined; var testNotificationId = 'TEST_ID'; var testNotificationData = { notificationsData: {'TEST_ID': {actionUrls: testActionUrls}} }; mockOnNotificationClickedDependencies(this); this.makeMockLocalFunctions(['selector']); var storageGetSavedArgs = new SaveMockArguments(); this.mockApis.expects(once()). instrumented_storage_local_get( storageGetSavedArgs.match(eq('notificationsData')), storageGetSavedArgs.match(ANYTHING)). will(invokeCallback(storageGetSavedArgs, 1, testNotificationData)); this.mockLocalFunctions.expects(once()).selector(undefined).will( returnValue(undefined)); // Invoking the tested function. onNotificationClicked( testNotificationId, this.mockLocalFunctions.functions().selector); }); TEST_F( 'GoogleNowBackgroundUnitTest', 'OnNotificationClicked_TabCreateSuccess', function() { // Tests the selected URL is OK and crome.tabs.create suceeds. // Setup and expectations. var testActionUrls = {testField: 'TEST VALUE'}; var testNotificationId = 'TEST_ID'; var testNotificationData = { notificationsData: {'TEST_ID': {actionUrls: testActionUrls}} }; var testActionUrl = 'http://testurl.com'; var testCreatedTab = {windowId: 239}; mockOnNotificationClickedDependencies(this); this.makeMockLocalFunctions(['selector']); var storageGetSavedArgs = new SaveMockArguments(); this.mockApis.expects(once()). instrumented_storage_local_get( storageGetSavedArgs.match(eq('notificationsData')), storageGetSavedArgs.match(ANYTHING)). will(invokeCallback(storageGetSavedArgs, 1, testNotificationData)); this.mockLocalFunctions.expects(once()).selector(testActionUrls).will( returnValue(testActionUrl)); var chromeTabsCreateSavedArgs = new SaveMockArguments(); this.mockApis.expects(once()). instrumented_tabs_create( chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})), chromeTabsCreateSavedArgs.match(ANYTHING)). will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab)); this.mockApis.expects(once()).chrome_windows_update( testCreatedTab.windowId, eqJSON({focused: true})); // Invoking the tested function. onNotificationClicked( testNotificationId, this.mockLocalFunctions.functions().selector); }); TEST_F( 'GoogleNowBackgroundUnitTest', 'OnNotificationClicked_TabCreateFail', function() { // Tests the selected URL is OK and crome.tabs.create fails. // In this case, the function should invoke chrome.windows.create as a // second attempt. // Setup and expectations. var testActionUrls = {testField: 'TEST VALUE'}; var testNotificationId = 'TEST_ID'; var testNotificationData = { notificationsData: {'TEST_ID': {actionUrls: testActionUrls}} }; var testActionUrl = 'http://testurl.com'; var testCreatedTab = undefined; // chrome.tabs.create fails mockOnNotificationClickedDependencies(this); this.makeMockLocalFunctions(['selector']); var storageGetSavedArgs = new SaveMockArguments(); this.mockApis.expects(once()). instrumented_storage_local_get( storageGetSavedArgs.match(eq('notificationsData')), storageGetSavedArgs.match(ANYTHING)). will(invokeCallback(storageGetSavedArgs, 1, testNotificationData)); this.mockLocalFunctions.expects(once()).selector(testActionUrls).will( returnValue(testActionUrl)); var chromeTabsCreateSavedArgs = new SaveMockArguments(); this.mockApis.expects(once()). instrumented_tabs_create( chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})), chromeTabsCreateSavedArgs.match(ANYTHING)). will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab)); this.mockApis.expects(once()).chrome_windows_create( eqJSON({url: testActionUrl, focused: true})); // Invoking the tested function. onNotificationClicked( testNotificationId, this.mockLocalFunctions.functions().selector); }); TEST_F( 'GoogleNowBackgroundUnitTest', 'ShowNotificationCards', function() { // Tests showNotificationCards function. Checks that the function properly // deletes the card that didn't get an update, updates existing card and // creates a new card that previously didn't exist. // Setup and expectations. var existingNotifications = { 'SHOULD BE DELETED': 'SOMETHING', 'SHOULD BE KEPT': 'SOMETHING' }; var notificationGroups = { TEST_FIELD: 'TEST VALUE' }; var cards = { 'SHOULD BE KEPT': [1], 'NEW CARD': [2] }; var fakeOnCardShownFunction = 'FAKE ON CARD SHOWN FUNCTION'; var expectedUpdatedNotifications = { 'SHOULD BE KEPT': 'KEPT CARD NOTIFICATION DATA', 'NEW CARD': 'NEW CARD NOTIFICATION DATA' }; this.makeAndRegisterMockApis([ 'cardSet.update', 'chrome.storage.local.set', 'instrumented.notifications.getAll' ]); this.makeMockLocalFunctions([ 'onSuccess' ]); var notificationsGetAllSavedArgs = new SaveMockArguments(); this.mockApis.expects(once()). instrumented_notifications_getAll( notificationsGetAllSavedArgs.match(ANYTHING)). will(invokeCallback( notificationsGetAllSavedArgs, 0, existingNotifications)); this.mockApis.expects(once()). cardSet_update( 'SHOULD BE KEPT', [1], eqJSON(notificationGroups), fakeOnCardShownFunction). will(returnValue('KEPT CARD NOTIFICATION DATA')); this.mockApis.expects(once()). cardSet_update( 'NEW CARD', [2], eqJSON(notificationGroups), fakeOnCardShownFunction). will(returnValue('NEW CARD NOTIFICATION DATA')); this.mockApis.expects(once()). cardSet_update( 'SHOULD BE DELETED', [], eqJSON(notificationGroups), fakeOnCardShownFunction). will(returnValue(undefined)); this.mockApis.expects(once()). chrome_storage_local_set( eqJSON({notificationsData: expectedUpdatedNotifications})); this.mockLocalFunctions.expects(once()). onSuccess(); // Invoking the tested function. showNotificationCards( notificationGroups, cards, this.mockLocalFunctions.functions().onSuccess, fakeOnCardShownFunction); }); TEST_F( 'GoogleNowBackgroundUnitTest', 'CombineGroup', function() { // Tests combineGroup function. Verifies that both notifications with and // without show time are handled correctly and that cards are correctly // added to existing cards with same ID or start a new combined card. // Setup and expectations. var combinedCards = { 'EXISTING CARD': [1] }; var receivedNotificationNoShowTime = { chromeNotificationId: 'EXISTING CARD', trigger: {hideTimeSec: 1} }; var receivedNotificationWithShowTime = { chromeNotificationId: 'NEW CARD', trigger: {showTimeSec: 2, hideTimeSec: 3} } var storedGroup = { cardsTimestamp: 10000, cards: [ receivedNotificationNoShowTime, receivedNotificationWithShowTime ] }; // Invoking the tested function. combineGroup(combinedCards, storedGroup); // Check the output value. var expectedCombinedCards = { 'EXISTING CARD': [ 1, { receivedNotification: receivedNotificationNoShowTime, hideTime: 11000 } ], 'NEW CARD': [ { receivedNotification: receivedNotificationWithShowTime, showTime: 12000, hideTime: 13000 } ] }; assertEquals( JSON.stringify(expectedCombinedCards), JSON.stringify(combinedCards)); }); TEST_F( 'GoogleNowBackgroundUnitTest', 'CombineAndShowNotificationCards', function() { // Tests combineAndShowNotificationCards function. // The test passes 2 groups to combineAndShowNotificationCards, checks // that it calls combineGroup() for each of these groups and calls // showNotificationCards() with the results of these combineGroup() calls. // Setup and expectations. var testGroups = { 'TEST GROUP 1': {testField: 'TEST VALUE 1'}, 'TEST GROUP 2': {testField: 'TEST VALUE 2'} }; var fakeOnSuccessFunction = 'FAKE ON SUCCESS FUNCTION'; var fakeOnCardShownFunction = 'FAKE ON CARD SHOWN FUNCTION'; this.makeAndRegisterMockGlobals( ['combineGroup', 'showNotificationCards']); var combineGroupSavedArgs = new SaveMockArguments(); this.mockGlobals.expects(once()). combineGroup( combineGroupSavedArgs.match(eqJSON({})), combineGroupSavedArgs.match(eqJSON({testField: 'TEST VALUE 1'}))). will(callFunction(function() { combineGroupSavedArgs.arguments[0].card1 = { testValue: 'TEST CARD VALUE 1' }; })); this.mockGlobals.expects(once()). combineGroup( combineGroupSavedArgs.match( eqJSON({card1: {testValue: 'TEST CARD VALUE 1'}})), combineGroupSavedArgs.match( eqJSON({testField: 'TEST VALUE 2'}))). will(callFunction(function() { combineGroupSavedArgs.arguments[0].card2 = { testValue: 'TEST CARD VALUE 2' }; })); this.mockGlobals.expects(once()). showNotificationCards( eqJSON(testGroups), eqJSON({ card1: {testValue: 'TEST CARD VALUE 1'}, card2: {testValue: 'TEST CARD VALUE 2'} }), fakeOnSuccessFunction, fakeOnCardShownFunction); // Invoking the tested function. combineAndShowNotificationCards( testGroups, fakeOnSuccessFunction, fakeOnCardShownFunction); }); TEST_F( 'GoogleNowBackgroundUnitTest', 'ProcessServerResponse', function() { // Tests processServerResponse function. // Setup and expectations. Date.now = function() { return 3000000; }; // GROUP1 was requested and contains cards c4 and c5. For c5, there is a // non-expired dismissal, so it will be ignored. // GROUP2 was not requested, but is contained in server response to // indicate that the group still exists. Stored group GROUP2 won't change. // GROUP3 is stored, but is not present in server's response, which means // it doesn't exist anymore. This group will be deleted. // GROUP4 doesn't contain cards, but it was requested. This is treated as // if it had an empty array of cards. Cards in the stored group will be // replaced with an empty array. // GROUP5 doesn't have next poll time, and it will be stored without next // poll time. var serverResponse = { groups: { GROUP1: {requested: true, nextPollSeconds: 46}, GROUP2: {requested: false}, GROUP4: {requested: true, nextPollSeconds: 45}, GROUP5: {requested: true} }, notifications: [ {notificationId: 'c4', groupName: 'GROUP1'}, {notificationId: 'c5', groupName: 'GROUP1'} ] }; var recentDismissals = { c4: 1800000, // expired dismissal c5: 1800001 // non-expired dismissal }; var storedGroups = { GROUP2: { cards: [{notificationId: 'c2'}], cardsTimestamp: 239, nextPollTime: 10000 }, GROUP3: { cards: [{notificationId: 'c3'}], cardsTimestamp: 240, nextPollTime: 10001 }, GROUP4: { cards: [{notificationId: 'c6'}], cardsTimestamp: 241, nextPollTime: 10002 } }; var expectedUpdatedGroups = { GROUP1: { cards: [{notificationId: 'c4', groupName: 'GROUP1'}], cardsTimestamp: 3000000, nextPollTime: 3046000 }, GROUP2: { cards: [{notificationId: 'c2'}], cardsTimestamp: 239, nextPollTime: 10000 }, GROUP4: { cards: [], cardsTimestamp: 3000000, nextPollTime: 3045000 }, GROUP5: { cards: [], cardsTimestamp: 3000000 } }; var expectedUpdatedRecentDismissals = { c5: 1800001 }; var fakeOnCardShownFunction = 'FAKE ON CARD SHOWN FUNCTION'; this.makeAndRegisterMockGlobals([ 'scheduleNextPoll', 'combineAndShowNotificationCards', 'recordEvent' ]); this.makeAndRegisterMockApis([ 'chrome.storage.local.set', 'instrumented.storage.local.get' ]); var storageGetSavedArgs = new SaveMockArguments(); this.mockApis.expects(once()). instrumented_storage_local_get( storageGetSavedArgs.match( eq(['notificationGroups', 'recentDismissals'])), storageGetSavedArgs.match(ANYTHING)). will(invokeCallback( storageGetSavedArgs, 1, { notificationGroups: storedGroups, recentDismissals: recentDismissals })); this.mockGlobals.expects(once()). scheduleNextPoll(eqJSON(expectedUpdatedGroups), true); var combineAndShowNotificationCardsSavedArgs = new SaveMockArguments(); this.mockGlobals.expects(once()). combineAndShowNotificationCards( combineAndShowNotificationCardsSavedArgs.match( eqJSON(expectedUpdatedGroups)), combineAndShowNotificationCardsSavedArgs.match( ANYTHING), combineAndShowNotificationCardsSavedArgs.match( eq(fakeOnCardShownFunction))). will(invokeCallback(combineAndShowNotificationCardsSavedArgs, 1)); this.mockApis.expects(once()). chrome_storage_local_set( eqJSON({ notificationGroups: expectedUpdatedGroups, recentDismissals: expectedUpdatedRecentDismissals})); this.mockGlobals.expects(once()). recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS); // Invoking the tested function. processServerResponse(serverResponse, fakeOnCardShownFunction); }); TEST_F( 'GoogleNowBackgroundUnitTest', 'ProcessServerResponseGoogleNowDisabled', function() { // Tests processServerResponse function for the case when the response // indicates that Google Now is disabled. // Setup and expectations. var serverResponse = { googleNowDisabled: true, groups: { GROUP1: {nextPollTimeSeconds: 200} } }; var storedGroups = { GROUP2: { cards: [{notificationId: 'c2'}], cardsTimestamp: 239, nextPollTime: 10000 }, GROUP3: { cards: [{notificationId: 'c3'}], cardsTimestamp: 240, nextPollTime: 10001 } }; var expectedUpdatedGroups = { }; var fakeOnCardShownFunction = 'FAKE ON CARD SHOWN FUNCTION'; this.makeAndRegisterMockGlobals([ 'scheduleNextPoll', 'combineAndShowNotificationCards', 'recordEvent', 'onStateChange' ]); this.makeAndRegisterMockApis([ 'chrome.storage.local.set', 'instrumented.storage.local.get' ]); this.mockApis.expects(once()). chrome_storage_local_set( eqJSON({googleNowEnabled: false})); this.mockGlobals.expects(once()).onStateChange(); var storageGetSavedArgs = new SaveMockArguments(); this.mockApis.expects(once()). instrumented_storage_local_get( storageGetSavedArgs.match( eq(['notificationGroups', 'recentDismissals'])), storageGetSavedArgs.match(ANYTHING)). will(invokeCallback( storageGetSavedArgs, 1, {notificationGroups: storedGroups})); this.mockGlobals.expects(once()). scheduleNextPoll(eqJSON(expectedUpdatedGroups), false); var combineAndShowNotificationCardsSavedArgs = new SaveMockArguments(); this.mockGlobals.expects(once()). combineAndShowNotificationCards( combineAndShowNotificationCardsSavedArgs.match( eqJSON(expectedUpdatedGroups)), combineAndShowNotificationCardsSavedArgs.match( ANYTHING), combineAndShowNotificationCardsSavedArgs.match( eq(fakeOnCardShownFunction))). will(invokeCallback(combineAndShowNotificationCardsSavedArgs, 1)); this.mockApis.expects(once()). chrome_storage_local_set( eqJSON({ notificationGroups: expectedUpdatedGroups, recentDismissals: {}})); this.mockGlobals.expects(once()). recordEvent(GoogleNowEvent.CARDS_PARSE_SUCCESS); // Invoking the tested function. processServerResponse(serverResponse, fakeOnCardShownFunction); });