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 1332