| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/python | |
| 2 | |
| 3 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
| 4 # Use of this source code is governed by a BSD-style license that can be | |
| 5 # found in the LICENSE file. | |
| 6 | |
| 7 """Tests for ChromeDriver. | |
| 8 | |
| 9 If your test is testing a specific part of the WebDriver API, consider adding | |
| 10 it to the appropriate place in the WebDriver tree instead. | |
| 11 """ | |
| 12 | |
| 13 import hashlib | |
| 14 import os | |
| 15 import platform | |
| 16 import sys | |
| 17 import tempfile | |
| 18 import unittest | |
| 19 import urllib | |
| 20 import urllib2 | |
| 21 import urlparse | |
| 22 | |
| 23 from chromedriver_launcher import ChromeDriverLauncher | |
| 24 import chromedriver_paths | |
| 25 from gtest_text_test_runner import GTestTextTestRunner | |
| 26 | |
| 27 sys.path += [chromedriver_paths.SRC_THIRD_PARTY] | |
| 28 sys.path += [chromedriver_paths.PYTHON_BINDINGS] | |
| 29 | |
| 30 try: | |
| 31 import simplejson as json | |
| 32 except ImportError: | |
| 33 import json | |
| 34 | |
| 35 from selenium.common.exceptions import WebDriverException | |
| 36 from selenium.webdriver.remote.command import Command | |
| 37 from selenium.webdriver.remote.webdriver import WebDriver | |
| 38 from selenium.webdriver.common.keys import Keys | |
| 39 from selenium.webdriver.common.desired_capabilities import DesiredCapabilities | |
| 40 | |
| 41 | |
| 42 def DataDir(): | |
| 43 """Returns the path to the data dir chrome/test/data.""" | |
| 44 return os.path.normpath( | |
| 45 os.path.join(os.path.dirname(__file__), os.pardir, "data")) | |
| 46 | |
| 47 | |
| 48 def GetFileURLForPath(path): | |
| 49 """Get file:// url for the given path. | |
| 50 Also quotes the url using urllib.quote(). | |
| 51 """ | |
| 52 abs_path = os.path.abspath(path) | |
| 53 if sys.platform == 'win32': | |
| 54 # Don't quote the ':' in drive letter ( say, C: ) on win. | |
| 55 # Also, replace '\' with '/' as expected in a file:/// url. | |
| 56 drive, rest = os.path.splitdrive(abs_path) | |
| 57 quoted_path = drive.upper() + urllib.quote((rest.replace('\\', '/'))) | |
| 58 return 'file:///' + quoted_path | |
| 59 else: | |
| 60 quoted_path = urllib.quote(abs_path) | |
| 61 return 'file://' + quoted_path | |
| 62 | |
| 63 | |
| 64 def IsWindows(): | |
| 65 return sys.platform == 'cygwin' or sys.platform.startswith('win') | |
| 66 | |
| 67 | |
| 68 def IsLinux(): | |
| 69 return sys.platform.startswith('linux') | |
| 70 | |
| 71 | |
| 72 def IsMac(): | |
| 73 return sys.platform.startswith('darwin') | |
| 74 | |
| 75 | |
| 76 class Request(urllib2.Request): | |
| 77 """Extends urllib2.Request to support all HTTP request types.""" | |
| 78 | |
| 79 def __init__(self, url, method=None, data=None): | |
| 80 """Initialise a new HTTP request. | |
| 81 | |
| 82 Arguments: | |
| 83 url: The full URL to send the request to. | |
| 84 method: The HTTP request method to use; defaults to 'GET'. | |
| 85 data: The data to send with the request as a string. Defaults to | |
| 86 None and is ignored if |method| is not 'POST' or 'PUT'. | |
| 87 """ | |
| 88 if method is None: | |
| 89 method = data is not None and 'POST' or 'GET' | |
| 90 elif method not in ('POST', 'PUT'): | |
| 91 data = None | |
| 92 self.method = method | |
| 93 urllib2.Request.__init__(self, url, data=data) | |
| 94 | |
| 95 def get_method(self): | |
| 96 """Returns the HTTP method used by this request.""" | |
| 97 return self.method | |
| 98 | |
| 99 | |
| 100 def SendRequest(url, method=None, data=None): | |
| 101 """Sends a HTTP request to the WebDriver server. | |
| 102 | |
| 103 Return values and exceptions raised are the same as those of | |
| 104 |urllib2.urlopen|. | |
| 105 | |
| 106 Arguments: | |
| 107 url: The full URL to send the request to. | |
| 108 method: The HTTP request method to use; defaults to 'GET'. | |
| 109 data: The data to send with the request as a string. Defaults to | |
| 110 None and is ignored if |method| is not 'POST' or 'PUT'. | |
| 111 | |
| 112 Returns: | |
| 113 A file-like object. | |
| 114 """ | |
| 115 request = Request(url, method=method, data=data) | |
| 116 request.add_header('Accept', 'application/json') | |
| 117 opener = urllib2.build_opener(urllib2.HTTPRedirectHandler()) | |
| 118 return opener.open(request) | |
| 119 | |
| 120 | |
| 121 class BasicTest(unittest.TestCase): | |
| 122 """Basic ChromeDriver tests.""" | |
| 123 | |
| 124 def setUp(self): | |
| 125 self._launcher = ChromeDriverLauncher() | |
| 126 | |
| 127 def tearDown(self): | |
| 128 self._launcher.Kill() | |
| 129 | |
| 130 def testShouldReturn403WhenSentAnUnknownCommandURL(self): | |
| 131 request_url = self._launcher.GetURL() + '/foo' | |
| 132 try: | |
| 133 SendRequest(request_url, method='GET') | |
| 134 self.fail('Should have raised a urllib.HTTPError for returned 403') | |
| 135 except urllib2.HTTPError, expected: | |
| 136 self.assertEquals(403, expected.code) | |
| 137 | |
| 138 def testShouldReturnHTTP405WhenSendingANonPostToTheSessionURL(self): | |
| 139 request_url = self._launcher.GetURL() + '/session' | |
| 140 try: | |
| 141 SendRequest(request_url, method='GET') | |
| 142 self.fail('Should have raised a urllib.HTTPError for returned 405') | |
| 143 except urllib2.HTTPError, expected: | |
| 144 self.assertEquals(405, expected.code) | |
| 145 self.assertEquals('POST', expected.hdrs['Allow']) | |
| 146 | |
| 147 def testShouldGetA404WhenAttemptingToDeleteAnUnknownSession(self): | |
| 148 request_url = self._launcher.GetURL() + '/session/unkown_session_id' | |
| 149 try: | |
| 150 SendRequest(request_url, method='DELETE') | |
| 151 self.fail('Should have raised a urllib.HTTPError for returned 404') | |
| 152 except urllib2.HTTPError, expected: | |
| 153 self.assertEquals(404, expected.code) | |
| 154 | |
| 155 def testShouldReturn204ForFaviconRequests(self): | |
| 156 request_url = self._launcher.GetURL() + '/favicon.ico' | |
| 157 # In python2.5, a 204 status code causes an exception. | |
| 158 if sys.version_info[0:2] == (2, 5): | |
| 159 try: | |
| 160 SendRequest(request_url, method='GET') | |
| 161 self.fail('Should have raised a urllib.HTTPError for returned 204') | |
| 162 except urllib2.HTTPError, expected: | |
| 163 self.assertEquals(204, expected.code) | |
| 164 else: | |
| 165 response = SendRequest(request_url, method='GET') | |
| 166 try: | |
| 167 self.assertEquals(204, response.code) | |
| 168 finally: | |
| 169 response.close() | |
| 170 | |
| 171 def testCanStartChromeDriverOnSpecificPort(self): | |
| 172 launcher = ChromeDriverLauncher(port=9520) | |
| 173 self.assertEquals(9520, launcher.GetPort()) | |
| 174 driver = WebDriver(launcher.GetURL(), DesiredCapabilities.CHROME) | |
| 175 driver.quit() | |
| 176 launcher.Kill() | |
| 177 | |
| 178 | |
| 179 class WebserverTest(unittest.TestCase): | |
| 180 """Tests the built-in ChromeDriver webserver.""" | |
| 181 | |
| 182 def testShouldNotServeFilesByDefault(self): | |
| 183 launcher = ChromeDriverLauncher() | |
| 184 try: | |
| 185 SendRequest(launcher.GetURL(), method='GET') | |
| 186 self.fail('Should have raised a urllib.HTTPError for returned 403') | |
| 187 except urllib2.HTTPError, expected: | |
| 188 self.assertEquals(403, expected.code) | |
| 189 finally: | |
| 190 launcher.Kill() | |
| 191 | |
| 192 def testCanServeFiles(self): | |
| 193 launcher = ChromeDriverLauncher(root_path=os.path.dirname(__file__)) | |
| 194 request_url = launcher.GetURL() + '/' + os.path.basename(__file__) | |
| 195 SendRequest(request_url, method='GET') | |
| 196 launcher.Kill() | |
| 197 | |
| 198 | |
| 199 class NativeInputTest(unittest.TestCase): | |
| 200 """Native input ChromeDriver tests.""" | |
| 201 | |
| 202 def setUp(self): | |
| 203 self._launcher = ChromeDriverLauncher(root_path=os.path.dirname(__file__)) | |
| 204 self._capabilities = DesiredCapabilities.CHROME | |
| 205 self._capabilities['chrome.nativeEvents'] = True | |
| 206 | |
| 207 def tearDown(self): | |
| 208 self._launcher.Kill() | |
| 209 | |
| 210 def testCanStartWithNativeEvents(self): | |
| 211 driver = WebDriver(self._launcher.GetURL(), self._capabilities) | |
| 212 self.assertTrue(driver.capabilities.has_key('chrome.nativeEvents')) | |
| 213 self.assertTrue(driver.capabilities['chrome.nativeEvents']) | |
| 214 | |
| 215 # Flaky on windows. See crbug.com/80295. | |
| 216 def DISABLED_testSendKeysNative(self): | |
| 217 driver = WebDriver(self._launcher.GetURL(), self._capabilities) | |
| 218 driver.get(self._launcher.GetURL() + '/test_page.html') | |
| 219 # Find the text input. | |
| 220 q = driver.find_element_by_name('key_input_test') | |
| 221 # Send some keys. | |
| 222 q.send_keys('tokyo') | |
| 223 self.assertEqual(q.text, 'tokyo') | |
| 224 | |
| 225 # Needs to run on a machine with an IME installed. | |
| 226 def DISABLED_testSendKeysNativeProcessedByIME(self): | |
| 227 driver = WebDriver(self._launcher.GetURL(), self.capabilities) | |
| 228 driver.get(self._launcher.GetURL() + '/test_page.html') | |
| 229 q = driver.find_element_by_name('key_input_test') | |
| 230 # Send key combination to turn IME on. | |
| 231 q.send_keys(Keys.F7) | |
| 232 q.send_keys('toukyou') | |
| 233 # Now turning it off. | |
| 234 q.send_keys(Keys.F7) | |
| 235 self.assertEqual(q.value, "\xe6\x9d\xb1\xe4\xba\xac") | |
| 236 | |
| 237 | |
| 238 class DesiredCapabilitiesTest(unittest.TestCase): | |
| 239 | |
| 240 def setUp(self): | |
| 241 self._launcher = ChromeDriverLauncher(root_path=os.path.dirname(__file__)) | |
| 242 | |
| 243 def tearDown(self): | |
| 244 self._launcher.Kill() | |
| 245 | |
| 246 def testCustomSwitches(self): | |
| 247 switches = ['enable-file-cookie', 'homepage=about:memory'] | |
| 248 capabilities = {'chrome.switches': switches} | |
| 249 | |
| 250 driver = WebDriver(self._launcher.GetURL(), capabilities) | |
| 251 url = driver.current_url | |
| 252 self.assertTrue('memory' in url, | |
| 253 'URL does not contain with "memory":' + url) | |
| 254 driver.get('about:version') | |
| 255 self.assertNotEqual(-1, driver.page_source.find('enable-file-cookie')) | |
| 256 | |
| 257 def testBinary(self): | |
| 258 binary_path = ChromeDriverLauncher.LocateExe() | |
| 259 self.assertNotEquals(None, binary_path) | |
| 260 if IsWindows(): | |
| 261 chrome_name = 'chrome.exe' | |
| 262 elif IsMac(): | |
| 263 chrome_name = 'Google Chrome.app/Contents/MacOS/Google Chrome' | |
| 264 if not os.path.exists(os.path.join(binary_path, chrome_name)): | |
| 265 chrome_name = 'Chromium.app/Contents/MacOS/Chromium' | |
| 266 elif IsLinux(): | |
| 267 chrome_name = 'chrome' | |
| 268 else: | |
| 269 self.fail('Unrecognized platform: ' + sys.platform) | |
| 270 binary_path = os.path.join(os.path.dirname(binary_path), chrome_name) | |
| 271 self.assertTrue(os.path.exists(binary_path), | |
| 272 'Binary not found: ' + binary_path) | |
| 273 capabilities = {'chrome.binary': binary_path} | |
| 274 | |
| 275 driver = WebDriver(self._launcher.GetURL(), capabilities) | |
| 276 | |
| 277 | |
| 278 class CookieTest(unittest.TestCase): | |
| 279 """Cookie test for the json webdriver protocol""" | |
| 280 | |
| 281 def setUp(self): | |
| 282 self._launcher = ChromeDriverLauncher(root_path=os.path.dirname(__file__)) | |
| 283 self._driver = WebDriver(self._launcher.GetURL(), | |
| 284 DesiredCapabilities.CHROME) | |
| 285 | |
| 286 def tearDown(self): | |
| 287 self._driver.quit() | |
| 288 self._launcher.Kill() | |
| 289 | |
| 290 def testAddCookie(self): | |
| 291 self._driver.get(self._launcher.GetURL() + '/test_page.html') | |
| 292 cookie_dict = None | |
| 293 cookie_dict = self._driver.get_cookie("chromedriver_cookie_test") | |
| 294 cookie_dict = {} | |
| 295 cookie_dict["name"] = "chromedriver_cookie_test" | |
| 296 cookie_dict["value"] = "this is a test" | |
| 297 self._driver.add_cookie(cookie_dict) | |
| 298 cookie_dict = self._driver.get_cookie("chromedriver_cookie_test") | |
| 299 self.assertNotEqual(cookie_dict, None) | |
| 300 self.assertEqual(cookie_dict["value"], "this is a test") | |
| 301 | |
| 302 def testDeleteCookie(self): | |
| 303 self.testAddCookie(); | |
| 304 self._driver.delete_cookie("chromedriver_cookie_test") | |
| 305 cookie_dict = self._driver.get_cookie("chromedriver_cookie_test") | |
| 306 self.assertEqual(cookie_dict, None) | |
| 307 | |
| 308 | |
| 309 class ScreenshotTest(unittest.TestCase): | |
| 310 """Tests to verify screenshot retrieval""" | |
| 311 | |
| 312 REDBOX = "automation_proxy_snapshot/set_size.html" | |
| 313 | |
| 314 def setUp(self): | |
| 315 self._launcher = ChromeDriverLauncher() | |
| 316 self._driver = WebDriver(self._launcher.GetURL(), {}) | |
| 317 | |
| 318 def tearDown(self): | |
| 319 self._driver.quit() | |
| 320 self._launcher.Kill() | |
| 321 | |
| 322 def testScreenCaptureAgainstReference(self): | |
| 323 # Create a red square of 2000x2000 pixels. | |
| 324 url = GetFileURLForPath(os.path.join(DataDir(), | |
| 325 self.REDBOX)) | |
| 326 url += "?2000,2000" | |
| 327 self._driver.get(url) | |
| 328 s = self._driver.get_screenshot_as_base64(); | |
| 329 self._driver.get_screenshot_as_file("/tmp/foo.png") | |
| 330 h = hashlib.md5(s).hexdigest() | |
| 331 # Compare the PNG created to the reference hash. | |
| 332 self.assertEquals(h, '12c0ade27e3875da3d8866f52d2fa84f') | |
| 333 | |
| 334 | |
| 335 class SessionTest(unittest.TestCase): | |
| 336 """Tests dealing with WebDriver sessions.""" | |
| 337 | |
| 338 def setUp(self): | |
| 339 self._launcher = ChromeDriverLauncher() | |
| 340 | |
| 341 def tearDown(self): | |
| 342 self._launcher.Kill() | |
| 343 | |
| 344 def testCreatingSessionShouldRedirectToCorrectURL(self): | |
| 345 request_url = self._launcher.GetURL() + '/session' | |
| 346 response = SendRequest(request_url, method='POST', | |
| 347 data='{"desiredCapabilities": {}}') | |
| 348 self.assertEquals(200, response.code) | |
| 349 self.session_url = response.geturl() # TODO(jleyba): verify this URL? | |
| 350 | |
| 351 data = json.loads(response.read()) | |
| 352 self.assertTrue(isinstance(data, dict)) | |
| 353 self.assertEquals(0, data['status']) | |
| 354 | |
| 355 url_parts = urlparse.urlparse(self.session_url)[2].split('/') | |
| 356 self.assertEquals(3, len(url_parts)) | |
| 357 self.assertEquals('', url_parts[0]) | |
| 358 self.assertEquals('session', url_parts[1]) | |
| 359 self.assertEquals(data['sessionId'], url_parts[2]) | |
| 360 | |
| 361 def testShouldBeGivenCapabilitiesWhenStartingASession(self): | |
| 362 driver = WebDriver(self._launcher.GetURL(), {}) | |
| 363 capabilities = driver.capabilities | |
| 364 | |
| 365 self.assertEquals('chrome', capabilities['browserName']) | |
| 366 self.assertTrue(capabilities['javascriptEnabled']) | |
| 367 self.assertTrue(capabilities['takesScreenshot']) | |
| 368 self.assertTrue(capabilities['cssSelectorsEnabled']) | |
| 369 | |
| 370 # Value depends on what version the server is starting. | |
| 371 self.assertTrue('version' in capabilities) | |
| 372 self.assertTrue( | |
| 373 isinstance(capabilities['version'], unicode), | |
| 374 'Expected a %s, but was %s' % (unicode, | |
| 375 type(capabilities['version']))) | |
| 376 | |
| 377 system = platform.system() | |
| 378 if system == 'Linux': | |
| 379 self.assertEquals('linux', capabilities['platform'].lower()) | |
| 380 elif system == 'Windows': | |
| 381 self.assertEquals('windows', capabilities['platform'].lower()) | |
| 382 elif system == 'Darwin': | |
| 383 self.assertEquals('mac', capabilities['platform'].lower()) | |
| 384 else: | |
| 385 # No python on ChromeOS, so we won't have a platform value, but | |
| 386 # the server will know and return the value accordingly. | |
| 387 self.assertEquals('chromeos', capabilities['platform'].lower()) | |
| 388 driver.quit() | |
| 389 | |
| 390 def testSessionCreationDeletion(self): | |
| 391 driver = WebDriver(self._launcher.GetURL(), DesiredCapabilities.CHROME) | |
| 392 driver.quit() | |
| 393 | |
| 394 def testMultipleSessionCreationDeletion(self): | |
| 395 for i in range(10): | |
| 396 driver = WebDriver(self._launcher.GetURL(), DesiredCapabilities.CHROME) | |
| 397 driver.quit() | |
| 398 | |
| 399 def testSessionCommandsAfterSessionDeletionReturn404(self): | |
| 400 driver = WebDriver(self._launcher.GetURL(), DesiredCapabilities.CHROME) | |
| 401 session_id = driver.session_id | |
| 402 driver.quit() | |
| 403 try: | |
| 404 response = SendRequest(self._launcher.GetURL() + '/session/' + session_id, | |
| 405 method='GET') | |
| 406 self.fail('Should have thrown 404 exception') | |
| 407 except urllib2.HTTPError, expected: | |
| 408 self.assertEquals(404, expected.code) | |
| 409 | |
| 410 def testMultipleConcurrentSessions(self): | |
| 411 drivers = [] | |
| 412 for i in range(10): | |
| 413 drivers += [WebDriver(self._launcher.GetURL(), | |
| 414 DesiredCapabilities.CHROME)] | |
| 415 for driver in drivers: | |
| 416 driver.quit() | |
| 417 | |
| 418 | |
| 419 class MouseTest(unittest.TestCase): | |
| 420 """Mouse command tests for the json webdriver protocol""" | |
| 421 | |
| 422 def setUp(self): | |
| 423 self._launcher = ChromeDriverLauncher(root_path=os.path.dirname(__file__)) | |
| 424 self._driver = WebDriver(self._launcher.GetURL(), | |
| 425 DesiredCapabilities.CHROME) | |
| 426 | |
| 427 def tearDown(self): | |
| 428 self._driver.quit() | |
| 429 self._launcher.Kill() | |
| 430 | |
| 431 def testClickElementThatNeedsContainerScrolling(self): | |
| 432 self._driver.get(self._launcher.GetURL() + '/test_page.html') | |
| 433 self._driver.find_element_by_name('hidden_scroll').click() | |
| 434 self.assertTrue(self._driver.execute_script('return window.success')) | |
| 435 | |
| 436 def testClickElementThatNeedsIframeScrolling(self): | |
| 437 self._driver.get(self._launcher.GetURL() + '/test_page.html') | |
| 438 self._driver.switch_to_frame('iframe') | |
| 439 self._driver.find_element_by_name('hidden_scroll').click() | |
| 440 self.assertTrue(self._driver.execute_script('return window.success')) | |
| 441 | |
| 442 def testClickElementThatNeedsPageScrolling(self): | |
| 443 self._driver.get(self._launcher.GetURL() + '/test_page.html') | |
| 444 self._driver.find_element_by_name('far_away').click() | |
| 445 self.assertTrue(self._driver.execute_script('return window.success')) | |
| 446 | |
| 447 # TODO(kkania): Move this test to the webdriver repo. | |
| 448 def testClickDoesSelectOption(self): | |
| 449 self._driver.get(self._launcher.GetURL() + '/test_page.html') | |
| 450 option = self._driver.find_element_by_name('option') | |
| 451 self.assertFalse(option.is_selected()) | |
| 452 option.click() | |
| 453 self.assertTrue(option.is_selected()) | |
| 454 | |
| 455 def testClickDoesUseFirstClientRect(self): | |
| 456 self._driver.get(self._launcher.GetURL() + '/test_page.html') | |
| 457 self._driver.find_element_by_name('wrapped').click() | |
| 458 self.assertTrue(self._driver.execute_script('return window.success')) | |
| 459 | |
| 460 | |
| 461 class TypingTest(unittest.TestCase): | |
| 462 | |
| 463 def setUp(self): | |
| 464 self._launcher = ChromeDriverLauncher(root_path=os.path.dirname(__file__)) | |
| 465 self._driver = WebDriver(self._launcher.GetURL(), {}) | |
| 466 self._driver.get(self._launcher.GetURL() + '/test_page.html') | |
| 467 | |
| 468 def tearDown(self): | |
| 469 self._driver.quit() | |
| 470 self._launcher.Kill() | |
| 471 | |
| 472 # See http://crbug.com/85243. | |
| 473 def testCanSendKeysToDescendantOfEditingHost(self): | |
| 474 self._driver.find_element_by_name('editable_child').send_keys('moo') | |
| 475 text = self._driver.find_element_by_name('editable').text | |
| 476 self.assertEquals('mooeditable', text) | |
| 477 | |
| 478 | |
| 479 class UrlBaseTest(unittest.TestCase): | |
| 480 """Tests that the server can be configured for a different URL base.""" | |
| 481 | |
| 482 def setUp(self): | |
| 483 self._launcher = ChromeDriverLauncher(url_base='/wd/hub') | |
| 484 | |
| 485 def tearDown(self): | |
| 486 self._launcher.Kill() | |
| 487 | |
| 488 def testCreatingSessionShouldRedirectToCorrectURL(self): | |
| 489 request_url = self._launcher.GetURL() + '/session' | |
| 490 response = SendRequest(request_url, method='POST', | |
| 491 data='{"desiredCapabilities":{}}') | |
| 492 self.assertEquals(200, response.code) | |
| 493 self.session_url = response.geturl() # TODO(jleyba): verify this URL? | |
| 494 | |
| 495 data = json.loads(response.read()) | |
| 496 self.assertTrue(isinstance(data, dict)) | |
| 497 self.assertEquals(0, data['status']) | |
| 498 | |
| 499 url_parts = urlparse.urlparse(self.session_url)[2].split('/') | |
| 500 self.assertEquals(5, len(url_parts)) | |
| 501 self.assertEquals('', url_parts[0]) | |
| 502 self.assertEquals('wd', url_parts[1]) | |
| 503 self.assertEquals('hub', url_parts[2]) | |
| 504 self.assertEquals('session', url_parts[3]) | |
| 505 self.assertEquals(data['sessionId'], url_parts[4]) | |
| 506 | |
| 507 | |
| 508 # TODO(jleyba): Port this to WebDriver's own python test suite. | |
| 509 class ElementEqualityTest(unittest.TestCase): | |
| 510 """Tests that the server properly checks element equality.""" | |
| 511 | |
| 512 def setUp(self): | |
| 513 self._launcher = ChromeDriverLauncher(root_path=os.path.dirname(__file__)) | |
| 514 self._driver = WebDriver(self._launcher.GetURL(), {}) | |
| 515 | |
| 516 def tearDown(self): | |
| 517 self._driver.quit() | |
| 518 self._launcher.Kill() | |
| 519 | |
| 520 def testElementEquality(self): | |
| 521 self._driver.get(self._launcher.GetURL() + '/test_page.html') | |
| 522 body1 = self._driver.find_element_by_tag_name('body') | |
| 523 body2 = self._driver.execute_script('return document.body') | |
| 524 | |
| 525 # TODO(jleyba): WebDriver's python bindings should expose a proper API | |
| 526 # for this. | |
| 527 result = body1._execute(Command.ELEMENT_EQUALS, { | |
| 528 'other': body2.id | |
| 529 }) | |
| 530 self.assertTrue(result['value']) | |
| 531 | |
| 532 | |
| 533 class LoggingTest(unittest.TestCase): | |
| 534 | |
| 535 def setUp(self): | |
| 536 self._launcher = ChromeDriverLauncher(root_path=os.path.dirname(__file__)) | |
| 537 | |
| 538 def tearDown(self): | |
| 539 self._launcher.Kill() | |
| 540 | |
| 541 def testNoVerboseLogging(self): | |
| 542 self._driver = WebDriver(self._launcher.GetURL(), {}) | |
| 543 self._driver.execute_script('console.log("HI")') | |
| 544 request_url = self._launcher.GetURL() + '/log' | |
| 545 req = SendRequest(request_url, method='GET') | |
| 546 log = req.read() | |
| 547 self.assertTrue(':INFO:' not in log, ':INFO: in log: ' + log) | |
| 548 | |
| 549 def testVerboseLogging(self): | |
| 550 self._driver = WebDriver(self._launcher.GetURL(), {'chrome.verbose': True}) | |
| 551 self._driver.execute_script('console.log("HI")') | |
| 552 request_url = self._launcher.GetURL() + '/log' | |
| 553 req = SendRequest(request_url, method='GET') | |
| 554 log = req.read() | |
| 555 self.assertTrue(':INFO:' in log, ':INFO: not in log: ' + log) | |
| 556 | |
| 557 | |
| 558 """Chrome functional test section. All implementation tests of ChromeDriver | |
| 559 should go above. | |
| 560 | |
| 561 TODO(dyu): Move these tests out of here when pyauto has these capabilities. | |
| 562 """ | |
| 563 | |
| 564 | |
| 565 def GetPathForDataFile(relative_path): | |
| 566 """Returns the path for a test data file residing in this directory.""" | |
| 567 return os.path.join(os.path.dirname(__file__), relative_path) | |
| 568 | |
| 569 | |
| 570 class AutofillTest(unittest.TestCase): | |
| 571 AUTOFILL_EDIT_ADDRESS = 'chrome://settings/autofillEditAddress' | |
| 572 AUTOFILL_EDIT_CC = 'chrome://settings/autofillEditCreditCard' | |
| 573 | |
| 574 def setUp(self): | |
| 575 self._launcher = ChromeDriverLauncher() | |
| 576 | |
| 577 def tearDown(self): | |
| 578 self._launcher.Kill() | |
| 579 | |
| 580 def NewDriver(self): | |
| 581 return WebDriver(self._launcher.GetURL(), {}) | |
| 582 | |
| 583 def _SelectOptionXpath(self, value): | |
| 584 """Returns an xpath query used to select an item from a dropdown list. | |
| 585 | |
| 586 Args: | |
| 587 value: Option selected for the drop-down list field. | |
| 588 """ | |
| 589 return '//option[@value="%s"]' % value | |
| 590 | |
| 591 def testPostalCodeAndStateLabelsBasedOnCountry(self): | |
| 592 """Verify postal code and state labels based on selected country.""" | |
| 593 import simplejson | |
| 594 test_data = simplejson.loads( | |
| 595 open(GetPathForDataFile('state_zip_labels.txt')).read()) | |
| 596 | |
| 597 driver = self.NewDriver() | |
| 598 driver.get(self.AUTOFILL_EDIT_ADDRESS) | |
| 599 # Initial check of State and ZIP labels. | |
| 600 state_label = driver.find_element_by_id('state-label').text | |
| 601 self.assertEqual('State', state_label) | |
| 602 zip_label = driver.find_element_by_id('postal-code-label').text | |
| 603 self.assertEqual('ZIP code', zip_label) | |
| 604 | |
| 605 for country_code in test_data: | |
| 606 query = self._SelectOptionXpath(country_code) | |
| 607 driver.find_element_by_id('country').find_element_by_xpath(query).select() | |
| 608 # Compare postal labels. | |
| 609 actual_postal_label = driver.find_element_by_id( | |
| 610 'postal-code-label').text | |
| 611 expected_postal_label = test_data[country_code]['postalCodeLabel'] | |
| 612 self.assertEqual( | |
| 613 actual_postal_label, expected_postal_label, | |
| 614 'Postal code label does not match Country "%s"' % country_code) | |
| 615 # Compare state labels. | |
| 616 actual_state_label = driver.find_element_by_id('state-label').text | |
| 617 expected_state_label = test_data[country_code]['stateLabel'] | |
| 618 self.assertEqual( | |
| 619 actual_state_label, expected_state_label, | |
| 620 'State label does not match Country "%s"' % country_code) | |
| 621 | |
| 622 def testDisplayLineItemForEntriesWithNoCCNum(self): | |
| 623 """Verify Autofill creates a line item for CC entries with no CC number.""" | |
| 624 creditcard_data = {'CREDIT_CARD_NAME': 'Jane Doe', | |
| 625 'CREDIT_CARD_EXP_MONTH': '12', | |
| 626 'CREDIT_CARD_EXP_4_DIGIT_YEAR': '2014'} | |
| 627 | |
| 628 driver = self.NewDriver() | |
| 629 driver.get(self.AUTOFILL_EDIT_CC) | |
| 630 driver.find_element_by_id('name-on-card').send_keys( | |
| 631 creditcard_data['CREDIT_CARD_NAME']) | |
| 632 query_month = self._SelectOptionXpath( | |
| 633 creditcard_data['CREDIT_CARD_EXP_MONTH']) | |
| 634 query_year = self._SelectOptionXpath( | |
| 635 creditcard_data['CREDIT_CARD_EXP_4_DIGIT_YEAR']) | |
| 636 driver.find_element_by_id('expiration-month').find_element_by_xpath( | |
| 637 query_month).select() | |
| 638 driver.find_element_by_id('expiration-year').find_element_by_xpath( | |
| 639 query_year).select() | |
| 640 driver.find_element_by_id( | |
| 641 'autofill-edit-credit-card-apply-button').click() | |
| 642 # Refresh the page to ensure the UI is up-to-date. | |
| 643 driver.refresh() | |
| 644 list_entry = driver.find_element_by_class_name('autofill-list-item') | |
| 645 self.assertTrue(list_entry.is_displayed) | |
| 646 self.assertEqual(list_entry.text, | |
| 647 creditcard_data['CREDIT_CARD_NAME'], | |
| 648 'Saved CC line item not same as what was entered.') | |
| 649 | |
| 650 | |
| 651 class FileUploadControlTest(unittest.TestCase): | |
| 652 """Tests dealing with file upload control.""" | |
| 653 | |
| 654 def setUp(self): | |
| 655 self._launcher = ChromeDriverLauncher(root_path=os.path.dirname(__file__)) | |
| 656 self._driver = WebDriver(self._launcher.GetURL(), | |
| 657 DesiredCapabilities.CHROME) | |
| 658 | |
| 659 def tearDown(self): | |
| 660 self._driver.quit() | |
| 661 self._launcher.Kill() | |
| 662 | |
| 663 def testSetFilePathToFileUploadControl(self): | |
| 664 """Verify a file path is set to the file upload control.""" | |
| 665 self._driver.get(self._launcher.GetURL() + '/upload.html') | |
| 666 | |
| 667 file = tempfile.NamedTemporaryFile() | |
| 668 | |
| 669 fileupload_single = self._driver.find_element_by_name('fileupload_single') | |
| 670 multiple = fileupload_single.get_attribute('multiple') | |
| 671 self.assertEqual('false', multiple) | |
| 672 fileupload_single.send_keys(file.name) | |
| 673 path = fileupload_single.value | |
| 674 self.assertTrue(path.endswith(os.path.basename(file.name))) | |
| 675 | |
| 676 def testSetMultipleFilePathsToFileuploadControlWithoutMultipleWillFail(self): | |
| 677 """Verify setting file paths to the file upload control without 'multiple' | |
| 678 attribute will fail.""" | |
| 679 self._driver.get(self._launcher.GetURL() + '/upload.html') | |
| 680 | |
| 681 files = [] | |
| 682 filepaths = [] | |
| 683 for index in xrange(4): | |
| 684 file = tempfile.NamedTemporaryFile() | |
| 685 # We need to hold the file objects because the files will be deleted on | |
| 686 # GC. | |
| 687 files.append(file) | |
| 688 filepath = file.name | |
| 689 filepaths.append(filepath) | |
| 690 | |
| 691 fileupload_single = self._driver.find_element_by_name('fileupload_single') | |
| 692 multiple = fileupload_single.get_attribute('multiple') | |
| 693 self.assertEqual('false', multiple) | |
| 694 self.assertRaises(WebDriverException, fileupload_single.send_keys, | |
| 695 filepaths[0], filepaths[1], filepaths[2], filepaths[3]) | |
| 696 | |
| 697 def testSetMultipleFilePathsToFileUploadControl(self): | |
| 698 """Verify multiple file paths are set to the file upload control.""" | |
| 699 self._driver.get(self._launcher.GetURL() + '/upload.html') | |
| 700 | |
| 701 files = [] | |
| 702 filepaths = [] | |
| 703 filenames = set() | |
| 704 for index in xrange(4): | |
| 705 file = tempfile.NamedTemporaryFile() | |
| 706 files.append(file) | |
| 707 filepath = file.name | |
| 708 filepaths.append(filepath) | |
| 709 filenames.add(os.path.basename(filepath)) | |
| 710 | |
| 711 fileupload_multi = self._driver.find_element_by_name('fileupload_multi') | |
| 712 multiple = fileupload_multi.get_attribute('multiple') | |
| 713 self.assertEqual('true', multiple) | |
| 714 fileupload_multi.send_keys(filepaths[0], filepaths[1], filepaths[2], | |
| 715 filepaths[3]) | |
| 716 | |
| 717 files_on_element = self._driver.execute_script( | |
| 718 'return document.getElementById("fileupload_multi").files;') | |
| 719 self.assertTrue(files_on_element) | |
| 720 self.assertEqual(4, len(files_on_element)) | |
| 721 for f in files_on_element: | |
| 722 self.assertTrue(f['name'] in filenames) | |
| 723 | |
| 724 | |
| 725 if __name__ == '__main__': | |
| 726 unittest.main(module='chromedriver_tests', | |
| 727 testRunner=GTestTextTestRunner(verbosity=1)) | |
| OLD | NEW |