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.
5 // TODO(robliao,vadimt): Determine the granularity of testing to perform.
8 * Test fixture for background.js.
10 * @extends {testing.Test}
12 function GoogleNowBackgroundUnitTest () {
13 testing.Test.call(this);
16 GoogleNowBackgroundUnitTest.prototype = {
17 __proto__: testing.Test.prototype,
21 'common_test_util.js',
22 'background_test_util.js',
27 TEST_F('GoogleNowBackgroundUnitTest', 'AreTasksConflicting', function() {
28 function testTaskPair(newTaskName, scheduledTaskName, expected) {
29 assertTrue(areTasksConflicting(newTaskName, scheduledTaskName) == expected,
30 '(' + newTaskName + ', ' + scheduledTaskName + ')');
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);
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);
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);
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);
54 var testNotificationId = 'TEST GROUP-SOME TEST ID';
55 var testChromeNotificationId = 'TEST CARD ID';
56 var testNotification1 =
57 {testNotificationField: 'TEST NOTIFICATION VALUE1', priority: -1};
58 var testNotification2 =
59 {testNotificationField: 'TEST NOTIFICATION VALUE2', priority: 0};
60 var testActionUrls1 = {testField: 'TEST VALUE1'};
61 var testActionUrls2 = {testField: 'TEST VALUE2'};
62 var testDismissal1 = {testDismissalField: 'TEST DISMISSAL VALUE 1'};
63 var testDismissal2 = {testDismissalField: 'TEST DISMISSAL VALUE 2'};
65 var testTimestamp1 = 300000;
66 var testTimestamp2 = 600000;
67 var testGroupRank1 = 19;
68 var testGroupRank2 = 23;
69 var testTriggerUnmerged = {showTimeSec: 100, hideTimeSec: 200};
70 var testTriggerMerged = {showTime: 300007, hideTime: 300011};
71 var testVersion1 = 29;
72 var testVersion2 = 31;
75 'GoogleNowBackgroundUnitTest',
76 'MergeCardsEmptyNoTrigger',
78 // Tests merging a card with an empty trigger into an 'undefined' merged
79 // card. This should start a new card.
81 // Invoking the tested function.
82 var resultingMergedCard = mergeCards(undefined, {
83 notificationId: testNotificationId,
84 chromeNotificationId: testChromeNotificationId,
85 version: testVersion1,
86 chromeNotificationOptions: testNotification1,
87 actionUrls: testActionUrls1,
88 dismissal: testDismissal1
89 }, testTimestamp1, testGroupRank1);
91 // Check the return value.
96 notificationId: testNotificationId,
97 parameters: testDismissal1
100 groupRank: testGroupRank1,
102 timestamp: testTimestamp1,
103 notification: testNotification1,
104 actionUrls: testActionUrls1,
105 version: testVersion1
107 JSON.stringify(resultingMergedCard));
111 'GoogleNowBackgroundUnitTest',
114 // Tests merging a unmerged card into a merged card.
115 // Unmerged card priority is greater than merged card one. Unmerged card
116 // rank is less than merged card one, and it's older.
120 trigger: testTriggerMerged,
121 version: testVersion1,
122 timestamp: testTimestamp2,
123 notification: testNotification1,
124 actionUrls: testActionUrls1,
125 groupRank: testGroupRank2,
127 [{notificationId: testNotificationId, parameters: testDismissal1}]
130 var unmergedNotification = {
131 notificationId: testNotificationId,
132 chromeNotificationId: testChromeNotificationId,
133 version: testVersion2,
134 chromeNotificationOptions: testNotification2,
135 actionUrls: testActionUrls2,
136 dismissal: testDismissal2,
137 trigger: testTriggerUnmerged
140 // Invoking the tested function.
141 var resultingMergedCard = mergeCards(
142 mergedCard, unmergedNotification, testTimestamp1, testGroupRank1);
144 // Check the return value.
147 trigger: testTriggerMerged,
148 version: testVersion1,
149 timestamp: testTimestamp2,
151 testNotificationField: 'TEST NOTIFICATION VALUE1',
154 actionUrls: testActionUrls1,
155 groupRank: testGroupRank2,
157 {notificationId: testNotificationId, parameters: testDismissal1},
158 {notificationId: testNotificationId, parameters: testDismissal2}
161 JSON.stringify(resultingMergedCard));
165 'GoogleNowBackgroundUnitTest',
168 // Tests merging a unmerged card into a merged card.
169 // Unmerged card priority is less than merged card one. Unmerged card rank
170 // is greater than merged card one, and it's older.
174 trigger: testTriggerMerged,
175 version: testVersion1,
176 timestamp: testTimestamp2,
177 notification: testNotification2,
178 actionUrls: testActionUrls1,
179 groupRank: testGroupRank1,
181 [{notificationId: testNotificationId, parameters: testDismissal1}]
184 var unmergedNotification = {
185 notificationId: testNotificationId,
186 chromeNotificationId: testChromeNotificationId,
187 version: testVersion2,
188 chromeNotificationOptions: testNotification1,
189 actionUrls: testActionUrls2,
190 dismissal: testDismissal2,
191 trigger: testTriggerUnmerged
194 // Invoking the tested function.
195 var resultingMergedCard = mergeCards(
196 mergedCard, unmergedNotification, testTimestamp1, testGroupRank2);
198 // Check the return value.
201 trigger: {showTime: 400000, hideTime: 500000},
202 version: testVersion1,
203 timestamp: testTimestamp2,
205 testNotificationField: 'TEST NOTIFICATION VALUE2',
208 actionUrls: testActionUrls1,
209 groupRank: testGroupRank2,
211 {notificationId: testNotificationId, parameters: testDismissal1},
212 {notificationId: testNotificationId, parameters: testDismissal2}
215 JSON.stringify(resultingMergedCard));
219 'GoogleNowBackgroundUnitTest',
222 // Tests merging a unmerged card into a merged card.
223 // Unmerged card priority is less than merged card one. Unmerged card rank
224 // is less than merged card one, and it's newer.
228 trigger: testTriggerMerged,
229 version: testVersion1,
230 timestamp: testTimestamp1,
231 notification: testNotification2,
232 actionUrls: testActionUrls1,
233 groupRank: testGroupRank2,
235 [{notificationId: testNotificationId, parameters: testDismissal1}]
238 var unmergedNotification = {
239 notificationId: testNotificationId,
240 chromeNotificationId: testChromeNotificationId,
241 version: testVersion2,
242 chromeNotificationOptions: testNotification1,
243 actionUrls: testActionUrls2,
244 dismissal: testDismissal2,
245 trigger: testTriggerUnmerged
248 // Invoking the tested function.
249 var resultingMergedCard = mergeCards(
250 mergedCard, unmergedNotification, testTimestamp2, testGroupRank1);
252 // Check the return value.
255 trigger: testTriggerMerged,
256 version: testVersion2,
257 timestamp: testTimestamp2,
259 testNotificationField: 'TEST NOTIFICATION VALUE1',
262 actionUrls: testActionUrls2,
263 groupRank: testGroupRank2,
265 {notificationId: testNotificationId, parameters: testDismissal1},
266 {notificationId: testNotificationId, parameters: testDismissal2}
269 JSON.stringify(resultingMergedCard));
273 'GoogleNowBackgroundUnitTest',
276 // Tests mergeGroup method.
279 this.makeAndRegisterMockGlobals(['mergeCards']);
281 this.mockGlobals.expects(once()).
284 eqJSON({chromeNotificationId: 'ID 1', testField: 'TEST_FIELD1'}),
287 will(returnValue({testField: 'RESULT 1'}));
288 this.mockGlobals.expects(once()).
290 eqJSON({testField: 'TEST_FIELD22'}),
291 eqJSON({chromeNotificationId: 'ID 2', testField: 'TEST_FIELD2'}),
294 will(returnValue({testField: 'RESULT 2'}));
298 {chromeNotificationId: 'ID 1', testField: 'TEST_FIELD1'},
299 {chromeNotificationId: 'ID 2', testField: 'TEST_FIELD2'}
301 cardsTimestamp: 300000,
302 nextPollTime: 600000,
307 'ID 2': { testField: 'TEST_FIELD22' },
308 'ID 3': { testField: 'TEST_FIELD3' }
311 // Invoking the tested function.
312 mergeGroup(mergedCards, group);
314 // Check the output parameter.
317 'ID 2': { testField: 'RESULT 2' },
318 'ID 3': { testField: 'TEST_FIELD3'},
319 'ID 1': { testField: 'RESULT 1' }}),
320 JSON.stringify(mergedCards));
324 * Mocks global functions and APIs that initialize() depends upon.
325 * @param {Test} fixture Test fixture.
327 function mockInitializeDependencies(fixture) {
328 fixture.makeAndRegisterMockGlobals([
330 'setBackgroundEnable',
333 fixture.makeAndRegisterMockApis([
334 'authenticationManager.isSignedIn',
335 'chrome.location.clearWatch',
336 'chrome.storage.local.remove',
337 'instrumented.metricsPrivate.getVariationParams',
338 'instrumented.notifications.getAll',
339 'instrumented.preferencesPrivate.googleGeolocationAccessEnabled.get',
340 'instrumented.storage.local.get',
342 'updateCardsAttempts.isRunning',
343 'updateCardsAttempts.stop'
348 * Sets up the test to expect the state machine calls and send
349 * the specified state machine state. Currently used to test initialize().
350 * Note that this CAN NOT be used if any of the methods below are called
351 * outside of this context with the same argument matchers.
352 * expects() calls cannot be chained with the same argument matchers.
353 * @param {object} fixture Test fixture.
354 * @param {string} testIdentityToken getAuthToken callback token.
355 * @param {boolean} testGeolocationPref Geolocation Preference callback value.
356 * @param {object} testExperimentVariationParams Response of
357 * metricsPrivate.getVariationParams
359 function expectStateMachineCalls(
363 testExperimentVariationParams) {
364 var authenticationManagerIsSignedInSavedArgs = new SaveMockArguments();
365 fixture.mockApis.expects(once()).
366 authenticationManager_isSignedIn(
367 authenticationManagerIsSignedInSavedArgs.match(ANYTHING)).
369 authenticationManagerIsSignedInSavedArgs,
373 var getVariationParamsSavedArgs = new SaveMockArguments();
374 fixture.mockApis.expects(once()).
375 instrumented_metricsPrivate_getVariationParams(
376 getVariationParamsSavedArgs.match(ANYTHING),
377 getVariationParamsSavedArgs.match(ANYTHING)).
379 getVariationParamsSavedArgs, 1, testExperimentVariationParams));
381 var googleGeolocationPrefGetSavedArgs = new SaveMockArguments();
382 fixture.mockApis.expects(once()).
383 instrumented_preferencesPrivate_googleGeolocationAccessEnabled_get(
384 googleGeolocationPrefGetSavedArgs.match(eqJSON({})),
385 googleGeolocationPrefGetSavedArgs.match(ANYTHING)).
387 googleGeolocationPrefGetSavedArgs, 1, {value: testGeolocationPref}));
389 fixture.mockGlobals.expects(once()).
390 setBackgroundEnable(ANYTHING);
394 * Sets up the test to expect the initialization calls that
395 * initialize() invokes.
396 * Note that this CAN NOT be used if any of the methods below are called
397 * outside of this context with the same argument matchers.
398 * expects() calls cannot be chained with the same argument matchers.
400 function expectInitialization(mockApisObj) {
401 var tasksAddSavedArgs = new SaveMockArguments();
402 mockApisObj.expects(once()).
404 tasksAddSavedArgs.match(ANYTHING),
405 tasksAddSavedArgs.match(ANYTHING)).
406 will(invokeCallback(tasksAddSavedArgs, 1, function() {}));
407 var updateCardsAttemptsIsRunningSavedArgs = new SaveMockArguments();
408 mockApisObj.expects(once()).
409 updateCardsAttempts_isRunning(
410 updateCardsAttemptsIsRunningSavedArgs.match(ANYTHING)).
413 updateCardsAttemptsIsRunningSavedArgs, 0, false));
417 'GoogleNowBackgroundUnitTest',
418 'Initialize_ToastStateEmpty',
420 // Tests the case when getAuthToken fails most likely because the user is
421 // not signed in. In this case, the function should quietly exit after
422 // finding out that getAuthToken fails.
424 // Setup and expectations.
425 var testIdentityToken = undefined;
426 var testGeolocationPref = false;
427 var testExperimentVariationParams = {};
429 mockInitializeDependencies(this);
431 this.mockGlobals.expects(once()).recordEvent(
432 GoogleNowEvent.EXTENSION_START);
434 this.mockGlobals.expects(once()).recordEvent(
435 GoogleNowEvent.STOPPED);
437 expectInitialization(this.mockApis);
439 expectStateMachineCalls(
443 testExperimentVariationParams);
445 // Invoking the tested function.
450 'GoogleNowBackgroundUnitTest',
451 'DISABLED_Initialize_ToastStateEmpty2',
453 // Tests the case when getAuthToken succeeds, and the user has never
454 // responded to the toast.
455 // In this case, the function should invoke showWelcomeToast().
457 // Setup and expectations.
458 var testIdentityToken = 'some identity token';
459 var testGeolocationPref = false;
460 var testExperimentVariationParams = {};
462 mockInitializeDependencies(this);
464 this.mockGlobals.expects(once()).recordEvent(
465 GoogleNowEvent.EXTENSION_START);
467 expectInitialization(this.mockApis);
469 expectStateMachineCalls(
473 testExperimentVariationParams);
475 var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
476 this.mockApis.expects(exactly(1)).
477 instrumented_notifications_getAll(
478 chromeNotificationGetAllSavedArgs.match(ANYTHING)).
480 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
481 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}));
483 // Invoking the tested function.
487 TEST_F('GoogleNowBackgroundUnitTest', 'Initialize_RunGoogleNow', function() {
488 // Tests if Google Now will invoke startPollingCards when all
489 // of the required state is fulfilled.
491 // Setup and expectations.
492 var testIdentityToken = 'some identity token';
493 var testGeolocationPref = true;
494 var testExperimentVariationParams = {};
496 mockInitializeDependencies(this);
498 this.mockGlobals.expects(once()).recordEvent(
499 GoogleNowEvent.EXTENSION_START);
501 expectInitialization(this.mockApis);
503 expectStateMachineCalls(
507 testExperimentVariationParams);
509 this.mockGlobals.expects(once()).startPollingCards();
511 // Invoking the tested function.
516 'GoogleNowBackgroundUnitTest',
517 'DISABLED_Initialize_NoGeolocation',
519 // Tests the case where everything is in place except for the
520 // Geolocation Preference after the user responded to the toast.
522 // Setup and expectations.
523 var testIdentityToken = 'some identity token';
524 var testGeolocationPref = false;
525 var testExperimentVariationParams = {};
527 mockInitializeDependencies(this);
529 this.mockGlobals.expects(once()).recordEvent(
530 GoogleNowEvent.EXTENSION_START);
532 this.mockGlobals.expects(once()).recordEvent(
533 GoogleNowEvent.USER_SUPPRESSED);
535 expectInitialization(this.mockApis);
537 expectStateMachineCalls(
541 testExperimentVariationParams);
543 var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
544 this.mockApis.expects(exactly(2)).
545 instrumented_notifications_getAll(
546 chromeNotificationGetAllSavedArgs.match(ANYTHING)).
548 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
549 invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}));
551 // Invoking the tested function.
556 * Mocks global functions and APIs that onNotificationClicked() depends upon.
557 * @param {Test} fixture Test fixture.
559 function mockOnNotificationClickedDependencies(fixture) {
560 fixture.makeAndRegisterMockApis([
561 'chrome.windows.create',
562 'chrome.windows.update',
563 'instrumented.storage.local.get',
564 'instrumented.tabs.create']);
568 'GoogleNowBackgroundUnitTest',
569 'OnNotificationClicked_NoData',
571 // Tests the case when there is no data associated with notification id.
572 // In this case, the function should do nothing.
574 // Setup and expectations.
575 var testNotificationId = 'TEST_ID';
576 var testNotificationData = {};
578 mockOnNotificationClickedDependencies(this);
579 this.makeMockLocalFunctions(['selector']);
581 var storageGetSavedArgs = new SaveMockArguments();
582 this.mockApis.expects(once()).
583 instrumented_storage_local_get(
584 storageGetSavedArgs.match(eq('notificationsData')),
585 storageGetSavedArgs.match(ANYTHING)).
586 will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
588 // Invoking the tested function.
589 onNotificationClicked(
590 testNotificationId, this.mockLocalFunctions.functions().selector);
594 'GoogleNowBackgroundUnitTest',
595 'OnNotificationClicked_ActionUrlsUndefined',
597 // Tests the case when the data associated with notification id is
599 // In this case, the function should do nothing.
601 // Setup and expectations.
602 var testActionUrls = undefined;
603 var testNotificationId = 'TEST_ID';
604 var testNotificationData = {
605 notificationsData: {'TEST_ID': {actionUrls: testActionUrls}}
608 mockOnNotificationClickedDependencies(this);
609 this.makeMockLocalFunctions(['selector']);
611 var storageGetSavedArgs = new SaveMockArguments();
612 this.mockApis.expects(once()).
613 instrumented_storage_local_get(
614 storageGetSavedArgs.match(eq('notificationsData')),
615 storageGetSavedArgs.match(ANYTHING)).
616 will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
617 this.mockLocalFunctions.expects(once()).selector(undefined).will(
618 returnValue(undefined));
620 // Invoking the tested function.
621 onNotificationClicked(
622 testNotificationId, this.mockLocalFunctions.functions().selector);
626 'GoogleNowBackgroundUnitTest',
627 'OnNotificationClicked_TabCreateSuccess',
629 // Tests the selected URL is OK and crome.tabs.create suceeds.
631 // Setup and expectations.
632 var testActionUrls = {testField: 'TEST VALUE'};
633 var testNotificationId = 'TEST_ID';
634 var testNotificationData = {
635 notificationsData: {'TEST_ID': {actionUrls: testActionUrls}}
637 var testActionUrl = 'http://testurl.com';
638 var testCreatedTab = {windowId: 239};
640 mockOnNotificationClickedDependencies(this);
641 this.makeMockLocalFunctions(['selector']);
643 var storageGetSavedArgs = new SaveMockArguments();
644 this.mockApis.expects(once()).
645 instrumented_storage_local_get(
646 storageGetSavedArgs.match(eq('notificationsData')),
647 storageGetSavedArgs.match(ANYTHING)).
648 will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
649 this.mockLocalFunctions.expects(once()).selector(testActionUrls).will(
650 returnValue(testActionUrl));
651 var chromeTabsCreateSavedArgs = new SaveMockArguments();
652 this.mockApis.expects(once()).
653 instrumented_tabs_create(
654 chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})),
655 chromeTabsCreateSavedArgs.match(ANYTHING)).
656 will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab));
657 this.mockApis.expects(once()).chrome_windows_update(
658 testCreatedTab.windowId,
659 eqJSON({focused: true}));
661 // Invoking the tested function.
662 onNotificationClicked(
663 testNotificationId, this.mockLocalFunctions.functions().selector);
667 'GoogleNowBackgroundUnitTest',
668 'OnNotificationClicked_TabCreateFail',
670 // Tests the selected URL is OK and crome.tabs.create fails.
671 // In this case, the function should invoke chrome.windows.create as a
674 // Setup and expectations.
675 var testActionUrls = {testField: 'TEST VALUE'};
676 var testNotificationId = 'TEST_ID';
677 var testNotificationData = {
678 notificationsData: {'TEST_ID': {actionUrls: testActionUrls}}
680 var testActionUrl = 'http://testurl.com';
681 var testCreatedTab = undefined; // chrome.tabs.create fails
683 mockOnNotificationClickedDependencies(this);
684 this.makeMockLocalFunctions(['selector']);
686 var storageGetSavedArgs = new SaveMockArguments();
687 this.mockApis.expects(once()).
688 instrumented_storage_local_get(
689 storageGetSavedArgs.match(eq('notificationsData')),
690 storageGetSavedArgs.match(ANYTHING)).
691 will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
692 this.mockLocalFunctions.expects(once()).selector(testActionUrls).will(
693 returnValue(testActionUrl));
694 var chromeTabsCreateSavedArgs = new SaveMockArguments();
695 this.mockApis.expects(once()).
696 instrumented_tabs_create(
697 chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})),
698 chromeTabsCreateSavedArgs.match(ANYTHING)).
699 will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab));
700 this.mockApis.expects(once()).chrome_windows_create(
701 eqJSON({url: testActionUrl, focused: true}));
703 // Invoking the tested function.
704 onNotificationClicked(
705 testNotificationId, this.mockLocalFunctions.functions().selector);