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 var TEST_NAME = 'GoogleNowBackgroundUnitTest';
32 TEST_F(TEST_NAME, 'AreTasksConflicting', function() {
33 function testTaskPair(newTaskName, scheduledTaskName, expected) {
34 assertTrue(areTasksConflicting(newTaskName, scheduledTaskName) == expected,
35 '(' + newTaskName + ', ' + scheduledTaskName + ')');
38 testTaskPair(UPDATE_CARDS_TASK_NAME, UPDATE_CARDS_TASK_NAME, true);
39 testTaskPair(UPDATE_CARDS_TASK_NAME, DISMISS_CARD_TASK_NAME, false);
40 testTaskPair(UPDATE_CARDS_TASK_NAME, RETRY_DISMISS_TASK_NAME, false);
41 testTaskPair(UPDATE_CARDS_TASK_NAME, STATE_CHANGED_TASK_NAME, false);
43 testTaskPair(DISMISS_CARD_TASK_NAME, UPDATE_CARDS_TASK_NAME, false);
44 testTaskPair(DISMISS_CARD_TASK_NAME, DISMISS_CARD_TASK_NAME, false);
45 testTaskPair(DISMISS_CARD_TASK_NAME, RETRY_DISMISS_TASK_NAME, false);
46 testTaskPair(DISMISS_CARD_TASK_NAME, STATE_CHANGED_TASK_NAME, false);
48 testTaskPair(RETRY_DISMISS_TASK_NAME, UPDATE_CARDS_TASK_NAME, true);
49 testTaskPair(RETRY_DISMISS_TASK_NAME, DISMISS_CARD_TASK_NAME, true);
50 testTaskPair(RETRY_DISMISS_TASK_NAME, RETRY_DISMISS_TASK_NAME, true);
51 testTaskPair(RETRY_DISMISS_TASK_NAME, STATE_CHANGED_TASK_NAME, false);
53 testTaskPair(STATE_CHANGED_TASK_NAME, UPDATE_CARDS_TASK_NAME, false);
54 testTaskPair(STATE_CHANGED_TASK_NAME, DISMISS_CARD_TASK_NAME, false);
55 testTaskPair(STATE_CHANGED_TASK_NAME, RETRY_DISMISS_TASK_NAME, false);
56 testTaskPair(STATE_CHANGED_TASK_NAME, STATE_CHANGED_TASK_NAME, false);
60 * Server Request Tests
62 TEST_F(TEST_NAME, 'AuthServerRequestSuccess', function() {
63 expectServerRequests(this, 200, '{}');
64 var callbackCalled = false;
65 requestFromServer('GET', 'test/target').then(function(request) {
66 callbackCalled = true;
67 assertTrue(request.status === 200);
68 assertTrue(request.responseText === '{}');
70 assertTrue(callbackCalled);
73 TEST_F(TEST_NAME, 'AuthServerRequestForbidden', function() {
74 this.makeAndRegisterMockApis(['authenticationManager.removeToken']);
75 this.mockApis.expects(once()).authenticationManager_removeToken(ANYTHING);
77 expectServerRequests(this, 403, '');
79 var thenCalled = false;
80 var catchCalled = false;
81 requestFromServer('GET', 'test/target').then(function(request) {
83 }).catch(function(request) {
84 // The promise is rejected on HTTP failures.
86 assertTrue(request.status === 403);
88 assertFalse(thenCalled);
89 assertTrue(catchCalled);
92 TEST_F(TEST_NAME, 'AuthServerRequestNoAuth', function() {
93 this.makeAndRegisterMockApis(['authenticationManager.removeToken']);
94 this.mockApis.expects(once()).authenticationManager_removeToken(ANYTHING);
96 expectServerRequests(this, 401, '');
98 var thenCalled = false;
99 var catchCalled = false;
100 requestFromServer('GET', 'test/target').then(function(request) {
102 }).catch(function(request) {
103 // The promise is rejected on HTTP failures.
105 assertTrue(request.status === 401);
107 assertFalse(thenCalled);
108 assertTrue(catchCalled);
111 function expectServerRequests(fixture, httpStatus, responseText) {
112 fixture.makeAndRegisterMockApis([
113 'authenticationManager.getAuthToken',
117 function XMLHttpRequest() {}
119 XMLHttpRequest.prototype = {
120 addEventListener: function(type, listener, wantsUntrusted) {},
121 setRequestHeader: function(header, value) {},
125 fixture.mockApis.expects(once()).authenticationManager_getAuthToken()
126 .will(returnValue(Promise.resolve('token')));
128 var mockXMLHttpRequest = mock(XMLHttpRequest);
129 var mockXMLHttpRequestProxy = mockXMLHttpRequest.proxy();
130 fixture.mockApis.expects(once())
131 .buildServerRequest(ANYTHING, ANYTHING, ANYTHING)
132 .will(returnValue(mockXMLHttpRequestProxy));
134 mockXMLHttpRequest.expects(once())
135 .setRequestHeader('Authorization', 'Bearer token');
137 var loadEndSavedArgs = new SaveMockArguments();
138 mockXMLHttpRequest.expects(once())
140 loadEndSavedArgs.match(eq('loadend')),
141 loadEndSavedArgs.match(ANYTHING),
142 loadEndSavedArgs.match(eq(false)));
144 mockXMLHttpRequestProxy.status = httpStatus;
145 mockXMLHttpRequestProxy.response = responseText;
146 mockXMLHttpRequestProxy.responseText = responseText;
148 mockXMLHttpRequest.expects(once()).send()
149 .will(invokeCallback(loadEndSavedArgs, 1, mockXMLHttpRequestProxy));
152 TEST_F(TEST_NAME, 'AuthServerRequestNoToken', function() {
153 this.makeAndRegisterMockApis([
154 'authenticationManager.getAuthToken',
158 this.mockApis.expects(once()).authenticationManager_getAuthToken()
159 .will(returnValue(Promise.reject()));
160 this.mockApis.expects(never()).buildServerRequest()
162 var thenCalled = false;
163 var catchCalled = false;
164 requestFromServer('GET', 'test/target').then(function(request) {
166 }).catch(function() {
169 assertFalse(thenCalled);
170 assertTrue(catchCalled);
174 * requestNotificationGroupsFromServer Tests
176 TEST_F(TEST_NAME, 'RequestNotificationGroupsFromServerEmpty', function() {
177 this.makeAndRegisterMockGlobals([
178 'shouldShowExplanatoryCard',
183 this.mockGlobals.expects(once()).shouldShowExplanatoryCard()
184 .will(returnValue(false));
186 this.mockGlobals.expects(once()).recordEvent(
187 GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL);
189 this.mockGlobals.expects(once()).recordEvent(
190 GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS);
192 var requestFromServerArgs = new SaveMockArguments();
193 this.mockGlobals.expects(once()).requestFromServer(
194 requestFromServerArgs.match(eq('GET')),
195 requestFromServerArgs.match(ANYTHING))
197 Promise.resolve({status: 200, responseText: "{}"})));
199 var thenCalled = false;
200 var catchCalled = false;
201 requestNotificationGroupsFromServer([]).then(function() {
203 }).catch(function() {
206 assertTrue(thenCalled);
207 assertFalse(catchCalled);
209 var pathAndQuery = requestFromServerArgs.arguments[1];
210 var query = pathAndQuery.split('?')[1];
211 assertTrue(query.search('timeZoneOffsetMs') >= 0);
212 assertTrue(query.search('uiLocale') >= 0);
213 assertFalse(query.search('cardExplanation') >= 0);
216 TEST_F(TEST_NAME, 'RequestNotificationGroupsFromServerWithGroups', function() {
217 this.makeAndRegisterMockGlobals([
218 'shouldShowExplanatoryCard',
223 this.mockGlobals.expects(once()).shouldShowExplanatoryCard()
224 .will(returnValue(false));
226 this.mockGlobals.expects(once()).recordEvent(
227 GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL);
229 this.mockGlobals.expects(once()).recordEvent(
230 GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS);
232 var requestFromServerArgs = new SaveMockArguments();
233 this.mockGlobals.expects(once()).requestFromServer(
234 requestFromServerArgs.match(eq('GET')),
235 requestFromServerArgs.match(ANYTHING))
237 Promise.resolve({status: 200, responseText: "{}"})));
239 var thenCalled = false;
240 var catchCalled = false;
241 requestNotificationGroupsFromServer(['A', 'B', 'C']).then(function() {
243 }).catch(function() {
246 assertTrue(thenCalled);
247 assertFalse(catchCalled);
249 var pathAndQuery = requestFromServerArgs.arguments[1];
250 var query = pathAndQuery.split('?')[1];
251 assertTrue(query.search('timeZoneOffsetMs') >= 0);
252 assertTrue(query.search('uiLocale') >= 0);
253 assertFalse(query.search('cardExplanation') >= 0);
254 assertTrue(query.search('requestTypes=A') >= 0);
255 assertTrue(query.search('requestTypes=B') >= 0);
256 assertTrue(query.search('requestTypes=C') >= 0);
259 TEST_F(TEST_NAME, 'RequestNotificationGroupsFromServerExplanatory', function() {
260 this.makeAndRegisterMockGlobals([
261 'shouldShowExplanatoryCard',
266 this.mockGlobals.expects(once()).shouldShowExplanatoryCard()
267 .will(returnValue(true));
269 this.mockGlobals.expects(once()).recordEvent(
270 GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL);
272 this.mockGlobals.expects(once()).recordEvent(
273 GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS);
275 var requestFromServerArgs = new SaveMockArguments();
276 this.mockGlobals.expects(once()).requestFromServer(
277 requestFromServerArgs.match(eq('GET')),
278 requestFromServerArgs.match(ANYTHING))
280 Promise.resolve({status: 200, responseText: "{}"})));
282 var thenCalled = false;
283 var catchCalled = false;
284 requestNotificationGroupsFromServer([]).then(function() {
286 }).catch(function() {
289 assertTrue(thenCalled);
290 assertFalse(catchCalled);
292 var pathAndQuery = requestFromServerArgs.arguments[1];
293 var query = pathAndQuery.split('?')[1];
294 assertTrue(query.search('timeZoneOffsetMs') >= 0);
295 assertTrue(query.search('uiLocale') >= 0);
296 assertTrue(query.search('cardExplanation=true') >= 0);
299 TEST_F(TEST_NAME, 'RequestNotificationGroupsFromServerFailure', function() {
300 this.makeAndRegisterMockGlobals([
301 'shouldShowExplanatoryCard',
306 this.mockGlobals.expects(once()).shouldShowExplanatoryCard()
307 .will(returnValue(false));
309 this.mockGlobals.expects(once()).recordEvent(
310 GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL);
312 this.mockGlobals.expects(never()).recordEvent(
313 GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS);
315 var requestFromServerArgs = new SaveMockArguments();
316 this.mockGlobals.expects(once()).requestFromServer(
317 requestFromServerArgs.match(eq('GET')),
318 requestFromServerArgs.match(ANYTHING))
320 Promise.reject({status: 401})));
322 var thenCalled = false;
323 var catchCalled = false;
324 requestNotificationGroupsFromServer([]).then(function() {
326 }).catch(function() {
329 assertFalse(thenCalled);
330 assertTrue(catchCalled);
334 * shouldScheduleRetryFromGroupList Tests
336 TEST_F(TEST_NAME, 'ShouldScheduleRetryEmptyGroupList', function() {
337 assertTrue(shouldScheduleRetryFromGroupList([]));
340 TEST_F(TEST_NAME, 'ShouldScheduleRetryNorOnlyGroupList', function() {
341 assertFalse(shouldScheduleRetryFromGroupList(['NOR']));
344 TEST_F(TEST_NAME, 'ShouldScheduleRetryNotOnlyGroupList', function() {
345 assertTrue(shouldScheduleRetryFromGroupList(['NOT']));
348 TEST_F(TEST_NAME, 'ShouldScheduleRetryMultipleGroupsList', function() {
349 assertTrue(shouldScheduleRetryFromGroupList(['NOR', 'NOT']));
353 * requestAndUpdateOptIn Tests
355 TEST_F(TEST_NAME, 'RequestAndUpdateOptInOptedIn', function() {
356 this.makeAndRegisterMockApis([
357 'chrome.storage.local.set',
361 this.mockApis.expects(once()).requestFromServer('GET', 'settings/optin')
362 .will(returnValue(Promise.resolve({
364 responseText: '{"value": true}'})));
366 this.mockApis.expects(once())
367 .chrome_storage_local_set(eqJSON({googleNowEnabled: true}));
369 var thenCalled = false;
370 var catchCalled = false;
371 requestAndUpdateOptedIn().then(function(optedIn) {
374 }).catch(function() {
377 assertTrue(thenCalled);
378 assertFalse(catchCalled);
381 TEST_F(TEST_NAME, 'RequestAndUpdateOptInOptedOut', function() {
382 this.makeAndRegisterMockApis([
383 'chrome.storage.local.set',
387 this.mockApis.expects(once()).requestFromServer('GET', 'settings/optin')
388 .will(returnValue(Promise.resolve({
390 responseText: '{"value": false}'})));
392 this.mockApis.expects(once())
393 .chrome_storage_local_set(eqJSON({googleNowEnabled: false}));
395 var thenCalled = false;
396 var catchCalled = false;
397 requestAndUpdateOptedIn().then(function(optedIn) {
399 assertFalse(optedIn);
400 }).catch(function() {
403 assertTrue(thenCalled);
404 assertFalse(catchCalled);
407 TEST_F(TEST_NAME, 'RequestAndUpdateOptInFailure', function() {
408 this.makeAndRegisterMockApis([
409 'chrome.storage.local.set',
413 this.mockApis.expects(once()).requestFromServer('GET', 'settings/optin')
414 .will(returnValue(Promise.reject({status: 404})));
416 this.mockApis.expects(never()).chrome_storage_local_set();
418 var thenCalled = false;
419 var catchCalled = false;
420 requestAndUpdateOptedIn().then(function() {
422 }).catch(function() {
425 assertFalse(thenCalled);
426 assertTrue(catchCalled);
430 * pollOptedInNoImmediateRecheck Tests
432 TEST_F(TEST_NAME, 'pollOptedInNoImmediateRecheckOptedIn', function() {
433 this.makeAndRegisterMockApis([
434 'requestAndUpdateOptedIn',
435 'instrumented.metricsPrivate.getVariationParams',
436 'optInPollAttempts.start'
439 this.mockApis.expects(once()).requestAndUpdateOptedIn()
440 .will(returnValue(Promise.resolve(true)));
442 this.mockApis.expects(never())
443 .instrumented_metricsPrivate_getVariationParams();
445 this.mockApis.expects(never()).optInPollAttempts_start();
447 pollOptedInNoImmediateRecheck();
450 TEST_F(TEST_NAME, 'pollOptedInNoImmediateRecheckOptedOut', function() {
451 this.makeAndRegisterMockApis([
452 'requestAndUpdateOptedIn',
453 'instrumented.metricsPrivate.getVariationParams',
454 'optInPollAttempts.start'
457 this.mockApis.expects(once()).requestAndUpdateOptedIn()
458 .will(returnValue(Promise.resolve(false)));
460 var getVariationParamsSavedArgs = new SaveMockArguments();
461 this.mockApis.expects(once())
462 .instrumented_metricsPrivate_getVariationParams(
463 getVariationParamsSavedArgs.match(eq('GoogleNow')),
464 getVariationParamsSavedArgs.match(ANYTHING))
465 .will(invokeCallback(getVariationParamsSavedArgs, 1, {}));
467 this.mockApis.expects(once())
468 .optInPollAttempts_start(DEFAULT_OPTIN_CHECK_PERIOD_SECONDS);
470 pollOptedInNoImmediateRecheck();
473 TEST_F(TEST_NAME, 'pollOptedInNoImmediateRecheckFailure', function() {
474 this.makeAndRegisterMockApis([
475 'requestAndUpdateOptedIn',
476 'instrumented.metricsPrivate.getVariationParams',
477 'optInPollAttempts.start'
480 this.mockApis.expects(once()).requestAndUpdateOptedIn()
481 .will(returnValue(Promise.reject()));
483 var getVariationParamsSavedArgs = new SaveMockArguments();
484 this.mockApis.expects(once())
485 .instrumented_metricsPrivate_getVariationParams(
486 getVariationParamsSavedArgs.match(eq('GoogleNow')),
487 getVariationParamsSavedArgs.match(ANYTHING))
488 .will(invokeCallback(getVariationParamsSavedArgs, 1, {}));
490 this.mockApis.expects(once())
491 .optInPollAttempts_start(DEFAULT_OPTIN_CHECK_PERIOD_SECONDS);
493 pollOptedInNoImmediateRecheck();
497 * getGroupsToRequest Tests
499 TEST_F(TEST_NAME, 'GetGroupsToRequestNone', function() {
500 this.makeAndRegisterMockApis([
501 'fillFromChromeLocalStorage',
505 this.mockApis.expects(once())
506 .fillFromChromeLocalStorage(eqJSON({notificationGroups: {}}))
507 .will(returnValue(Promise.resolve({notificationGroups: {}})));
509 this.mockApis.expects(once()).Date_now().will(returnValue(20));
511 getGroupsToRequest().then(function(groupsToRequest) {
512 assertTrue(JSON.stringify(groupsToRequest) === '[]');
516 TEST_F(TEST_NAME, 'GetGroupsToRequestWithGroups', function() {
517 this.makeAndRegisterMockApis([
518 'fillFromChromeLocalStorage',
522 this.mockApis.expects(once())
523 .fillFromChromeLocalStorage(eqJSON({notificationGroups: {}}))
524 .will(returnValue(Promise.resolve({notificationGroups: {
525 TIME18: {nextPollTime: 18},
526 TIME19: {nextPollTime: 19},
527 TIME20: {nextPollTime: 20},
528 TIME21: {nextPollTime: 21},
529 TIME22: {nextPollTime: 22},
533 this.mockApis.expects(once()).Date_now().will(returnValue(20));
535 getGroupsToRequest().then(function(groupsToRequest) {
536 assertTrue(groupsToRequest.length == 3);
537 assertTrue(groupsToRequest.indexOf('TIME18') >= 0);
538 assertTrue(groupsToRequest.indexOf('TIME19') >= 0);
539 assertTrue(groupsToRequest.indexOf('TIME20') >= 0);
546 TEST_F(TEST_NAME, 'CombineGroup', function() {
547 // Tests combineGroup function. Verifies that both notifications with and
548 // without show time are handled correctly and that cards are correctly
549 // added to existing cards with same ID or start a new combined card.
551 // Setup and expectations.
552 var combinedCards = {
556 var receivedNotificationNoShowTime = {
557 chromeNotificationId: 'EXISTING CARD',
558 trigger: {hideTimeSec: 1}
560 var receivedNotificationWithShowTime = {
561 chromeNotificationId: 'NEW CARD',
562 trigger: {showTimeSec: 2, hideTimeSec: 3}
566 cardsTimestamp: 10000,
568 receivedNotificationNoShowTime,
569 receivedNotificationWithShowTime
573 // Invoking the tested function.
574 combineGroup(combinedCards, storedGroup);
576 // Check the output value.
577 var expectedCombinedCards = {
581 receivedNotification: receivedNotificationNoShowTime,
587 receivedNotification: receivedNotificationWithShowTime,
595 JSON.stringify(expectedCombinedCards),
596 JSON.stringify(combinedCards));
600 * Mocks global functions and APIs that initialize() depends upon.
601 * @param {Test} fixture Test fixture.
603 function mockInitializeDependencies(fixture) {
604 fixture.makeAndRegisterMockGlobals([
605 'pollOptedInNoImmediateRecheck',
608 'setBackgroundEnable',
612 fixture.makeAndRegisterMockApis([
613 'authenticationManager.isSignedIn',
614 'chrome.storage.local.remove',
615 'fillFromChromeLocalStorage',
616 'instrumented.metricsPrivate.getVariationParams',
617 'instrumented.notifications.getAll',
618 'instrumented.notifications.getPermissionLevel',
619 'instrumented.webstorePrivate.getBrowserLogin',
620 'optInPollAttempts.isRunning',
621 'optInPollAttempts.stop',
623 'updateCardsAttempts.isRunning',
624 'updateCardsAttempts.stop'
629 * Sets up the test to expect the state machine calls and send
630 * the specified state machine state. Currently used to test initialize().
631 * Note that this CAN NOT be used if any of the methods below are called
632 * outside of this context with the same argument matchers.
633 * expects() calls cannot be chained with the same argument matchers.
634 * @param {object} fixture Test fixture.
635 * @param {string} testIdentityToken getAuthToken callback token.
636 * @param {object} testExperimentVariationParams Response of
637 * metricsPrivate.getVariationParams.
638 * @param {string} testExperimentVariationParams Response of
639 * notifications.getPermissionLevel.
640 * @param {boolean} testGoogleNowEnabled True if the user is opted in to Google
643 function expectStateMachineCalls(
646 testExperimentVariationParams,
647 testNotificationPermissionLevel,
648 testGoogleNowEnabled) {
649 fixture.mockApis.expects(once()).
650 authenticationManager_isSignedIn().
651 will(returnValue(new Promise(function(resolve) {
652 resolve(!!testIdentityToken);
655 var getVariationParamsSavedArgs = new SaveMockArguments();
656 fixture.mockApis.expects(once()).
657 instrumented_metricsPrivate_getVariationParams(
658 getVariationParamsSavedArgs.match(ANYTHING),
659 getVariationParamsSavedArgs.match(ANYTHING)).
661 getVariationParamsSavedArgs, 1, testExperimentVariationParams));
663 var notificationGetPermissionLevelSavedArgs = new SaveMockArguments();
664 fixture.mockApis.expects(once()).
665 instrumented_notifications_getPermissionLevel(
666 notificationGetPermissionLevelSavedArgs.match(ANYTHING)).
668 notificationGetPermissionLevelSavedArgs,
670 testNotificationPermissionLevel))
672 expectChromeLocalStorageGet(
674 {googleNowEnabled: false},
675 {googleNowEnabled: testGoogleNowEnabled});
677 var updateCardsAttemptsIsRunningSavedArgs = new SaveMockArguments();
678 fixture.mockApis.expects(once()).
679 updateCardsAttempts_isRunning(
680 updateCardsAttemptsIsRunningSavedArgs.match(ANYTHING)).
683 updateCardsAttemptsIsRunningSavedArgs, 0, undefined));
685 var optInPollAttemptsIsRunningSavedArgs = new SaveMockArguments();
686 fixture.mockApis.expects(once()).
687 optInPollAttempts_isRunning(
688 optInPollAttemptsIsRunningSavedArgs.match(ANYTHING)).
691 optInPollAttemptsIsRunningSavedArgs, 0, undefined));
695 * Sets up the test to expect the initialization calls that
696 * initialize() invokes.
697 * Note that this CAN NOT be used if any of the methods below are called
698 * outside of this context with the same argument matchers.
699 * expects() calls cannot be chained with the same argument matchers.
701 function expectInitialization(fixture) {
702 var tasksAddSavedArgs = new SaveMockArguments();
703 fixture.mockApis.expects(once()).
705 tasksAddSavedArgs.match(ANYTHING),
706 tasksAddSavedArgs.match(ANYTHING)).
707 will(invokeCallback(tasksAddSavedArgs, 1, function() {}));
709 // The ordering here between stubs and expects is important.
710 // We only care about the EXTENSION_START event. The other events are covered
711 // by the NoCards tests below. Reversing the calls will cause all recordEvent
712 // calls to be unexpected.
713 fixture.mockGlobals.stubs().recordEvent(ANYTHING);
715 expects(once()).recordEvent(GoogleNowEvent.EXTENSION_START);
718 TEST_F(TEST_NAME,'Initialize_SignedOut', function() {
719 // Tests the case when getAuthToken fails most likely because the user is
720 // not signed in. In this case, the function should quietly exit after
721 // finding out that getAuthToken fails.
723 // Setup and expectations.
724 var testIdentityToken = undefined;
725 var testExperimentVariationParams = {};
726 var testNotificationPermissionLevel = 'denied';
727 var testGoogleNowEnabled = undefined;
729 mockInitializeDependencies(this);
731 expectInitialization(this);
733 expectStateMachineCalls(
736 testExperimentVariationParams,
737 testNotificationPermissionLevel,
738 testGoogleNowEnabled);
740 this.mockGlobals.expects(once()).setBackgroundEnable(false);
741 this.mockGlobals.expects(never()).startPollingCards();
742 this.mockGlobals.expects(once()).stopPollingCards();
743 this.mockGlobals.expects(once()).removeAllCards();
744 this.mockGlobals.expects(never()).pollOptedInNoImmediateRecheck();
745 this.mockApis.expects(once()).optInPollAttempts_stop();
747 // Invoking the tested function.
751 TEST_F(TEST_NAME,'Initialize_NotificationDisabled', function() {
752 // Tests the case when Google Now is disabled in the notifications center.
754 // Setup and expectations.
755 var testIdentityToken = 'some identity token';
756 var testExperimentVariationParams = {};
757 var testNotificationPermissionLevel = 'denied';
758 var testGoogleNowEnabled = undefined;
760 mockInitializeDependencies(this);
762 expectInitialization(this);
764 expectStateMachineCalls(
767 testExperimentVariationParams,
768 testNotificationPermissionLevel,
769 testGoogleNowEnabled);
771 this.mockGlobals.expects(once()).setBackgroundEnable(false);
772 this.mockGlobals.expects(never()).startPollingCards();
773 this.mockGlobals.expects(once()).stopPollingCards();
774 this.mockGlobals.expects(once()).removeAllCards();
775 this.mockGlobals.expects(never()).pollOptedInNoImmediateRecheck();
776 this.mockApis.expects(once()).optInPollAttempts_stop();
778 // Invoking the tested function.
782 TEST_F(TEST_NAME, 'Initialize_NoBackground', function() {
783 // Tests when the no background variation is received.
785 // Setup and expectations.
786 var testIdentityToken = 'some identity token';
787 var testExperimentVariationParams = {canEnableBackground: 'false'};
788 var testNotificationPermissionLevel = 'granted';
789 var testGoogleNowEnabled = true;
791 mockInitializeDependencies(this);
793 expectInitialization(this);
795 expectStateMachineCalls(
798 testExperimentVariationParams,
799 testNotificationPermissionLevel,
800 testGoogleNowEnabled);
802 this.mockGlobals.expects(once()).setBackgroundEnable(false);
803 this.mockGlobals.expects(once()).startPollingCards();
804 this.mockGlobals.expects(never()).stopPollingCards();
805 this.mockGlobals.expects(never()).removeAllCards();
806 this.mockGlobals.expects(never()).pollOptedInNoImmediateRecheck();
807 this.mockApis.expects(once()).optInPollAttempts_stop();
809 // Invoking the tested function.
813 TEST_F(TEST_NAME, 'Initialize_GoogleNowDisabled', function() {
814 // Tests when the user has Google Now disabled.
816 // Setup and expectations.
817 var testIdentityToken = 'some identity token';
818 var testExperimentVariationParams = {};
819 var testNotificationPermissionLevel = 'granted';
820 var testGoogleNowEnabled = false;
822 mockInitializeDependencies(this);
824 expectInitialization(this);
826 expectStateMachineCalls(
829 testExperimentVariationParams,
830 testNotificationPermissionLevel,
831 testGoogleNowEnabled);
833 this.mockGlobals.expects(once()).setBackgroundEnable(false);
834 this.mockGlobals.expects(never()).startPollingCards();
835 this.mockGlobals.expects(once()).stopPollingCards();
836 this.mockGlobals.expects(once()).removeAllCards();
837 this.mockGlobals.expects(once()).pollOptedInNoImmediateRecheck();
838 this.mockApis.expects(never()).optInPollAttempts_stop();
840 // Invoking the tested function.
844 TEST_F(TEST_NAME, 'Initialize_RunGoogleNow', function() {
845 // Tests if Google Now will invoke startPollingCards when all
846 // of the required state is fulfilled.
848 // Setup and expectations.
849 var testIdentityToken = 'some identity token';
850 var testExperimentVariationParams = {};
851 var testNotificationPermissionLevel = 'granted';
852 var testGoogleNowEnabled = true;
854 mockInitializeDependencies(this);
856 expectInitialization(this);
858 expectStateMachineCalls(
861 testExperimentVariationParams,
862 testNotificationPermissionLevel,
863 testGoogleNowEnabled);
865 this.mockGlobals.expects(once()).setBackgroundEnable(true);
866 this.mockGlobals.expects(once()).startPollingCards();
867 this.mockGlobals.expects(never()).stopPollingCards();
868 this.mockGlobals.expects(never()).removeAllCards();
869 this.mockGlobals.expects(never()).pollOptedInNoImmediateRecheck();
870 this.mockApis.expects(once()).optInPollAttempts_stop();
872 // Invoking the tested function.
877 * No Cards Event Recording Tests
879 TEST_F(TEST_NAME, 'NoCardsSignedOut', function() {
880 var signedIn = false;
881 var notificationEnabled = false;
882 var googleNowEnabled = false;
883 this.makeAndRegisterMockGlobals([
886 'setBackgroundEnable',
887 'setShouldPollCards',
888 'setShouldPollOptInStatus']);
890 this.mockGlobals.stubs().removeAllCards();
891 this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
892 this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
893 this.mockGlobals.stubs().setShouldPollOptInStatus(ANYTHING);
895 this.mockGlobals.expects(once()).recordEvent(
896 GoogleNowEvent.STOPPED);
897 this.mockGlobals.expects(once()).recordEvent(
898 GoogleNowEvent.SIGNED_OUT);
899 this.mockGlobals.expects(never()).recordEvent(
900 GoogleNowEvent.NOTIFICATION_DISABLED);
901 this.mockGlobals.expects(never()).recordEvent(
902 GoogleNowEvent.GOOGLE_NOW_DISABLED);
903 updateRunningState(signedIn, true, notificationEnabled, googleNowEnabled);
906 TEST_F(TEST_NAME, 'NoCardsNotificationsDisabled', function() {
908 var notificationEnabled = false;
909 var googleNowEnabled = false;
910 this.makeAndRegisterMockGlobals([
913 'setBackgroundEnable',
914 'setShouldPollCards',
915 'setShouldPollOptInStatus']);
917 this.mockGlobals.stubs().removeAllCards();
918 this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
919 this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
920 this.mockGlobals.stubs().setShouldPollOptInStatus(ANYTHING);
922 this.mockGlobals.expects(once()).recordEvent(
923 GoogleNowEvent.STOPPED);
924 this.mockGlobals.expects(never()).recordEvent(
925 GoogleNowEvent.SIGNED_OUT);
926 this.mockGlobals.expects(once()).recordEvent(
927 GoogleNowEvent.NOTIFICATION_DISABLED);
928 this.mockGlobals.expects(never()).recordEvent(
929 GoogleNowEvent.GOOGLE_NOW_DISABLED);
930 updateRunningState(signedIn, true, notificationEnabled, googleNowEnabled);
933 TEST_F(TEST_NAME, 'NoCardsGoogleNowDisabled', function() {
935 var notificationEnabled = true;
936 var googleNowEnabled = false;
937 this.makeAndRegisterMockGlobals([
940 'setBackgroundEnable',
941 'setShouldPollCards',
942 'setShouldPollOptInStatus']);
944 this.mockGlobals.stubs().removeAllCards();
945 this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
946 this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
947 this.mockGlobals.stubs().setShouldPollOptInStatus(ANYTHING);
949 this.mockGlobals.expects(never()).recordEvent(
950 GoogleNowEvent.STOPPED);
951 this.mockGlobals.expects(never()).recordEvent(
952 GoogleNowEvent.SIGNED_OUT);
953 this.mockGlobals.expects(never()).recordEvent(
954 GoogleNowEvent.NOTIFICATION_DISABLED);
955 this.mockGlobals.expects(once()).recordEvent(
956 GoogleNowEvent.GOOGLE_NOW_DISABLED);
957 updateRunningState(signedIn, true, notificationEnabled, googleNowEnabled);
960 TEST_F(TEST_NAME, 'NoCardsEverythingEnabled', function() {
962 var notificationEnabled = true;
963 var googleNowEnabled = true;
964 this.makeAndRegisterMockGlobals([
967 'setBackgroundEnable',
968 'setShouldPollCards',
969 'setShouldPollOptInStatus']);
971 this.mockGlobals.stubs().removeAllCards();
972 this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
973 this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
974 this.mockGlobals.stubs().setShouldPollOptInStatus(ANYTHING);
976 this.mockGlobals.expects(never()).recordEvent(
977 GoogleNowEvent.STOPPED);
978 this.mockGlobals.expects(never()).recordEvent(
979 GoogleNowEvent.SIGNED_OUT);
980 this.mockGlobals.expects(never()).recordEvent(
981 GoogleNowEvent.NOTIFICATION_DISABLED);
982 this.mockGlobals.expects(never()).recordEvent(
983 GoogleNowEvent.GOOGLE_NOW_DISABLED);
984 updateRunningState(signedIn, true, notificationEnabled, googleNowEnabled);
988 * Mocks global functions and APIs that onNotificationClicked() depends upon.
989 * @param {Test} fixture Test fixture.
991 function mockOnNotificationClickedDependencies(fixture) {
992 fixture.makeAndRegisterMockApis([
993 'chrome.windows.create',
994 'chrome.windows.update',
995 'fillFromChromeLocalStorage',
996 'instrumented.tabs.create']);
999 TEST_F(TEST_NAME, 'OnNotificationClicked_NoData', function() {
1000 // Tests the case when there is no data associated with notification id.
1001 // In this case, the function should do nothing.
1003 // Setup and expectations.
1004 var testNotificationId = 'TEST_ID';
1005 var testNotificationDataRequest = {notificationsData: {}};
1006 var testNotificationData = {notificationsData: {}};
1008 mockOnNotificationClickedDependencies(this);
1009 this.makeMockLocalFunctions(['selector']);
1011 expectChromeLocalStorageGet(
1012 this, testNotificationDataRequest, testNotificationData);
1014 // Invoking the tested function.
1015 onNotificationClicked(
1016 testNotificationId, this.mockLocalFunctions.functions().selector);
1019 TEST_F(TEST_NAME, 'OnNotificationClicked_ActionUrlsUndefined', function() {
1020 // Tests the case when the data associated with notification id is
1022 // In this case, the function should do nothing.
1024 // Setup and expectations.
1025 var testActionUrls = undefined;
1026 var testNotificationId = 'TEST_ID';
1027 var testNotificationDataRequest = {notificationsData: {}};
1028 var testNotificationData = {
1029 notificationsData: {'TEST_ID': {actionUrls: testActionUrls}}
1032 mockOnNotificationClickedDependencies(this);
1033 this.makeMockLocalFunctions(['selector']);
1035 expectChromeLocalStorageGet(
1036 this, testNotificationDataRequest, testNotificationData);
1038 this.mockLocalFunctions.expects(once())
1040 testNotificationData.notificationsData[testNotificationId]))
1041 .will(returnValue(undefined));
1043 // Invoking the tested function.
1044 onNotificationClicked(
1045 testNotificationId, this.mockLocalFunctions.functions().selector);
1048 TEST_F(TEST_NAME, 'OnNotificationClicked_TabCreateSuccess', function() {
1049 // Tests the selected URL is OK and crome.tabs.create suceeds.
1051 // Setup and expectations.
1052 var testActionUrls = {testField: 'TEST VALUE'};
1053 var testNotificationId = 'TEST_ID';
1054 var testNotificationDataRequest = {notificationsData: {}};
1055 var testNotificationData = {
1056 notificationsData: {'TEST_ID': {actionUrls: testActionUrls}}
1058 var testActionUrl = 'http://testurl.com';
1059 var testCreatedTab = {windowId: 239};
1061 mockOnNotificationClickedDependencies(this);
1062 this.makeMockLocalFunctions(['selector']);
1064 expectChromeLocalStorageGet(
1065 this, testNotificationDataRequest, testNotificationData);
1066 this.mockLocalFunctions.expects(once())
1068 testNotificationData.notificationsData[testNotificationId]))
1069 .will(returnValue(testActionUrl));
1070 var chromeTabsCreateSavedArgs = new SaveMockArguments();
1071 this.mockApis.expects(once()).
1072 instrumented_tabs_create(
1073 chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})),
1074 chromeTabsCreateSavedArgs.match(ANYTHING)).
1075 will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab));
1076 this.mockApis.expects(once()).chrome_windows_update(
1077 testCreatedTab.windowId,
1078 eqJSON({focused: true}));
1080 // Invoking the tested function.
1081 onNotificationClicked(
1082 testNotificationId, this.mockLocalFunctions.functions().selector);
1085 TEST_F(TEST_NAME, 'OnNotificationClicked_TabCreateFail', function() {
1086 // Tests the selected URL is OK and crome.tabs.create fails.
1087 // In this case, the function should invoke chrome.windows.create as a
1090 // Setup and expectations.
1091 var testActionUrls = {testField: 'TEST VALUE'};
1092 var testNotificationId = 'TEST_ID';
1093 var testNotificationDataRequest = {notificationsData: {}};
1094 var testNotificationData = {
1095 notificationsData: {'TEST_ID': {actionUrls: testActionUrls}}
1097 var testActionUrl = 'http://testurl.com';
1098 var testCreatedTab = undefined; // chrome.tabs.create fails
1100 mockOnNotificationClickedDependencies(this);
1101 this.makeMockLocalFunctions(['selector']);
1103 expectChromeLocalStorageGet(
1104 this, testNotificationDataRequest, testNotificationData);
1105 this.mockLocalFunctions.expects(once())
1107 testNotificationData.notificationsData[testNotificationId]))
1108 .will(returnValue(testActionUrl));
1109 var chromeTabsCreateSavedArgs = new SaveMockArguments();
1110 this.mockApis.expects(once()).
1111 instrumented_tabs_create(
1112 chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})),
1113 chromeTabsCreateSavedArgs.match(ANYTHING)).
1114 will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab));
1115 this.mockApis.expects(once()).chrome_windows_create(
1116 eqJSON({url: testActionUrl, focused: true}));
1118 // Invoking the tested function.
1119 onNotificationClicked(
1120 testNotificationId, this.mockLocalFunctions.functions().selector);
1123 TEST_F(TEST_NAME, 'ShowNotificationGroups', function() {
1124 // Tests showNotificationGroups function. Checks that the function properly
1125 // deletes the card that didn't get an update, updates existing card and
1126 // creates a new card that previously didn't exist.
1128 // Setup and expectations.
1129 var existingNotifications = {
1130 'SHOULD BE DELETED': 'SOMETHING',
1131 'SHOULD BE KEPT': 'SOMETHING'
1135 chromeNotificationId: 'SHOULD BE KEPT',
1136 trigger: {showTimeSec: 0, hideTimeSec: 0}
1139 var keptNotification = {
1140 receivedNotification: keptCard,
1146 chromeNotificationId: 'NEW CARD',
1147 trigger: {showTimeSec: 0, hideTimeSec: 0}
1150 var newNotification = {
1151 receivedNotification: newCard,
1156 var notificationGroups = {
1157 'TEST GROUP 1': {cards: [keptCard], cardsTimestamp: 0},
1158 'TEST GROUP 2': {cards: [newCard], cardsTimestamp: 0}
1161 var fakeOnCardShownFunction = 'FAKE ON CARD SHOWN FUNCTION';
1163 var expectedUpdatedNotifications = {
1164 'SHOULD BE KEPT': 'KEPT CARD NOTIFICATION DATA',
1165 'NEW CARD': 'NEW CARD NOTIFICATION DATA'
1168 this.makeAndRegisterMockApis([
1170 'chrome.storage.local.set',
1171 'instrumented.notifications.getAll'
1173 this.makeMockLocalFunctions([
1177 var notificationsGetAllSavedArgs = new SaveMockArguments();
1178 this.mockApis.expects(once()).
1179 instrumented_notifications_getAll(
1180 notificationsGetAllSavedArgs.match(ANYTHING)).
1181 will(invokeCallback(
1182 notificationsGetAllSavedArgs, 0, existingNotifications));
1184 this.mockApis.expects(once()).
1187 eqJSON([keptNotification]),
1188 eqJSON(notificationGroups),
1189 fakeOnCardShownFunction).
1190 will(returnValue('KEPT CARD NOTIFICATION DATA'));
1191 this.mockApis.expects(once()).
1194 eqJSON([newNotification]),
1195 eqJSON(notificationGroups),
1196 fakeOnCardShownFunction).
1197 will(returnValue('NEW CARD NOTIFICATION DATA'));
1198 this.mockApis.expects(once()).
1200 'SHOULD BE DELETED',
1202 eqJSON(notificationGroups),
1203 fakeOnCardShownFunction).
1204 will(returnValue(undefined));
1206 this.mockApis.expects(once()).
1207 chrome_storage_local_set(
1208 eqJSON({notificationsData: expectedUpdatedNotifications}));
1210 this.mockLocalFunctions.expects(once()).
1211 onSuccess(undefined);
1213 // Invoking the tested function.
1214 showNotificationGroups(notificationGroups, fakeOnCardShownFunction)
1215 .then(this.mockLocalFunctions.functions().onSuccess);
1218 TEST_F(TEST_NAME, 'ProcessServerResponse', function() {
1219 // Tests processServerResponse function.
1221 // Setup and expectations.
1222 Date.now = function() { return 3000000; };
1224 // GROUP1 was requested and contains cards c4 and c5. For c5, there is a
1225 // non-expired dismissal, so it will be ignored.
1226 // GROUP2 was not requested, but is contained in server response to
1227 // indicate that the group still exists. Stored group GROUP2 won't change.
1228 // GROUP3 is stored, but is not present in server's response, which means
1229 // it doesn't exist anymore. This group will be deleted.
1230 // GROUP4 doesn't contain cards, but it was requested. This is treated as
1231 // if it had an empty array of cards. Cards in the stored group will be
1232 // replaced with an empty array.
1233 // GROUP5 doesn't have next poll time, and it will be stored without next
1235 var serverResponse = {
1237 GROUP1: {requested: true, nextPollSeconds: 46},
1238 GROUP2: {requested: false},
1239 GROUP4: {requested: true, nextPollSeconds: 45},
1240 GROUP5: {requested: true}
1243 {notificationId: 'c4', groupName: 'GROUP1'},
1244 {notificationId: 'c5', groupName: 'GROUP1'}
1248 var recentDismissals = {
1249 c4: 1800000, // expired dismissal
1250 c5: 1800001 // non-expired dismissal
1253 var storedGroups = {
1255 cards: [{notificationId: 'c2'}],
1256 cardsTimestamp: 239,
1260 cards: [{notificationId: 'c3'}],
1261 cardsTimestamp: 240,
1265 cards: [{notificationId: 'c6'}],
1266 cardsTimestamp: 241,
1271 var expectedUpdatedGroups = {
1273 cards: [{notificationId: 'c4', groupName: 'GROUP1'}],
1274 cardsTimestamp: 3000000,
1275 nextPollTime: 3046000
1278 cards: [{notificationId: 'c2'}],
1279 cardsTimestamp: 239,
1284 cardsTimestamp: 3000000,
1285 nextPollTime: 3045000
1289 cardsTimestamp: 3000000
1293 var expectedUpdatedRecentDismissals = {
1297 this.makeAndRegisterMockGlobals([
1298 'scheduleNextCardsPoll'
1301 this.makeAndRegisterMockApis([
1302 'fillFromChromeLocalStorage',
1305 expectChromeLocalStorageGet(
1308 notificationGroups: {},
1309 recentDismissals: {}
1312 notificationGroups: storedGroups,
1313 recentDismissals: recentDismissals
1316 this.mockGlobals.expects(once())
1317 .scheduleNextCardsPoll(eqJSON(expectedUpdatedGroups));
1319 // Invoking the tested function.
1320 processServerResponse(serverResponse);
1323 TEST_F(TEST_NAME, 'ProcessServerResponseGoogleNowDisabled', function() {
1324 // Tests processServerResponse function for the case when the response
1325 // indicates that Google Now is disabled.
1327 // Setup and expectations.
1328 var serverResponse = {
1329 googleNowDisabled: true,
1333 this.makeAndRegisterMockGlobals([
1334 'scheduleNextCardsPoll'
1337 this.makeAndRegisterMockApis([
1338 'chrome.storage.local.set',
1339 'fillFromChromeLocalStorage'
1342 this.mockApis.expects(once()).
1343 chrome_storage_local_set(eqJSON({googleNowEnabled: false}));
1345 this.mockGlobals.expects(never()).scheduleNextCardsPoll();
1347 // Invoking the tested function.
1348 processServerResponse(serverResponse);