For debugging/testing, introduce method to switch debug mode dynamically, and set...
[chromium-blink-merge.git] / chrome / browser / resources / google_now / background_unittest.gtestjs
bloba0c41ca729df730cf0d4169bf013ba9b676a47db
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.
7 /**
8  * Test fixture for background.js.
9  * @constructor
10  * @extends {testing.Test}
11  */
12 function GoogleNowBackgroundUnitTest () {
13   testing.Test.call(this);
16 GoogleNowBackgroundUnitTest.prototype = {
17   __proto__: testing.Test.prototype,
19   /** @override */
20   extraLibraries: [
21     'common_test_util.js',
22     'background_test_util.js',
23     'background.js'
24   ]
27 TEST_F('GoogleNowBackgroundUnitTest', 'AreTasksConflicting', function() {
28   function testTaskPair(newTaskName, scheduledTaskName, expected) {
29     assertTrue(areTasksConflicting(newTaskName, scheduledTaskName) == expected,
30                '(' + newTaskName + ', ' + scheduledTaskName + ')');
31   }
33   testTaskPair(UPDATE_CARDS_TASK_NAME, UPDATE_CARDS_TASK_NAME, true);
34   testTaskPair(UPDATE_CARDS_TASK_NAME, DISMISS_CARD_TASK_NAME, false);
35   testTaskPair(UPDATE_CARDS_TASK_NAME, RETRY_DISMISS_TASK_NAME, false);
36   testTaskPair(UPDATE_CARDS_TASK_NAME, STATE_CHANGED_TASK_NAME, false);
38   testTaskPair(DISMISS_CARD_TASK_NAME, UPDATE_CARDS_TASK_NAME, false);
39   testTaskPair(DISMISS_CARD_TASK_NAME, DISMISS_CARD_TASK_NAME, false);
40   testTaskPair(DISMISS_CARD_TASK_NAME, RETRY_DISMISS_TASK_NAME, false);
41   testTaskPair(DISMISS_CARD_TASK_NAME, STATE_CHANGED_TASK_NAME, false);
43   testTaskPair(RETRY_DISMISS_TASK_NAME, UPDATE_CARDS_TASK_NAME, true);
44   testTaskPair(RETRY_DISMISS_TASK_NAME, DISMISS_CARD_TASK_NAME, true);
45   testTaskPair(RETRY_DISMISS_TASK_NAME, RETRY_DISMISS_TASK_NAME, true);
46   testTaskPair(RETRY_DISMISS_TASK_NAME, STATE_CHANGED_TASK_NAME, false);
48   testTaskPair(STATE_CHANGED_TASK_NAME, UPDATE_CARDS_TASK_NAME, false);
49   testTaskPair(STATE_CHANGED_TASK_NAME, DISMISS_CARD_TASK_NAME, false);
50   testTaskPair(STATE_CHANGED_TASK_NAME, RETRY_DISMISS_TASK_NAME, false);
51   testTaskPair(STATE_CHANGED_TASK_NAME, STATE_CHANGED_TASK_NAME, false);
52 });
54 var testNotificationId = 'TEST GROUP-SOME TEST ID';
55 var testChromeNotificationId = 'TEST CARD ID';
56 var testNotification1 =
57     {testNotificationField: 'TEST NOTIFICATION VALUE1', priority: -1};
58 var testNotification2 =
59     {testNotificationField: 'TEST NOTIFICATION VALUE2', priority: 0};
60 var testActionUrls1 = {testField: 'TEST VALUE1'};
61 var testActionUrls2 = {testField: 'TEST VALUE2'};
62 var testDismissal1 = {testDismissalField: 'TEST DISMISSAL VALUE 1'};
63 var testDismissal2 = {testDismissalField: 'TEST DISMISSAL VALUE 2'};
64 var testVersion = 7;
65 var testTimestamp1 = 300000;
66 var testTimestamp2 = 600000;
67 var testGroupRank1 = 19;
68 var testGroupRank2 = 23;
69 var testTriggerUnmerged = {showTimeSec: 100, hideTimeSec: 200};
70 var testTriggerMerged = {showTime: 300007, hideTime: 300011};
71 var testVersion1 = 29;
72 var testVersion2 = 31;
74 TEST_F(
75     'GoogleNowBackgroundUnitTest',
76     'MergeCardsEmptyNoTrigger',
77     function() {
78       // Tests merging a card with an empty trigger into an 'undefined' merged
79       // card. This should start a new card.
81       // Invoking the tested function.
82       var resultingMergedCard = mergeCards(undefined, {
83         notificationId: testNotificationId,
84         chromeNotificationId: testChromeNotificationId,
85         version: testVersion1,
86         chromeNotificationOptions: testNotification1,
87         actionUrls: testActionUrls1,
88         dismissal: testDismissal1
89       }, testTimestamp1, testGroupRank1);
91       // Check the return value.
92       assertEquals(
93           JSON.stringify({
94             dismissals: [
95               {
96                 notificationId: testNotificationId,
97                 parameters: testDismissal1
98               }
99             ],
100             groupRank: testGroupRank1,
101             trigger: {},
102             timestamp: testTimestamp1,
103             notification: testNotification1,
104             actionUrls: testActionUrls1,
105             version: testVersion1
106           }),
107         JSON.stringify(resultingMergedCard));
108     });
110 TEST_F(
111     'GoogleNowBackgroundUnitTest',
112     'MergeCards1',
113     function() {
114       // Tests merging a unmerged card into a merged card.
115       // Unmerged card priority is greater than merged card one. Unmerged card
116       // rank is less than merged card one, and it's older.
118       // Setup.
119       var mergedCard = {
120         trigger: testTriggerMerged,
121         version: testVersion1,
122         timestamp: testTimestamp2,
123         notification: testNotification1,
124         actionUrls: testActionUrls1,
125         groupRank: testGroupRank2,
126         dismissals:
127             [{notificationId: testNotificationId, parameters: testDismissal1}]
128       };
130       var unmergedNotification = {
131         notificationId: testNotificationId,
132         chromeNotificationId: testChromeNotificationId,
133         version: testVersion2,
134         chromeNotificationOptions: testNotification2,
135         actionUrls: testActionUrls2,
136         dismissal: testDismissal2,
137         trigger: testTriggerUnmerged
138       };
140       // Invoking the tested function.
141       var resultingMergedCard = mergeCards(
142           mergedCard, unmergedNotification, testTimestamp1, testGroupRank1);
144       // Check the return value.
145       assertEquals(
146           JSON.stringify({
147             trigger: testTriggerMerged,
148             version: testVersion1,
149             timestamp: testTimestamp2,
150             notification: {
151                 testNotificationField: 'TEST NOTIFICATION VALUE1',
152                 priority: 0
153              },
154             actionUrls: testActionUrls1,
155             groupRank: testGroupRank2,
156             dismissals: [
157               {notificationId: testNotificationId, parameters: testDismissal1},
158               {notificationId: testNotificationId, parameters: testDismissal2}
159             ]
160           }),
161         JSON.stringify(resultingMergedCard));
162     });
164 TEST_F(
165     'GoogleNowBackgroundUnitTest',
166     'MergeCards2',
167     function() {
168       // Tests merging a unmerged card into a merged card.
169       // Unmerged card priority is less than merged card one. Unmerged card rank
170       // is greater than merged card one, and it's older.
172       // Setup.
173       var mergedCard = {
174         trigger: testTriggerMerged,
175         version: testVersion1,
176         timestamp: testTimestamp2,
177         notification: testNotification2,
178         actionUrls: testActionUrls1,
179         groupRank: testGroupRank1,
180         dismissals:
181             [{notificationId: testNotificationId, parameters: testDismissal1}]
182       };
184       var unmergedNotification = {
185         notificationId: testNotificationId,
186         chromeNotificationId: testChromeNotificationId,
187         version: testVersion2,
188         chromeNotificationOptions: testNotification1,
189         actionUrls: testActionUrls2,
190         dismissal: testDismissal2,
191         trigger: testTriggerUnmerged
192       };
194       // Invoking the tested function.
195       var resultingMergedCard = mergeCards(
196           mergedCard, unmergedNotification, testTimestamp1, testGroupRank2);
198       // Check the return value.
199       assertEquals(
200           JSON.stringify({
201             trigger: {showTime: 400000, hideTime: 500000},
202             version: testVersion1,
203             timestamp: testTimestamp2,
204             notification: {
205                 testNotificationField: 'TEST NOTIFICATION VALUE2',
206                 priority: 0
207              },
208             actionUrls: testActionUrls1,
209             groupRank: testGroupRank2,
210             dismissals: [
211               {notificationId: testNotificationId, parameters: testDismissal1},
212               {notificationId: testNotificationId, parameters: testDismissal2}
213             ]
214           }),
215         JSON.stringify(resultingMergedCard));
216     });
218 TEST_F(
219     'GoogleNowBackgroundUnitTest',
220     'MergeCards3',
221     function() {
222       // Tests merging a unmerged card into a merged card.
223       // Unmerged card priority is less than merged card one. Unmerged card rank
224       // is less than merged card one, and it's newer.
226       // Setup.
227       var mergedCard = {
228         trigger: testTriggerMerged,
229         version: testVersion1,
230         timestamp: testTimestamp1,
231         notification: testNotification2,
232         actionUrls: testActionUrls1,
233         groupRank: testGroupRank2,
234         dismissals:
235             [{notificationId: testNotificationId, parameters: testDismissal1}]
236       };
238       var unmergedNotification = {
239         notificationId: testNotificationId,
240         chromeNotificationId: testChromeNotificationId,
241         version: testVersion2,
242         chromeNotificationOptions: testNotification1,
243         actionUrls: testActionUrls2,
244         dismissal: testDismissal2,
245         trigger: testTriggerUnmerged
246       };
248       // Invoking the tested function.
249       var resultingMergedCard = mergeCards(
250           mergedCard, unmergedNotification, testTimestamp2, testGroupRank1);
252       // Check the return value.
253       assertEquals(
254           JSON.stringify({
255             trigger: testTriggerMerged,
256             version: testVersion2,
257             timestamp: testTimestamp2,
258             notification: {
259                 testNotificationField: 'TEST NOTIFICATION VALUE1',
260                 priority: 0
261              },
262             actionUrls: testActionUrls2,
263             groupRank: testGroupRank2,
264             dismissals: [
265               {notificationId: testNotificationId, parameters: testDismissal1},
266               {notificationId: testNotificationId, parameters: testDismissal2}
267             ]
268           }),
269         JSON.stringify(resultingMergedCard));
270     });
272 TEST_F(
273     'GoogleNowBackgroundUnitTest',
274     'MergeGroup',
275     function() {
276       // Tests mergeGroup method.
278       // Setup.
279       this.makeAndRegisterMockGlobals(['mergeCards']);
281       this.mockGlobals.expects(once()).
282           mergeCards(
283               undefined,
284               eqJSON({chromeNotificationId: 'ID 1', testField: 'TEST_FIELD1'}),
285               300000,
286               17).
287           will(returnValue({testField: 'RESULT 1'}));
288       this.mockGlobals.expects(once()).
289           mergeCards(
290               eqJSON({testField: 'TEST_FIELD22'}),
291               eqJSON({chromeNotificationId: 'ID 2', testField: 'TEST_FIELD2'}),
292               300000,
293               17).
294           will(returnValue({testField: 'RESULT 2'}));
296       var group = {
297         cards: [
298           {chromeNotificationId: 'ID 1', testField: 'TEST_FIELD1'},
299           {chromeNotificationId: 'ID 2', testField: 'TEST_FIELD2'}
300         ],
301         cardsTimestamp: 300000,
302         nextPollTime: 600000,
303         rank: 17
304       };
306       var mergedCards = {
307         'ID 2': { testField: 'TEST_FIELD22' },
308         'ID 3': { testField: 'TEST_FIELD3' }
309       };
311       // Invoking the tested function.
312       mergeGroup(mergedCards, group);
314       // Check the output parameter.
315       assertEquals(
316           JSON.stringify({
317             'ID 2': { testField: 'RESULT 2' },
318             'ID 3': { testField: 'TEST_FIELD3'},
319             'ID 1': { testField: 'RESULT 1' }}),
320           JSON.stringify(mergedCards));
321     });
324  * Mocks global functions and APIs that initialize() depends upon.
325  * @param {Test} fixture Test fixture.
326  */
327 function mockInitializeDependencies(fixture) {
328   fixture.makeAndRegisterMockGlobals([
329     'recordEvent',
330     'setBackgroundEnable',
331     'startPollingCards'
332   ]);
333   fixture.makeAndRegisterMockApis([
334     'authenticationManager.isSignedIn',
335     'chrome.location.clearWatch',
336     'chrome.storage.local.remove',
337     'instrumented.metricsPrivate.getVariationParams',
338     'instrumented.notifications.getAll',
339     'instrumented.preferencesPrivate.googleGeolocationAccessEnabled.get',
340     'instrumented.storage.local.get',
341     'tasks.add',
342     'updateCardsAttempts.isRunning',
343     'updateCardsAttempts.stop'
344   ]);
348  * Sets up the test to expect the state machine calls and send
349  * the specified state machine state. Currently used to test initialize().
350  * Note that this CAN NOT be used if any of the methods below are called
351  * outside of this context with the same argument matchers.
352  * expects() calls cannot be chained with the same argument matchers.
353  * @param {object} fixture Test fixture.
354  * @param {string} testIdentityToken getAuthToken callback token.
355  * @param {boolean} testGeolocationPref Geolocation Preference callback value.
356  * @param {object} testExperimentVariationParams Response of
357  *     metricsPrivate.getVariationParams
358  */
359 function expectStateMachineCalls(
360     fixture,
361     testIdentityToken,
362     testGeolocationPref,
363     testExperimentVariationParams) {
364   var authenticationManagerIsSignedInSavedArgs = new SaveMockArguments();
365   fixture.mockApis.expects(once()).
366       authenticationManager_isSignedIn(
367           authenticationManagerIsSignedInSavedArgs.match(ANYTHING)).
368       will(invokeCallback(
369           authenticationManagerIsSignedInSavedArgs,
370           0,
371           testIdentityToken));
373   var getVariationParamsSavedArgs = new SaveMockArguments();
374   fixture.mockApis.expects(once()).
375       instrumented_metricsPrivate_getVariationParams(
376           getVariationParamsSavedArgs.match(ANYTHING),
377           getVariationParamsSavedArgs.match(ANYTHING)).
378       will(invokeCallback(
379           getVariationParamsSavedArgs, 1, testExperimentVariationParams));
381   var googleGeolocationPrefGetSavedArgs = new SaveMockArguments();
382   fixture.mockApis.expects(once()).
383       instrumented_preferencesPrivate_googleGeolocationAccessEnabled_get(
384           googleGeolocationPrefGetSavedArgs.match(eqJSON({})),
385           googleGeolocationPrefGetSavedArgs.match(ANYTHING)).
386       will(invokeCallback(
387           googleGeolocationPrefGetSavedArgs, 1, {value: testGeolocationPref}));
389   fixture.mockGlobals.expects(once()).
390       setBackgroundEnable(ANYTHING);
394  * Sets up the test to expect the initialization calls that
395  * initialize() invokes.
396  * Note that this CAN NOT be used if any of the methods below are called
397  * outside of this context with the same argument matchers.
398  * expects() calls cannot be chained with the same argument matchers.
399  */
400 function expectInitialization(mockApisObj) {
401   var tasksAddSavedArgs = new SaveMockArguments();
402   mockApisObj.expects(once()).
403       tasks_add(
404           tasksAddSavedArgs.match(ANYTHING),
405           tasksAddSavedArgs.match(ANYTHING)).
406       will(invokeCallback(tasksAddSavedArgs, 1, function() {}));
407   var updateCardsAttemptsIsRunningSavedArgs = new SaveMockArguments();
408   mockApisObj.expects(once()).
409       updateCardsAttempts_isRunning(
410           updateCardsAttemptsIsRunningSavedArgs.match(ANYTHING)).
411       will(
412           invokeCallback(
413              updateCardsAttemptsIsRunningSavedArgs, 0, false));
416 TEST_F(
417     'GoogleNowBackgroundUnitTest',
418     'Initialize_ToastStateEmpty',
419     function() {
420       // Tests the case when getAuthToken fails most likely because the user is
421       // not signed in. In this case, the function should quietly exit after
422       // finding out that getAuthToken fails.
424       // Setup and expectations.
425       var testIdentityToken = undefined;
426       var testGeolocationPref = false;
427       var testExperimentVariationParams = {};
429       mockInitializeDependencies(this);
431       this.mockGlobals.expects(once()).recordEvent(
432           GoogleNowEvent.EXTENSION_START);
434       this.mockGlobals.expects(once()).recordEvent(
435           GoogleNowEvent.STOPPED);
437       expectInitialization(this.mockApis);
439       expectStateMachineCalls(
440           this,
441           testIdentityToken,
442           testGeolocationPref,
443           testExperimentVariationParams);
445       // Invoking the tested function.
446       initialize();
447     });
449 TEST_F(
450     'GoogleNowBackgroundUnitTest',
451     'DISABLED_Initialize_ToastStateEmpty2',
452     function() {
453       // Tests the case when getAuthToken succeeds, and the user has never
454       // responded to the toast.
455       // In this case, the function should invoke showWelcomeToast().
457       // Setup and expectations.
458       var testIdentityToken = 'some identity token';
459       var testGeolocationPref = false;
460       var testExperimentVariationParams = {};
462       mockInitializeDependencies(this);
464       this.mockGlobals.expects(once()).recordEvent(
465           GoogleNowEvent.EXTENSION_START);
467       expectInitialization(this.mockApis);
469       expectStateMachineCalls(
470           this,
471           testIdentityToken,
472           testGeolocationPref,
473           testExperimentVariationParams);
475       var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
476       this.mockApis.expects(exactly(1)).
477           instrumented_notifications_getAll(
478               chromeNotificationGetAllSavedArgs.match(ANYTHING)).
479           will(
480               invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
481               invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}));
483       // Invoking the tested function.
484       initialize();
485     });
487 TEST_F('GoogleNowBackgroundUnitTest', 'Initialize_RunGoogleNow', function() {
488   // Tests if Google Now will invoke startPollingCards when all
489   // of the required state is fulfilled.
491   // Setup and expectations.
492   var testIdentityToken = 'some identity token';
493   var testGeolocationPref = true;
494   var testExperimentVariationParams = {};
496   mockInitializeDependencies(this);
498   this.mockGlobals.expects(once()).recordEvent(
499         GoogleNowEvent.EXTENSION_START);
501   expectInitialization(this.mockApis);
503   expectStateMachineCalls(
504       this,
505       testIdentityToken,
506       testGeolocationPref,
507       testExperimentVariationParams);
509   this.mockGlobals.expects(once()).startPollingCards();
511   // Invoking the tested function.
512   initialize();
515 TEST_F(
516     'GoogleNowBackgroundUnitTest',
517     'DISABLED_Initialize_NoGeolocation',
518     function() {
519   // Tests the case where everything is in place except for the
520   // Geolocation Preference after the user responded to the toast.
522   // Setup and expectations.
523   var testIdentityToken = 'some identity token';
524   var testGeolocationPref = false;
525   var testExperimentVariationParams = {};
527   mockInitializeDependencies(this);
529   this.mockGlobals.expects(once()).recordEvent(
530         GoogleNowEvent.EXTENSION_START);
532   this.mockGlobals.expects(once()).recordEvent(
533       GoogleNowEvent.USER_SUPPRESSED);
535   expectInitialization(this.mockApis);
537   expectStateMachineCalls(
538       this,
539       testIdentityToken,
540       testGeolocationPref,
541       testExperimentVariationParams);
543   var chromeNotificationGetAllSavedArgs = new SaveMockArguments();
544   this.mockApis.expects(exactly(2)).
545       instrumented_notifications_getAll(
546           chromeNotificationGetAllSavedArgs.match(ANYTHING)).
547       will(
548           invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}),
549           invokeCallback(chromeNotificationGetAllSavedArgs, 0, {}));
551   // Invoking the tested function.
552   initialize();
556  * Mocks global functions and APIs that onNotificationClicked() depends upon.
557  * @param {Test} fixture Test fixture.
558  */
559 function mockOnNotificationClickedDependencies(fixture) {
560   fixture.makeAndRegisterMockApis([
561       'chrome.windows.create',
562       'chrome.windows.update',
563       'instrumented.storage.local.get',
564       'instrumented.tabs.create']);
567 TEST_F(
568     'GoogleNowBackgroundUnitTest',
569     'OnNotificationClicked_NoData',
570     function() {
571       // Tests the case when there is no data associated with notification id.
572       // In this case, the function should do nothing.
574       // Setup and expectations.
575       var testNotificationId = 'TEST_ID';
576       var testNotificationData = {};
578       mockOnNotificationClickedDependencies(this);
579       this.makeMockLocalFunctions(['selector']);
581       var storageGetSavedArgs = new SaveMockArguments();
582       this.mockApis.expects(once()).
583           instrumented_storage_local_get(
584               storageGetSavedArgs.match(eq('notificationsData')),
585               storageGetSavedArgs.match(ANYTHING)).
586           will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
588       // Invoking the tested function.
589       onNotificationClicked(
590           testNotificationId, this.mockLocalFunctions.functions().selector);
591     });
593 TEST_F(
594     'GoogleNowBackgroundUnitTest',
595     'OnNotificationClicked_ActionUrlsUndefined',
596     function() {
597       // Tests the case when the data associated with notification id is
598       // 'undefined'.
599       // In this case, the function should do nothing.
601       // Setup and expectations.
602       var testActionUrls = undefined;
603       var testNotificationId = 'TEST_ID';
604       var testNotificationData = {
605           notificationsData: {'TEST_ID': {actionUrls: testActionUrls}}
606       };
608       mockOnNotificationClickedDependencies(this);
609       this.makeMockLocalFunctions(['selector']);
611       var storageGetSavedArgs = new SaveMockArguments();
612       this.mockApis.expects(once()).
613           instrumented_storage_local_get(
614               storageGetSavedArgs.match(eq('notificationsData')),
615               storageGetSavedArgs.match(ANYTHING)).
616           will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
617       this.mockLocalFunctions.expects(once()).selector(undefined).will(
618           returnValue(undefined));
620       // Invoking the tested function.
621       onNotificationClicked(
622           testNotificationId, this.mockLocalFunctions.functions().selector);
623     });
625 TEST_F(
626     'GoogleNowBackgroundUnitTest',
627     'OnNotificationClicked_TabCreateSuccess',
628     function() {
629       // Tests the selected URL is OK and crome.tabs.create suceeds.
631       // Setup and expectations.
632       var testActionUrls = {testField: 'TEST VALUE'};
633       var testNotificationId = 'TEST_ID';
634       var testNotificationData = {
635           notificationsData: {'TEST_ID': {actionUrls: testActionUrls}}
636       };
637       var testActionUrl = 'http://testurl.com';
638       var testCreatedTab = {windowId: 239};
640       mockOnNotificationClickedDependencies(this);
641       this.makeMockLocalFunctions(['selector']);
643       var storageGetSavedArgs = new SaveMockArguments();
644       this.mockApis.expects(once()).
645           instrumented_storage_local_get(
646               storageGetSavedArgs.match(eq('notificationsData')),
647               storageGetSavedArgs.match(ANYTHING)).
648           will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
649       this.mockLocalFunctions.expects(once()).selector(testActionUrls).will(
650           returnValue(testActionUrl));
651       var chromeTabsCreateSavedArgs = new SaveMockArguments();
652       this.mockApis.expects(once()).
653           instrumented_tabs_create(
654               chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})),
655               chromeTabsCreateSavedArgs.match(ANYTHING)).
656           will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab));
657       this.mockApis.expects(once()).chrome_windows_update(
658           testCreatedTab.windowId,
659           eqJSON({focused: true}));
661       // Invoking the tested function.
662       onNotificationClicked(
663           testNotificationId, this.mockLocalFunctions.functions().selector);
664     });
666 TEST_F(
667     'GoogleNowBackgroundUnitTest',
668     'OnNotificationClicked_TabCreateFail',
669     function() {
670       // Tests the selected URL is OK and crome.tabs.create fails.
671       // In this case, the function should invoke chrome.windows.create as a
672       // second attempt.
674       // Setup and expectations.
675       var testActionUrls = {testField: 'TEST VALUE'};
676       var testNotificationId = 'TEST_ID';
677       var testNotificationData = {
678         notificationsData: {'TEST_ID': {actionUrls: testActionUrls}}
679       };
680       var testActionUrl = 'http://testurl.com';
681       var testCreatedTab = undefined; // chrome.tabs.create fails
683       mockOnNotificationClickedDependencies(this);
684       this.makeMockLocalFunctions(['selector']);
686       var storageGetSavedArgs = new SaveMockArguments();
687       this.mockApis.expects(once()).
688           instrumented_storage_local_get(
689               storageGetSavedArgs.match(eq('notificationsData')),
690               storageGetSavedArgs.match(ANYTHING)).
691           will(invokeCallback(storageGetSavedArgs, 1, testNotificationData));
692       this.mockLocalFunctions.expects(once()).selector(testActionUrls).will(
693           returnValue(testActionUrl));
694       var chromeTabsCreateSavedArgs = new SaveMockArguments();
695       this.mockApis.expects(once()).
696           instrumented_tabs_create(
697               chromeTabsCreateSavedArgs.match(eqJSON({url: testActionUrl})),
698               chromeTabsCreateSavedArgs.match(ANYTHING)).
699           will(invokeCallback(chromeTabsCreateSavedArgs, 1, testCreatedTab));
700       this.mockApis.expects(once()).chrome_windows_create(
701           eqJSON({url: testActionUrl, focused: true}));
703       // Invoking the tested function.
704       onNotificationClicked(
705           testNotificationId, this.mockLocalFunctions.functions().selector);
706     });