Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / resources / google_now / background_unittest.gtestjs
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // TODO(robliao,vadimt): Determine the granularity of testing to perform.
6
7 /**
8  * Test fixture for background.js.
9  * @constructor
10  * @extends {testing.Test}
11  */
12 function GoogleNowBackgroundUnitTest () {
13   testing.Test.call(this);
14 }
15
16 GoogleNowBackgroundUnitTest.prototype = {
17   __proto__: testing.Test.prototype,
18
19   /** @override */
20   extraLibraries: [
21     'common_test_util.js',
22     'background_test_util.js',
23     'background.js'
24   ]
25 };
26
27 var TEST_NAME = 'GoogleNowBackgroundUnitTest';
28
29 /**
30  * Tasks Conflict Test
31  */
32 TEST_F(TEST_NAME, 'AreTasksConflicting', function() {
33   function testTaskPair(newTaskName, scheduledTaskName, expected) {
34     assertTrue(areTasksConflicting(newTaskName, scheduledTaskName) == expected,
35                '(' + newTaskName + ', ' + scheduledTaskName + ')');
36   }
37
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);
42
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);
47
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);
52
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);
57 });
58
59 /**
60  * Server Request Tests
61  */
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 === '{}');
69   });
70   assertTrue(callbackCalled);
71 });
72
73 TEST_F(TEST_NAME, 'AuthServerRequestForbidden', function() {
74   this.makeAndRegisterMockApis(['authenticationManager.removeToken']);
75   this.mockApis.expects(once()).authenticationManager_removeToken(ANYTHING);
76
77   expectServerRequests(this, 403, '');
78
79   var thenCalled = false;
80   var catchCalled = false;
81   requestFromServer('GET', 'test/target').then(function(request) {
82     thenCalled = true;
83   }).catch(function(request) {
84     // The promise is rejected on HTTP failures.
85     catchCalled = true;
86     assertTrue(request.status === 403);
87   });
88   assertFalse(thenCalled);
89   assertTrue(catchCalled);
90 });
91
92 TEST_F(TEST_NAME, 'AuthServerRequestNoAuth', function() {
93   this.makeAndRegisterMockApis(['authenticationManager.removeToken']);
94   this.mockApis.expects(once()).authenticationManager_removeToken(ANYTHING);
95
96   expectServerRequests(this, 401, '');
97
98   var thenCalled = false;
99   var catchCalled = false;
100   requestFromServer('GET', 'test/target').then(function(request) {
101     thenCalled = true;
102   }).catch(function(request) {
103     // The promise is rejected on HTTP failures.
104     catchCalled = true;
105     assertTrue(request.status === 401);
106   });
107   assertFalse(thenCalled);
108   assertTrue(catchCalled);
109 });
110
111 function expectServerRequests(fixture, httpStatus, responseText) {
112   fixture.makeAndRegisterMockApis([
113     'authenticationManager.getAuthToken',
114     'buildServerRequest'
115   ]);
116
117   function XMLHttpRequest() {}
118
119   XMLHttpRequest.prototype = {
120     addEventListener: function(type, listener, wantsUntrusted) {},
121     setRequestHeader: function(header, value) {},
122     send: function() {}
123   }
124
125   fixture.mockApis.expects(once()).authenticationManager_getAuthToken()
126       .will(returnValue(Promise.resolve('token')));
127
128   var mockXMLHttpRequest = mock(XMLHttpRequest);
129   var mockXMLHttpRequestProxy = mockXMLHttpRequest.proxy();
130   fixture.mockApis.expects(once())
131       .buildServerRequest(ANYTHING, ANYTHING, ANYTHING)
132       .will(returnValue(mockXMLHttpRequestProxy));
133
134   mockXMLHttpRequest.expects(once())
135       .setRequestHeader('Authorization', 'Bearer token');
136
137   var loadEndSavedArgs = new SaveMockArguments();
138   mockXMLHttpRequest.expects(once())
139       .addEventListener(
140           loadEndSavedArgs.match(eq('loadend')),
141           loadEndSavedArgs.match(ANYTHING),
142           loadEndSavedArgs.match(eq(false)));
143
144   mockXMLHttpRequestProxy.status = httpStatus;
145   mockXMLHttpRequestProxy.response = responseText;
146   mockXMLHttpRequestProxy.responseText = responseText;
147
148   mockXMLHttpRequest.expects(once()).send()
149       .will(invokeCallback(loadEndSavedArgs, 1, mockXMLHttpRequestProxy));
150 }
151
152 TEST_F(TEST_NAME, 'AuthServerRequestNoToken', function() {
153   this.makeAndRegisterMockApis([
154     'authenticationManager.getAuthToken',
155     'buildServerRequest'
156   ]);
157
158   this.mockApis.expects(once()).authenticationManager_getAuthToken()
159       .will(returnValue(Promise.reject()));
160   this.mockApis.expects(never()).buildServerRequest()
161
162   var thenCalled = false;
163   var catchCalled = false;
164   requestFromServer('GET', 'test/target').then(function(request) {
165     thenCalled = true;
166   }).catch(function() {
167     catchCalled = true;
168   });
169   assertFalse(thenCalled);
170   assertTrue(catchCalled);
171 })
172
173 /**
174  * requestNotificationGroupsFromServer Tests
175  */
176 TEST_F(TEST_NAME, 'RequestNotificationGroupsFromServerEmpty', function() {
177   this.makeAndRegisterMockGlobals([
178     'shouldShowExplanatoryCard',
179     'recordEvent',
180     'requestFromServer'
181   ]);
182
183   this.mockGlobals.expects(once()).shouldShowExplanatoryCard()
184       .will(returnValue(false));
185
186   this.mockGlobals.expects(once()).recordEvent(
187       GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL);
188
189   this.mockGlobals.expects(once()).recordEvent(
190       GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS);
191
192   var requestFromServerArgs = new SaveMockArguments();
193   this.mockGlobals.expects(once()).requestFromServer(
194       requestFromServerArgs.match(eq('GET')),
195       requestFromServerArgs.match(ANYTHING))
196       .will(returnValue(
197           Promise.resolve({status: 200, responseText: "{}"})));
198
199   var thenCalled = false;
200   var catchCalled = false;
201   requestNotificationGroupsFromServer([]).then(function() {
202     thenCalled = true;
203   }).catch(function() {
204     catchCalled = true;
205   });
206   assertTrue(thenCalled);
207   assertFalse(catchCalled);
208
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);
214 });
215
216 TEST_F(TEST_NAME, 'RequestNotificationGroupsFromServerWithGroups', function() {
217   this.makeAndRegisterMockGlobals([
218     'shouldShowExplanatoryCard',
219     'recordEvent',
220     'requestFromServer'
221   ]);
222
223   this.mockGlobals.expects(once()).shouldShowExplanatoryCard()
224       .will(returnValue(false));
225
226   this.mockGlobals.expects(once()).recordEvent(
227       GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL);
228
229   this.mockGlobals.expects(once()).recordEvent(
230       GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS);
231
232   var requestFromServerArgs = new SaveMockArguments();
233   this.mockGlobals.expects(once()).requestFromServer(
234       requestFromServerArgs.match(eq('GET')),
235       requestFromServerArgs.match(ANYTHING))
236       .will(returnValue(
237           Promise.resolve({status: 200, responseText: "{}"})));
238
239   var thenCalled = false;
240   var catchCalled = false;
241   requestNotificationGroupsFromServer(['A', 'B', 'C']).then(function() {
242     thenCalled = true;
243   }).catch(function() {
244     catchCalled = true;
245   });
246   assertTrue(thenCalled);
247   assertFalse(catchCalled);
248
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);
257 });
258
259 TEST_F(TEST_NAME, 'RequestNotificationGroupsFromServerExplanatory', function() {
260   this.makeAndRegisterMockGlobals([
261     'shouldShowExplanatoryCard',
262     'recordEvent',
263     'requestFromServer'
264   ]);
265
266   this.mockGlobals.expects(once()).shouldShowExplanatoryCard()
267       .will(returnValue(true));
268
269   this.mockGlobals.expects(once()).recordEvent(
270       GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL);
271
272   this.mockGlobals.expects(once()).recordEvent(
273       GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS);
274
275   var requestFromServerArgs = new SaveMockArguments();
276   this.mockGlobals.expects(once()).requestFromServer(
277       requestFromServerArgs.match(eq('GET')),
278       requestFromServerArgs.match(ANYTHING))
279       .will(returnValue(
280           Promise.resolve({status: 200, responseText: "{}"})));
281
282   var thenCalled = false;
283   var catchCalled = false;
284   requestNotificationGroupsFromServer([]).then(function() {
285     thenCalled = true;
286   }).catch(function() {
287     catchCalled = true;
288   });
289   assertTrue(thenCalled);
290   assertFalse(catchCalled);
291
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);
297 });
298
299 TEST_F(TEST_NAME, 'RequestNotificationGroupsFromServerFailure', function() {
300   this.makeAndRegisterMockGlobals([
301     'shouldShowExplanatoryCard',
302     'recordEvent',
303     'requestFromServer'
304   ]);
305
306   this.mockGlobals.expects(once()).shouldShowExplanatoryCard()
307       .will(returnValue(false));
308
309   this.mockGlobals.expects(once()).recordEvent(
310       GoogleNowEvent.REQUEST_FOR_CARDS_TOTAL);
311
312   this.mockGlobals.expects(never()).recordEvent(
313       GoogleNowEvent.REQUEST_FOR_CARDS_SUCCESS);
314
315   var requestFromServerArgs = new SaveMockArguments();
316   this.mockGlobals.expects(once()).requestFromServer(
317       requestFromServerArgs.match(eq('GET')),
318       requestFromServerArgs.match(ANYTHING))
319       .will(returnValue(
320           Promise.reject({status: 401})));
321
322   var thenCalled = false;
323   var catchCalled = false;
324   requestNotificationGroupsFromServer([]).then(function() {
325     thenCalled = true;
326   }).catch(function() {
327     catchCalled = true;
328   });
329   assertFalse(thenCalled);
330   assertTrue(catchCalled);
331 });
332
333 /**
334  * requestAndUpdateOptIn Tests
335  */
336 TEST_F(TEST_NAME, 'RequestAndUpdateOptInOptedIn', function() {
337   this.makeAndRegisterMockApis([
338     'chrome.storage.local.set',
339     'requestFromServer'
340   ]);
341
342   this.mockApis.expects(once()).requestFromServer('GET', 'settings/optin')
343       .will(returnValue(Promise.resolve({
344         status: 200,
345         responseText: '{"value": true}'})));
346
347   this.mockApis.expects(once())
348       .chrome_storage_local_set(eqJSON({googleNowEnabled: true}));
349
350   var thenCalled = false;
351   var catchCalled = false;
352   requestAndUpdateOptedIn().then(function(optedIn) {
353     thenCalled = true;
354     assertTrue(optedIn);
355   }).catch(function() {
356     catchCalled = true;
357   });
358   assertTrue(thenCalled);
359   assertFalse(catchCalled);
360 });
361
362 TEST_F(TEST_NAME, 'RequestAndUpdateOptInOptedOut', function() {
363   this.makeAndRegisterMockApis([
364     'chrome.storage.local.set',
365     'requestFromServer'
366   ]);
367
368   this.mockApis.expects(once()).requestFromServer('GET', 'settings/optin')
369       .will(returnValue(Promise.resolve({
370         status: 200,
371         responseText: '{"value": false}'})));
372
373   this.mockApis.expects(once())
374       .chrome_storage_local_set(eqJSON({googleNowEnabled: false}));
375
376   var thenCalled = false;
377   var catchCalled = false;
378   requestAndUpdateOptedIn().then(function(optedIn) {
379     thenCalled = true;
380     assertFalse(optedIn);
381   }).catch(function() {
382     catchCalled = true;
383   });
384   assertTrue(thenCalled);
385   assertFalse(catchCalled);
386 });
387
388 TEST_F(TEST_NAME, 'RequestAndUpdateOptInFailure', function() {
389   this.makeAndRegisterMockApis([
390     'chrome.storage.local.set',
391     'requestFromServer'
392   ]);
393
394   this.mockApis.expects(once()).requestFromServer('GET', 'settings/optin')
395       .will(returnValue(Promise.reject({status: 404})));
396
397   this.mockApis.expects(never()).chrome_storage_local_set();
398
399   var thenCalled = false;
400   var catchCalled = false;
401   requestAndUpdateOptedIn().then(function() {
402     thenCalled = true;
403   }).catch(function() {
404     catchCalled = true;
405   });
406   assertFalse(thenCalled);
407   assertTrue(catchCalled);
408 });
409
410 /**
411  * pollOptedInNoImmediateRecheck Tests
412  */
413 TEST_F(TEST_NAME, 'pollOptedInNoImmediateRecheckOptedIn', function() {
414   this.makeAndRegisterMockApis([
415     'requestAndUpdateOptedIn',
416     'instrumented.metricsPrivate.getVariationParams',
417     'optInPollAttempts.start'
418   ]);
419
420   this.mockApis.expects(once()).requestAndUpdateOptedIn()
421       .will(returnValue(Promise.resolve(true)));
422
423   this.mockApis.expects(never())
424       .instrumented_metricsPrivate_getVariationParams();
425
426   this.mockApis.expects(never()).optInPollAttempts_start();
427
428   pollOptedInNoImmediateRecheck();
429 });
430
431 TEST_F(TEST_NAME, 'pollOptedInNoImmediateRecheckOptedOut', function() {
432   this.makeAndRegisterMockApis([
433     'requestAndUpdateOptedIn',
434     'instrumented.metricsPrivate.getVariationParams',
435     'optInPollAttempts.start'
436   ]);
437
438   this.mockApis.expects(once()).requestAndUpdateOptedIn()
439       .will(returnValue(Promise.resolve(false)));
440
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, {}));
447
448   this.mockApis.expects(once())
449       .optInPollAttempts_start(DEFAULT_OPTIN_CHECK_PERIOD_SECONDS);
450
451   pollOptedInNoImmediateRecheck();
452 });
453
454 TEST_F(TEST_NAME, 'pollOptedInNoImmediateRecheckFailure', function() {
455   this.makeAndRegisterMockApis([
456     'requestAndUpdateOptedIn',
457     'instrumented.metricsPrivate.getVariationParams',
458     'optInPollAttempts.start'
459   ]);
460
461   this.mockApis.expects(once()).requestAndUpdateOptedIn()
462       .will(returnValue(Promise.reject()));
463
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, {}));
470
471   this.mockApis.expects(once())
472       .optInPollAttempts_start(DEFAULT_OPTIN_CHECK_PERIOD_SECONDS);
473
474   pollOptedInNoImmediateRecheck();
475 });
476
477 /**
478  * getGroupsToRequest Tests
479  */
480 TEST_F(TEST_NAME, 'GetGroupsToRequestNone', function() {
481   this.makeAndRegisterMockApis([
482     'fillFromChromeLocalStorage',
483     'Date.now'
484   ]);
485
486   this.mockApis.expects(once())
487       .fillFromChromeLocalStorage(eqJSON({notificationGroups: {}}))
488       .will(returnValue(Promise.resolve({notificationGroups: {}})));
489
490   this.mockApis.expects(once()).Date_now().will(returnValue(20));
491
492   getGroupsToRequest().then(function(groupsToRequest) {
493     assertTrue(JSON.stringify(groupsToRequest) === '[]');
494   });
495 });
496
497 TEST_F(TEST_NAME, 'GetGroupsToRequestWithGroups', function() {
498   this.makeAndRegisterMockApis([
499     'fillFromChromeLocalStorage',
500     'Date.now'
501   ]);
502
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},
511         TIMEUNDEF: {}
512       }})));
513
514   this.mockApis.expects(once()).Date_now().will(returnValue(20));
515
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);
521   });
522 });
523
524 /**
525  * combineGroup Tests
526  */
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.
531
532   // Setup and expectations.
533   var combinedCards = {
534     'EXISTING CARD': [1]
535   };
536
537   var receivedNotificationNoShowTime = {
538     chromeNotificationId: 'EXISTING CARD',
539     trigger: {hideTimeSec: 1}
540   };
541   var receivedNotificationWithShowTime = {
542     chromeNotificationId: 'NEW CARD',
543     trigger: {showTimeSec: 2, hideTimeSec: 3}
544   }
545
546   var storedGroup = {
547     cardsTimestamp: 10000,
548     cards: [
549       receivedNotificationNoShowTime,
550       receivedNotificationWithShowTime
551     ]
552   };
553
554   // Invoking the tested function.
555   combineGroup(combinedCards, storedGroup);
556
557   // Check the output value.
558   var expectedCombinedCards = {
559     'EXISTING CARD': [
560       1,
561       {
562         receivedNotification: receivedNotificationNoShowTime,
563         hideTime: 11000
564       }
565     ],
566     'NEW CARD': [
567       {
568         receivedNotification: receivedNotificationWithShowTime,
569         showTime: 12000,
570         hideTime: 13000
571       }
572     ]
573   };
574
575   assertEquals(
576       JSON.stringify(expectedCombinedCards),
577       JSON.stringify(combinedCards));
578 });
579
580 /**
581  * Mocks global functions and APIs that initialize() depends upon.
582  * @param {Test} fixture Test fixture.
583  */
584 function mockInitializeDependencies(fixture) {
585   fixture.makeAndRegisterMockGlobals([
586     'pollOptedInNoImmediateRecheck',
587     'recordEvent',
588     'removeAllCards',
589     'setBackgroundEnable',
590     'startPollingCards',
591     'stopPollingCards'
592   ]);
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',
603     'tasks.add',
604     'updateCardsAttempts.isRunning',
605     'updateCardsAttempts.stop'
606   ]);
607 }
608
609 /**
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
622  *     Now.
623  */
624 function expectStateMachineCalls(
625     fixture,
626     testIdentityToken,
627     testExperimentVariationParams,
628     testNotificationPermissionLevel,
629     testGoogleNowEnabled) {
630   fixture.mockApis.expects(once()).
631       authenticationManager_isSignedIn().
632       will(returnValue(new Promise(function(resolve) {
633         resolve(!!testIdentityToken);
634       })));
635
636   var getVariationParamsSavedArgs = new SaveMockArguments();
637   fixture.mockApis.expects(once()).
638       instrumented_metricsPrivate_getVariationParams(
639           getVariationParamsSavedArgs.match(ANYTHING),
640           getVariationParamsSavedArgs.match(ANYTHING)).
641       will(invokeCallback(
642           getVariationParamsSavedArgs, 1, testExperimentVariationParams));
643
644   var notificationGetPermissionLevelSavedArgs = new SaveMockArguments();
645   fixture.mockApis.expects(once()).
646       instrumented_notifications_getPermissionLevel(
647           notificationGetPermissionLevelSavedArgs.match(ANYTHING)).
648       will(invokeCallback(
649           notificationGetPermissionLevelSavedArgs,
650           0,
651           testNotificationPermissionLevel))
652
653   expectChromeLocalStorageGet(
654       fixture,
655       {googleNowEnabled: false},
656       {googleNowEnabled: testGoogleNowEnabled});
657
658   var updateCardsAttemptsIsRunningSavedArgs = new SaveMockArguments();
659   fixture.mockApis.expects(once()).
660       updateCardsAttempts_isRunning(
661           updateCardsAttemptsIsRunningSavedArgs.match(ANYTHING)).
662       will(
663           invokeCallback(
664               updateCardsAttemptsIsRunningSavedArgs, 0, undefined));
665
666   var optInPollAttemptsIsRunningSavedArgs = new SaveMockArguments();
667   fixture.mockApis.expects(once()).
668       optInPollAttempts_isRunning(
669           optInPollAttemptsIsRunningSavedArgs.match(ANYTHING)).
670       will(
671           invokeCallback(
672               optInPollAttemptsIsRunningSavedArgs, 0, undefined));
673 }
674
675 /**
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.
681  */
682 function expectInitialization(fixture) {
683   var tasksAddSavedArgs = new SaveMockArguments();
684   fixture.mockApis.expects(once()).
685       tasks_add(
686           tasksAddSavedArgs.match(ANYTHING),
687           tasksAddSavedArgs.match(ANYTHING)).
688       will(invokeCallback(tasksAddSavedArgs, 1, function() {}));
689
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);
695   fixture.mockGlobals.
696       expects(once()).recordEvent(GoogleNowEvent.EXTENSION_START);
697 }
698
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.
703
704   // Setup and expectations.
705   var testIdentityToken = undefined;
706   var testExperimentVariationParams = {};
707   var testNotificationPermissionLevel = 'denied';
708   var testGoogleNowEnabled = undefined;
709
710   mockInitializeDependencies(this);
711
712   expectInitialization(this);
713
714   expectStateMachineCalls(
715       this,
716       testIdentityToken,
717       testExperimentVariationParams,
718       testNotificationPermissionLevel,
719       testGoogleNowEnabled);
720
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();
727
728   // Invoking the tested function.
729   initialize();
730 });
731
732 TEST_F(TEST_NAME,'Initialize_NotificationDisabled', function() {
733   // Tests the case when Google Now is disabled in the notifications center.
734
735   // Setup and expectations.
736   var testIdentityToken = 'some identity token';
737   var testExperimentVariationParams = {};
738   var testNotificationPermissionLevel = 'denied';
739   var testGoogleNowEnabled = undefined;
740
741   mockInitializeDependencies(this);
742
743   expectInitialization(this);
744
745   expectStateMachineCalls(
746       this,
747       testIdentityToken,
748       testExperimentVariationParams,
749       testNotificationPermissionLevel,
750       testGoogleNowEnabled);
751
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();
758
759   // Invoking the tested function.
760   initialize();
761 });
762
763 TEST_F(TEST_NAME, 'Initialize_NoBackground', function() {
764   // Tests when the no background variation is received.
765
766   // Setup and expectations.
767   var testIdentityToken = 'some identity token';
768   var testExperimentVariationParams = {canEnableBackground: 'false'};
769   var testNotificationPermissionLevel = 'granted';
770   var testGoogleNowEnabled = true;
771
772   mockInitializeDependencies(this);
773
774   expectInitialization(this);
775
776   expectStateMachineCalls(
777       this,
778       testIdentityToken,
779       testExperimentVariationParams,
780       testNotificationPermissionLevel,
781       testGoogleNowEnabled);
782
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();
789
790   // Invoking the tested function.
791   initialize();
792 });
793
794 TEST_F(TEST_NAME, 'Initialize_GoogleNowDisabled', function() {
795   // Tests when the user has Google Now disabled.
796
797   // Setup and expectations.
798   var testIdentityToken = 'some identity token';
799   var testExperimentVariationParams = {};
800   var testNotificationPermissionLevel = 'granted';
801   var testGoogleNowEnabled = false;
802
803   mockInitializeDependencies(this);
804
805   expectInitialization(this);
806
807   expectStateMachineCalls(
808       this,
809       testIdentityToken,
810       testExperimentVariationParams,
811       testNotificationPermissionLevel,
812       testGoogleNowEnabled);
813
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();
820
821   // Invoking the tested function.
822   initialize();
823 });
824
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.
828
829   // Setup and expectations.
830   var testIdentityToken = 'some identity token';
831   var testExperimentVariationParams = {};
832   var testNotificationPermissionLevel = 'granted';
833   var testGoogleNowEnabled = true;
834
835   mockInitializeDependencies(this);
836
837   expectInitialization(this);
838
839   expectStateMachineCalls(
840       this,
841       testIdentityToken,
842       testExperimentVariationParams,
843       testNotificationPermissionLevel,
844       testGoogleNowEnabled);
845
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();
852
853   // Invoking the tested function.
854   initialize();
855 });
856
857 /**
858  * No Cards Event Recording Tests
859  */
860 TEST_F(TEST_NAME, 'NoCardsSignedOut', function() {
861   var signedIn = false;
862   var notificationEnabled = false;
863   var googleNowEnabled = false;
864   this.makeAndRegisterMockGlobals([
865       'recordEvent',
866       'removeAllCards',
867       'setBackgroundEnable',
868       'setShouldPollCards',
869       'setShouldPollOptInStatus']);
870
871   this.mockGlobals.stubs().removeAllCards();
872   this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
873   this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
874   this.mockGlobals.stubs().setShouldPollOptInStatus(ANYTHING);
875
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);
885 });
886
887 TEST_F(TEST_NAME, 'NoCardsNotificationsDisabled', function() {
888   var signedIn = true;
889   var notificationEnabled = false;
890   var googleNowEnabled = false;
891   this.makeAndRegisterMockGlobals([
892       'recordEvent',
893       'removeAllCards',
894       'setBackgroundEnable',
895       'setShouldPollCards',
896       'setShouldPollOptInStatus']);
897
898   this.mockGlobals.stubs().removeAllCards();
899   this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
900   this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
901   this.mockGlobals.stubs().setShouldPollOptInStatus(ANYTHING);
902
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);
912 });
913
914 TEST_F(TEST_NAME, 'NoCardsGoogleNowDisabled', function() {
915   var signedIn = true;
916   var notificationEnabled = true;
917   var googleNowEnabled = false;
918   this.makeAndRegisterMockGlobals([
919       'recordEvent',
920       'removeAllCards',
921       'setBackgroundEnable',
922       'setShouldPollCards',
923       'setShouldPollOptInStatus']);
924
925   this.mockGlobals.stubs().removeAllCards();
926   this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
927   this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
928   this.mockGlobals.stubs().setShouldPollOptInStatus(ANYTHING);
929
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);
939 });
940
941 TEST_F(TEST_NAME, 'NoCardsEverythingEnabled', function() {
942   var signedIn = true;
943   var notificationEnabled = true;
944   var googleNowEnabled = true;
945   this.makeAndRegisterMockGlobals([
946       'recordEvent',
947       'removeAllCards',
948       'setBackgroundEnable',
949       'setShouldPollCards',
950       'setShouldPollOptInStatus']);
951
952   this.mockGlobals.stubs().removeAllCards();
953   this.mockGlobals.stubs().setBackgroundEnable(ANYTHING);
954   this.mockGlobals.stubs().setShouldPollCards(ANYTHING);
955   this.mockGlobals.stubs().setShouldPollOptInStatus(ANYTHING);
956
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);
966 });
967
968 /**
969  * Mocks global functions and APIs that onNotificationClicked() depends upon.
970  * @param {Test} fixture Test fixture.
971  */
972 function mockOnNotificationClickedDependencies(fixture) {
973   fixture.makeAndRegisterMockApis([
974     'chrome.windows.create',
975     'chrome.windows.update',
976     'fillFromChromeLocalStorage',
977     'instrumented.tabs.create']);
978 }
979
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.
983
984   // Setup and expectations.
985   var testNotificationId = 'TEST_ID';
986   var testNotificationDataRequest = {notificationsData: {}};
987   var testNotificationData = {notificationsData: {}};
988
989   mockOnNotificationClickedDependencies(this);
990   this.makeMockLocalFunctions(['selector']);
991
992   expectChromeLocalStorageGet(
993       this, testNotificationDataRequest, testNotificationData);
994
995   // Invoking the tested function.
996   onNotificationClicked(
997       testNotificationId, this.mockLocalFunctions.functions().selector);
998 });
999
1000 TEST_F(TEST_NAME, 'OnNotificationClicked_ActionUrlsUndefined', function() {
1001   // Tests the case when the data associated with notification id is
1002   // 'undefined'.
1003   // In this case, the function should do nothing.
1004
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}}
1011   };
1012
1013   mockOnNotificationClickedDependencies(this);
1014   this.makeMockLocalFunctions(['selector']);
1015
1016   expectChromeLocalStorageGet(
1017       this, testNotificationDataRequest, testNotificationData);
1018
1019   this.mockLocalFunctions.expects(once())
1020       .selector(eqJSON(
1021           testNotificationData.notificationsData[testNotificationId]))
1022       .will(returnValue(undefined));
1023
1024   // Invoking the tested function.
1025   onNotificationClicked(
1026       testNotificationId, this.mockLocalFunctions.functions().selector);
1027 });
1028
1029 TEST_F(TEST_NAME, 'OnNotificationClicked_TabCreateSuccess', function() {
1030   // Tests the selected URL is OK and crome.tabs.create suceeds.
1031
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}}
1038   };
1039   var testActionUrl = 'http://testurl.com';
1040   var testCreatedTab = {windowId: 239};
1041
1042   mockOnNotificationClickedDependencies(this);
1043   this.makeMockLocalFunctions(['selector']);
1044
1045   expectChromeLocalStorageGet(
1046       this, testNotificationDataRequest, testNotificationData);
1047   this.mockLocalFunctions.expects(once())
1048       .selector(eqJSON(
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}));
1060
1061   // Invoking the tested function.
1062   onNotificationClicked(
1063       testNotificationId, this.mockLocalFunctions.functions().selector);
1064 });
1065
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
1069   // second attempt.
1070
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}}
1077   };
1078   var testActionUrl = 'http://testurl.com';
1079   var testCreatedTab = undefined; // chrome.tabs.create fails
1080
1081   mockOnNotificationClickedDependencies(this);
1082   this.makeMockLocalFunctions(['selector']);
1083
1084   expectChromeLocalStorageGet(
1085       this, testNotificationDataRequest, testNotificationData);
1086   this.mockLocalFunctions.expects(once())
1087       .selector(eqJSON(
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}));
1098
1099   // Invoking the tested function.
1100   onNotificationClicked(
1101       testNotificationId, this.mockLocalFunctions.functions().selector);
1102 });
1103
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.
1108
1109   // Setup and expectations.
1110   var existingNotifications = {
1111     'SHOULD BE DELETED': 'SOMETHING',
1112     'SHOULD BE KEPT': 'SOMETHING'
1113   };
1114
1115   var keptCard = {
1116     chromeNotificationId: 'SHOULD BE KEPT',
1117     trigger: {showTimeSec: 0, hideTimeSec: 0}
1118   };
1119
1120   var keptNotification = {
1121     receivedNotification: keptCard,
1122     showTime: 0,
1123     hideTime: 0
1124   };
1125
1126   var newCard = {
1127     chromeNotificationId: 'NEW CARD',
1128     trigger: {showTimeSec: 0, hideTimeSec: 0}
1129   };
1130
1131   var newNotification = {
1132     receivedNotification: newCard,
1133     showTime: 0,
1134     hideTime: 0
1135   };
1136
1137   var notificationGroups = {
1138     'TEST GROUP 1': {cards: [keptCard], cardsTimestamp: 0},
1139     'TEST GROUP 2': {cards: [newCard], cardsTimestamp: 0}
1140   };
1141
1142   var fakeOnCardShownFunction = 'FAKE ON CARD SHOWN FUNCTION';
1143
1144   var expectedUpdatedNotifications = {
1145     'SHOULD BE KEPT': 'KEPT CARD NOTIFICATION DATA',
1146     'NEW CARD': 'NEW CARD NOTIFICATION DATA'
1147   };
1148
1149   this.makeAndRegisterMockApis([
1150     'cardSet.update',
1151     'chrome.storage.local.set',
1152     'instrumented.notifications.getAll'
1153   ]);
1154   this.makeMockLocalFunctions([
1155     'onSuccess'
1156   ]);
1157
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));
1164
1165   this.mockApis.expects(once()).
1166       cardSet_update(
1167           'SHOULD BE KEPT',
1168           eqJSON([keptNotification]),
1169           eqJSON(notificationGroups),
1170           fakeOnCardShownFunction).
1171       will(returnValue('KEPT CARD NOTIFICATION DATA'));
1172   this.mockApis.expects(once()).
1173       cardSet_update(
1174           'NEW CARD',
1175           eqJSON([newNotification]),
1176           eqJSON(notificationGroups),
1177           fakeOnCardShownFunction).
1178       will(returnValue('NEW CARD NOTIFICATION DATA'));
1179   this.mockApis.expects(once()).
1180       cardSet_update(
1181           'SHOULD BE DELETED',
1182           [],
1183           eqJSON(notificationGroups),
1184           fakeOnCardShownFunction).
1185       will(returnValue(undefined));
1186
1187   this.mockApis.expects(once()).
1188       chrome_storage_local_set(
1189           eqJSON({notificationsData: expectedUpdatedNotifications}));
1190
1191   this.mockLocalFunctions.expects(once()).
1192       onSuccess(undefined);
1193
1194   // Invoking the tested function.
1195   showNotificationGroups(notificationGroups, fakeOnCardShownFunction)
1196       .then(this.mockLocalFunctions.functions().onSuccess);
1197 });
1198
1199 TEST_F(TEST_NAME, 'ProcessServerResponse', function() {
1200   // Tests processServerResponse function.
1201
1202   // Setup and expectations.
1203   Date.now = function() { return 3000000; };
1204
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
1215   // poll time.
1216   var serverResponse = {
1217     groups: {
1218       GROUP1: {requested: true, nextPollSeconds: 46},
1219       GROUP2: {requested: false},
1220       GROUP4: {requested: true, nextPollSeconds: 45},
1221       GROUP5: {requested: true}
1222     },
1223     notifications: [
1224       {notificationId: 'c4', groupName: 'GROUP1'},
1225       {notificationId: 'c5', groupName: 'GROUP1'}
1226     ]
1227   };
1228
1229   var recentDismissals = {
1230     c4: 1800000, // expired dismissal
1231     c5: 1800001  // non-expired dismissal
1232   };
1233
1234   var storedGroups = {
1235     GROUP2: {
1236       cards: [{notificationId: 'c2'}],
1237       cardsTimestamp: 239,
1238       nextPollTime: 10000
1239     },
1240     GROUP3: {
1241       cards: [{notificationId: 'c3'}],
1242       cardsTimestamp: 240,
1243       nextPollTime: 10001
1244     },
1245     GROUP4: {
1246       cards: [{notificationId: 'c6'}],
1247       cardsTimestamp: 241,
1248       nextPollTime: 10002
1249     }
1250   };
1251
1252   var expectedUpdatedGroups = {
1253     GROUP1: {
1254       cards: [{notificationId: 'c4', groupName: 'GROUP1'}],
1255       cardsTimestamp: 3000000,
1256       nextPollTime: 3046000
1257     },
1258     GROUP2: {
1259       cards: [{notificationId: 'c2'}],
1260       cardsTimestamp: 239,
1261       nextPollTime: 10000
1262     },
1263     GROUP4: {
1264       cards: [],
1265       cardsTimestamp: 3000000,
1266       nextPollTime: 3045000
1267     },
1268     GROUP5: {
1269       cards: [],
1270       cardsTimestamp: 3000000
1271     }
1272   };
1273
1274   var expectedUpdatedRecentDismissals = {
1275     c5: 1800001
1276   };
1277
1278   this.makeAndRegisterMockGlobals([
1279     'scheduleNextCardsPoll'
1280   ]);
1281
1282   this.makeAndRegisterMockApis([
1283     'fillFromChromeLocalStorage',
1284   ]);
1285
1286   expectChromeLocalStorageGet(
1287       this,
1288       {
1289         notificationGroups: {},
1290         recentDismissals: {}
1291       },
1292       {
1293         notificationGroups: storedGroups,
1294         recentDismissals: recentDismissals
1295       });
1296
1297   this.mockGlobals.expects(once())
1298       .scheduleNextCardsPoll(eqJSON(expectedUpdatedGroups));
1299
1300   // Invoking the tested function.
1301   processServerResponse(serverResponse);
1302 });
1303
1304 TEST_F(TEST_NAME, 'ProcessServerResponseGoogleNowDisabled', function() {
1305   // Tests processServerResponse function for the case when the response
1306   // indicates that Google Now is disabled.
1307
1308   // Setup and expectations.
1309   var serverResponse = {
1310     googleNowDisabled: true,
1311     groups: {}
1312   };
1313
1314   this.makeAndRegisterMockGlobals([
1315     'scheduleNextCardsPoll'
1316   ]);
1317
1318   this.makeAndRegisterMockApis([
1319     'chrome.storage.local.set',
1320     'fillFromChromeLocalStorage'
1321   ]);
1322
1323   this.mockApis.expects(once()).
1324       chrome_storage_local_set(eqJSON({googleNowEnabled: false}));
1325
1326   this.mockGlobals.expects(never()).scheduleNextCardsPoll();
1327
1328   // Invoking the tested function.
1329   processServerResponse(serverResponse);
1330 });
1331