Home | History | Annotate | Download | only in google_now
      1 // Copyright 2013 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.
      4 
      5 // TODO(robliao,vadimt): Determine the granularity of testing to perform.
      6 
      7 /**
      8  * Test fixture for background.js.
      9  * @constructor
     10  * @extends {testing.Test}
     11  */
     12 function GoogleNowBackgroundUnitTest () {
     13   testing.Test.call(this);
     14 }
     15 
     16 GoogleNowBackgroundUnitTest.prototype = {
     17   __proto__: testing.Test.prototype,
     18 
     19   /** @override */
     20   extraLibraries: [
     21     'common_test_util.js',
     22     'background_test_util.js',
     23     'background.js'
     24   ]
     25 };
     26 
     27 TEST_F('GoogleNowBackgroundUnitTest', 'AreTasksConflicting', function() {
     28   function testTaskPair(newTaskName, scheduledTaskName, expected) {
     29     assertTrue(areTasksConflicting(newTaskName, scheduledTaskName) == expected,
     30                '(' + newTaskName + ', ' + scheduledTaskName + ')');
     31   }
     32 
     33   testTaskPair(UPDATE_CARDS_TASK_NAME, UPDATE_CARDS_TASK_NAME, true);
     34   testTaskPair(UPDATE_CARDS_TASK_NAME, DISMISS_CARD_TASK_NAME, false);
     35   testTaskPair(UPDATE_CARDS_TASK_NAME, RETRY_DISMISS_TASK_NAME, false);
     36   testTaskPair(UPDATE_CARDS_TASK_NAME, STATE_CHANGED_TASK_NAME, false);
     37 
     38   testTaskPair(DISMISS_CARD_TASK_NAME, UPDATE_CARDS_TASK_NAME, false);
     39   testTaskPair(DISMISS_CARD_TASK_NAME, DISMISS_CARD_TASK_NAME, false);
     40   testTaskPair(DISMISS_CARD_TASK_NAME, RETRY_DISMISS_TASK_NAME, false);
     41   testTaskPair(DISMISS_CARD_TASK_NAME, STATE_CHANGED_TASK_NAME, false);
     42 
     43   testTaskPair(RETRY_DISMISS_TASK_NAME, UPDATE_CARDS_TASK_NAME, true);
     44   testTaskPair(RETRY_DISMISS_TASK_NAME, DISMISS_CARD_TASK_NAME, true);
     45   testTaskPair(RETRY_DISMISS_TASK_NAME, RETRY_DISMISS_TASK_NAME, true);
     46   testTaskPair(RETRY_DISMISS_TASK_NAME, STATE_CHANGED_TASK_NAME, false);
     47 
     48   testTaskPair(STATE_CHANGED_TASK_NAME, UPDATE_CARDS_TASK_NAME, false);
     49   testTaskPair(STATE_CHANGED_TASK_NAME, DISMISS_CARD_TASK_NAME, false);
     50   testTaskPair(STATE_CHANGED_TASK_NAME, RETRY_DISMISS_TASK_NAME, false);
     51   testTaskPair(STATE_CHANGED_TASK_NAME, STATE_CHANGED_TASK_NAME, false);
     52 });
     53 
     54 /**
     55  * Mocks global functions and APIs that initialize() depends upon.
     56  * @param {Test} fixture Test fixture.
     57  */
     58 function mockInitializeDependencies(fixture) {
     59   fixture.makeAndRegisterMockGlobals([
     60     'recordEvent',
     61     'setBackgroundEnable',
     62     'startPollingCards'
     63   ]);
     64   fixture.makeAndRegisterMockApis([
     65     'authenticationManager.isSignedIn',
     66     'chrome.location.clearWatch',
     67     'chrome.storage.local.remove',
     68     'instrumented.metricsPrivate.getVariationParams',
     69     'instrumented.notifications.getAll',
     70     'instrumented.notifications.getPermissionLevel',
     71     'instrumented.preferencesPrivate.googleGeolocationAccessEnabled.get',
     72     'instrumented.storage.local.get',
     73     'tasks.add',
     74     'updateCardsAttempts.isRunning',
     75     'updateCardsAttempts.stop'
     76   ]);
     77 }
     78 
     79 /**
     80  * Sets up the test to expect the state machine calls and send
     81  * the specified state machine state. Currently used to test initialize().
     82  * Note that this CAN NOT be used if any of the methods below are called
     83  * outside of this context with the same argument matchers.
     84  * expects() calls cannot be chained with the same argument matchers.
     85  * @param {object} fixture Test fixture.
     86  * @param {string} testIdentityToken getAuthToken callback token.
     87  * @param {boolean} testGeolocationPref Geolocation Preference callback value.
     88  * @param {object} testExperimentVariationParams Response of
     89  *     metricsPrivate.getVariationParams.
     90  * @param {string} testExperimentVariationParams Response of
     91  *     notifications.getPermissionLevel.
     92  * @param {boolean} testGoogleNowEnabled True if the user is opted in to Google
     93  *     Now.
     94  */
     95 function expectStateMachineCalls(
     96     fixture,
     97     testIdentityToken,
     98     testGeolocationPref,
     99     testExperimentVariationParams,
    100     testNotificationPermissionLevel,
    101     testGoogleNowEnabled) {
    102   var authenticationManagerIsSignedInSavedArgs = new SaveMockArguments();
    103   fixture.mockApis.expects(once()).
    104       authenticationManager_isSignedIn(
    105           authenticationManagerIsSignedInSavedArgs.match(ANYTHING)).
    106       will(invokeCallback(
    107           authenticationManagerIsSignedInSavedArgs,
    108           0,
    109           testIdentityToken));
    110 
    111   var getVariationParamsSavedArgs = new SaveMockArguments();
    112   fixture.mockApis.expects(once()).
    113       instrumented_metricsPrivate_getVariationParams(
    114           getVariationParamsSavedArgs.match(ANYTHING),
    115           getVariationParamsSavedArgs.match(ANYTHING)).
    116       will(invokeCallback(
    117           getVariationParamsSavedArgs, 1, testExperimentVariationParams));
    118 
    119   var googleGeolocationPrefGetSavedArgs = new SaveMockArguments();
    120   fixture.mockApis.expects(once()).
    121       instrumented_preferencesPrivate_googleGeolocationAccessEnabled_get(
    122           googleGeolocationPrefGetSavedArgs.match(eqJSON({})),
    123           googleGeolocationPrefGetSavedArgs.match(ANYTHING)).
    124       will(invokeCallback(
    125           googleGeolocationPrefGetSavedArgs, 1, {value: testGeolocationPref}));
    126 
    127   var notificationGetPermissionLevelSavedArgs = new SaveMockArguments();
    128   fixture.mockApis.expects(once()).
    129       instrumented_notifications_getPermissionLevel(
    130           notificationGetPermissionLevelSavedArgs.match(ANYTHING)).
    131       will(invokeCallback(
    132           notificationGetPermissionLevelSavedArgs,
    133           0,
    134           testNotificationPermissionLevel))
    135 
    136    var storageGetSavedArgs = new SaveMockArguments();	 
    137    fixture.mockApis.expects(once()).	 
    138        instrumented_storage_local_get(	 
    139            storageGetSavedArgs.match(eq('googleNowEnabled')),	 
    140            storageGetSavedArgs.match(ANYTHING)).	 
    141        will(invokeCallback(
    142           storageGetSavedArgs, 1, {googleNowEnabled: testGoogleNowEnabled}));	 
    143 
    144   fixture.mockGlobals.expects(once()).
    145       setBackgroundEnable(ANYTHING);
    146 }
    147 
    148 /**
    149  * Sets up the test to expect the initialization calls that
    150  * initialize() invokes.
    151  * Note that this CAN NOT be used if any of the methods below are called
    152  * outside of this context with the same argument matchers.
    153  * expects() calls cannot be chained with the same argument matchers.
    154  */
    155 function expectInitialization(mockApisObj) {
    156   var tasksAddSavedArgs = new SaveMockArguments();
    157   mockApisObj.expects(once()).
    158       tasks_add(
    159           tasksAddSavedArgs.match(ANYTHING),
    160           tasksAddSavedArgs.match(ANYTHING)).
    161       will(invokeCallback(tasksAddSavedArgs, 1, function() {}));
    162   var updateCardsAttemptsIsRunningSavedArgs = new SaveMockArguments();
    163   mockApisObj.expects(once()).
    164       updateCardsAttempts_isRunning(
    165           updateCardsAttemptsIsRunningSavedArgs.match(ANYTHING)).
    166       will(
    167           invokeCallback(
    168              updateCardsAttemptsIsRunningSavedArgs, 0, false));
    169 }
    170 
    171 TEST_F(
    172     'GoogleNowBackgroundUnitTest',
    173     'Initialize_ToastStateEmpty',
    174     function() {
    175       // Tests the case when getAuthToken fails most likely because the user is
    176       // not signed in. In this case, the function should quietly exit after
    177       // finding out that getAuthToken fails.
    178 
    179       // Setup and expectations.
    180       var testIdentityToken = undefined;
    181       var testGeolocationPref = false;
    182       var testExperimentVariationParams = {};
    183       var testNotificationPermissionLevel = 'denied';
    184       var testGoogleNowEnabled = undefined;
    185 
    186       mockInitializeDependencies(this);
    187 
    188       this.mockGlobals.expects(once()).recordEvent(
    189           GoogleNowEvent.EXTENSION_START);
    190 
    191       this.mockGlobals.expects(once()).recordEvent(
    192           GoogleNowEvent.STOPPED);
    193 
    194       expectInitialization(this.mockApis);
    195 
    196       expectStateMachineCalls(
    197           this,
    198           testIdentityToken,
    199           testGeolocationPref,
    200           testExperimentVariationParams,
    201           testNotificationPermissionLevel,
    202           testGoogleNowEnabled);
    203 
    204       // Invoking the tested function.
    205       initialize();
    206     });
    207 
    208 TEST_F(
    209     'GoogleNowBackgroundUnitTest',
    210     'DISABLED_Initialize_ToastStateEmpty2',
    211     function() {
    212       // Tests the case when getAuthToken succeeds, and the user has never
    213       // responded to the toast.
    214       // In this case, the function should invoke showWelcomeToast().
    215 
    216       // Setup and expectations.
    217       var testIdentityToken = 'some identity token';
    218       var testGeolocationPref = false;
    219       var testExperimentVariationParams = {};
    220       var testNotificationPermissionLevel = 'denied';
    221       var testGoogleNowEnabled = undefined;
    222 
    223       mockInitializeDependencies(this);
    224 
    225       this.mockGlobals.expects(once()).recordEvent(
    226           GoogleNowEvent.EXTENSION_START);
    227 
    228       expectInitialization(this.mockApis);
    229 
    230       expectStateMachineCalls(
    231           this,
    232           testIdentityToken,
    233           testGeolocationPref,
    234           testExperimentVariationParams,
    235           testNotificationPermissionLevel,
    236           testGoogleNowEnabled);
    237 
    238       var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
    239       this.mockApis.expects(exactly(1)).
    240           instrumented_notifications_getAll(
    241               chromeNotificationGetAllSavedArgs.match(ANYTHING)).
    242           will(
    243               invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
    244               invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}));
    245 
    246       // Invoking the tested function.
    247       initialize();
    248     });
    249 
    250 TEST_F('GoogleNowBackgroundUnitTest', 'Initialize_RunGoogleNow', function() {
    251   // Tests if Google Now will invoke startPollingCards when all
    252   // of the required state is fulfilled.
    253 
    254   // Setup and expectations.
    255   var testIdentityToken = 'some identity token';
    256   var testGeolocationPref = true;
    257   var testExperimentVariationParams = {};
    258   var testNotificationPermissionLevel = 'granted';
    259   var testGoogleNowEnabled = true;
    260 
    261   mockInitializeDependencies(this);
    262 
    263   this.mockGlobals.expects(once()).recordEvent(
    264         GoogleNowEvent.EXTENSION_START);
    265 
    266   expectInitialization(this.mockApis);
    267 
    268   expectStateMachineCalls(
    269       this,
    270       testIdentityToken,
    271       testGeolocationPref,
    272       testExperimentVariationParams,
    273       testNotificationPermissionLevel,
    274       testGoogleNowEnabled);
    275 
    276   this.mockGlobals.expects(once()).startPollingCards();
    277 
    278   // Invoking the tested function.
    279   initialize();
    280 });
    281 
    282 TEST_F(
    283     'GoogleNowBackgroundUnitTest',
    284     'DISABLED_Initialize_NoGeolocation',
    285     function() {
    286   // Tests the case where everything is in place except for the
    287   // Geolocation Preference after the user responded to the toast.
    288 
    289   // Setup and expectations.
    290   var testIdentityToken = 'some identity token';
    291   var testGeolocationPref = false;
    292   var testExperimentVariationParams = {};
    293   var testNotificationPermissionLevel = 'denied';
    294   var testGoogleNowEnabled = undefined;
    295 
    296 
    297   mockInitializeDependencies(this);
    298 
    299   this.mockGlobals.expects(once()).recordEvent(
    300         GoogleNowEvent.EXTENSION_START);
    301 
    302   this.mockGlobals.expects(once()).recordEvent(
    303       GoogleNowEvent.USER_SUPPRESSED);
    304 
    305   expectInitialization(this.mockApis);
    306 
    307   expectStateMachineCalls(
    308       this,
    309       testIdentityToken,
    310       testGeolocationPref,
    311       testExperimentVariationParams,
    312       testNotificationPermissionLevel,
    313       testNotificationPermissionLevel,
    314       testGoogleNowEnabled);
    315 
    316   var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
    317   this.mockApis.expects(exactly(2)).
    318       instrumented_notifications_getAll(
    319           chromeNotificationGetAllSavedArgs.match(ANYTHING)).
    320       will(
    321           invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
    322           invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}));
    323 
    324   // Invoking the tested function.
    325   initialize();
    326 });
    327 
    328 /**
    329  * Mocks global functions and APIs that onNotificationClicked() depends upon.
    330  * @param {Test} fixture Test fixture.
    331  */
    332 function mockOnNotificationClickedDependencies(fixture) {
    333   fixture.makeAndRegisterMockApis([
    334       'chrome.windows.create',
    335       'chrome.windows.update',
    336       'instrumented.storage.local.get',
    337       'instrumented.tabs.create']);
    338 }
    339 
    340 TEST_F(
    341     'GoogleNowBackgroundUnitTest',
    342     'OnNotificationClicked_NoData',
    343     function() {
    344       // Tests the case when there is no data associated with notification id.
    345       // In this case, the function should do nothing.
    346 
    347       // Setup and expectations.
    348       var testNotificationId = 'TEST_ID';
    349       var testNotificationData = {};
    350 
    351       mockOnNotificationClickedDependencies(this);
    352       this.makeMockLocalFunctions(['selector']);
    353 
    354       var storageGetSavedArgs = new SaveMockArguments();
    355       this.mockApis.expects(once()).
    356           instrumented_storage_local_get(
    357               storageGetSavedArgs.match(eq('notificationsData')),
    358               storageGetSavedArgs.match(ANYTHING)).
    359           will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
    360 
    361       // Invoking the tested function.
    362       onNotificationClicked(
    363           testNotificationId, this.mockLocalFunctions.functions().selector);
    364     });
    365 
    366 TEST_F(
    367     'GoogleNowBackgroundUnitTest',
    368     'OnNotificationClicked_ActionUrlsUndefined',
    369     function() {
    370       // Tests the case when the data associated with notification id is
    371       // 'undefined'.
    372       // In this case, the function should do nothing.
    373 
    374       // Setup and expectations.
    375       var testActionUrls = undefined;
    376       var testNotificationId = 'TEST_ID';
    377       var testNotificationData = {
    378           notificationsData: {'TEST_ID': {actionUrls: testActionUrls}}
    379       };
    380 
    381       mockOnNotificationClickedDependencies(this);
    382       this.makeMockLocalFunctions(['selector']);
    383 
    384       var storageGetSavedArgs = new SaveMockArguments();
    385       this.mockApis.expects(once()).
    386           instrumented_storage_local_get(
    387               storageGetSavedArgs.match(eq('notificationsData')),
    388               storageGetSavedArgs.match(ANYTHING)).
    389           will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
    390       this.mockLocalFunctions.expects(once()).selector(undefined).will(
    391           returnValue(undefined));
    392 
    393       // Invoking the tested function.
    394       onNotificationClicked(
    395           testNotificationId, this.mockLocalFunctions.functions().selector);
    396     });
    397 
    398 TEST_F(
    399     'GoogleNowBackgroundUnitTest',
    400     'OnNotificationClicked_TabCreateSuccess',
    401     function() {
    402       // Tests the selected URL is OK and crome.tabs.create suceeds.
    403 
    404       // Setup and expectations.
    405       var testActionUrls = {testField: 'TEST VALUE'};
    406       var testNotificationId = 'TEST_ID';
    407       var testNotificationData = {
    408           notificationsData: {'TEST_ID': {actionUrls: testActionUrls}}
    409       };
    410       var testActionUrl = 'http://testurl.com';
    411       var testCreatedTab = {windowId: 239};
    412 
    413       mockOnNotificationClickedDependencies(this);
    414       this.makeMockLocalFunctions(['selector']);
    415 
    416       var storageGetSavedArgs = new SaveMockArguments();
    417       this.mockApis.expects(once()).
    418           instrumented_storage_local_get(
    419               storageGetSavedArgs.match(eq('notificationsData')),
    420               storageGetSavedArgs.match(ANYTHING)).
    421           will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
    422       this.mockLocalFunctions.expects(once()).selector(testActionUrls).will(
    423           returnValue(testActionUrl));
    424       var chromeTabsCreateSavedArgs = new SaveMockArguments();
    425       this.mockApis.expects(once()).
    426           instrumented_tabs_create(
    427               chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})),
    428               chromeTabsCreateSavedArgs.match(ANYTHING)).
    429           will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab));
    430       this.mockApis.expects(once()).chrome_windows_update(
    431           testCreatedTab.windowId,
    432           eqJSON({focused: true}));
    433 
    434       // Invoking the tested function.
    435       onNotificationClicked(
    436           testNotificationId, this.mockLocalFunctions.functions().selector);
    437     });
    438 
    439 TEST_F(
    440     'GoogleNowBackgroundUnitTest',
    441     'OnNotificationClicked_TabCreateFail',
    442     function() {
    443       // Tests the selected URL is OK and crome.tabs.create fails.
    444       // In this case, the function should invoke chrome.windows.create as a
    445       // second attempt.
    446 
    447       // Setup and expectations.
    448       var testActionUrls = {testField: 'TEST VALUE'};
    449       var testNotificationId = 'TEST_ID';
    450       var testNotificationData = {
    451         notificationsData: {'TEST_ID': {actionUrls: testActionUrls}}
    452       };
    453       var testActionUrl = 'http://testurl.com';
    454       var testCreatedTab = undefined; // chrome.tabs.create fails
    455 
    456       mockOnNotificationClickedDependencies(this);
    457       this.makeMockLocalFunctions(['selector']);
    458 
    459       var storageGetSavedArgs = new SaveMockArguments();
    460       this.mockApis.expects(once()).
    461           instrumented_storage_local_get(
    462               storageGetSavedArgs.match(eq('notificationsData')),
    463               storageGetSavedArgs.match(ANYTHING)).
    464           will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
    465       this.mockLocalFunctions.expects(once()).selector(testActionUrls).will(
    466           returnValue(testActionUrl));
    467       var chromeTabsCreateSavedArgs = new SaveMockArguments();
    468       this.mockApis.expects(once()).
    469           instrumented_tabs_create(
    470               chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})),
    471               chromeTabsCreateSavedArgs.match(ANYTHING)).
    472           will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab));
    473       this.mockApis.expects(once()).chrome_windows_create(
    474           eqJSON({url: testActionUrl, focused: true}));
    475 
    476       // Invoking the tested function.
    477       onNotificationClicked(
    478           testNotificationId, this.mockLocalFunctions.functions().selector);
    479     });
    480