- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / test / functional / gtalk / gtalk_base_test.py
1 # Copyright (c) 2012 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 """Base GTalk tests.
6
7 This module contains a set of common utilities for querying
8 and manipulating the Google Talk Chrome Extension.
9 """
10
11 import logging
12 import re
13 import os
14
15 import pyauto_gtalk
16 import pyauto
17 import pyauto_errors
18
19
20 class GTalkBaseTest(pyauto.PyUITest):
21   """Base test class for testing GTalk."""
22
23   _injected_js = None
24
25   def Prompt(self, text):
26     """Pause execution with debug output.
27
28     Args:
29       text: The debug output.
30     """
31     text = str(text)
32     raw_input('--------------------> ' + text)
33
34   def InstallGTalkExtension(self, gtalk_version):
35     """Download and install the GTalk extension."""
36     extension_path = os.path.abspath(
37         os.path.join(self.DataDir(), 'extensions', 'gtalk',
38                      gtalk_version + '.crx'))
39     self.assertTrue(
40         os.path.exists(extension_path),
41         msg='Failed to find GTalk extension: ' + extension_path)
42
43     extension = self.GetGTalkExtensionInfo()
44     if extension:
45       logging.info('Extension already installed. Skipping install...\n')
46       return
47
48     self.InstallExtension(extension_path, False)
49     extension = self.GetGTalkExtensionInfo()
50     self.assertTrue(extension, msg='Failed to install GTalk extension.')
51     self.assertTrue(extension['is_enabled'], msg='GTalk extension is disabled.')
52
53   def UninstallGTalkExtension(self):
54     """Uninstall the GTalk extension (if present)"""
55     extension = self.GetGTalkExtensionInfo()
56     if extension:
57       self.UninstallExtensionById(extension['id'])
58
59   def GetGTalkExtensionInfo(self):
60     """Get the data object about the GTalk extension."""
61     extensions = [x for x in self.GetExtensionsInfo()
62         if x['name'] == 'Chat for Google']
63     return extensions[0] if len(extensions) == 1 else None
64
65   def RunInMole(self, js, mole_index=0):
66     """Execute javascript in a chat mole.
67
68     Args:
69       js: The javascript to run.
70       mole_index: The index of the mole in which to run the JS.
71
72     Returns:
73       The resulting value from executing the javascript.
74     """
75     return self._RunInRenderView(self.GetMoleInfo(mole_index), js,
76         '//iframe[1]')
77
78   def RunInAllMoles(self, js):
79     """Execute javascript in all chat moles.
80
81     Args:
82       js: The javascript to run.
83     """
84     moles = self.GetMolesInfo()
85     for mole in moles:
86       self._RunInRenderView(mole, js, '//iframe[1]')
87
88   def RunInRoster(self, js):
89     """Execute javascript in the chat roster.
90
91     Args:
92       js: The javascript to run.
93
94     Returns:
95       The resulting value from executing the javascript.
96     """
97     return self._RunInRenderView(self.GetViewerInfo(), js,
98         '//iframe[1]\n//iframe[1]')
99
100   def RunInLoginPage(self, js, xpath=''):
101     """Execute javascript in the gaia login popup.
102
103     Args:
104       js: The javascript to run.
105       xpath: The xpath to the frame in which to execute the javascript.
106
107     Returns:
108       The resulting value from executing the javascript.
109     """
110     return self._RunInTab(self.GetLoginPageInfo(), js, xpath)
111
112   def RunInViewer(self, js, xpath=''):
113     """Execute javascript in the GTalk viewer window.
114
115     Args:
116       js: The javascript to run.
117       xpath: The xpath to the frame in which to execute the javascript.
118
119     Returns:
120       The resulting value from executing the javascript.
121     """
122     return self._RunInRenderView(self.GetViewerInfo(), js, xpath)
123
124   def RunInBackground(self, js, xpath=''):
125     """Execute javascript in the GTalk viewer window.
126
127     Args:
128       js: The javascript to run.
129       xpath: The xpath to the frame in which to execute the javascript.
130
131     Returns:
132       The resulting value from executing the javascript.
133     """
134     background_view = self.GetBackgroundInfo()
135     return self._RunInRenderView(background_view['view'], js, xpath)
136
137   def GetMoleInfo(self, mole_index=0):
138     """Get the data object about a given chat mole.
139
140     Args:
141       mole_index: The index of the mole to retrieve.
142
143     Returns:
144       Data object describing mole.
145     """
146     extension = self.GetGTalkExtensionInfo()
147     return self._GetExtensionViewInfo(
148         'chrome-extension://%s/panel.html' % extension['id'],
149         mole_index)
150
151   def GetMolesInfo(self):
152     """Get the data objects for all of the chat moles.
153
154     Returns:
155       Set of data objects describing moles.
156     """
157     extension = self.GetGTalkExtensionInfo()
158     return self._GetMatchingExtensionViews(
159         'chrome-extension://%s/panel.html' % extension['id'])
160
161   def GetViewerInfo(self):
162     """Get the data object about the GTalk viewer dialog."""
163     extension = self.GetGTalkExtensionInfo()
164     return self._GetExtensionViewInfo(
165         'chrome-extension://%s/viewer.html' % extension['id'])
166
167   def GetLoginPageInfo(self):
168     """Get the data object about the gaia login popup."""
169     return self._GetTabInfo('https://accounts.google.com/ServiceLogin?')
170
171   def GetBackgroundInfo(self):
172     """Get the data object about the GTalk background page."""
173     extension_views = self.GetBrowserInfo()['extension_views']
174     for extension_view in extension_views:
175       if 'Google Talk' in extension_view['name'] and \
176           'EXTENSION_BACKGROUND_PAGE' == extension_view['view_type']:
177         return extension_view
178     return None
179
180   def WaitUntilResult(self, result, func, msg):
181     """Loop func until a condition matches is satified.
182
183     Args:
184       result: Value of func() at which to stop.
185       func: Function to run at each iteration.
186       msg: Error to print upon timing out.
187     """
188     assert callable(func)
189     self.assertTrue(self.WaitUntil(
190         lambda: func(), expect_retval=result), msg=msg)
191
192   def WaitUntilCondition(self, func, matches, msg):
193     """Loop func until condition matches is satified.
194
195     Args:
196       func: Function to run at each iteration.
197       matches: Funtion to evalute output and determine whether to stop.
198       msg: Error to print upon timing out.
199     """
200     assert callable(func)
201     assert callable(matches)
202     self.assertTrue(self.WaitUntil(
203         lambda: matches(func())), msg=msg)
204
205   def _WrapJs(self, statement):
206     """Wrap the javascript to be executed.
207
208     Args:
209       statement: The piece of javascript to wrap.
210
211     Returns:
212       The wrapped javascript.
213     """
214     return """
215             window.domAutomationController.send(
216             (function(){
217             %s
218             try{return %s}
219             catch(e){return "JS_ERROR: " + e}})())
220            """ % (self._GetInjectedJs(), statement)
221
222   def _RunInTab(self, tab, js, xpath=''):
223     """Execute javascript in a given tab.
224
225     Args:
226       tab: The data object for the Chrome window tab returned by
227           _GetTabInfo.
228       js: The javascript to run.
229       xpath: The xpath to the frame in which to execute the javascript.
230
231     Returns:
232       The resulting value from executing the javascript.
233     """
234     if not tab:
235       logging.debug('Tab not found: %s' % tab)
236       return False
237     logging.info('Run in tab: %s' % js)
238
239     value = self.ExecuteJavascript(
240         self._WrapJs(js),
241         tab_index = tab['index'],
242         windex = tab['windex'],
243         frame_xpath = xpath)
244     self._LogRun(js, value)
245     return value
246
247   def _RunInRenderView(self, view, js, xpath=''):
248     """Execute javascript in a given render view.
249
250     Args:
251       view: The data object for the Chrome render view returned by
252           _GetExtensionViewInfo.
253       js: The javascript to run.
254       xpath: The xpath to the frame in which to execute the javascript.
255
256     Returns:
257       The resulting value from executing the javascript.
258     """
259     if not view:
260       logging.debug('View not found: %s' % view)
261       return False
262     logging.info('Run in view: %s' % js)
263
264     value = self.ExecuteJavascriptInRenderView(
265         self._WrapJs(js),
266         view,
267         frame_xpath = xpath)
268     self._LogRun(js, value)
269     return value
270
271   def _LogRun(self, js, value):
272     """Log a particular run.
273
274     Args:
275       js: The javascript statement executed.
276       value: The return value for the execution.
277     """
278     # works around UnicodeEncodeError: 'ascii' codec can't encode...
279     out = value
280     if not isinstance(value, basestring):
281       out = str(value)
282     out = re.sub('\s', ';', out[:300])
283     logging.info(js + ' ===> ' + out.encode('utf-8'))
284
285   def _GetTabInfo(self, url_query, index=0):
286     """Get the data object for a given tab.
287
288     Args:
289       url_query: The substring of the URL to search for.
290       index: The index within the list of matches to return.
291
292     Returns:
293       The data object for the tab.
294     """
295     windows = self.GetBrowserInfo()['windows']
296     i = 0
297     for win in windows:
298       for tab in win['tabs']:
299         if tab['url'] and url_query in tab['url']:
300           # Store reference to windex used in _RunInTab.
301           tab['windex'] = win['index']
302           if i == index:
303             return tab
304           i = i + 1
305     return None
306
307   def _GetExtensionViewInfo(self, url_query, index=0):
308     """Get the data object for a given extension view.
309
310     Args:
311       url_query: The substring of the URL to search for.
312       index: The index within the list of matches to return.
313
314     Returns:
315       The data object for the tab.
316     """
317
318     candidate_views = self._GetMatchingExtensionViews(url_query)
319     if len(candidate_views) > index:
320       return candidate_views[index]
321     return None
322
323   def _GetMatchingExtensionViews(self, url_query):
324     """Gets the data objects for the extension views matching the url_query.
325
326     Args:
327       url_query: The substring of the URL to search for.
328
329     Returns:
330       An array of matching data objects.
331     """
332     extension_views = self.GetBrowserInfo()['extension_views']
333     candidate_views = list()
334     for extension_view in extension_views:
335       if extension_view['url'] and url_query in extension_view['url']:
336         candidate_views.append(extension_view['view'])
337
338     # No guarantee on view order, so sort the views to get the correct one for
339     # a given index.
340     candidate_views.sort()
341     return candidate_views
342
343   def _GetInjectedJs(self):
344     """Get the javascript to inject in the execution environment."""
345     if self._injected_js is None:
346       self._injected_js = open(
347           os.path.join(os.path.dirname(__file__), 'jsutils.js')).read()
348     return self._injected_js