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 * requestAndUpdateOptIn Tests
336 TEST_F(TEST_NAME, 'RequestAndUpdateOptInOptedIn', function() {
337 this.makeAndRegisterMockApis([
338 'chrome.storage.local.set',
342 this.mockApis.expects(once()).requestFromServer('GET', 'settings/optin')
343 .will(returnValue(Promise.resolve({
345 responseText: '{"value": true}'})));
347 this.mockApis.expects(once())
348 .chrome_storage_local_set(eqJSON({googleNowEnabled: true}));
350 var thenCalled = false;
351 var catchCalled = false;
352 requestAndUpdateOptedIn().then(function(optedIn) {
355 }).catch(function() {
358 assertTrue(thenCalled);
359 assertFalse(catchCalled);
362 TEST_F(TEST_NAME, 'RequestAndUpdateOptInOptedOut', function() {
363 this.makeAndRegisterMockApis([
364 'chrome.storage.local.set',
368 this.mockApis.expects(once()).requestFromServer('GET', 'settings/optin')
369 .will(returnValue(Promise.resolve({
371 responseText: '{"value": false}'})));
373 this.mockApis.expects(once())
374 .chrome_storage_local_set(eqJSON({googleNowEnabled: false}));
376 var thenCalled = false;
377 var catchCalled = false;
378 requestAndUpdateOptedIn().then(function(optedIn) {
380 assertFalse(optedIn);
381 }).catch(function() {
384 assertTrue(thenCalled);
385 assertFalse(catchCalled);
388 TEST_F(TEST_NAME, 'RequestAndUpdateOptInFailure', function() {
389 this.makeAndRegisterMockApis([
390 'chrome.storage.local.set',
394 this.mockApis.expects(once()).requestFromServer('GET', 'settings/optin')
395 .will(returnValue(Promise.reject({status: 404})));
397 this.mockApis.expects(never()).chrome_storage_local_set();
399 var thenCalled = false;
400 var catchCalled = false;
401 requestAndUpdateOptedIn().then(function() {
403 }).catch(function() {
406 assertFalse(thenCalled);
407 assertTrue(catchCalled);
411 * pollOptedInNoImmediateRecheck Tests
413 TEST_F(TEST_NAME, 'pollOptedInNoImmediateRecheckOptedIn', function() {
414 this.makeAndRegisterMockApis([
415 'requestAndUpdateOptedIn',
416 'instrumented.metricsPrivate.getVariationParams',
417 'optInPollAttempts.start'
420 this.mockApis.expects(once()).requestAndUpdateOptedIn()
421 .will(returnValue(Promise.resolve(true)));
423 this.mockApis.expects(never())
424 .instrumented_metricsPrivate_getVariationParams();
426 this.mockApis.expects(never()).optInPollAttempts_start();
428 pollOptedInNoImmediateRecheck();
431 TEST_F(TEST_NAME, 'pollOptedInNoImmediateRecheckOptedOut', function() {
432 this.makeAndRegisterMockApis([
433 'requestAndUpdateOptedIn',
434 'instrumented.metricsPrivate.getVariationParams',
435 'optInPollAttempts.start'
438 this.mockApis.expects(once()).requestAndUpdateOptedIn()
439 .will(returnValue(Promise.resolve(false)));
441 var getVariationParamsSavedArgs = new SaveMockArguments();
442 this.mockApis.expects(once())
443 .instrumented_metricsPrivate_getVariationParams(
444 getVariationParamsSavedArgs.match(eq('GoogleNow')),
445 getVariationParamsSavedArgs.match(ANYTHING))
446 .will(invokeCallback(getVariationParamsSavedArgs, 1, {}));
448 this.mockApis.expects(once())
449 .optInPollAttempts_start(DEFAULT_OPTIN_CHECK_PERIOD_SECONDS);
451 pollOptedInNoImmediateRecheck();
454 TEST_F(TEST_NAME, 'pollOptedInNoImmediateRecheckFailure', function() {
455 this.makeAndRegisterMockApis([
456 'requestAndUpdateOptedIn',
457 'instrumented.metricsPrivate.getVariationParams',
458 'optInPollAttempts.start'
461 this.mockApis.expects(once()).requestAndUpdateOptedIn()
462 .will(returnValue(Promise.reject()));
464 var getVariationParamsSavedArgs = new SaveMockArguments();
465 this.mockApis.expects(once())
466 .instrumented_metricsPrivate_getVariationParams(
467 getVariationParamsSavedArgs.match(eq('GoogleNow')),
468 getVariationParamsSavedArgs.match(ANYTHING))
469 .will(invokeCallback(getVariationParamsSavedArgs, 1, {}));
471 this.mockApis.expects(once())
472 .optInPollAttempts_start(DEFAULT_OPTIN_CHECK_PERIOD_SECONDS);
474 pollOptedInNoImmediateRecheck();
478 * getGroupsToRequest Tests
480 TEST_F(TEST_NAME, 'GetGroupsToRequestNone', function() {
481 this.makeAndRegisterMockApis([
482 'fillFromChromeLocalStorage',
486 this.mockApis.expects(once())
487 .fillFromChromeLocalStorage(eqJSON({notificationGroups: {}}))
488 .will(returnValue(Promise.resolve({notificationGroups: {}})));
490 this.mockApis.expects(once()).Date_now().will(returnValue(20));
492 getGroupsToRequest().then(function(groupsToRequest) {
493 assertTrue(JSON.stringify(groupsToRequest) === '[]');
497 TEST_F(TEST_NAME, 'GetGroupsToRequestWithGroups', function() {
498 this.makeAndRegisterMockApis([
499 'fillFromChromeLocalStorage',
503 this.mockApis.expects(once())
504 .fillFromChromeLocalStorage(eqJSON({notificationGroups: {}}))
505 .will(returnValue(Promise.resolve({notificationGroups: {
506 TIME18: {nextPollTime: 18},
507 TIME19: {nextPollTime: 19},
508 TIME20: {nextPollTime: 20},
509 TIME21: {nextPollTime: 21},
510 TIME22: {nextPollTime: 22},
514 this.mockApis.expects(once()).Date_now().will(returnValue(20));
516 getGroupsToRequest().then(function(groupsToRequest) {
517 assertTrue(groupsToRequest.length == 3);
518 assertTrue(groupsToRequest.indexOf('TIME18') >= 0);
519 assertTrue(groupsToRequest.indexOf('TIME19') >= 0);
520 assertTrue(groupsToRequest.indexOf('TIME20') >= 0);
527 TEST_F(TEST_NAME, 'CombineGroup', function() {
528 // Tests combineGroup function. Verifies that both notifications with and
529 // without show time are handled correctly and that cards are correctly
530 // added to existing cards with same ID or start a new combined card.
532 // Setup and expectations.
533 var combinedCards = {
537 var receivedNotificationNoShowTime = {
538 chromeNotificationId: 'EXISTING CARD',
539 trigger: {hideTimeSec: 1}
541 var receivedNotificationWithShowTime = {
542 chromeNotificationId: 'NEW CARD',
543 trigger: {showTimeSec: 2, hideTimeSec: 3}
547 cardsTimestamp: 10000,
549 receivedNotificationNoShowTime,
550 receivedNotificationWithShowTime
554 // Invoking the tested function.
555 combineGroup(combinedCards, storedGroup);
557 // Check the output value.
558 var expectedCombinedCards = {
562 receivedNotification: receivedNotificationNoShowTime,
568 receivedNotification: receivedNotificationWithShowTime,
576 JSON.stringify(expectedCombinedCards),
577 JSON.stringify(combinedCards));
581 * Mocks global functions and APIs that initialize() depends upon.
582 * @param {Test} fixture Test fixture.
584 function mockInitializeDependencies(fixture) {
585 fixture.makeAndRegisterMockGlobals([
586 'pollOptedInNoImmediateRecheck',
589 'setBackgroundEnable',
593 fixture.makeAndRegisterMockApis([
594 'authenticationManager.isSignedIn',
595 'chrome.storage.local.remove',
596 'fillFromChromeLocalStorage',
597 'instrumented.metricsPrivate.getVariationParams',
598 'instrumented.notifications.getAll',
599 'instrumented.notifications.getPermissionLevel',
600 'instrumented.webstorePrivate.getBrowserLogin',
601 'optInPollAttempts.isRunning',
602 'optInPollAttempts.stop',
604 'updateCardsAttempts.isRunning',
605 'updateCardsAttempts.stop'
610 * Sets up the test to expect the state machine calls and send
611 * the specified state machine state. Currently used to test initialize().
612 * Note that this CAN NOT be used if any of the methods below are called
613 * outside of this context with the same argument matchers.
614 * expects() calls cannot be chained with the same argument matchers.
615 * @param {object} fixture Test fixture.
616 * @param {string} testIdentityToken getAuthToken callback token.
617 * @param {object} testExperimentVariationParams Response of
618 * metricsPrivate.getVariationParams.
619 * @param {string} testExperimentVariationParams Response of
620 * notifications.getPermissionLevel.
621 * @param {boolean} testGoogleNowEnabled True if the user is opted in to Google
624 function expectStateMachineCalls(
627 testExperimentVariationParams,
628 testNotificationPermissionLevel,
629 testGoogleNowEnabled) {
630 fixture.mockApis.expects(once()).
631 authenticationManager_isSignedIn().
632 will(returnValue(new Promise(function(resolve) {
633 resolve(!!testIdentityToken);
636 var getVariationParamsSavedArgs = new SaveMockArguments();
637 fixture.mockApis.expects(once()).
638 instrumented_metricsPrivate_getVariationParams(
639 getVariationParamsSavedArgs.match(ANYTHING),
640 getVariationParamsSavedArgs.match(ANYTHING)).
642 getVariationParamsSavedArgs, 1, testExperimentVariationParams));
644 var notificationGetPermissionLevelSavedArgs = new SaveMockArguments();
645 fixture.mockApis.expects(once()).
646 instrumented_notifications_getPermissionLevel(
647 notificationGetPermissionLevelSavedArgs.match(ANYTHING)).
649 notificationGetPermissionLevelSavedArgs,
651 testNotificationPermissionLevel))
653 expectChromeLocalStorageGet(
655 {googleNowEnabled: false},
656 {googleNowEnabled: testGoogleNowEnabled});
658 var updateCardsAttemptsIsRunningSavedArgs = new SaveMockArguments();
659 fixture.mockApis.expects(once()).
660 updateCardsAttempts_isRunning(
661 updateCardsAttemptsIsRunningSavedArgs.match(ANYTHING)).
664 updateCardsAttemptsIsRunningSavedArgs, 0, undefined));
666 var optInPollAttemptsIsRunningSavedArgs = new SaveMockArguments();
667 fixture.mockApis.expects(once()).
668 optInPollAttempts_isRunning(
669 optInPollAttemptsIsRunningSavedArgs.match(ANYTHING)).
672 optInPollAttemptsIsRunningSavedArgs, 0, undefined));
676 * Sets up the test to expect the initialization calls that
677 * initialize() invokes.
678 * Note that this CAN NOT be used if any of the methods below are called
679 * outside of this context with the same argument matchers.
680 * expects() calls cannot be chained with the same argument matchers.
682 function expectInitialization(fixture) {
683 var tasksAddSavedArgs = new SaveMockArguments();
684 fixture.mockApis.expects(once()).
686 tasksAddSavedArgs.match(ANYTHING),
687 tasksAddSavedArgs.match(ANYTHING)).
688 will(invokeCallback(tasksAddSavedArgs, 1, function() {}));
690 // The ordering here between stubs and expects is important.
691 // We only care about the EXTENSION_START event. The other events are covered
692 // by the NoCards tests below. Reversing the calls will cause all recordEvent
693 // calls to be unexpected.
694 fixture.mockGlobals.stubs().recordEvent(ANYTHING);
696 expects(once()).recordEvent(GoogleNowEvent.EXTENSION_START);
699 TEST_F(TEST_NAME,'Initialize_SignedOut', function() {
700 // Tests the case when getAuthToken fails most likely because the user is
701 // not signed in. In this case, the function should quietly exit after
702 // finding out that getAuthToken fails.
704 // Setup and expectations.
705 var testIdentityToken = undefined;
706 var testExperimentVariationParams = {};
707 var testNotificationPermissionLevel = 'denied';
708 var testGoogleNowEnabled = undefined;
710 mockInitializeDependencies(this);
712 expectInitialization(this);
714 expectStateMachineCalls(
717 testExperimentVariationParams,
718 testNotificationPermissionLevel,
719 testGoogleNowEnabled);
721 this.mockGlobals.expects(once()).setBackgroundEnable(false);
722 this.mockGlobals.expects(never()).startPollingCards();
723 this.mockGlobals.expects(once()).stopPollingCards();
724 this.mockGlobals.expects(once()).removeAllCards();
725 this.mockGlobals.expects(never()).pollOptedInNoImmediateRecheck();
726 this.mockApis.expects(once()).optInPollAttempts_stop();
728 // Invoking the tested function.
732 TEST_F(TEST_NAME,'Initialize_NotificationDisabled', function() {
733 // Tests the case when Google Now is disabled in the notifications center.
735 // Setup and expectations.
736 var testIdentityToken = 'some identity token';
737 var testExperimentVariationParams = {};
738 var testNotificationPermissionLevel = 'denied';
739 var testGoogleNowEnabled = undefined;
741 mockInitializeDependencies(this);
743 expectInitialization(this);
745 expectStateMachineCalls(
748 testExperimentVariationParams,
749 testNotificationPermissionLevel,
750 testGoogleNowEnabled);
752 this.mockGlobals.expects(once()).setBackgroundEnable(false);
753 this.mockGlobals.expects(never()).startPollingCards();
754 this.mockGlobals.expects(once()).stopPollingCards();
755 this.mockGlobals.expects(once()).removeAllCards();
756 this.mockGlobals.expects(never()).pollOptedInNoImmediateRecheck();
757 this.mockApis.expects(once()).optInPollAttempts_stop();
759 // Invoking the tested function.
763 TEST_F(TEST_NAME, 'Initialize_NoBackground', function() {
764 // Tests when the no background variation is received.
766 // Setup and expectations.
767 var testIdentityToken = 'some identity token';
768 var testExperimentVariationParams = {canEnableBackground: 'false'};
769 var testNotificationPermissionLevel = 'granted';
770 var testGoogleNowEnabled = true;
772 mockInitializeDependencies(this);
774 expectInitialization(this);
776 expectStateMachineCalls(
779 testExperimentVariationParams,
780 testNotificationPermissionLevel,
781 testGoogleNowEnabled);
783 this.mockGlobals.expects(once()).setBackgroundEnable(false);
784 this.mockGlobals.expects(once()).startPollingCards();
785 this.mockGlobals.expects(never()).stopPollingCards();
786 this.mockGlobals.expects(never()).removeAllCards();
787 this.mockGlobals.expects(never()).pollOptedInNoImmediateRecheck();
788 this.mockApis.expects(once()).optInPollAttempts_stop();
790 // Invoking the tested function.
794 TEST_F(TEST_NAME, 'Initialize_GoogleNowDisabled', function() {
795 // Tests when the user has Google Now disabled.
797 // Setup and expectations.
798 var testIdentityToken = 'some identity token';
799 var testExperimentVariationParams = {};
800 var testNotificationPermissionLevel = 'granted';
801 var testGoogleNowEnabled = false;
803 mockInitializeDependencies(this);
805 expectInitialization(this);
807 expectStateMachineCalls(
810 testExperimentVariationParams,
811 testNotificationPermissionLevel,
812 testGoogleNowEnabled);
814 this.mockGlobals.expects(once()).setBackgroundEnable(false);
815 this.mockGlobals.expects(never()).startPollingCards();
816 this.mockGlobals.expects(once()).stopPollingCards();
817 this.mockGlobals.expects(once()).removeAllCards();
818 this.mockGlobals.expects(once()).pollOptedInNoImmediateRecheck();
819 this.mockApis.expects(never()).optInPollAttempts_stop();
821 // Invoking the tested function.
825 TEST_F(TEST_NAME, 'Initialize_RunGoogleNow', function() {
826 // Tests if Google Now will invoke startPollingCards when all
827 // of the required state is fulfilled.
829 // Setup and expectations.
830 var testIdentityToken = 'some identity token';
831 var testExperimentVariationParams = {};
832 var testNotificationPermissionLevel = 'granted';
833 var testGoogleNowEnabled = true;
835 mockInitializeDependencies(this);
837 expectInitialization(this);
839 expectStateMachineCalls(
842 testExperimentVariationParams,
843 testNotificationPermissionLevel,
844 testGoogleNowEnabled);
846 this.mockGlobals.expects(once()).setBackgroundEnable(true);
847 this.mockGlobals.expects(once()).startPollingCards();
848 this.mockGlobals.expects(never()).stopPollingCards();
849 this.mockGlobals.expects(never()).removeAllCards();
850 this.mockGlobals.expects(never()).pollOptedInNoImmediateRecheck();
851 this.mockApis.expects(once()).optInPollAttempts_stop();
853 // Invoking the tested function.
858 * No Cards Event Recording Tests
860 TEST_F(TEST_NAME, 'NoCardsSignedOut', function() {
861 var signedIn = false;
862 var notificationEnabled = false;
863 var googleNowEnabled = false;
864 this.makeAndRegisterMockGlobals([
867 'setBackgroundEnable',
868 'setShouldPollCards',
869 'setShouldPollOptInStatus']);
871 this.mockGlobals.stubs().removeAllCards();
872 this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
873 this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
874 this.mockGlobals.stubs().setShouldPollOptInStatus(ANYTHING);
876 this.mockGlobals.expects(once()).recordEvent(
877 GoogleNowEvent.STOPPED);
878 this.mockGlobals.expects(once()).recordEvent(
879 GoogleNowEvent.SIGNED_OUT);
880 this.mockGlobals.expects(never()).recordEvent(
881 GoogleNowEvent.NOTIFICATION_DISABLED);
882 this.mockGlobals.expects(never()).recordEvent(
883 GoogleNowEvent.GOOGLE_NOW_DISABLED);
884 updateRunningState(signedIn, true, notificationEnabled, googleNowEnabled);
887 TEST_F(TEST_NAME, 'NoCardsNotificationsDisabled', function() {
889 var notificationEnabled = false;
890 var googleNowEnabled = false;
891 this.makeAndRegisterMockGlobals([
894 'setBackgroundEnable',
895 'setShouldPollCards',
896 'setShouldPollOptInStatus']);
898 this.mockGlobals.stubs().removeAllCards();
899 this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
900 this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
901 this.mockGlobals.stubs().setShouldPollOptInStatus(ANYTHING);
903 this.mockGlobals.expects(once()).recordEvent(
904 GoogleNowEvent.STOPPED);
905 this.mockGlobals.expects(never()).recordEvent(
906 GoogleNowEvent.SIGNED_OUT);
907 this.mockGlobals.expects(once()).recordEvent(
908 GoogleNowEvent.NOTIFICATION_DISABLED);
909 this.mockGlobals.expects(never()).recordEvent(
910 GoogleNowEvent.GOOGLE_NOW_DISABLED);
911 updateRunningState(signedIn, true, notificationEnabled, googleNowEnabled);
914 TEST_F(TEST_NAME, 'NoCardsGoogleNowDisabled', function() {
916 var notificationEnabled = true;
917 var googleNowEnabled = false;
918 this.makeAndRegisterMockGlobals([
921 'setBackgroundEnable',
922 'setShouldPollCards',
923 'setShouldPollOptInStatus']);
925 this.mockGlobals.stubs().removeAllCards();
926 this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
927 this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
928 this.mockGlobals.stubs().setShouldPollOptInStatus(ANYTHING);
930 this.mockGlobals.expects(never()).recordEvent(
931 GoogleNowEvent.STOPPED);
932 this.mockGlobals.expects(never()).recordEvent(
933 GoogleNowEvent.SIGNED_OUT);
934 this.mockGlobals.expects(never()).recordEvent(
935 GoogleNowEvent.NOTIFICATION_DISABLED);
936 this.mockGlobals.expects(once()).recordEvent(
937 GoogleNowEvent.GOOGLE_NOW_DISABLED);
938 updateRunningState(signedIn, true, notificationEnabled, googleNowEnabled);
941 TEST_F(TEST_NAME, 'NoCardsEverythingEnabled', function() {
943 var notificationEnabled = true;
944 var googleNowEnabled = true;
945 this.makeAndRegisterMockGlobals([
948 'setBackgroundEnable',
949 'setShouldPollCards',
950 'setShouldPollOptInStatus']);
952 this.mockGlobals.stubs().removeAllCards();
953 this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
954 this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
955 this.mockGlobals.stubs().setShouldPollOptInStatus(ANYTHING);
957 this.mockGlobals.expects(never()).recordEvent(
958 GoogleNowEvent.STOPPED);
959 this.mockGlobals.expects(never()).recordEvent(
960 GoogleNowEvent.SIGNED_OUT);
961 this.mockGlobals.expects(never()).recordEvent(
962 GoogleNowEvent.NOTIFICATION_DISABLED);
963 this.mockGlobals.expects(never()).recordEvent(
964 GoogleNowEvent.GOOGLE_NOW_DISABLED);
965 updateRunningState(signedIn, true, notificationEnabled, googleNowEnabled);
969 * Mocks global functions and APIs that onNotificationClicked() depends upon.
970 * @param {Test} fixture Test fixture.
972 function mockOnNotificationClickedDependencies(fixture) {
973 fixture.makeAndRegisterMockApis([
974 'chrome.windows.create',
975 'chrome.windows.update',
976 'fillFromChromeLocalStorage',
977 'instrumented.tabs.create']);
980 TEST_F(TEST_NAME, 'OnNotificationClicked_NoData', function() {
981 // Tests the case when there is no data associated with notification id.
982 // In this case, the function should do nothing.
984 // Setup and expectations.
985 var testNotificationId = 'TEST_ID';
986 var testNotificationDataRequest = {notificationsData: {}};
987 var testNotificationData = {notificationsData: {}};
989 mockOnNotificationClickedDependencies(this);
990 this.makeMockLocalFunctions(['selector']);
992 expectChromeLocalStorageGet(
993 this, testNotificationDataRequest, testNotificationData);
995 // Invoking the tested function.
996 onNotificationClicked(
997 testNotificationId, this.mockLocalFunctions.functions().selector);
1000 TEST_F(TEST_NAME, 'OnNotificationClicked_ActionUrlsUndefined', function() {
1001 // Tests the case when the data associated with notification id is
1003 // In this case, the function should do nothing.
1005 // Setup and expectations.
1006 var testActionUrls = undefined;
1007 var testNotificationId = 'TEST_ID';
1008 var testNotificationDataRequest = {notificationsData: {}};
1009 var testNotificationData = {
1010 notificationsData: {'TEST_ID': {actionUrls: testActionUrls}}
1013 mockOnNotificationClickedDependencies(this);
1014 this.makeMockLocalFunctions(['selector']);
1016 expectChromeLocalStorageGet(
1017 this, testNotificationDataRequest, testNotificationData);
1019 this.mockLocalFunctions.expects(once())
1021 testNotificationData.notificationsData[testNotificationId]))
1022 .will(returnValue(undefined));
1024 // Invoking the tested function.
1025 onNotificationClicked(
1026 testNotificationId, this.mockLocalFunctions.functions().selector);
1029 TEST_F(TEST_NAME, 'OnNotificationClicked_TabCreateSuccess', function() {
1030 // Tests the selected URL is OK and crome.tabs.create suceeds.
1032 // Setup and expectations.
1033 var testActionUrls = {testField: 'TEST VALUE'};
1034 var testNotificationId = 'TEST_ID';
1035 var testNotificationDataRequest = {notificationsData: {}};
1036 var testNotificationData = {
1037 notificationsData: {'TEST_ID': {actionUrls: testActionUrls}}
1039 var testActionUrl = 'http://testurl.com';
1040 var testCreatedTab = {windowId: 239};
1042 mockOnNotificationClickedDependencies(this);
1043 this.makeMockLocalFunctions(['selector']);
1045 expectChromeLocalStorageGet(
1046 this, testNotificationDataRequest, testNotificationData);
1047 this.mockLocalFunctions.expects(once())
1049 testNotificationData.notificationsData[testNotificationId]))
1050 .will(returnValue(testActionUrl));
1051 var chromeTabsCreateSavedArgs = new SaveMockArguments();
1052 this.mockApis.expects(once()).
1053 instrumented_tabs_create(
1054 chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})),
1055 chromeTabsCreateSavedArgs.match(ANYTHING)).
1056 will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab));
1057 this.mockApis.expects(once()).chrome_windows_update(
1058 testCreatedTab.windowId,
1059 eqJSON({focused: true}));
1061 // Invoking the tested function.
1062 onNotificationClicked(
1063 testNotificationId, this.mockLocalFunctions.functions().selector);
1066 TEST_F(TEST_NAME, 'OnNotificationClicked_TabCreateFail', function() {
1067 // Tests the selected URL is OK and crome.tabs.create fails.
1068 // In this case, the function should invoke chrome.windows.create as a
1071 // Setup and expectations.
1072 var testActionUrls = {testField: 'TEST VALUE'};
1073 var testNotificationId = 'TEST_ID';
1074 var testNotificationDataRequest = {notificationsData: {}};
1075 var testNotificationData = {
1076 notificationsData: {'TEST_ID': {actionUrls: testActionUrls}}
1078 var testActionUrl = 'http://testurl.com';
1079 var testCreatedTab = undefined; // chrome.tabs.create fails
1081 mockOnNotificationClickedDependencies(this);
1082 this.makeMockLocalFunctions(['selector']);
1084 expectChromeLocalStorageGet(
1085 this, testNotificationDataRequest, testNotificationData);
1086 this.mockLocalFunctions.expects(once())
1088 testNotificationData.notificationsData[testNotificationId]))
1089 .will(returnValue(testActionUrl));
1090 var chromeTabsCreateSavedArgs = new SaveMockArguments();
1091 this.mockApis.expects(once()).
1092 instrumented_tabs_create(
1093 chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})),
1094 chromeTabsCreateSavedArgs.match(ANYTHING)).
1095 will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab));
1096 this.mockApis.expects(once()).chrome_windows_create(
1097 eqJSON({url: testActionUrl, focused: true}));
1099 // Invoking the tested function.
1100 onNotificationClicked(
1101 testNotificationId, this.mockLocalFunctions.functions().selector);
1104 TEST_F(TEST_NAME, 'ShowNotificationGroups', function() {
1105 // Tests showNotificationGroups function. Checks that the function properly
1106 // deletes the card that didn't get an update, updates existing card and
1107 // creates a new card that previously didn't exist.
1109 // Setup and expectations.
1110 var existingNotifications = {
1111 'SHOULD BE DELETED': 'SOMETHING',
1112 'SHOULD BE KEPT': 'SOMETHING'
1116 chromeNotificationId: 'SHOULD BE KEPT',
1117 trigger: {showTimeSec: 0, hideTimeSec: 0}
1120 var keptNotification = {
1121 receivedNotification: keptCard,
1127 chromeNotificationId: 'NEW CARD',
1128 trigger: {showTimeSec: 0, hideTimeSec: 0}
1131 var newNotification = {
1132 receivedNotification: newCard,
1137 var notificationGroups = {
1138 'TEST GROUP 1': {cards: [keptCard], cardsTimestamp: 0},
1139 'TEST GROUP 2': {cards: [newCard], cardsTimestamp: 0}
1142 var fakeOnCardShownFunction = 'FAKE ON CARD SHOWN FUNCTION';
1144 var expectedUpdatedNotifications = {
1145 'SHOULD BE KEPT': 'KEPT CARD NOTIFICATION DATA',
1146 'NEW CARD': 'NEW CARD NOTIFICATION DATA'
1149 this.makeAndRegisterMockApis([
1151 'chrome.storage.local.set',
1152 'instrumented.notifications.getAll'
1154 this.makeMockLocalFunctions([
1158 var notificationsGetAllSavedArgs = new SaveMockArguments();
1159 this.mockApis.expects(once()).
1160 instrumented_notifications_getAll(
1161 notificationsGetAllSavedArgs.match(ANYTHING)).
1162 will(invokeCallback(
1163 notificationsGetAllSavedArgs, 0, existingNotifications));
1165 this.mockApis.expects(once()).
1168 eqJSON([keptNotification]),
1169 eqJSON(notificationGroups),
1170 fakeOnCardShownFunction).
1171 will(returnValue('KEPT CARD NOTIFICATION DATA'));
1172 this.mockApis.expects(once()).
1175 eqJSON([newNotification]),
1176 eqJSON(notificationGroups),
1177 fakeOnCardShownFunction).
1178 will(returnValue('NEW CARD NOTIFICATION DATA'));
1179 this.mockApis.expects(once()).
1181 'SHOULD BE DELETED',
1183 eqJSON(notificationGroups),
1184 fakeOnCardShownFunction).
1185 will(returnValue(undefined));
1187 this.mockApis.expects(once()).
1188 chrome_storage_local_set(
1189 eqJSON({notificationsData: expectedUpdatedNotifications}));
1191 this.mockLocalFunctions.expects(once()).
1192 onSuccess(undefined);
1194 // Invoking the tested function.
1195 showNotificationGroups(notificationGroups, fakeOnCardShownFunction)
1196 .then(this.mockLocalFunctions.functions().onSuccess);
1199 TEST_F(TEST_NAME, 'ProcessServerResponse', function() {
1200 // Tests processServerResponse function.
1202 // Setup and expectations.
1203 Date.now = function() { return 3000000; };
1205 // GROUP1 was requested and contains cards c4 and c5. For c5, there is a
1206 // non-expired dismissal, so it will be ignored.
1207 // GROUP2 was not requested, but is contained in server response to
1208 // indicate that the group still exists. Stored group GROUP2 won't change.
1209 // GROUP3 is stored, but is not present in server's response, which means
1210 // it doesn't exist anymore. This group will be deleted.
1211 // GROUP4 doesn't contain cards, but it was requested. This is treated as
1212 // if it had an empty array of cards. Cards in the stored group will be
1213 // replaced with an empty array.
1214 // GROUP5 doesn't have next poll time, and it will be stored without next
1216 var serverResponse = {
1218 GROUP1: {requested: true, nextPollSeconds: 46},
1219 GROUP2: {requested: false},
1220 GROUP4: {requested: true, nextPollSeconds: 45},
1221 GROUP5: {requested: true}
1224 {notificationId: 'c4', groupName: 'GROUP1'},
1225 {notificationId: 'c5', groupName: 'GROUP1'}
1229 var recentDismissals = {
1230 c4: 1800000, // expired dismissal
1231 c5: 1800001 // non-expired dismissal
1234 var storedGroups = {
1236 cards: [{notificationId: 'c2'}],
1237 cardsTimestamp: 239,
1241 cards: [{notificationId: 'c3'}],
1242 cardsTimestamp: 240,
1246 cards: [{notificationId: 'c6'}],
1247 cardsTimestamp: 241,
1252 var expectedUpdatedGroups = {
1254 cards: [{notificationId: 'c4', groupName: 'GROUP1'}],
1255 cardsTimestamp: 3000000,
1256 nextPollTime: 3046000
1259 cards: [{notificationId: 'c2'}],
1260 cardsTimestamp: 239,
1265 cardsTimestamp: 3000000,
1266 nextPollTime: 3045000
1270 cardsTimestamp: 3000000
1274 var expectedUpdatedRecentDismissals = {
1278 this.makeAndRegisterMockGlobals([
1279 'scheduleNextCardsPoll'
1282 this.makeAndRegisterMockApis([
1283 'fillFromChromeLocalStorage',
1286 expectChromeLocalStorageGet(
1289 notificationGroups: {},
1290 recentDismissals: {}
1293 notificationGroups: storedGroups,
1294 recentDismissals: recentDismissals
1297 this.mockGlobals.expects(once())
1298 .scheduleNextCardsPoll(eqJSON(expectedUpdatedGroups));
1300 // Invoking the tested function.
1301 processServerResponse(serverResponse);
1304 TEST_F(TEST_NAME, 'ProcessServerResponseGoogleNowDisabled', function() {
1305 // Tests processServerResponse function for the case when the response
1306 // indicates that Google Now is disabled.
1308 // Setup and expectations.
1309 var serverResponse = {
1310 googleNowDisabled: true,
1314 this.makeAndRegisterMockGlobals([
1315 'scheduleNextCardsPoll'
1318 this.makeAndRegisterMockApis([
1319 'chrome.storage.local.set',
1320 'fillFromChromeLocalStorage'
1323 this.mockApis.expects(once()).
1324 chrome_storage_local_set(eqJSON({googleNowEnabled: false}));
1326 this.mockGlobals.expects(never()).scheduleNextCardsPoll();
1328 // Invoking the tested function.
1329 processServerResponse(serverResponse);