- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / test / functional / ntp.py
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import copy
7 import os
8
9 import pyauto_functional  # Must be imported before pyauto
10 import pyauto
11 import test_utils
12
13
14 class NTPTest(pyauto.PyUITest):
15   """Test of the NTP."""
16
17   # Default apps are registered in ProfileImpl::RegisterComponentExtensions().
18   _EXPECTED_DEFAULT_APPS = [
19     {u'title': u'Chrome Web Store'},
20   ]
21   if pyauto.PyUITest.IsChromeOS():
22     _EXPECTED_DEFAULT_APPS.append({u'title': u'Files'})
23     _EXPECTED_DEFAULT_APPS.append({u'title': u'Chrome'})
24   else:
25     _EXPECTED_DEFAULT_APPS.append({u'title': u'Cloud Print'})
26
27   # Default menu and thumbnail mode preferences are set in
28   # ShownSectionsHandler::RegisterUserPrefs.
29   if pyauto.PyUITest.IsChromeOS():
30     _EXPECTED_DEFAULT_THUMB_INFO = {
31       u'apps': True,
32       u'most_visited': False
33     }
34     _EXPECTED_DEFAULT_MENU_INFO = {
35       u'apps': False,
36       u'most_visited': True,
37       u'recently_closed': True
38     }
39   else:
40     _EXPECTED_DEFAULT_THUMB_INFO = {
41       u'apps': False,
42       u'most_visited': True
43     }
44     _EXPECTED_DEFAULT_MENU_INFO = {
45       u'apps': False,
46       u'most_visited': False,
47       u'recently_closed': False
48     }
49
50   def Debug(self):
51     """Test method for experimentation.
52
53     This method is not run automatically.
54     """
55     while True:
56       raw_input('Interact with the browser and hit <enter> to dump NTP info...')
57       print '*' * 20
58       self.pprint(self._GetNTPInfo())
59
60   def __init__(self, methodName='runTest'):
61     super(NTPTest, self).__init__(methodName)
62
63     # Create some dummy file urls we can use in the tests.
64     filenames = ['title1.html', 'title2.html']
65     titles = [u'', u'Title Of Awesomeness']
66     urls = map(lambda name: self.GetFileURLForDataPath(name), filenames)
67     self.PAGES = map(lambda url, title: {'url': url, 'title': title},
68                      urls, titles)
69
70   def _NTPContainsThumbnail(self, check_thumbnail):
71     """Returns whether the NTP's Most Visited section contains the given
72     thumbnail."""
73     for thumbnail in self.GetNTPThumbnails():
74       if check_thumbnail['url'] == thumbnail['url']:
75         return True
76     return False
77
78   def testFreshProfile(self):
79     """Tests that the NTP with a fresh profile is correct"""
80     thumbnails = self.GetNTPThumbnails()
81     default_sites = self.GetNTPDefaultSites()
82     self.assertEqual(len(default_sites), len(thumbnails))
83     for thumbnail, default_site in zip(thumbnails, default_sites):
84       self.assertEqual(thumbnail['url'], default_site)
85     self.assertEqual(0, len(self.GetNTPRecentlyClosed()))
86
87   def testRemoveDefaultThumbnails(self):
88     """Tests that the default thumbnails can be removed"""
89     self.RemoveNTPDefaultThumbnails()
90     self.assertFalse(self.GetNTPThumbnails())
91     self.RestoreAllNTPThumbnails()
92     self.assertEqual(len(self.GetNTPDefaultSites()),
93                      len(self.GetNTPThumbnails()))
94     self.RemoveNTPDefaultThumbnails()
95     self.assertFalse(self.GetNTPThumbnails())
96
97   def testOneMostVisitedSite(self):
98     """Tests that a site is added to the most visited sites"""
99     self.RemoveNTPDefaultThumbnails()
100     self.NavigateToURL(self.PAGES[1]['url'])
101     thumbnail = self.GetNTPThumbnails()[0]
102     self.assertEqual(self.PAGES[1]['url'], thumbnail['url'])
103     self.assertEqual(self.PAGES[1]['title'], thumbnail['title'])
104
105   def testRemoveThumbnail(self):
106     """Tests removing a thumbnail works"""
107     self.RemoveNTPDefaultThumbnails()
108     for page in self.PAGES:
109       self.AppendTab(pyauto.GURL(page['url']))
110
111     thumbnails = self.GetNTPThumbnails()
112     for thumbnail in thumbnails:
113       self.assertEquals(thumbnail, self.GetNTPThumbnails()[0])
114       self.RemoveNTPThumbnail(thumbnail)
115       self.assertFalse(self._NTPContainsThumbnail(thumbnail))
116     self.assertFalse(self.GetNTPThumbnails())
117
118   def testIncognitoNotAppearInMostVisited(self):
119     """Tests that visiting a page in incognito mode does cause it to appear in
120     the Most Visited section"""
121     self.RemoveNTPDefaultThumbnails()
122     self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW)
123     self.NavigateToURL(self.PAGES[0]['url'], 1, 0)
124     self.assertFalse(self.GetNTPThumbnails())
125
126   def testDifferentProfileNotAppearInMostVisited(self):
127     """Tests that visiting a page in one profile does not cause it to appear in
128     the Most Visited section of another."""
129     self.RemoveNTPDefaultThumbnails()
130     self.OpenNewBrowserWindowWithNewProfile()
131     self.NavigateToURL(self.PAGES[0]['url'], 1, 0)
132     self.assertFalse(self.GetNTPThumbnails())
133
134   def testThumbnailPersistence(self):
135     """Tests that thumbnails persist across Chrome restarts"""
136     self.RemoveNTPDefaultThumbnails()
137     for page in self.PAGES:
138       self.AppendTab(pyauto.GURL(page['url']))
139     thumbnails = self.GetNTPThumbnails()
140     self.RestartBrowser(clear_profile=False)
141     self.assertEqual(thumbnails, self.GetNTPThumbnails())
142
143   def testRestoreAllRemovedThumbnails(self):
144     """Tests restoring all removed thumbnails"""
145     for page in self.PAGES:
146       self.AppendTab(pyauto.GURL(page['url']))
147
148     thumbnails = self.GetNTPThumbnails()
149     for thumbnail in thumbnails:
150       self.RemoveNTPThumbnail(thumbnail)
151
152     self.RestoreAllNTPThumbnails()
153     self.assertEquals(thumbnails, self.GetNTPThumbnails())
154
155   def testThumbnailRanking(self):
156     """Tests that the thumbnails are ordered according to visit count"""
157     self.RemoveNTPDefaultThumbnails()
158     for page in self.PAGES:
159       self.AppendTab(pyauto.GURL(page['url']))
160     thumbnails = self.GetNTPThumbnails()
161     self.assertEqual(self.PAGES[0]['url'], self.GetNTPThumbnails()[0]['url'])
162     self.AppendTab(pyauto.GURL(self.PAGES[1]['url']))
163     self.assertEqual(self.PAGES[1]['url'], self.GetNTPThumbnails()[0]['url'])
164     self.AppendTab(pyauto.GURL(self.PAGES[0]['url']))
165     self.AppendTab(pyauto.GURL(self.PAGES[0]['url']))
166     self.assertEqual(self.PAGES[0]['url'], self.GetNTPThumbnails()[0]['url'])
167
168   def testThumbnailTitleChangeAfterPageTitleChange(self):
169     """Tests that once a page title changes, the thumbnail title changes too"""
170     self.RemoveNTPDefaultThumbnails()
171     self.NavigateToURL(self.PAGES[0]['url'])
172     self.assertEqual(self.PAGES[0]['title'],
173                      self.GetNTPThumbnails()[0]['title'])
174     self.ExecuteJavascript('window.domAutomationController.send(' +
175                            'document.title = "new title")')
176     self.assertEqual('new title', self.GetNTPThumbnails()[0]['title'])
177
178   def testCloseOneTab(self):
179     """Tests that closing a tab populates the recently closed list"""
180     self.RemoveNTPDefaultThumbnails()
181     self.AppendTab(pyauto.GURL(self.PAGES[1]['url']))
182     self.CloseTab(tab_index=1)
183     self.assertEqual(self.PAGES[1]['url'],
184                      self.GetNTPRecentlyClosed()[0]['url'])
185     self.assertEqual(self.PAGES[1]['title'],
186                      self.GetNTPRecentlyClosed()[0]['title'])
187
188   def testCloseOneWindow(self):
189     """Tests that closing a window populates the recently closed list"""
190     self.RemoveNTPDefaultThumbnails()
191     self.OpenNewBrowserWindow(True)
192     self.NavigateToURL(self.PAGES[0]['url'], 1, 0)
193     self.AppendTab(pyauto.GURL(self.PAGES[1]['url']), 1)
194     self.CloseBrowserWindow(1)
195     expected = [{ u'type': u'window',
196                   u'tabs': [
197                   { u'type': u'tab',
198                     u'url': self.PAGES[0]['url'],
199                     u'direction': u'ltr' },
200                   { u'type': u'tab',
201                     u'url': self.PAGES[1]['url']}]
202                 }]
203     self.assertEquals(expected, test_utils.StripUnmatchedKeys(
204         self.GetNTPRecentlyClosed(), expected))
205
206   def testCloseMultipleTabs(self):
207     """Tests closing multiple tabs populates the Recently Closed section in
208     order"""
209     self.RemoveNTPDefaultThumbnails()
210     self.AppendTab(pyauto.GURL(self.PAGES[0]['url']))
211     self.AppendTab(pyauto.GURL(self.PAGES[1]['url']))
212     self.CloseTab(tab_index=2)
213     self.CloseTab(tab_index=1)
214     expected = [{ u'type': u'tab',
215                   u'url': self.PAGES[0]['url']
216                 },
217                 { u'type': u'tab',
218                   u'url': self.PAGES[1]['url']
219                 }]
220     self.assertEquals(expected, test_utils.StripUnmatchedKeys(
221         self.GetNTPRecentlyClosed(), expected))
222
223   def testCloseWindowWithOneTab(self):
224     """Tests that closing a window with only one tab only shows up as a tab in
225     the Recently Closed section"""
226     self.RemoveNTPDefaultThumbnails()
227     self.OpenNewBrowserWindow(True)
228     self.NavigateToURL(self.PAGES[0]['url'], 1, 0)
229     self.CloseBrowserWindow(1)
230     expected = [{ u'type': u'tab',
231                   u'url': self.PAGES[0]['url']
232                 }]
233     self.assertEquals(expected, test_utils.StripUnmatchedKeys(
234         self.GetNTPRecentlyClosed(), expected))
235
236   def testCloseMultipleWindows(self):
237     """Tests closing multiple windows populates the Recently Closed list"""
238     self.RemoveNTPDefaultThumbnails()
239     self.OpenNewBrowserWindow(True)
240     self.NavigateToURL(self.PAGES[0]['url'], 1, 0)
241     self.AppendTab(pyauto.GURL(self.PAGES[1]['url']), 1)
242     self.OpenNewBrowserWindow(True)
243     self.NavigateToURL(self.PAGES[1]['url'], 2, 0)
244     self.AppendTab(pyauto.GURL(self.PAGES[0]['url']), 2)
245     self.CloseBrowserWindow(2)
246     self.CloseBrowserWindow(1)
247     expected = [{ u'type': u'window',
248                   u'tabs': [
249                   { u'type': u'tab',
250                     u'url': self.PAGES[0]['url'],
251                     u'direction': u'ltr' },
252                   { u'type': u'tab',
253                     u'url': self.PAGES[1]['url']}]
254                 },
255                 { u'type': u'window',
256                   u'tabs': [
257                   { u'type': u'tab',
258                     u'url': self.PAGES[1]['url'],
259                     u'direction': u'ltr' },
260                   { u'type': u'tab',
261                     u'url': self.PAGES[0]['url']}]
262                 }]
263     self.assertEquals(expected, test_utils.StripUnmatchedKeys(
264         self.GetNTPRecentlyClosed(), expected))
265
266   def testRecentlyClosedIncognito(self):
267     """Tests that we don't record closure of Incognito tabs or windows"""
268     #self.RemoveNTPDefaultThumbnails()
269     self.RunCommand(pyauto.IDC_NEW_INCOGNITO_WINDOW)
270     self.NavigateToURL(self.PAGES[0]['url'], 1, 0)
271     self.AppendTab(pyauto.GURL(self.PAGES[0]['url']), 1)
272     self.AppendTab(pyauto.GURL(self.PAGES[1]['url']), 1)
273     self.CloseTab(windex=1)
274     self.assertFalse(self.GetNTPRecentlyClosed())
275     self.CloseBrowserWindow(1)
276     self.assertFalse(self.GetNTPRecentlyClosed())
277
278   def _VerifyAppInfo(self, actual_info, expected_info):
279     """Ensures that the actual app info contains the expected app info.
280
281     This method assumes that both the actual and expected information for each
282     app contains at least the 'title' attribute.  Both sets of info are
283     considered to match if the actual info contains at least the specified
284     expected info (if the actual info contains additional values that are not
285     specified in the expected info, that's ok).  This function will fail the
286     current test if both sets of info don't match.
287
288     Args:
289       actual_info: A list of dictionaries representing the information from
290                    all apps that would currently be displayed on the NTP.
291       expected_info: A corrresponding list of dictionaries representing the
292                      information that is expected.
293     """
294     # Ensure all app info dictionaries contain at least the 'title' attribute.
295     self.assertTrue(all(map(lambda app: 'title' in app, actual_info)) and
296                     all(map(lambda app: 'title' in app, expected_info)),
297                     msg='At least one app is missing the "title" attribute.')
298
299     # Sort both app lists by title to ensure they're in a known order.
300     actual_info = sorted(actual_info, key=lambda app: app['title'])
301     expected_info = sorted(expected_info, key=lambda app: app['title'])
302
303     # Ensure the expected info matches the actual info.
304     self.assertTrue(len(actual_info) == len(expected_info),
305                     msg='Expected %d app(s) on NTP, but got %d instead.' % (
306                         len(expected_info), len(actual_info)))
307     for i, expected_app in enumerate(expected_info):
308       for attribute in expected_app:
309         self.assertTrue(attribute in actual_info[i],
310                         msg='Expected attribute "%s" not found in app info.' % (
311                             attribute))
312         self.assertTrue(expected_app[attribute] == actual_info[i][attribute],
313                         msg='For attribute "%s", expected value "%s", but got '
314                             '"%s".' % (attribute, expected_app[attribute],
315                                        actual_info[i][attribute]))
316
317   def _InstallAndVerifySamplePackagedApp(self):
318     """Installs a sample packaged app and verifies the install is successful.
319
320     Returns:
321       The string ID of the installed app.
322     """
323     app_crx_file = os.path.abspath(os.path.join(
324         self.DataDir(), 'pyauto_private', 'apps', 'countdown.crx'))
325     return self.InstallExtension(app_crx_file)
326
327   def testGetAppsInNewProfile(self):
328     """Ensures that the only app in a new profile is the Web Store app."""
329     app_info = self.GetNTPApps()
330     self._VerifyAppInfo(app_info, self._EXPECTED_DEFAULT_APPS)
331
332   def testGetAppsWhenInstallApp(self):
333     """Ensures that an installed app is reflected in the app info in the NTP."""
334     self._InstallAndVerifySamplePackagedApp()
335     app_info = self.GetNTPApps()
336     expected_app_info = [
337       {
338         u'title': u'Countdown'
339       }
340     ]
341     expected_app_info.extend(self._EXPECTED_DEFAULT_APPS)
342     self._VerifyAppInfo(app_info, expected_app_info)
343
344   def testGetAppsWhenInstallNonApps(self):
345     """Ensures installed non-apps are not reflected in the NTP app info."""
346     # Install a regular extension and a theme.
347     ext_crx_file = os.path.abspath(os.path.join(self.DataDir(), 'extensions',
348                                                 'page_action.crx'))
349     self.InstallExtension(ext_crx_file)
350     theme_crx_file = os.path.abspath(os.path.join(self.DataDir(), 'extensions',
351                                                   'theme.crx'))
352     self.SetTheme(theme_crx_file)
353     # Verify that no apps are listed on the NTP except for the Web Store.
354     app_info = self.GetNTPApps()
355     self._VerifyAppInfo(app_info, self._EXPECTED_DEFAULT_APPS)
356
357   def testUninstallApp(self):
358     """Ensures that an uninstalled app is reflected in the NTP app info."""
359     # First, install an app and verify that it exists in the NTP app info.
360     installed_app_id = self._InstallAndVerifySamplePackagedApp()
361     app_info = self.GetNTPApps()
362     expected_app_info = [
363       {
364         u'title': u'Countdown'
365       }
366     ]
367     expected_app_info.extend(self._EXPECTED_DEFAULT_APPS)
368     self._VerifyAppInfo(app_info, expected_app_info)
369
370     # Next, uninstall the app and verify that it is removed from the NTP.
371     self.assertTrue(self.UninstallExtensionById(installed_app_id),
372                     msg='Call to UninstallExtensionById() returned False.')
373     app_info = self.GetNTPApps()
374     self._VerifyAppInfo(app_info, self._EXPECTED_DEFAULT_APPS)
375
376   def testCannotUninstallWebStore(self):
377     """Ensures that the WebStore app cannot be uninstalled."""
378     # Verify that the WebStore app is already installed in a fresh profile.
379     app_info = self.GetNTPApps()
380     self._VerifyAppInfo(app_info, self._EXPECTED_DEFAULT_APPS)
381     self.assertTrue(app_info and 'id' in app_info[0],
382                     msg='Cannot identify ID of WebStore app.')
383     webstore_id = app_info[0]['id']
384
385     # Attempt to uninstall the WebStore app and verify that it still exists
386     # in the App info of the NTP even after we try to uninstall it.
387     self.assertFalse(self.UninstallExtensionById(webstore_id),
388                      msg='Call to UninstallExtensionById() returned True.')
389     self._VerifyAppInfo(self.GetNTPApps(), self._EXPECTED_DEFAULT_APPS)
390
391   def testLaunchAppWithDefaultSettings(self):
392     """Verifies that an app can be launched with the default settings."""
393     # Install an app.
394     installed_app_id = self._InstallAndVerifySamplePackagedApp()
395
396     # Launch the app from the NTP.
397     self.LaunchApp(installed_app_id)
398
399     # Verify that the second tab in the first window is the app launch URL.
400     # It should be the second tab, not the first, since the call to LaunchApp
401     # should have first opened the NTP in a new tab, and then launched the app
402     # from there.
403     info = self.GetBrowserInfo()
404     actual_tab_url = info['windows'][0]['tabs'][1]['url']
405     expected_app_url_start = 'chrome-extension://' + installed_app_id
406     self.assertTrue(actual_tab_url.startswith(expected_app_url_start),
407                     msg='The app was not launched.')
408
409   def testLaunchAppRegularTab(self):
410     """Verifies that an app can be launched in a regular tab."""
411     installed_app_id = self._InstallAndVerifySamplePackagedApp()
412
413     self.SetAppLaunchType(installed_app_id, 'regular', windex=0)
414     self.LaunchApp(installed_app_id)
415
416     # Verify that the second tab in the first window is the app launch URL.
417     info = self.GetBrowserInfo()
418     actual_tab_url = info['windows'][0]['tabs'][1]['url']
419     expected_app_url_start = 'chrome-extension://' + installed_app_id
420     self.assertTrue(actual_tab_url.startswith(expected_app_url_start),
421                     msg='The app was not launched in a regular tab.')
422
423   def testLaunchAppPinnedTab(self):
424     """Verifies that an app can be launched in a pinned tab."""
425     installed_app_id = self._InstallAndVerifySamplePackagedApp()
426
427     self.SetAppLaunchType(installed_app_id, 'pinned', windex=0)
428     self.LaunchApp(installed_app_id)
429
430     # Verify that the first tab in the first window is the app launch URL, and
431     # that it is a pinned tab.
432     info = self.GetBrowserInfo()
433     actual_tab_url = info['windows'][0]['tabs'][0]['url']
434     expected_app_url_start = 'chrome-extension://' + installed_app_id
435     self.assertTrue(actual_tab_url.startswith(expected_app_url_start) and
436                     info['windows'][0]['tabs'][0]['pinned'],
437                     msg='The app was not launched in a pinned tab.')
438
439   def testLaunchAppFullScreen(self):
440     """Verifies that an app can be launched in fullscreen mode."""
441     installed_app_id = self._InstallAndVerifySamplePackagedApp()
442
443     self.SetAppLaunchType(installed_app_id, 'fullscreen', windex=0)
444     self.LaunchApp(installed_app_id)
445
446     # Verify that the second tab in the first window is the app launch URL, and
447     # that the window is fullscreen.
448     info = self.GetBrowserInfo()
449     actual_tab_url = info['windows'][0]['tabs'][1]['url']
450     expected_app_url_start = 'chrome-extension://' + installed_app_id
451     self.assertTrue(actual_tab_url.startswith(expected_app_url_start) and
452                     info['windows'][0]['fullscreen'],
453                     msg='The app was not launched in fullscreen mode.')
454
455   def testLaunchAppNewWindow(self):
456     """Verifies that an app can be launched in a new window."""
457     installed_app_id = self._InstallAndVerifySamplePackagedApp()
458
459     self.SetAppLaunchType(installed_app_id, 'window', windex=0)
460     self.LaunchApp(installed_app_id)
461
462     # Verify that a second window exists (at index 1), and that its first tab
463     # is the app launch URL.
464     info = self.GetBrowserInfo()
465     self.assertTrue(len(info['windows']) == 2,
466                     msg='A second window does not exist.')
467     actual_tab_url = info['windows'][1]['tabs'][0]['url']
468     expected_app_url_start = 'chrome-extension://' + installed_app_id
469     self.assertTrue(actual_tab_url.startswith(expected_app_url_start),
470                     msg='The app was not launched in the new window.')
471
472 if __name__ == '__main__':
473   pyauto_functional.Main()