Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 #!/usr/bin/python | |
| 2 # Copyright (c) 2011 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 """The base test class for GTalk tests. | |
| 7 | |
| 8 This module contains a set of common utilities used by unittest for querying | |
| 9 and manipulating the Google Talk Chrome Extension (http//go/quasar) | |
| 10 """ | |
| 11 | |
| 12 import logging | |
| 13 import os | |
| 14 import random | |
|
Nirnimesh
2011/11/11 01:01:21
unused
wud
2011/11/17 21:17:53
Done.
| |
| 15 import sys | |
|
Nirnimesh
2011/11/11 01:01:21
unused
wud
2011/11/17 21:17:53
Done.
| |
| 16 import tempfile | |
|
Nirnimesh
2011/11/11 01:01:21
unused
wud
2011/11/17 21:17:53
Done.
| |
| 17 import urllib2 | |
|
Nirnimesh
2011/11/11 01:01:21
unused
wud
2011/11/17 21:17:53
Done.
| |
| 18 | |
| 19 import pyauto_gtalk # must preceed pyauto | |
|
Nirnimesh
2011/11/11 01:01:21
leave another space before #
wud
2011/11/17 21:17:53
Done.
| |
| 20 import pyauto | |
| 21 import pyauto_errors | |
| 22 | |
| 23 | |
| 24 class GTalkBaseTest(pyauto.PyUITest): | |
| 25 """Base test class for testing GTalk.""" | |
| 26 | |
|
Nirnimesh
2011/11/11 01:01:21
you should define
_injected_js = None
here. And t
wud
2011/11/17 21:17:53
Ah, thanks!
| |
| 27 def InstallGTalkExtension(self): | |
| 28 """Download and install the GTalk extension.""" | |
| 29 self.UninstallGTalkExtension() | |
| 30 | |
| 31 extension_path = os.path.abspath( | |
| 32 os.path.join(self.DataDir(), 'extensions', 'quasar', 'quasar.crx')) | |
|
Nirnimesh
2011/11/11 01:01:21
change dirname to gtalk?
wud
2011/11/17 21:17:53
Done.
| |
| 33 self.assertTrue(os.path.exists(extension_path), | |
| 34 'Failed to find GTalk extension') | |
|
Nirnimesh
2011/11/11 01:01:21
Use named params: msg='...'
Also, it would be nice
wud
2011/11/17 21:17:53
Done.
| |
| 35 | |
| 36 self.InstallExtension(extension_path, False) | |
| 37 extension = self.GetGTalkExtensionInfo() | |
| 38 self.assertTrue(extension, 'Failed to install GTalk extension') | |
|
Nirnimesh
2011/11/11 01:01:21
msg='Failed to...'
(repeat everywhere else)
wud
2011/11/17 21:17:53
Done.
| |
| 39 self.assertTrue(extension['is_enabled'], 'GTalk extension is disabled') | |
| 40 | |
| 41 def UninstallGTalkExtension(self): | |
| 42 """Uninstall the GTalk extension (if exists)""" | |
|
Nirnimesh
2011/11/11 01:01:21
exists -> present
wud
2011/11/17 21:17:53
Done.
| |
| 43 extension = self.GetGTalkExtensionInfo() | |
| 44 if extension: self.UninstallExtensionById(extension['id']) | |
|
Nirnimesh
2011/11/11 01:01:21
move self.UninstallExtensionById(extension['id'])
wud
2011/11/17 21:17:53
Done.
| |
| 45 | |
| 46 def GetGTalkExtensionInfo(self): | |
| 47 """Get the data object about the GTalk extension.""" | |
| 48 extensions = [x for x in self.GetExtensionsInfo() | |
| 49 if x['name'] == 'Google Talk'] | |
| 50 return extensions[0] if len(extensions) == 1 else None | |
| 51 | |
| 52 def RunInMole(self, js, mole_index=0): | |
| 53 """Execute javascript in a chat mole. | |
| 54 | |
| 55 Args: | |
| 56 js: The javascript to run. | |
| 57 mole_index: The index of the mole in which to run the JS. | |
| 58 | |
| 59 Returns: | |
| 60 The resulting value from executing the javascript. | |
| 61 """ | |
| 62 return self._RunInTab(self.GetMoleInfo(mole_index), js) | |
| 63 | |
| 64 def RunInRoster(self, js): | |
| 65 """Execute javascript in the chat roster. | |
| 66 | |
| 67 Args: | |
| 68 js: The javascript to run. | |
| 69 | |
| 70 Returns: | |
| 71 The resulting value from executing the javascript. | |
| 72 """ | |
| 73 return self._RunInTab(self.GetViewerInfo(), js, '//iframe[1]\n//iframe[1]') | |
| 74 | |
| 75 def RunInLoginPage(self, js, xpath=''): | |
| 76 """Execute javascript in the gaia login popup. | |
| 77 | |
| 78 Args: | |
| 79 js: The javascript to run. | |
| 80 xpath: The xpath to the frame in which to execute the javascript. | |
| 81 | |
| 82 Returns: | |
| 83 The resulting value from executing the javascript. | |
| 84 """ | |
| 85 return self._RunInTab(self.GetLoginPageInfo(), js, xpath) | |
| 86 | |
| 87 def RunInViewer(self, js, xpath=''): | |
| 88 """Execute javascript in the GTalk viewer window. | |
| 89 | |
| 90 Args: | |
| 91 js: The javascript to run. | |
| 92 xpath: The xpath to the frame in which to execute the javascript. | |
| 93 | |
| 94 Returns: | |
| 95 The resulting value from executing the javascript. | |
| 96 """ | |
| 97 return self._RunInTab(self.GetViewerInfo(), js, xpath) | |
| 98 | |
| 99 def RunInBackground(self, js, xpath=''): | |
| 100 """Execute javascript in the GTalk viewer window. | |
| 101 | |
| 102 Args: | |
| 103 js: The javascript to run. | |
| 104 xpath: The xpath to the frame in which to execute the javascript. | |
| 105 | |
| 106 Returns: | |
| 107 The resulting value from executing the javascript. | |
| 108 """ | |
| 109 background_view = self.GetBackgroundInfo() | |
| 110 value = self.ExecuteJavascriptInRenderView( | |
| 111 self._WrapJs(js), background_view['view']) | |
| 112 self._LogRun(js, value) | |
| 113 return value | |
| 114 | |
| 115 def GetMoleInfo(self, mole_index=0): | |
| 116 """Get the data object about a given chat mole. | |
| 117 | |
| 118 Args: | |
| 119 mole_index: The index of the mole to retrieve. | |
| 120 | |
| 121 Returns: | |
| 122 Data object describing mole. | |
| 123 """ | |
| 124 return self._GetTabInfo('/pmole?', mole_index) | |
| 125 | |
| 126 def GetViewerInfo(self): | |
| 127 """Get the data object about the GTalk viewer dialog.""" | |
| 128 extension = self.GetGTalkExtensionInfo() | |
| 129 return self._GetTabInfo( | |
| 130 'chrome-extension://' + extension['id'] + '/viewer.html') | |
| 131 | |
| 132 def GetLoginPageInfo(self): | |
| 133 """Get the data object about the gaia login popup.""" | |
| 134 return self._GetTabInfo('https://accounts.google.com/ServiceLogin?') | |
| 135 | |
| 136 def GetBackgroundInfo(self): | |
| 137 """Get the data object about the GTalk background page.""" | |
| 138 extension_views = self.GetBrowserInfo()['extension_views'] | |
| 139 for extension_view in extension_views: | |
| 140 if 'Google Talk' in extension_view['name'] and \ | |
| 141 'EXTENSION_BACKGROUND_PAGE' == extension_view['view_type']: | |
| 142 return extension_view | |
| 143 return None; | |
| 144 | |
| 145 def WaitUntilResult(self, result, func, msg): | |
| 146 """Loop func until a condition matches is satified. | |
| 147 | |
| 148 Args: | |
| 149 result: Value of func() at which to stop. | |
| 150 func: Function to run at each iteration. | |
| 151 msg: Error to print upon timing out. | |
| 152 """ | |
| 153 self.assertTrue(self.WaitUntil( | |
|
Nirnimesh
2011/11/11 01:01:21
This is better written as:
self.assertTrue(self.Wa
wud
2011/11/17 21:17:53
Thanks.
| |
| 154 lambda: result == func()), msg) | |
| 155 | |
| 156 def WaitUntilCondition(self, func, matches, msg): | |
| 157 """Loop func until condition matches is satified. | |
| 158 | |
| 159 Args: | |
| 160 func: Function to run at each iteration. | |
| 161 matches: Funtion to evalute output and determine whether to stop. | |
| 162 msg: Error to print upon timing out. | |
| 163 """ | |
|
Nirnimesh
2011/11/11 01:01:21
assert callable(matches)
wud
2011/11/17 21:17:53
Done. Also added for func.
| |
| 164 self.assertTrue(self.WaitUntil( | |
| 165 lambda: matches(func())), msg) | |
| 166 | |
| 167 def _WrapJs(self, statement): | |
| 168 """Wrap the javascript to be executed. | |
| 169 | |
| 170 Args: | |
| 171 statement: The piece of javascript to wrap. | |
| 172 | |
| 173 Returns: | |
| 174 The wrapped javascript. | |
| 175 """ | |
| 176 return 'window.domAutomationController.send(' + \ | |
|
Nirnimesh
2011/11/11 01:01:21
this will look cleaner as a heredoc.
return """
wud
2011/11/17 21:17:53
Thanks. Didn't know about heredoc.
| |
| 177 '(function(){' + self._GetInjectedJs() + \ | |
| 178 'try{return ' + statement + '}' + \ | |
| 179 'catch(e){return "JS_ERROR: " + e}})())' | |
| 180 | |
| 181 def _RunInTab(self, tab, js, xpath=''): | |
| 182 """Execute javascript in a given tab. | |
| 183 | |
| 184 Args: | |
| 185 tab: The data object for the tab. | |
|
frankf
2011/11/11 01:35:03
more descriptive variable name.
wud
2011/11/17 21:17:53
Updated description. The variable name "tab", refe
| |
| 186 js: The javascript to run. | |
| 187 xpath: The xpath to the frame in which to execute the javascript. | |
| 188 | |
| 189 Returns: | |
| 190 The resulting value from executing the javascript. | |
| 191 """ | |
| 192 if not tab: | |
| 193 logging.debug("Tab not found: %s" % tab) | |
|
frankf
2011/11/11 01:35:03
Be consistent with quotes (All ' or all ")
wud
2011/11/17 21:17:53
Done.
| |
| 194 return False | |
| 195 logging.info("Run in tab: " + js) | |
| 196 | |
| 197 # Catch any JSONInterfaceError thrown while running. | |
| 198 try: | |
| 199 value = self.ExecuteJavascriptInTab(self._WrapJs(js), | |
| 200 windex = tab['windex'], | |
| 201 frame_xpath = xpath) | |
| 202 except pyauto_error.JSONInterfaceError as e: | |
|
Nirnimesh
2011/11/11 01:01:21
It's not a good idea to catch this. This represent
wud
2011/11/17 21:17:53
In some cases (e.g., I believe when an expected el
Nirnimesh
2011/11/30 23:57:36
Such an issue is actually a symptom of js error. Y
| |
| 203 logging.debug("Error running JS: %s" % js) | |
| 204 value = False | |
| 205 self._LogRun(js, value) | |
| 206 return value | |
| 207 | |
| 208 def _LogRun(self, js, value): | |
| 209 """Log a particular run. | |
| 210 | |
| 211 Args: | |
| 212 js: The javascript statement executed. | |
| 213 value: The return value for the execution. | |
| 214 """ | |
| 215 out = value | |
| 216 if not isinstance(value, basestring): | |
|
Nirnimesh
2011/11/11 01:01:21
not necessary. out = str(value) will work regardle
wud
2011/11/17 21:17:53
Done.
| |
| 217 out = str(value) | |
| 218 out = out[:300] | |
|
Nirnimesh
2011/11/11 01:01:21
218-220 can be:
re.sub('\s', '', out[:300])
Also,
wud
2011/11/17 21:17:53
Done.
| |
| 219 out = out.replace("\n", '') | |
| 220 out = out.replace("\r", '') | |
| 221 logging.info(js + ' ===> ' + out.encode('utf-8')) | |
| 222 | |
| 223 def _GetTabInfo(self, url_query, index=0): | |
| 224 """Get the data object for a given tab. | |
| 225 | |
| 226 Args: | |
| 227 url_query: The substring of the URL to search for. | |
| 228 index: The index within the list of matches to return. | |
| 229 | |
| 230 Returns: | |
| 231 The data object for the tab. | |
| 232 """ | |
| 233 windows = self.GetBrowserInfo()['windows'] | |
| 234 i = 0 | |
| 235 for win in windows: | |
| 236 for tab in win['tabs']: | |
| 237 if tab['url'] and url_query in tab['url']: | |
| 238 tab['windex'] = win['index'] | |
|
Nirnimesh
2011/11/11 01:01:21
what is this for?
wud
2011/11/17 21:17:53
A reference to the windex used in _RunInTab.
| |
| 239 if i == index: | |
| 240 return tab | |
| 241 i = i + 1 | |
| 242 return None | |
| 243 | |
| 244 def _GetInjectedJs(self): | |
| 245 """Get the javascript to inject in the execution environment.""" | |
| 246 if self._injected_js == None: | |
|
Nirnimesh
2011/11/11 01:01:21
s/==/is/
wud
2011/11/17 21:17:53
Done.
| |
| 247 jsfile = open(os.path.dirname(__file__) + '/jsutils.js') | |
|
Nirnimesh
2011/11/11 01:01:21
247-250 can be written as:
self._injected_js = op
wud
2011/11/17 21:17:53
Thanks, done.
| |
| 248 js = jsfile.read() | |
| 249 jsfile.close() | |
| 250 self._injected_js = js | |
| 251 return self._injected_js | |
| 252 | |
| 253 def action_max_timeout_ms(self): | |
|
Nirnimesh
2011/11/11 01:01:21
what is this for?
wud
2011/11/17 21:17:53
This is the default timeout used by WaitUntil. Set
Nirnimesh
2011/11/30 23:57:36
I don't think you should override this. This contr
| |
| 254 """Get the default timeout for each WaitUntil command.""" | |
| 255 return 30000; | |
| 256 | |
| 257 def __init__(self, methodName='runTest'): | |
| 258 pyauto.PyUITest.__init__(self, methodName) | |
| 259 self._injected_js = None | |
| OLD | NEW |