Home | History | Annotate | Download | only in test
      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 """Tests for ChromeDriver.
      6 
      7 If your test is testing a specific part of the WebDriver API, consider adding
      8 it to the appropriate place in the WebDriver tree instead.
      9 """
     10 
     11 import binascii
     12 from distutils import archive_util
     13 import hashlib
     14 import httplib
     15 import os
     16 import platform
     17 import signal
     18 import subprocess
     19 import sys
     20 import tempfile
     21 import threading
     22 import time
     23 import unittest
     24 import urllib
     25 import urllib2
     26 import urlparse
     27 
     28 from chromedriver_factory import ChromeDriverFactory
     29 from chromedriver_launcher import ChromeDriverLauncher
     30 from chromedriver_test import ChromeDriverTest
     31 import test_paths
     32 import util
     33 
     34 try:
     35   import simplejson as json
     36 except ImportError:
     37   import json
     38 
     39 from selenium.common.exceptions import NoSuchWindowException
     40 from selenium.common.exceptions import WebDriverException
     41 from selenium.webdriver.common.action_chains import ActionChains
     42 from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
     43 from selenium.webdriver.common.keys import Keys
     44 from selenium.webdriver.remote.command import Command
     45 from selenium.webdriver.remote.webdriver import WebDriver
     46 from selenium.webdriver.support.ui import WebDriverWait
     47 
     48 
     49 def SkipIf(should_skip):
     50   """Decorator which allows skipping individual test cases."""
     51   if should_skip:
     52     return lambda func: None
     53   return lambda func: func
     54 
     55 
     56 class Request(urllib2.Request):
     57   """Extends urllib2.Request to support all HTTP request types."""
     58 
     59   def __init__(self, url, method=None, data=None):
     60     """Initialise a new HTTP request.
     61 
     62     Arguments:
     63       url: The full URL to send the request to.
     64       method: The HTTP request method to use; defaults to 'GET'.
     65       data: The data to send with the request as a string. Defaults to
     66           None and is ignored if |method| is not 'POST' or 'PUT'.
     67     """
     68     if method is None:
     69       method = data is not None and 'POST' or 'GET'
     70     elif method not in ('POST', 'PUT'):
     71       data = None
     72     self.method = method
     73     urllib2.Request.__init__(self, url, data=data)
     74 
     75   def get_method(self):
     76     """Returns the HTTP method used by this request."""
     77     return self.method
     78 
     79 
     80 def SendRequest(url, method=None, data=None):
     81   """Sends a HTTP request to the WebDriver server.
     82 
     83   Return values and exceptions raised are the same as those of
     84   |urllib2.urlopen|.
     85 
     86   Arguments:
     87     url: The full URL to send the request to.
     88     method: The HTTP request method to use; defaults to 'GET'.
     89     data: The data to send with the request as a string. Defaults to
     90         None and is ignored if |method| is not 'POST' or 'PUT'.
     91 
     92     Returns:
     93       A file-like object.
     94   """
     95   request = Request(url, method=method, data=data)
     96   request.add_header('Accept', 'application/json')
     97   opener = urllib2.build_opener(urllib2.HTTPRedirectHandler())
     98   return opener.open(request)
     99 
    100 
    101 class BasicTest(ChromeDriverTest):
    102   """Basic ChromeDriver tests."""
    103 
    104   def setUp(self):
    105     self._server2 = ChromeDriverLauncher(self.GetDriverPath()).Launch()
    106 
    107   def tearDown(self):
    108     self._server2.Kill()
    109 
    110   def testShouldReturn403WhenSentAnUnknownCommandURL(self):
    111     request_url = self._server2.GetUrl() + '/foo'
    112     try:
    113       SendRequest(request_url, method='GET')
    114       self.fail('Should have raised a urllib.HTTPError for returned 403')
    115     except urllib2.HTTPError, expected:
    116       self.assertEquals(403, expected.code)
    117 
    118   def testShouldReturnHTTP405WhenSendingANonPostToTheSessionURL(self):
    119     request_url = self._server2.GetUrl() + '/session'
    120     try:
    121       SendRequest(request_url, method='GET')
    122       self.fail('Should have raised a urllib.HTTPError for returned 405')
    123     except urllib2.HTTPError, expected:
    124       self.assertEquals(405, expected.code)
    125       self.assertEquals('POST', expected.hdrs['Allow'])
    126 
    127   def testShouldGetA404WhenAttemptingToDeleteAnUnknownSession(self):
    128     request_url = self._server2.GetUrl() + '/session/unkown_session_id'
    129     try:
    130       SendRequest(request_url, method='DELETE')
    131       self.fail('Should have raised a urllib.HTTPError for returned 404')
    132     except urllib2.HTTPError, expected:
    133       self.assertEquals(404, expected.code)
    134 
    135   def testShouldReturn204ForFaviconRequests(self):
    136     request_url = self._server2.GetUrl() + '/favicon.ico'
    137     # In python2.5, a 204 status code causes an exception.
    138     if sys.version_info[0:2] == (2, 5):
    139       try:
    140         SendRequest(request_url, method='GET')
    141         self.fail('Should have raised a urllib.HTTPError for returned 204')
    142       except urllib2.HTTPError, expected:
    143         self.assertEquals(204, expected.code)
    144     else:
    145       response = SendRequest(request_url, method='GET')
    146       try:
    147         self.assertEquals(204, response.code)
    148       finally:
    149         response.close()
    150 
    151   def testCreatingSessionShouldRedirectToCorrectURL(self):
    152     request_url = self._server2.GetUrl() + '/session'
    153     response = SendRequest(request_url, method='POST',
    154                            data='{"desiredCapabilities": {}}')
    155     self.assertEquals(200, response.code)
    156     self.session_url = response.geturl()  # TODO(jleyba): verify this URL?
    157 
    158     data = json.loads(response.read())
    159     self.assertTrue(isinstance(data, dict))
    160     self.assertEquals(0, data['status'])
    161 
    162     url_parts = urlparse.urlparse(self.session_url)[2].split('/')
    163     self.assertEquals(3, len(url_parts))
    164     self.assertEquals('', url_parts[0])
    165     self.assertEquals('session', url_parts[1])
    166     self.assertEquals(data['sessionId'], url_parts[2])
    167 
    168 
    169 class WebserverTest(ChromeDriverTest):
    170   """Tests the built-in ChromeDriver webserver."""
    171 
    172   def testShouldNotServeFilesByDefault(self):
    173     server = ChromeDriverLauncher(self.GetDriverPath()).Launch()
    174     try:
    175       SendRequest(server.GetUrl(), method='GET')
    176       self.fail('Should have raised a urllib.HTTPError for returned 403')
    177     except urllib2.HTTPError, expected:
    178       self.assertEquals(403, expected.code)
    179     finally:
    180       server.Kill()
    181 
    182   def testCanServeFiles(self):
    183     launcher = ChromeDriverLauncher(self.GetDriverPath(),
    184                                     root_path=os.path.dirname(__file__))
    185     server = launcher.Launch()
    186     request_url = server.GetUrl() + '/' + os.path.basename(__file__)
    187     SendRequest(request_url, method='GET')
    188     server.Kill()
    189 
    190 
    191 class DesiredCapabilitiesTest(ChromeDriverTest):
    192   """Tests for webdriver desired capabilities."""
    193 
    194   def testCustomSwitches(self):
    195     switches = ['enable-file-cookie']
    196     capabilities = {'chrome.switches': switches}
    197 
    198     driver = self.GetNewDriver(capabilities)
    199     driver.get('about:version')
    200     self.assertNotEqual(-1, driver.page_source.find('enable-file-cookie'))
    201     driver.quit()
    202 
    203   def testBinary(self):
    204     self.GetNewDriver({'chrome.binary': self.GetChromePath()})
    205 
    206   def testUserProfile(self):
    207     """Test starting WebDriver session with custom profile."""
    208 
    209     # Open a new session and save the user profile.
    210     profile_dir = tempfile.mkdtemp()
    211     capabilities = {'chrome.switches': ['--user-data-dir=' + profile_dir]}
    212     driver = self.GetNewDriver(capabilities)
    213     driver.get(self.GetTestDataUrl() + '/test_page.html')
    214     # Create a cookie.
    215     cookie_dict = {}
    216     cookie_dict['name'] = 'test_user_profile'
    217     cookie_dict['value'] = 'chrome profile'
    218     cookie_dict['expiry'] = time.time() + 120
    219     driver.add_cookie(cookie_dict)
    220     driver.quit()
    221 
    222     profile_zip = archive_util.make_archive(os.path.join(profile_dir,
    223                                                          'profile'),
    224                                             'zip',
    225                                             root_dir=profile_dir,
    226                                             base_dir='Default')
    227     f = open(profile_zip, 'rb')
    228     base64_user_profile = binascii.b2a_base64(f.read()).strip()
    229     f.close()
    230     os.remove(profile_zip)
    231 
    232     # Start new session with the saved user profile.
    233     capabilities = {'chrome.profile': base64_user_profile}
    234     driver = self.GetNewDriver(capabilities)
    235     driver.get(self.GetTestDataUrl() + '/test_page.html')
    236     cookie_dict = driver.get_cookie('test_user_profile')
    237     self.assertNotEqual(cookie_dict, None)
    238     self.assertEqual(cookie_dict['value'], 'chrome profile')
    239     driver.quit()
    240 
    241   def testInstallExtensions(self):
    242     """Test starting web driver with multiple extensions."""
    243     extensions = ['ext_test_1.crx', 'ext_test_2.crx']
    244     base64_extensions = []
    245     for ext in extensions:
    246       f = open(test_paths.GetTestDataPath(ext), 'rb')
    247       base64_ext = (binascii.b2a_base64(f.read()).strip())
    248       base64_extensions.append(base64_ext)
    249       f.close()
    250     capabilities = {'chrome.extensions': base64_extensions}
    251     driver = self.GetNewDriver(capabilities)
    252     extension_names = [x.get_name() for x in driver.get_installed_extensions()]
    253     self.assertEquals(2, len(extension_names))
    254     self.assertTrue('ExtTest1' in extension_names)
    255     self.assertTrue('ExtTest2' in extension_names)
    256     driver.quit()
    257 
    258   def testPrefs(self):
    259     """Test that chromedriver can set user preferences."""
    260     driver = self.GetNewDriver({
    261       'chrome.noWebsiteTestingDefaults': True,
    262       'chrome.prefs': {
    263         'profile.default_content_settings': {
    264           'popups': 1
    265         },
    266       }
    267     })
    268     driver.get(self.GetTestDataUrl() + '/empty.html')
    269     driver.execute_script('window.open("about:blank")')
    270     self.assertEquals(2, len(driver.window_handles))
    271 
    272   def testLoadAsync(self):
    273     """Test that chromedriver can load pages asynchronously."""
    274     driver = self.GetNewDriver({'chrome.loadAsync': True})
    275 
    276     # Check that navigate doesn't wait for the page to load.
    277     driver.get(self.GetTestDataUrl() + '/hang')
    278 
    279     # Check that the navigation actually starts.
    280     def IsEmptyPage(driver):
    281       return driver.current_url.endswith('empty.html')
    282     driver.get(self.GetTestDataUrl() + '/empty.html')
    283     WebDriverWait(driver, 10).until(IsEmptyPage)
    284 
    285 
    286 class DetachProcessTest(ChromeDriverTest):
    287 
    288   def setUp(self):
    289     self._server2 = ChromeDriverLauncher(self.GetDriverPath()).Launch()
    290     self._factory2 = ChromeDriverFactory(self._server2)
    291 
    292   def tearDown(self):
    293     self._server2.Kill()
    294 
    295   # TODO(kkania): Remove this when Chrome 15 is stable.
    296   # crbug.com/134982
    297   def DISABLED_testDetachProcess(self):
    298     # This is a weak test. Its purpose is to just make sure we can start
    299     # Chrome successfully in detached mode. There's not an easy way to know
    300     # if Chrome is shutting down due to the channel error when the client
    301     # disconnects.
    302     driver = self._factory2.GetNewDriver({'chrome.detach': True})
    303     driver.get('about:memory')
    304     pid = int(driver.find_elements_by_xpath('//*[@jscontent="pid"]')[0].text)
    305     self._server2.Kill()
    306     try:
    307       util.Kill(pid)
    308     except OSError:
    309       self.fail('Chrome quit after detached chromedriver server was killed')
    310 
    311 
    312 class CookieTest(ChromeDriverTest):
    313   """Cookie test for the json webdriver protocol"""
    314 
    315   def testAddCookie(self):
    316     driver = self.GetNewDriver()
    317     driver.get(self.GetTestDataUrl() + '/test_page.html')
    318     cookie_dict = None
    319     cookie_dict = driver.get_cookie("chromedriver_cookie_test")
    320     cookie_dict = {}
    321     cookie_dict["name"] = "chromedriver_cookie_test"
    322     cookie_dict["value"] = "this is a test"
    323     driver.add_cookie(cookie_dict)
    324     cookie_dict = driver.get_cookie("chromedriver_cookie_test")
    325     self.assertNotEqual(cookie_dict, None)
    326     self.assertEqual(cookie_dict["value"], "this is a test")
    327 
    328   def testDeleteCookie(self):
    329     driver = self.GetNewDriver()
    330     self.testAddCookie();
    331     driver.delete_cookie("chromedriver_cookie_test")
    332     cookie_dict = driver.get_cookie("chromedriver_cookie_test")
    333     self.assertEqual(cookie_dict, None)
    334 
    335 
    336 class ScreenshotTest(ChromeDriverTest):
    337   """Tests to verify screenshot retrieval"""
    338 
    339   REDBOX = "automation_proxy_snapshot/set_size.html"
    340 
    341   def testScreenCaptureAgainstReference(self):
    342     # Create a red square of 2000x2000 pixels.
    343     url = util.GetFileURLForPath(test_paths.GetChromeTestDataPath(self.REDBOX))
    344     url += '?2000,2000'
    345     driver = self.GetNewDriver()
    346     driver.get(url)
    347     s = driver.get_screenshot_as_base64()
    348     h = hashlib.md5(s).hexdigest()
    349     # Compare the PNG created to the reference hash.
    350     self.assertEquals(h, '12c0ade27e3875da3d8866f52d2fa84f')
    351 
    352   # This test requires Flash and must be run on a VM or via remote desktop.
    353   # See crbug.com/96317.
    354   def testSnapshotWithWindowlessFlashAndTransparentOverlay(self):
    355     if not util.IsWin():
    356       return
    357 
    358     driver = self.GetNewDriver()
    359     driver.get(self.GetTestDataUrl() + '/plugin_transparency_test.html')
    360     snapshot = driver.get_screenshot_as_base64()
    361     self.assertEquals(hashlib.md5(snapshot).hexdigest(),
    362                       '72e5b8525e48758bae59997472f27f14')
    363 
    364 
    365 class SessionTest(ChromeDriverTest):
    366   """Tests dealing with WebDriver sessions."""
    367 
    368   def testShouldBeGivenCapabilitiesWhenStartingASession(self):
    369     driver = self.GetNewDriver()
    370     capabilities = driver.capabilities
    371 
    372     self.assertEquals('chrome', capabilities['browserName'])
    373     self.assertTrue(capabilities['javascriptEnabled'])
    374     self.assertTrue(capabilities['takesScreenshot'])
    375     self.assertTrue(capabilities['cssSelectorsEnabled'])
    376 
    377     # Value depends on what version the server is starting.
    378     self.assertTrue('version' in capabilities)
    379     self.assertTrue(
    380         isinstance(capabilities['version'], unicode),
    381         'Expected a %s, but was %s' % (unicode,
    382                                        type(capabilities['version'])))
    383 
    384     system = platform.system()
    385     if system == 'Linux':
    386       self.assertEquals('linux', capabilities['platform'].lower())
    387     elif system == 'Windows':
    388       self.assertEquals('windows', capabilities['platform'].lower())
    389     elif system == 'Darwin':
    390       self.assertEquals('mac', capabilities['platform'].lower())
    391     else:
    392       # No python on ChromeOS, so we won't have a platform value, but
    393       # the server will know and return the value accordingly.
    394       self.assertEquals('chromeos', capabilities['platform'].lower())
    395 
    396   def testSessionCreationDeletion(self):
    397     self.GetNewDriver().quit()
    398 
    399   # crbug.com/103396
    400   def DISABLED_testMultipleSessionCreationDeletion(self):
    401     for i in range(10):
    402       self.GetNewDriver().quit()
    403 
    404   def testSessionCommandsAfterSessionDeletionReturn404(self):
    405     driver = self.GetNewDriver()
    406     url = self.GetTestDataUrl()
    407     url += '/session/' + driver.session_id
    408     driver.quit()
    409     try:
    410       response = SendRequest(url, method='GET')
    411       self.fail('Should have thrown 404 exception')
    412     except urllib2.HTTPError, expected:
    413       self.assertEquals(404, expected.code)
    414 
    415   def testMultipleConcurrentSessions(self):
    416     drivers = []
    417     for i in range(10):
    418       drivers += [self.GetNewDriver()]
    419     for driver in drivers:
    420       driver.quit()
    421 
    422 
    423 class ShutdownTest(ChromeDriverTest):
    424 
    425   def setUp(self):
    426     super(ShutdownTest, self).setUp()
    427     self._custom_server = ChromeDriverLauncher(self.GetDriverPath()).Launch()
    428     self._custom_factory = ChromeDriverFactory(self._custom_server,
    429                                                self.GetChromePath())
    430 
    431   def tearDown(self):
    432     self._custom_server.Kill()
    433     super(ShutdownTest, self).tearDown()
    434 
    435   def testShutdownWithSession(self):
    436     driver = self._custom_factory.GetNewDriver()
    437     driver.get(self._custom_server.GetUrl() + '/status')
    438     driver.find_element_by_tag_name('body')
    439     self._custom_server.Kill()
    440 
    441   def testShutdownWithBusySession(self):
    442     def _Hang(driver):
    443       """Waits for the process to quit and then notifies."""
    444       try:
    445         driver.get(self._custom_server.GetUrl() + '/hang')
    446       except httplib.BadStatusLine:
    447         pass
    448 
    449     driver = self._custom_factory.GetNewDriver()
    450     wait_thread = threading.Thread(target=_Hang, args=(driver,))
    451     wait_thread.start()
    452     wait_thread.join(5)
    453     self.assertTrue(wait_thread.isAlive())
    454 
    455     self._custom_server.Kill()
    456     wait_thread.join(10)
    457     self.assertFalse(wait_thread.isAlive())
    458 
    459 
    460 class MouseTest(ChromeDriverTest):
    461   """Mouse command tests for the json webdriver protocol"""
    462 
    463   def setUp(self):
    464     super(MouseTest, self).setUp()
    465     self._driver = self.GetNewDriver()
    466 
    467   def testCanClickTransparentElement(self):
    468     self._driver.get(self.GetTestDataUrl() + '/transparent.html')
    469     self._driver.find_element_by_tag_name('a').click()
    470     self.assertTrue(self._driver.execute_script('return window.success'))
    471 
    472   # crbug.com/136875
    473   def DISABLED_testClickElementThatNeedsContainerScrolling(self):
    474     self._driver.get(self.GetTestDataUrl() + '/test_page.html')
    475     self._driver.find_element_by_name('hidden_scroll').click()
    476     self.assertTrue(self._driver.execute_script('return window.success'))
    477 
    478   # crbug.com/136875
    479   def DISABLED_testClickElementThatNeedsIframeScrolling(self):
    480     self._driver.get(self.GetTestDataUrl() + '/test_page.html')
    481     self._driver.switch_to_frame('iframe')
    482     self._driver.find_element_by_name('hidden_scroll').click()
    483     self.assertTrue(self._driver.execute_script('return window.success'))
    484 
    485   def testClickElementThatNeedsPageScrolling(self):
    486     self._driver.get(self.GetTestDataUrl() + '/test_page.html')
    487     self._driver.find_element_by_name('far_away').click()
    488     self.assertTrue(self._driver.execute_script('return window.success'))
    489 
    490   # TODO(kkania): Move this test to the webdriver repo.
    491   def testClickDoesSelectOption(self):
    492     self._driver.get(self.GetTestDataUrl() + '/test_page.html')
    493     option = self._driver.find_element_by_name('option')
    494     self.assertFalse(option.is_selected())
    495     option.click()
    496     self.assertTrue(option.is_selected())
    497 
    498   def testClickDoesUseFirstClientRect(self):
    499     self._driver.get(self.GetTestDataUrl() + '/test_page.html')
    500     self._driver.find_element_by_name('wrapped').click()
    501     self.assertTrue(self._driver.execute_script('return window.success'))
    502 
    503   def testThrowErrorIfNotClickable(self):
    504     self._driver.get(self.GetTestDataUrl() + '/not_clickable.html')
    505     elem = self._driver.find_element_by_name('click')
    506     self.assertRaises(WebDriverException, elem.click)
    507 
    508 
    509 # crbug.com/109698: when running in xvfb, 2 extra mouse moves are received.
    510 # crbug.com/138125: fails if the mouse cursor is left over the page.
    511 @SkipIf(True)
    512 class MouseEventTest(ChromeDriverTest):
    513   """Tests for checking the correctness of mouse events."""
    514 
    515   def setUp(self):
    516     super(MouseEventTest, self).setUp()
    517     self._driver = self.GetNewDriver()
    518     ActionChains(self._driver).key_down([Keys.CONTROL, Keys.SHIFT]).perform()
    519     self._driver.get(self.GetTestDataUrl() + '/events.html')
    520     self._divs = self._driver.find_elements_by_tag_name('div')
    521 
    522   def _CheckEvent(self, event, event_type, mouse_button, x, y):
    523     """Checks the given event properties.
    524 
    525     This function expects the ctrl and shift keys to be pressed.
    526     """
    527     self.assertEquals(event_type, event['type'])
    528     self.assertEquals(mouse_button, event['button'])
    529     self.assertEquals(False, event['altKey'])
    530     self.assertEquals(True, event['ctrlKey'])
    531     self.assertEquals(True, event['shiftKey'])
    532     self.assertEquals(x, event['x'])
    533     self.assertEquals(y, event['y'])
    534 
    535   def _GetElementMiddle(self, elem):
    536     x = elem.location['x']
    537     y = elem.location['y']
    538     return (x + (elem.size['width'] + 1) / 2, y + (elem.size['height'] + 1) / 2)
    539 
    540   def testMoveCommand(self):
    541     x = self._divs[0].location['x']
    542     y = self._divs[0].location['y']
    543     center_x, center_y = self._GetElementMiddle(self._divs[0])
    544 
    545     # Move to element.
    546     ActionChains(self._driver).move_to_element(self._divs[0]).perform()
    547     events = self._driver.execute_script('return takeEvents()')
    548     self.assertEquals(1, len(events))
    549     self._CheckEvent(events[0], 'mousemove', 0, center_x, center_y)
    550 
    551     # Move by offset.
    552     ActionChains(self._driver).move_by_offset(1, 2).perform()
    553     events = self._driver.execute_script('return takeEvents()')
    554     self.assertEquals(1, len(events))
    555     self._CheckEvent(events[0], 'mousemove', 0, center_x + 1, center_y + 2)
    556 
    557     # Move to element and offset.
    558     ActionChains(self._driver).move_to_element_with_offset(
    559         self._divs[0], 2, 1).perform()
    560     events = self._driver.execute_script('return takeEvents()')
    561     self.assertEquals(1, len(events))
    562     self._CheckEvent(events[0], 'mousemove', 0, x + 2, y + 1)
    563 
    564   def testClickCommand(self):
    565     center_x, center_y = self._GetElementMiddle(self._divs[0])
    566 
    567     # Left click element.
    568     ActionChains(self._driver).click(self._divs[0]).perform()
    569     events = self._driver.execute_script('return takeEvents()')
    570     self.assertEquals(3, len(events))
    571     self._CheckEvent(events[0], 'mousemove', 0, center_x, center_y)
    572     self._CheckEvent(events[1], 'mousedown', 0, center_x, center_y)
    573     self._CheckEvent(events[2], 'mouseup', 0, center_x, center_y)
    574 
    575     # Left click.
    576     ActionChains(self._driver).click(None).perform()
    577     events = self._driver.execute_script('return takeEvents()')
    578     self.assertEquals(2, len(events))
    579     self._CheckEvent(events[0], 'mousedown', 0, center_x, center_y)
    580     self._CheckEvent(events[1], 'mouseup', 0, center_x, center_y)
    581 
    582     # Right click.
    583     ActionChains(self._driver).context_click(None).perform()
    584     events = self._driver.execute_script('return takeEvents()')
    585     self.assertEquals(2, len(events))
    586     self._CheckEvent(events[0], 'mousedown', 2, center_x, center_y)
    587     self._CheckEvent(events[1], 'mouseup', 2, center_x, center_y)
    588 
    589   def testButtonDownUpCommand(self):
    590     center_x, center_y = self._GetElementMiddle(self._divs[0])
    591     center_x2, center_y2 = self._GetElementMiddle(self._divs[1])
    592 
    593     # Press and release element.
    594     ActionChains(self._driver).click_and_hold(self._divs[0]).release(
    595         self._divs[1]).perform()
    596     events = self._driver.execute_script('return takeEvents()')
    597     self.assertEquals(4, len(events))
    598     self._CheckEvent(events[0], 'mousemove', 0, center_x, center_y)
    599     self._CheckEvent(events[1], 'mousedown', 0, center_x, center_y)
    600     self._CheckEvent(events[2], 'mousemove', 0, center_x2, center_y2)
    601     self._CheckEvent(events[3], 'mouseup', 0, center_x2, center_y2)
    602 
    603     # Press and release.
    604     ActionChains(self._driver).click_and_hold(None).release(None).perform()
    605     events = self._driver.execute_script('return takeEvents()')
    606     self.assertEquals(2, len(events))
    607     self._CheckEvent(events[0], 'mousedown', 0, center_x2, center_y2)
    608     self._CheckEvent(events[1], 'mouseup', 0, center_x2, center_y2)
    609 
    610   def testDoubleClickCommand(self):
    611     center_x, center_y = self._GetElementMiddle(self._divs[0])
    612 
    613     # Double click element.
    614     ActionChains(self._driver).double_click(self._divs[0]).perform()
    615     events = self._driver.execute_script('return takeEvents()')
    616     self.assertEquals(6, len(events))
    617     self._CheckEvent(events[5], 'dblclick', 0, center_x, center_y)
    618 
    619     # Double click.
    620     ActionChains(self._driver).double_click(None).perform()
    621     events = self._driver.execute_script('return takeEvents()')
    622     self.assertEquals(5, len(events))
    623     self._CheckEvent(events[4], 'dblclick', 0, center_x, center_y)
    624 
    625   def testElementAPIClick(self):
    626     center_x, center_y = self._GetElementMiddle(self._divs[0])
    627 
    628     # Left click element.
    629     self._divs[0].click()
    630     events = self._driver.execute_script('return takeEvents()')
    631     self.assertEquals(3, len(events))
    632     self._CheckEvent(events[0], 'mousemove', 0, center_x, center_y)
    633     self._CheckEvent(events[1], 'mousedown', 0, center_x, center_y)
    634     self._CheckEvent(events[2], 'mouseup', 0, center_x, center_y)
    635 
    636 
    637 class TypingTest(ChromeDriverTest):
    638 
    639   def setUp(self):
    640     super(TypingTest, self).setUp()
    641     self._driver = self.GetNewDriver()
    642 
    643   def testSendKeysToEditingHostDiv(self):
    644     self._driver.get(self.GetTestDataUrl() + '/content_editable.html')
    645     div = self._driver.find_element_by_name('editable')
    646     # Break into two to ensure element doesn't lose focus.
    647     div.send_keys('hi')
    648     div.send_keys(' there')
    649     self.assertEquals('hi there', div.text)
    650 
    651   def testSendKeysToNonFocusableChildOfEditingHost(self):
    652     self._driver.get(self.GetTestDataUrl() + '/content_editable.html')
    653     child = self._driver.find_element_by_name('editable_child')
    654     self.assertRaises(WebDriverException, child.send_keys, 'hi')
    655 
    656   def testSendKeysToFocusableChildOfEditingHost(self):
    657     self._driver.get(self.GetTestDataUrl() + '/content_editable.html')
    658     child = self._driver.find_element_by_tag_name('input')
    659     child.send_keys('hi')
    660     child.send_keys(' there')
    661     self.assertEquals('hi there', child.get_attribute('value'))
    662 
    663   def testSendKeysToDesignModePage(self):
    664     self._driver.get(self.GetTestDataUrl() + '/design_mode_doc.html')
    665     body = self._driver.find_element_by_tag_name('body')
    666     body.send_keys('hi')
    667     body.send_keys(' there')
    668     self.assertEquals('hi there', body.text)
    669 
    670   def testSendKeysToDesignModeIframe(self):
    671     self._driver.get(self.GetTestDataUrl() + '/content_editable.html')
    672     self._driver.switch_to_frame(0)
    673     body = self._driver.find_element_by_tag_name('body')
    674     body.send_keys('hi')
    675     body.send_keys(' there')
    676     self.assertEquals('hi there', body.text)
    677 
    678   def testSendKeysToTransparentElement(self):
    679     self._driver.get(self.GetTestDataUrl() + '/transparent.html')
    680     text_box = self._driver.find_element_by_tag_name('input')
    681     text_box.send_keys('hi')
    682     self.assertEquals('hi', text_box.get_attribute('value'))
    683 
    684   def testSendKeysDesignModePageAfterNavigate(self):
    685     self._driver.get(self.GetTestDataUrl() + '/test_page.html')
    686     self._driver.get(self.GetTestDataUrl() + '/design_mode_doc.html')
    687     body = self._driver.find_element_by_tag_name('body')
    688     body.send_keys('hi')
    689     body.send_keys(' there')
    690     self.assertEquals('hi there', body.text)
    691 
    692   def testAppendsToTextInput(self):
    693     self._driver.get(self.GetTestDataUrl() + '/keyboard.html')
    694     text_elem = self._driver.find_element_by_name('input')
    695     text_elem.send_keys(' text')
    696     self.assertEquals('more text', text_elem.get_attribute('value'))
    697     area_elem = self._driver.find_element_by_name('area')
    698     area_elem.send_keys(' text')
    699     self.assertEquals('more text', area_elem.get_attribute('value'))
    700 
    701   def testTextAreaKeepsCursorPosition(self):
    702     self._driver.get(self.GetTestDataUrl() + '/keyboard.html')
    703     area_elem = self._driver.find_element_by_name('area')
    704     area_elem.send_keys(' text')
    705     area_elem.send_keys(Keys.LEFT * 9)
    706     area_elem.send_keys('much ')
    707     self.assertEquals('much more text', area_elem.get_attribute('value'))
    708 
    709   def testWithWebWidgets(self):
    710     def SetHTML(html):
    711       """Sets the page HTML.
    712 
    713       The given HTML should not contain single quotes.
    714       """
    715       assert '\'' not in html
    716       self._driver.execute_script('document.body.innerHTML = \'%s\'' % html)
    717     SetHTML('<input type="checkbox">check</input>')
    718     elem = self._driver.find_element_by_tag_name('input')
    719     elem.send_keys(' ')
    720     self.assertTrue(elem.is_selected())
    721     elem.send_keys(' ')
    722     self.assertFalse(elem.is_selected())
    723 
    724     SetHTML('<input type="radio" name="g" checked>1</input>' +
    725             '<input type="radio" name="g">2</input>')
    726     elem1, elem2 = self._driver.find_elements_by_tag_name('input')
    727     elem1.send_keys(Keys.RIGHT)
    728     self.assertTrue(elem2.is_selected())
    729     elem2.send_keys(Keys.LEFT)
    730     self.assertFalse(elem2.is_selected())
    731 
    732     SetHTML('<select><option>a</option><option>b</option></select>')
    733     elem = self._driver.find_element_by_tag_name('select')
    734     elem.send_keys('b')
    735     self.assertEquals('b', elem.get_attribute('value'))
    736 
    737     handler = 'javascript:document.title=\\x27success\\x27'
    738     SetHTML('<input type="button" onclick="%s"></input>' % handler)
    739     elem = self._driver.find_element_by_tag_name('input')
    740     elem.send_keys(' ')
    741     self.assertEquals('success', self._driver.title)
    742 
    743 
    744 class UrlBaseTest(ChromeDriverTest):
    745   """Tests that the server can be configured for a different URL base."""
    746 
    747   def setUp(self):
    748     self._server2 = ChromeDriverLauncher(self.GetDriverPath(),
    749                                          url_base='/wd/hub').Launch()
    750 
    751   def tearDown(self):
    752     self._server2.Kill()
    753 
    754   def testCreatingSessionShouldRedirectToCorrectURL(self):
    755     request_url = self._server2.GetUrl() + '/session'
    756     response = SendRequest(request_url, method='POST',
    757                            data='{"desiredCapabilities":{}}')
    758     self.assertEquals(200, response.code)
    759     self.session_url = response.geturl()  # TODO(jleyba): verify this URL?
    760 
    761     data = json.loads(response.read())
    762     self.assertTrue(isinstance(data, dict))
    763     self.assertEquals(0, data['status'])
    764 
    765     url_parts = urlparse.urlparse(self.session_url)[2].split('/')
    766     self.assertEquals(5, len(url_parts))
    767     self.assertEquals('', url_parts[0])
    768     self.assertEquals('wd', url_parts[1])
    769     self.assertEquals('hub', url_parts[2])
    770     self.assertEquals('session', url_parts[3])
    771     self.assertEquals(data['sessionId'], url_parts[4])
    772 
    773 
    774 # TODO(jleyba): Port this to WebDriver's own python test suite.
    775 class ElementEqualityTest(ChromeDriverTest):
    776   """Tests that the server properly checks element equality."""
    777 
    778   def setUp(self):
    779     super(ElementEqualityTest, self).setUp()
    780     self._driver = self.GetNewDriver()
    781 
    782   def tearDown(self):
    783     self._driver.quit()
    784 
    785   def testElementEquality(self):
    786     self._driver.get(self.GetTestDataUrl() + '/test_page.html')
    787     body1 = self._driver.find_element_by_tag_name('body')
    788     body2 = self._driver.execute_script('return document.body')
    789 
    790     # TODO(jleyba): WebDriver's python bindings should expose a proper API
    791     # for this.
    792     result = body1._execute(Command.ELEMENT_EQUALS, {
    793       'other': body2.id
    794     })
    795     self.assertTrue(result['value'])
    796 
    797 
    798 class LoggingTest(ChromeDriverTest):
    799 
    800   def testLogging(self):
    801     url = self.GetServer().GetUrl()
    802     req = SendRequest(url + '/log', method='GET')
    803     log = req.read()
    804     self.assertTrue('INFO' in log, msg='INFO not in log: ' + log)
    805 
    806 
    807 class FileUploadControlTest(ChromeDriverTest):
    808   """Tests dealing with file upload control."""
    809 
    810   def setUp(self):
    811     super(FileUploadControlTest, self).setUp()
    812     self._driver = self.GetNewDriver()
    813 
    814   # Fails on win - crbug.com/131782
    815   def DISABLED_testSetFilePathToFileUploadControl(self):
    816     """Verify a file path is set to the file upload control."""
    817     self._driver.get(self.GetTestDataUrl() + '/upload.html')
    818 
    819     tmp_file = tempfile.NamedTemporaryFile()
    820 
    821     fileupload_single = self._driver.find_element_by_name('fileupload_single')
    822     multiple = fileupload_single.get_attribute('multiple')
    823     self.assertEqual('false', multiple)
    824     fileupload_single.send_keys(tmp_file.name)
    825     path = fileupload_single.get_attribute('value')
    826     self.assertTrue(path.endswith(os.path.basename(tmp_file.name)))
    827 
    828   def testSetMultipleFilePathsToFileuploadControlWithoutMultipleWillFail(self):
    829     """Verify setting file paths to the file upload control without 'multiple'
    830     attribute will fail."""
    831     self._driver.get(self.GetTestDataUrl() + '/upload.html')
    832 
    833     files = []
    834     filepaths = []
    835     for index in xrange(4):
    836       tmp_file = tempfile.NamedTemporaryFile()
    837       # We need to hold the file objects because the files will be deleted on
    838       # GC.
    839       files.append(tmp_file)
    840       filepath = tmp_file.name
    841       filepaths.append(filepath)
    842 
    843     fileupload_single = self._driver.find_element_by_name('fileupload_single')
    844     self.assertFalse(fileupload_single.get_attribute('multiple'))
    845     self.assertRaises(WebDriverException, fileupload_single.send_keys,
    846                       '\n'.join(filepaths))
    847 
    848   def testSetMultipleFilePathsToFileUploadControl(self):
    849     """Verify multiple file paths are set to the file upload control."""
    850     self._driver.get(self.GetTestDataUrl() + '/upload.html')
    851 
    852     files = []
    853     filepaths = []
    854     filenames = set()
    855     for index in xrange(4):
    856       tmp_file = tempfile.NamedTemporaryFile()
    857       files.append(tmp_file)
    858       filepath = tmp_file.name
    859       filepaths.append(filepath)
    860       filenames.add(os.path.basename(filepath))
    861 
    862     fileupload_multi = self._driver.find_element_by_name('fileupload_multi')
    863     multiple = fileupload_multi.get_attribute('multiple')
    864     self.assertEqual('true', multiple)
    865     fileupload_multi.send_keys('\n'.join(filepaths))
    866 
    867     files_on_element = self._driver.execute_script(
    868         'return document.getElementById("fileupload_multi").files;')
    869     self.assertTrue(files_on_element)
    870     self.assertEqual(4, len(files_on_element))
    871     for f in files_on_element:
    872       self.assertTrue(f['name'] in filenames)
    873 
    874 
    875 class FrameSwitchingTest(ChromeDriverTest):
    876 
    877   def testGetWindowHandles(self):
    878     driver = self.GetNewDriver({'chrome.switches': ['disable-popup-blocking']})
    879     driver.get(self.GetTestDataUrl() + '/test_page.html')
    880     driver.execute_script('window.popup = window.open("about:blank")')
    881     self.assertEquals(2, len(driver.window_handles))
    882     driver.execute_script('window.popup.close()')
    883     self.assertEquals(1, len(driver.window_handles))
    884 
    885   def testSwitchToSameWindow(self):
    886     driver = self.GetNewDriver({'chrome.switches': ['disable-popup-blocking']})
    887     driver.get(self.GetTestDataUrl() + '/test_page.html')
    888     driver.switch_to_window(driver.window_handles[0])
    889     self.assertEquals('test_page.html', driver.current_url.split('/')[-1])
    890 
    891   def testClosedWindowThrows(self):
    892     driver = self.GetNewDriver({'chrome.switches': ['disable-popup-blocking']})
    893     driver.get(self.GetTestDataUrl() + '/test_page.html')
    894     driver.execute_script('window.open("about:blank")')
    895     driver.close()
    896     self.assertRaises(WebDriverException, driver.close)
    897 
    898   def testSwitchFromClosedWindow(self):
    899     driver = self.GetNewDriver({'chrome.switches': ['disable-popup-blocking']})
    900     driver.get(self.GetTestDataUrl() + '/test_page.html')
    901     driver.execute_script('window.open("about:blank")')
    902     old_window = driver.current_window_handle
    903     driver.close()
    904     driver.switch_to_window(driver.window_handles[0])
    905     self.assertEquals('about:blank', driver.current_url)
    906 
    907   def testSwitchToWindowWhileInSubframe(self):
    908     driver = self.GetNewDriver({'chrome.switches': ['disable-popup-blocking']})
    909     driver.get(self.GetTestDataUrl() + '/test_page.html')
    910     driver.execute_script('window.open("about:blank")')
    911     driver.switch_to_frame(0)
    912     driver.switch_to_window(driver.window_handles[1])
    913     self.assertEquals('about:blank', driver.current_url)
    914 
    915   # Tests that the indexing is absolute and not based on index of frame in its
    916   # parent element.
    917   # See crbug.com/88685.
    918   def testSwitchToFrameByIndex(self):
    919     driver = self.GetNewDriver({'chrome.switches': ['disable-popup-blocking']})
    920     driver.get(self.GetTestDataUrl() + '/switch_to_frame_by_index.html')
    921     for i in range(3):
    922       driver.switch_to_frame(i)
    923       self.assertEquals(str(i), driver.current_url.split('?')[-1])
    924       driver.switch_to_default_content()
    925 
    926 
    927 class AlertTest(ChromeDriverTest):
    928 
    929   def testAlertOnLoadDoesNotHang(self):
    930     driver = self.GetNewDriver()
    931     self.assertRaises(WebDriverException, driver.get,
    932                       self.GetTestDataUrl() + '/alert_on_load.html')
    933     driver.switch_to_alert().accept()
    934 
    935   def testAlertWhenTypingThrows(self):
    936     driver = self.GetNewDriver()
    937     driver.get(self.GetTestDataUrl() + '/alerts.html')
    938     input_box = driver.find_element_by_name('onkeypress')
    939     self.assertRaises(WebDriverException, input_box.send_keys, 'a')
    940 
    941   def testAlertJustAfterTypingDoesNotThrow(self):
    942     driver = self.GetNewDriver()
    943     driver.get(self.GetTestDataUrl() + '/alerts.html')
    944     driver.find_element_by_name('onkeyup').send_keys('a')
    945     driver.switch_to_alert().accept()
    946 
    947   def testAlertOnScriptDoesNotHang(self):
    948     driver = self.GetNewDriver()
    949     driver.get(self.GetTestDataUrl() + '/alerts.html')
    950     self.assertRaises(WebDriverException, driver.execute_script, 'alert("ok")')
    951 
    952   # See http://code.google.com/p/selenium/issues/detail?id=2671.
    953   def testCanPerformJSBasedActionsThatCauseAlertsAtTheEnd(self):
    954     driver = self.GetNewDriver()
    955     driver.execute_script(
    956         'var select = document.createElement("select");' +
    957         'select.innerHTML = "<option>1</option><option>2</option>";' +
    958         'select.addEventListener("change", function() { alert("hi"); });' +
    959         'document.body.appendChild(select);')
    960 
    961     # Shouldn't throw an exception, even though an alert appears mid-script.
    962     driver.find_elements_by_tag_name('option')[-1].click()
    963 
    964   def testMustHandleAlertFirst(self):
    965     driver = self.GetNewDriver()
    966     driver.get(self.GetTestDataUrl() + '/alerts.html')
    967     input_box = driver.find_element_by_name('normal')
    968     driver.execute_async_script('arguments[0](); window.alert("ok")')
    969 
    970     self.assertRaises(WebDriverException, driver.execute_script, 'a = 1')
    971 
    972     self.assertRaises(WebDriverException, input_box.send_keys, 'abc')
    973 
    974     self.assertRaises(WebDriverException, driver.get,
    975                       self.GetTestDataUrl() + '/test_page.html')
    976 
    977     self.assertRaises(WebDriverException, driver.refresh)
    978     self.assertRaises(WebDriverException, driver.back)
    979     self.assertRaises(WebDriverException, driver.forward)
    980     self.assertRaises(WebDriverException, driver.get_screenshot_as_base64)
    981 
    982   def testCanHandleAlertInSubframe(self):
    983     driver = self.GetNewDriver()
    984     driver.get(self.GetTestDataUrl() + '/alerts.html')
    985     driver.switch_to_frame('subframe')
    986     driver.execute_async_script('arguments[0](); window.alert("ok")')
    987     driver.switch_to_alert().accept()
    988 
    989 
    990 class WindowTest(ChromeDriverTest):
    991   """Tests for WebDriver window commands."""
    992 
    993   def setUp(self):
    994     super(WindowTest, self).setUp()
    995     self._driver = self.GetNewDriver()
    996 
    997   def testSize(self):
    998     size = self._driver.get_window_size()
    999     self._driver.set_window_size(size['width'], size['height'])
   1000     self.assertEquals(size, self._driver.get_window_size())
   1001     self._driver.set_window_size(800, 600)
   1002     self.assertEquals(800, self._driver.get_window_size()['width'])
   1003     self.assertEquals(600, self._driver.get_window_size()['height'])
   1004 
   1005   def testPosition(self):
   1006     pos = self._driver.get_window_position()
   1007     self._driver.set_window_position(pos['x'], pos['y'])
   1008     self.assertEquals(pos, self._driver.get_window_position())
   1009     self._driver.set_window_position(100, 200)
   1010     self.assertEquals(100, self._driver.get_window_position()['x'])
   1011     self.assertEquals(200, self._driver.get_window_position()['y'])
   1012 
   1013   # Systems without window manager (Xvfb, Xvnc) do not implement maximization.
   1014   @SkipIf(util.IsLinux())
   1015   def testMaximize(self):
   1016     old_size = self._driver.get_window_size()
   1017     self._driver.maximize_window()
   1018     new_size = self._driver.get_window_size()
   1019     self.assertTrue(old_size['width'] <= new_size['width'])
   1020     self.assertTrue(old_size['height'] <= new_size['height'])
   1021 
   1022   def testWindowHandle(self):
   1023     """Test specifying window handle."""
   1024     self._driver.execute_script(
   1025         'window.open("about:blank", "name", "height=200, width=200")')
   1026     windows = self._driver.window_handles
   1027     self.assertEquals(2, len(windows))
   1028     self._driver.set_window_size(400, 300, windows[1])
   1029     self.assertEquals(400, self._driver.get_window_size(windows[1])['width'])
   1030     self.assertEquals(300, self._driver.get_window_size(windows[1])['height'])
   1031     self.assertNotEquals(self._driver.get_window_size(windows[1]),
   1032                          self._driver.get_window_size(windows[0]))
   1033 
   1034   def testInvalidWindowHandle(self):
   1035     """Tests specifying invalid handle."""
   1036     invalid_handle = 'f1-120'
   1037     self.assertRaises(WebDriverException, self._driver.set_window_size,
   1038                       400, 300, invalid_handle)
   1039     self.assertRaises(NoSuchWindowException, self._driver.get_window_size,
   1040                       invalid_handle)
   1041     self.assertRaises(NoSuchWindowException, self._driver.set_window_position,
   1042                       1, 1, invalid_handle)
   1043     self.assertRaises(NoSuchWindowException, self._driver.get_window_position,
   1044                       invalid_handle)
   1045 
   1046 
   1047 class GeolocationTest(ChromeDriverTest):
   1048   """Tests for WebDriver geolocation commands."""
   1049 
   1050   def testGeolocation(self):
   1051     """Tests the get and set geolocation commands."""
   1052     driver = self.GetNewDriver()
   1053     driver.get(self.GetTestDataUrl() + '/empty.html')
   1054 
   1055     # TODO(kkania): Update the python bindings and get rid of these.
   1056     driver.command_executor._commands.update({
   1057         'getLoc': ('GET', '/session/$sessionId/location'),
   1058         'setLoc': ('POST', '/session/$sessionId/location')
   1059     })
   1060     def getLocation():
   1061       return driver.execute('getLoc')['value']
   1062     def setLocation(location):
   1063       driver.execute('setLoc', {'location': location})
   1064     expected_location = {'latitude': 50, 'longitude': 50, 'altitude': 300}
   1065     setLocation(expected_location)
   1066     location = getLocation()
   1067     self.assertEquals(expected_location, location)
   1068 
   1069     driver.set_script_timeout(10)
   1070     result = driver.execute_async_script("""
   1071        var callback = arguments[0];
   1072        window.navigator.geolocation.getCurrentPosition(
   1073            function success(result) { callback(result.coords); },
   1074            function fail(error) { callback(error.message); });""")
   1075     self.assertEquals(expected_location['latitude'], result['latitude'])
   1076     self.assertEquals(expected_location['longitude'], result['longitude'])
   1077     self.assertEquals(expected_location['altitude'], result['altitude'])
   1078 
   1079 
   1080 class ExtensionTest(ChromeDriverTest):
   1081 
   1082   INFOBAR_BROWSER_ACTION_EXTENSION = test_paths.TEST_DATA_PATH + \
   1083       '/infobar_browser_action_extension'
   1084   PAGE_ACTION_EXTENSION = test_paths.TEST_DATA_PATH + \
   1085       '/page_action_extension'
   1086   APP_SHELL = test_paths.TEST_DATA_PATH + \
   1087       '/app_shell_extension'
   1088 
   1089   def testExtensionInstallAndUninstall(self):
   1090     driver = self.GetNewDriver()
   1091     self.assertEquals(0, len(driver.get_installed_extensions()))
   1092     ext = driver.install_extension(self.PAGE_ACTION_EXTENSION)
   1093     extensions = driver.get_installed_extensions()
   1094     self.assertEquals(1, len(extensions))
   1095     self.assertEquals(ext.id, extensions[0].id)
   1096     ext.uninstall()
   1097     self.assertEquals(0, len(driver.get_installed_extensions()))
   1098 
   1099   def testExtensionInfo(self):
   1100     driver = self.GetNewDriver()
   1101     ext = driver.install_extension(self.PAGE_ACTION_EXTENSION)
   1102     self.assertEquals('Page action extension', ext.get_name())
   1103     self.assertEquals('1.0', ext.get_version())
   1104     self.assertEquals(32, len(ext.id))
   1105     self.assertTrue(ext.is_enabled())
   1106     ext.set_enabled(True)
   1107     ext.set_enabled(False)
   1108     self.assertFalse(ext.is_enabled())
   1109     ext.set_enabled(True)
   1110     self.assertTrue(ext.is_enabled())
   1111 
   1112   def _testExtensionView(self, driver, view_handle, extension):
   1113     """Tests that the given view supports basic WebDriver functionality."""
   1114     driver.switch_to_window(view_handle)
   1115     self.assertTrue(driver.execute_script('return true'))
   1116     checkbox = driver.find_element_by_id('checkbox')
   1117     checkbox.click()
   1118     self.assertTrue(checkbox.is_selected())
   1119     textfield = driver.find_element_by_id('textfield')
   1120     textfield.send_keys('test')
   1121     self.assertEquals('test', textfield.get_attribute('value'))
   1122     self.assertEquals('test', driver.title)
   1123     self.assertTrue(driver.current_url.endswith('view_checks.html'))
   1124     self.assertTrue('Should be in page source' in driver.page_source)
   1125     driver.close()
   1126     def is_view_closed(driver):
   1127       return len(filter(lambda view: view['handle'] == view_handle,
   1128                         extension._get_views())) == 0
   1129     WebDriverWait(driver, 10).until(is_view_closed)
   1130 
   1131   # Mac extension infobars are currently broken: crbug.com/107573.
   1132   @SkipIf(util.IsMac())
   1133   def testInfobarView(self):
   1134     driver = self.GetNewDriver({'chrome.switches':
   1135                                 ['enable-experimental-extension-apis']})
   1136     ext = driver.install_extension(self.INFOBAR_BROWSER_ACTION_EXTENSION)
   1137     driver.switch_to_window(ext.get_bg_page_handle())
   1138     driver.set_script_timeout(10)
   1139     driver.execute_async_script('waitForInfobar(arguments[0])')
   1140     self._testExtensionView(driver, ext.get_infobar_handles()[0], ext)
   1141 
   1142   def testBrowserActionPopupView(self):
   1143     driver = self.GetNewDriver({'chrome.switches':
   1144                                 ['enable-experimental-extension-apis']})
   1145     ext = driver.install_extension(self.INFOBAR_BROWSER_ACTION_EXTENSION)
   1146     ext.click_browser_action()
   1147     self._testExtensionView(driver, ext.get_popup_handle(), ext)
   1148 
   1149   def testPageActionPopupView(self):
   1150     driver = self.GetNewDriver()
   1151     ext = driver.install_extension(self.PAGE_ACTION_EXTENSION)
   1152     def is_page_action_visible(driver):
   1153       return ext.is_page_action_visible()
   1154     WebDriverWait(driver, 10).until(is_page_action_visible)
   1155     ext.click_page_action()
   1156     self._testExtensionView(driver, ext.get_popup_handle(), ext)
   1157 
   1158   def testAppShellView(self):
   1159     driver = self.GetNewDriver({'chrome.switches':
   1160                                 ['enable-experimental-extension-apis']})
   1161     ext = driver.install_extension(self.APP_SHELL)
   1162 
   1163     # Navigates to the new tab page to launch the app.
   1164     driver.get('chrome:newtab')
   1165     app = driver.find_element_by_xpath("//div[@title='App Shell']")
   1166     app.click()
   1167     def is_app_window_launched(driver):
   1168       return ext.get_app_shell_handle() is not None
   1169     WebDriverWait(driver, 10).until(is_app_window_launched)
   1170     self._testExtensionView(driver, ext.get_app_shell_handle(), ext)
   1171 
   1172 
   1173 class BadJSTest(ChromeDriverTest):
   1174   """Tests that ensure sites with hacky JS don't break ChromeDriver."""
   1175 
   1176   def testFindElementDoesNotUseNativeFuncs(self):
   1177     driver = self.GetNewDriver()
   1178     driver.get(self.GetTestDataUrl() + '/bad_native_funcs.html')
   1179     # This will throw an exception if any native funcs are used.
   1180     driver.find_element_by_tag_name('body').find_elements_by_tag_name('div')
   1181 
   1182 
   1183 class ContentSettingsTest(ChromeDriverTest):
   1184   """Tests that various types of content are allowed by default."""
   1185 
   1186   def testPopups(self):
   1187     driver = self.GetNewDriver()
   1188     driver.get(self.GetTestDataUrl() + '/empty.html')
   1189     driver.execute_script('window.open("about:blank")')
   1190     self.assertEquals(2, len(driver.window_handles))
   1191 
   1192   # Failing on win7: crbug.com/141231.
   1193   @SkipIf(util.IsWin())
   1194   def testPopupsCanBeResized(self):
   1195     """Regression test for chromedriver issue 126."""
   1196     driver = self.GetNewDriver()
   1197     driver.get(self.GetTestDataUrl() + '/empty.html')
   1198     driver.execute_script(
   1199         'window.open("empty.html", "popup", "width=500,height=500")')
   1200     driver.switch_to_window(driver.window_handles[1])
   1201     size = driver.get_window_size()
   1202     bigger_size = dict(map(lambda x: (x, size[x] + 100), size))
   1203     smaller_size = dict(map(lambda x: (x, size[x] - 100), size))
   1204     driver.set_window_size(bigger_size['width'], bigger_size['height'])
   1205     self.assertEquals(bigger_size, driver.get_window_size())
   1206     driver.set_window_size(smaller_size['width'], smaller_size['height'])
   1207     self.assertEquals(smaller_size, driver.get_window_size())
   1208 
   1209   def testGeolocation(self):
   1210     driver = self.GetNewDriver()
   1211     driver.get(self.GetTestDataUrl() + '/empty.html')
   1212     driver.set_script_timeout(10)
   1213     # Will timeout if infobar appears.
   1214     driver.execute_async_script(
   1215         'navigator.geolocation.getCurrentPosition(arguments[0], arguments[0]);')
   1216 
   1217   def testMediaStream(self):
   1218     driver = self.GetNewDriver()
   1219     # Allowing camera/mic access by default only works for https sites.
   1220     driver.get(self.GetHttpsTestDataUrl() + '/empty.html')
   1221     driver.set_script_timeout(10)
   1222     # Will timeout if infobar appears.
   1223     driver.execute_async_script(
   1224         'navigator.webkitGetUserMedia({audio:true, video:true},' +
   1225         '                             arguments[0], arguments[0]);')
   1226