run_py_tests.py revision ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16
1#!/usr/bin/env python
2# Copyright 2013 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"""End to end tests for ChromeDriver."""
7
8import base64
9import optparse
10import os
11import sys
12import tempfile
13import time
14import unittest
15
16_THIS_DIR = os.path.abspath(os.path.dirname(__file__))
17sys.path.insert(1, os.path.join(_THIS_DIR, os.pardir))
18sys.path.insert(1, os.path.join(_THIS_DIR, os.pardir, 'client'))
19sys.path.insert(1, os.path.join(_THIS_DIR, os.pardir, 'server'))
20
21import chrome_paths
22import chromedriver
23import unittest_util
24import util
25import server
26from webelement import WebElement
27import webserver
28
29_TEST_DATA_DIR = os.path.join(chrome_paths.GetTestData(), 'chromedriver')
30
31if util.IsLinux():
32  sys.path.insert(0, os.path.join(chrome_paths.GetSrc(), 'build', 'android'))
33  from pylib import android_commands
34  from pylib import forwarder
35  from pylib import valgrind_tools
36
37
38_DESKTOP_OS_SPECIFIC_FILTER = []
39if util.IsWindows():
40  _DESKTOP_OS_SPECIFIC_FILTER = [
41      # https://code.google.com/p/chromedriver/issues/detail?id=214
42      'ChromeDriverTest.testCloseWindow',
43      # https://code.google.com/p/chromedriver/issues/detail?id=299
44      'ChromeLogPathCapabilityTest.testChromeLogPath',
45  ]
46elif util.IsLinux():
47  _DESKTOP_OS_SPECIFIC_FILTER = [
48      # Xvfb doesn't support maximization.
49      'ChromeDriverTest.testWindowMaximize',
50      # https://code.google.com/p/chromedriver/issues/detail?id=302
51      'ChromeDriverTest.testWindowPosition',
52      'ChromeDriverTest.testWindowSize',
53  ]
54elif util.IsMac():
55  _DESKTOP_OS_SPECIFIC_FILTER = [
56      # https://code.google.com/p/chromedriver/issues/detail?id=304
57      'ChromeDriverTest.testGoBackAndGoForward',
58  ]
59
60
61_DESKTOP_NEGATIVE_FILTER = {}
62_DESKTOP_NEGATIVE_FILTER['HEAD'] = (
63    _DESKTOP_OS_SPECIFIC_FILTER + [
64        # https://code.google.com/p/chromedriver/issues/detail?id=213
65        'ChromeDriverTest.testClickElementInSubFrame',
66        # This test is flaky since it uses setTimeout.
67        # Re-enable once crbug.com/177511 is fixed and we can remove setTimeout.
68        'ChromeDriverTest.testAlert',
69        # Desktop doesn't support TAP.
70        'ChromeDriverTest.testSingleTapElement',
71    ]
72)
73
74
75def _GetDesktopNegativeFilter(version_name):
76  if version_name in _DESKTOP_NEGATIVE_FILTER:
77    return _DESKTOP_NEGATIVE_FILTER[version_name]
78  return _DESKTOP_NEGATIVE_FILTER['HEAD']
79
80
81_ANDROID_NEGATIVE_FILTER = {}
82_ANDROID_NEGATIVE_FILTER['com.google.android.apps.chrome'] = (
83    _DESKTOP_NEGATIVE_FILTER['HEAD'] + [
84        # Android doesn't support switches and extensions.
85        'ChromeSwitchesCapabilityTest.*',
86        'ChromeExtensionsCapabilityTest.*',
87        # https://code.google.com/p/chromedriver/issues/detail?id=262
88        'ChromeDriverTest.testCloseWindow',
89        'ChromeDriverTest.testGetWindowHandles',
90        'ChromeDriverTest.testSwitchToWindow',
91        'ChromeDriverTest.testShouldHandleNewWindowLoadingProperly',
92        # https://code.google.com/p/chromedriver/issues/detail?id=259
93        'ChromeDriverTest.testSendKeysToElement',
94        # https://code.google.com/p/chromedriver/issues/detail?id=270
95        'ChromeDriverTest.testPopups',
96        # https://code.google.com/p/chromedriver/issues/detail?id=298
97        'ChromeDriverTest.testWindowPosition',
98        'ChromeDriverTest.testWindowSize',
99        'ChromeDriverTest.testWindowMaximize',
100        'ChromeLogPathCapabilityTest.testChromeLogPath',
101        # Don't enable perf testing on Android yet.
102        'PerfTest.testSessionStartTime',
103        'PerfTest.testSessionStopTime',
104        'PerfTest.testColdExecuteScript',
105    ]
106)
107_ANDROID_NEGATIVE_FILTER['org.chromium.chrome.testshell'] = (
108    _ANDROID_NEGATIVE_FILTER['com.google.android.apps.chrome'] + []
109)
110
111
112class ChromeDriverBaseTest(unittest.TestCase):
113  """Base class for testing chromedriver functionalities."""
114
115  def __init__(self, *args, **kwargs):
116    super(ChromeDriverBaseTest, self).__init__(*args, **kwargs)
117    self._drivers = []
118
119  def tearDown(self):
120    for driver in self._drivers:
121      try:
122        driver.Quit()
123      except:
124        pass
125
126  def CreateDriver(self, server_url=None, **kwargs):
127    if server_url is None:
128      server_url = _CHROMEDRIVER_SERVER_URL
129    driver = chromedriver.ChromeDriver(server_url,
130                                       chrome_binary=_CHROME_BINARY,
131                                       android_package=_ANDROID_PACKAGE,
132                                       **kwargs)
133    self._drivers += [driver]
134    return driver
135
136
137class ChromeDriverTest(ChromeDriverBaseTest):
138  """End to end tests for ChromeDriver."""
139
140  @staticmethod
141  def GlobalSetUp():
142    ChromeDriverTest._http_server = webserver.WebServer(
143        chrome_paths.GetTestData())
144    if _ANDROID_PACKAGE:
145      ChromeDriverTest._adb = android_commands.AndroidCommands()
146      host_port = ChromeDriverTest._http_server._server.server_port
147      forwarder.Forwarder.Map(
148          [(host_port, host_port)], ChromeDriverTest._adb)
149
150  @staticmethod
151  def GlobalTearDown():
152    if _ANDROID_PACKAGE:
153      forwarder.Forwarder.UnmapAllDevicePorts(ChromeDriverTest._adb)
154    ChromeDriverTest._http_server.Shutdown()
155
156  @staticmethod
157  def GetHttpUrlForFile(file_path):
158    return ChromeDriverTest._http_server.GetUrl() + file_path
159
160  def setUp(self):
161    self._driver = self.CreateDriver()
162
163  def testStartStop(self):
164    pass
165
166  def testLoadUrl(self):
167    self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
168
169  def testGetCurrentWindowHandle(self):
170    self._driver.GetCurrentWindowHandle()
171
172  def _WaitForNewWindow(self, old_handles):
173    """Wait for at least one new window to show up in 20 seconds.
174
175    Args:
176      old_handles: Handles to all old windows before the new window is added.
177
178    Returns:
179      Handle to a new window. None if timeout.
180    """
181    timeout = time.time() + 20
182    while time.time() < timeout:
183      new_handles = self._driver.GetWindowHandles()
184      if len(new_handles) > len(old_handles):
185        for index, old_handle in enumerate(old_handles):
186          self.assertEquals(old_handle, new_handles[index])
187        return new_handles[len(old_handles)]
188      time.sleep(0.01)
189    return None
190
191  def testCloseWindow(self):
192    self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html'))
193    old_handles = self._driver.GetWindowHandles()
194    self._driver.FindElement('id', 'link').Click()
195    new_window_handle = self._WaitForNewWindow(old_handles)
196    self.assertNotEqual(None, new_window_handle)
197    self._driver.SwitchToWindow(new_window_handle)
198    self.assertEquals(new_window_handle, self._driver.GetCurrentWindowHandle())
199    self.assertRaises(chromedriver.NoSuchElement,
200                      self._driver.FindElement, 'id', 'link')
201    self._driver.CloseWindow()
202    self.assertRaises(chromedriver.NoSuchWindow,
203                      self._driver.GetCurrentWindowHandle)
204    new_handles = self._driver.GetWindowHandles()
205    for old_handle in old_handles:
206      self.assertTrue(old_handle in new_handles)
207    for handle in new_handles:
208      self._driver.SwitchToWindow(handle)
209      self.assertEquals(handle, self._driver.GetCurrentWindowHandle())
210      self._driver.CloseWindow()
211
212  def testGetWindowHandles(self):
213    self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html'))
214    old_handles = self._driver.GetWindowHandles()
215    self._driver.FindElement('id', 'link').Click()
216    self.assertNotEqual(None, self._WaitForNewWindow(old_handles))
217
218  def testSwitchToWindow(self):
219    self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html'))
220    self.assertEquals(
221        1, self._driver.ExecuteScript('window.name = "oldWindow"; return 1;'))
222    window1_handle = self._driver.GetCurrentWindowHandle()
223    old_handles = self._driver.GetWindowHandles()
224    self._driver.FindElement('id', 'link').Click()
225    new_window_handle = self._WaitForNewWindow(old_handles)
226    self.assertNotEqual(None, new_window_handle)
227    self._driver.SwitchToWindow(new_window_handle)
228    self.assertEquals(new_window_handle, self._driver.GetCurrentWindowHandle())
229    self.assertRaises(chromedriver.NoSuchElement,
230                      self._driver.FindElement, 'id', 'link')
231    self._driver.SwitchToWindow('oldWindow')
232    self.assertEquals(window1_handle, self._driver.GetCurrentWindowHandle())
233
234  def testEvaluateScript(self):
235    self.assertEquals(1, self._driver.ExecuteScript('return 1'))
236    self.assertEquals(None, self._driver.ExecuteScript(''))
237
238  def testEvaluateScriptWithArgs(self):
239    script = ('document.body.innerHTML = "<div>b</div><div>c</div>";'
240              'return {stuff: document.querySelectorAll("div")};')
241    stuff = self._driver.ExecuteScript(script)['stuff']
242    script = 'return arguments[0].innerHTML + arguments[1].innerHTML'
243    self.assertEquals(
244        'bc', self._driver.ExecuteScript(script, stuff[0], stuff[1]))
245
246  def testEvaluateInvalidScript(self):
247    self.assertRaises(chromedriver.ChromeDriverException,
248                      self._driver.ExecuteScript, '{{{')
249
250  def testExecuteAsyncScript(self):
251    self._driver.SetTimeout('script', 3000)
252    self.assertRaises(
253        chromedriver.ScriptTimeout,
254        self._driver.ExecuteAsyncScript,
255        'var callback = arguments[0];'
256        'setTimeout(function(){callback(1);}, 10000);')
257    self.assertEquals(
258        2,
259        self._driver.ExecuteAsyncScript(
260            'var callback = arguments[0];'
261            'setTimeout(function(){callback(2);}, 300);'))
262
263  def testSwitchToFrame(self):
264    self._driver.ExecuteScript(
265        'var frame = document.createElement("iframe");'
266        'frame.id="id";'
267        'frame.name="name";'
268        'document.body.appendChild(frame);')
269    self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
270    self._driver.SwitchToFrame('id')
271    self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
272    self._driver.SwitchToMainFrame()
273    self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
274    self._driver.SwitchToFrame('name')
275    self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
276    self._driver.SwitchToMainFrame()
277    self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
278    self._driver.SwitchToFrameByIndex(0)
279    self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
280    self._driver.SwitchToMainFrame()
281    self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
282    self._driver.SwitchToFrame(self._driver.FindElement('tag name', 'iframe'))
283    self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
284
285  def testExecuteInRemovedFrame(self):
286    self._driver.ExecuteScript(
287        'var frame = document.createElement("iframe");'
288        'frame.id="id";'
289        'frame.name="name";'
290        'document.body.appendChild(frame);'
291        'window.addEventListener("message",'
292        '    function(event) { document.body.removeChild(frame); });')
293    self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
294    self._driver.SwitchToFrame('id')
295    self.assertTrue(self._driver.ExecuteScript('return window.top != window'))
296    self._driver.ExecuteScript('parent.postMessage("remove", "*");')
297    self.assertTrue(self._driver.ExecuteScript('return window.top == window'))
298
299  def testGetTitle(self):
300    script = 'document.title = "title"; return 1;'
301    self.assertEquals(1, self._driver.ExecuteScript(script))
302    self.assertEquals('title', self._driver.GetTitle())
303
304  def testGetPageSource(self):
305    self._driver.Load(self.GetHttpUrlForFile('/chromedriver/page_test.html'))
306    self.assertTrue('Link to empty.html' in self._driver.GetPageSource())
307
308  def testFindElement(self):
309    self._driver.ExecuteScript(
310        'document.body.innerHTML = "<div>a</div><div>b</div>";')
311    self.assertTrue(
312        isinstance(self._driver.FindElement('tag name', 'div'), WebElement))
313
314  def testFindElements(self):
315    self._driver.ExecuteScript(
316        'document.body.innerHTML = "<div>a</div><div>b</div>";')
317    divs = self._driver.FindElements('tag name', 'div')
318    self.assertTrue(isinstance(divs, list))
319    self.assertEquals(2, len(divs))
320    for div in divs:
321      self.assertTrue(isinstance(div, WebElement))
322
323  def testFindChildElement(self):
324    self._driver.ExecuteScript(
325        'document.body.innerHTML = "<div><br><br></div><div><a></a></div>";')
326    element = self._driver.FindElement('tag name', 'div')
327    self.assertTrue(
328        isinstance(element.FindElement('tag name', 'br'), WebElement))
329
330  def testFindChildElements(self):
331    self._driver.ExecuteScript(
332        'document.body.innerHTML = "<div><br><br></div><div><br></div>";')
333    element = self._driver.FindElement('tag name', 'div')
334    brs = element.FindElements('tag name', 'br')
335    self.assertTrue(isinstance(brs, list))
336    self.assertEquals(2, len(brs))
337    for br in brs:
338      self.assertTrue(isinstance(br, WebElement))
339
340  def testHoverOverElement(self):
341    div = self._driver.ExecuteScript(
342        'document.body.innerHTML = "<div>old</div>";'
343        'var div = document.getElementsByTagName("div")[0];'
344        'div.addEventListener("mouseover", function() {'
345        '  document.body.appendChild(document.createElement("br"));'
346        '});'
347        'return div;')
348    div.HoverOver()
349    self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
350
351  def testClickElement(self):
352    div = self._driver.ExecuteScript(
353        'document.body.innerHTML = "<div>old</div>";'
354        'var div = document.getElementsByTagName("div")[0];'
355        'div.addEventListener("click", function() {'
356        '  var div = document.getElementsByTagName("div")[0];'
357        '  div.innerHTML="new<br>";'
358        '});'
359        'return div;')
360    div.Click()
361    self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
362
363  def testSingleTapElement(self):
364    div = self._driver.ExecuteScript(
365        'document.body.innerHTML = "<div>old</div>";'
366        'var div = document.getElementsByTagName("div")[0];'
367        'div.addEventListener("click", function() {'
368        '  var div = document.getElementsByTagName("div")[0];'
369        '  div.innerHTML="new<br>";'
370        '});'
371        'return div;')
372    div.SingleTap()
373    self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
374
375  def testClickElementInSubFrame(self):
376    self._driver.Load(self.GetHttpUrlForFile('/chromedriver/frame_test.html'))
377    frame = self._driver.FindElement('tag name', 'iframe')
378    self._driver.SwitchToFrame(frame)
379    # Test clicking element in the sub frame.
380    self.testClickElement()
381
382  def testClearElement(self):
383    text = self._driver.ExecuteScript(
384        'document.body.innerHTML = \'<input type="text" value="abc">\';'
385        'var input = document.getElementsByTagName("input")[0];'
386        'input.addEventListener("change", function() {'
387        '  document.body.appendChild(document.createElement("br"));'
388        '});'
389        'return input;')
390    text.Clear()
391    self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
392
393  def testSendKeysToElement(self):
394    text = self._driver.ExecuteScript(
395        'document.body.innerHTML = \'<input type="text">\';'
396        'var input = document.getElementsByTagName("input")[0];'
397        'input.addEventListener("change", function() {'
398        '  document.body.appendChild(document.createElement("br"));'
399        '});'
400        'return input;')
401    text.SendKeys('0123456789+-*/ Hi')
402    text.SendKeys(', there!')
403    value = self._driver.ExecuteScript('return arguments[0].value;', text)
404    self.assertEquals('0123456789+-*/ Hi, there!', value)
405
406  def testGetCurrentUrl(self):
407    self.assertTrue('data:' in self._driver.GetCurrentUrl())
408
409  def testGoBackAndGoForward(self):
410    self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
411    self._driver.GoBack()
412    self._driver.GoForward()
413
414  def testRefresh(self):
415    self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
416    self._driver.Refresh()
417
418  def testMouseMoveTo(self):
419    div = self._driver.ExecuteScript(
420        'document.body.innerHTML = "<div>old</div>";'
421        'var div = document.getElementsByTagName("div")[0];'
422        'div.style["width"] = "100px";'
423        'div.style["height"] = "100px";'
424        'div.addEventListener("mouseover", function() {'
425        '  var div = document.getElementsByTagName("div")[0];'
426        '  div.innerHTML="new<br>";'
427        '});'
428        'return div;')
429    self._driver.MouseMoveTo(div, 10, 10)
430    self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
431
432  def testMouseClick(self):
433    div = self._driver.ExecuteScript(
434        'document.body.innerHTML = "<div>old</div>";'
435        'var div = document.getElementsByTagName("div")[0];'
436        'div.style["width"] = "100px";'
437        'div.style["height"] = "100px";'
438        'div.addEventListener("click", function() {'
439        '  var div = document.getElementsByTagName("div")[0];'
440        '  div.innerHTML="new<br>";'
441        '});'
442        'return div;')
443    self._driver.MouseMoveTo(div)
444    self._driver.MouseClick()
445    self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
446
447  def testMouseButtonDownAndUp(self):
448    self._driver.ExecuteScript(
449        'document.body.innerHTML = "<div>old</div>";'
450        'var div = document.getElementsByTagName("div")[0];'
451        'div.style["width"] = "100px";'
452        'div.style["height"] = "100px";'
453        'div.addEventListener("mousedown", function() {'
454        '  var div = document.getElementsByTagName("div")[0];'
455        '  div.innerHTML="new1<br>";'
456        '});'
457        'div.addEventListener("mouseup", function() {'
458        '  var div = document.getElementsByTagName("div")[0];'
459        '  div.innerHTML="new2<a></a>";'
460        '});')
461    self._driver.MouseMoveTo(None, 50, 50)
462    self._driver.MouseButtonDown()
463    self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
464    self._driver.MouseButtonUp()
465    self.assertEquals(1, len(self._driver.FindElements('tag name', 'a')))
466
467  def testMouseDoubleClick(self):
468    div = self._driver.ExecuteScript(
469        'document.body.innerHTML = "<div>old</div>";'
470        'var div = document.getElementsByTagName("div")[0];'
471        'div.style["width"] = "100px";'
472        'div.style["height"] = "100px";'
473        'div.addEventListener("dblclick", function() {'
474        '  var div = document.getElementsByTagName("div")[0];'
475        '  div.innerHTML="new<br>";'
476        '});'
477        'return div;')
478    self._driver.MouseMoveTo(div, 1, 1)
479    self._driver.MouseDoubleClick()
480    self.assertEquals(1, len(self._driver.FindElements('tag name', 'br')))
481
482  def testAlert(self):
483    self.assertFalse(self._driver.IsAlertOpen())
484    self._driver.ExecuteScript(
485        'window.setTimeout('
486        '    function() { window.confirmed = confirm(\'HI\'); },'
487        '    0);')
488    self.assertTrue(self._driver.IsAlertOpen())
489    self.assertEquals('HI', self._driver.GetAlertMessage())
490    self._driver.HandleAlert(False)
491    self.assertFalse(self._driver.IsAlertOpen())
492    self.assertEquals(False,
493                      self._driver.ExecuteScript('return window.confirmed'))
494
495  def testShouldHandleNewWindowLoadingProperly(self):
496    """Tests that ChromeDriver determines loading correctly for new windows."""
497    sync_server = webserver.SyncWebServer()
498    self._http_server.SetDataForPath(
499        '/newwindow',
500        """
501        <html>
502        <body>
503        <a href='%s' target='_blank'>new window/tab</a>
504        </body>
505        </html>""" % sync_server.GetUrl())
506    self._driver.Load(self._http_server.GetUrl() + '/newwindow')
507    old_windows = self._driver.GetWindowHandles()
508    self._driver.FindElement('tagName', 'a').Click()
509    new_window = self._WaitForNewWindow(old_windows)
510    self.assertNotEqual(None, new_window)
511
512    self.assertFalse(self._driver.IsLoading())
513    self._driver.SwitchToWindow(new_window)
514    self.assertTrue(self._driver.IsLoading())
515    sync_server.RespondWithContent('<html>new window</html>')
516    self._driver.ExecuteScript('return 1')  # Shouldn't hang.
517
518  def testPopups(self):
519    self._driver.Load(self.GetHttpUrlForFile('/chromedriver/empty.html'))
520    old_handles = self._driver.GetWindowHandles()
521    self._driver.ExecuteScript('window.open("about:blank")')
522    new_window_handle = self._WaitForNewWindow(old_handles)
523    self.assertNotEqual(None, new_window_handle)
524
525  def testNoSuchFrame(self):
526    self.assertRaises(chromedriver.NoSuchFrame,
527                      self._driver.SwitchToFrame, 'nosuchframe')
528    self.assertRaises(chromedriver.NoSuchFrame,
529                      self._driver.SwitchToFrame,
530                      self._driver.FindElement('tagName', 'body'))
531
532  def testWindowPosition(self):
533    position = self._driver.GetWindowPosition()
534    self._driver.SetWindowPosition(position[0], position[1])
535    self.assertEquals(position, self._driver.GetWindowPosition())
536
537    # Resize so the window isn't moved offscreen.
538    # See https://code.google.com/p/chromedriver/issues/detail?id=297.
539    self._driver.SetWindowSize(300, 300)
540
541    self._driver.SetWindowPosition(100, 200)
542    self.assertEquals([100, 200], self._driver.GetWindowPosition())
543
544  def testWindowSize(self):
545    size = self._driver.GetWindowSize()
546    self._driver.SetWindowSize(size[0], size[1])
547    self.assertEquals(size, self._driver.GetWindowSize())
548
549    self._driver.SetWindowSize(600, 400)
550    self.assertEquals([600, 400], self._driver.GetWindowSize())
551
552  def testWindowMaximize(self):
553    self._driver.SetWindowPosition(100, 200)
554    self._driver.SetWindowSize(600, 400)
555    self._driver.MaximizeWindow()
556
557    self.assertNotEqual([100, 200], self._driver.GetWindowPosition())
558    self.assertNotEqual([600, 400], self._driver.GetWindowSize())
559    # Set size first so that the window isn't moved offscreen.
560    # See https://code.google.com/p/chromedriver/issues/detail?id=297.
561    self._driver.SetWindowSize(600, 400)
562    self._driver.SetWindowPosition(100, 200)
563    self.assertEquals([100, 200], self._driver.GetWindowPosition())
564    self.assertEquals([600, 400], self._driver.GetWindowSize())
565
566  def testContextMenuEventFired(self):
567    self._driver.Load(self.GetHttpUrlForFile('/chromedriver/context_menu.html'))
568    self._driver.MouseMoveTo(self._driver.FindElement('tagName', 'div'))
569    self._driver.MouseClick(2)
570    self.assertTrue(self._driver.ExecuteScript('return success'))
571
572
573class ChromeSwitchesCapabilityTest(ChromeDriverBaseTest):
574  """Tests that chromedriver properly processes chromeOptions.args capabilities.
575
576  Makes sure the switches are passed to Chrome.
577  """
578
579  def testSwitchWithoutArgument(self):
580    """Tests that switch --dom-automation can be passed to Chrome.
581
582    Unless --dom-automation is specified, window.domAutomationController
583    is undefined.
584    """
585    driver = self.CreateDriver(chrome_switches=['dom-automation'])
586    self.assertNotEqual(
587        None,
588        driver.ExecuteScript('return window.domAutomationController'))
589
590
591class ChromeExtensionsCapabilityTest(ChromeDriverBaseTest):
592  """Tests that chromedriver properly processes chromeOptions.extensions."""
593
594  def testExtensionsInstall(self):
595    """Checks that chromedriver can take the extensions."""
596    crx_1 = os.path.join(_TEST_DATA_DIR, 'ext_test_1.crx')
597    crx_2 = os.path.join(_TEST_DATA_DIR, 'ext_test_2.crx')
598    crx_1_encoded = base64.b64encode(open(crx_1, 'rb').read())
599    crx_2_encoded = base64.b64encode(open(crx_2, 'rb').read())
600    extensions = [crx_1_encoded, crx_2_encoded]
601    self.CreateDriver(chrome_extensions=extensions)
602
603
604class ChromeLogPathCapabilityTest(ChromeDriverBaseTest):
605  """Tests that chromedriver properly processes chromeOptions.logPath."""
606
607  LOG_MESSAGE = 'Welcome to ChromeLogPathCapabilityTest!'
608
609  def testChromeLogPath(self):
610    """Checks that user can specify the path of the chrome log.
611
612    Verifies that a log message is written into the specified log file.
613    """
614    tmp_log_path = tempfile.NamedTemporaryFile()
615    driver = self.CreateDriver(chrome_log_path=tmp_log_path.name)
616    driver.ExecuteScript('console.info("%s")' % self.LOG_MESSAGE)
617    driver.Quit()
618    self.assertTrue(self.LOG_MESSAGE in open(tmp_log_path.name).read())
619
620
621class SessionHandlingTest(ChromeDriverBaseTest):
622  """Tests for session operations."""
623  def testQuitASessionMoreThanOnce(self):
624    driver = self.CreateDriver()
625    driver.Quit()
626    driver.Quit()
627
628
629class PerfTest(ChromeDriverBaseTest):
630  """Tests for ChromeDriver perf."""
631  def setUp(self):
632    self.assertTrue(_REFERENCE_CHROMEDRIVER is not None,
633                    'must supply a reference-chromedriver arg')
634
635  def _RunDriverPerfTest(self, name, test_func):
636    """Runs a perf test comparing a reference and new ChromeDriver server.
637
638    Args:
639      name: The name of the perf test.
640      test_func: Called with the server url to perform the test action. Must
641                 return the time elapsed.
642    """
643    class Results(object):
644      ref = []
645      new = []
646
647    ref_server = server.Server(_REFERENCE_CHROMEDRIVER)
648    results = Results()
649    result_url_pairs = zip([results.new, results.ref],
650                           [_CHROMEDRIVER_SERVER_URL, ref_server.GetUrl()])
651    for iteration in range(30):
652      for result, url in result_url_pairs:
653        result += [test_func(url)]
654      # Reverse the order for the next run.
655      result_url_pairs = result_url_pairs[::-1]
656
657    def PrintResult(build, result):
658      mean = sum(result) / len(result)
659      avg_dev = sum([abs(sample - mean) for sample in result]) / len(result)
660      print 'perf result', build, name, mean, avg_dev, result
661      util.AddBuildStepText('%s %s: %.3f+-%.3f' % (
662          build, name, mean, avg_dev))
663
664    # Discard first result, which may be off due to cold start.
665    PrintResult('new', results.new[1:])
666    PrintResult('ref', results.ref[1:])
667
668  def testSessionStartTime(self):
669    def Run(url):
670      start = time.time()
671      driver = self.CreateDriver(url)
672      end = time.time()
673      driver.Quit()
674      return end - start
675    self._RunDriverPerfTest('session start', Run)
676
677  def testSessionStopTime(self):
678    def Run(url):
679      driver = self.CreateDriver(url)
680      start = time.time()
681      driver.Quit()
682      end = time.time()
683      return end - start
684    self._RunDriverPerfTest('session stop', Run)
685
686  def testColdExecuteScript(self):
687    def Run(url):
688      driver = self.CreateDriver(url)
689      start = time.time()
690      driver.ExecuteScript('return 1')
691      end = time.time()
692      driver.Quit()
693      return end - start
694    self._RunDriverPerfTest('cold exe js', Run)
695
696if __name__ == '__main__':
697  parser = optparse.OptionParser()
698  parser.add_option(
699      '', '--chromedriver',
700      help='Path to chromedriver server (REQUIRED!)')
701  parser.add_option(
702      '', '--reference-chromedriver',
703      help='Path to the reference chromedriver server')
704  parser.add_option(
705      '', '--chrome', help='Path to a build of the chrome binary')
706  parser.add_option(
707      '', '--chrome-version', default='HEAD',
708      help='Version of chrome. Default is \'HEAD\'.')
709  parser.add_option(
710      '', '--filter', type='string', default='*',
711      help=('Filter for specifying what tests to run, "*" will run all. E.g., '
712            '*testStartStop'))
713  parser.add_option(
714      '', '--android-package', help='Android package name')
715  options, args = parser.parse_args()
716
717  if not options.chromedriver or not os.path.exists(options.chromedriver):
718    parser.error('chromedriver is required or the given path is invalid.' +
719                 'Please run "%s --help" for help' % __file__)
720
721  chromedriver_server = server.Server(os.path.abspath(options.chromedriver))
722  global _CHROMEDRIVER_SERVER_URL
723  _CHROMEDRIVER_SERVER_URL = chromedriver_server.GetUrl()
724
725  global _REFERENCE_CHROMEDRIVER
726  _REFERENCE_CHROMEDRIVER = options.reference_chromedriver
727
728  global _CHROME_BINARY
729  if options.chrome:
730    _CHROME_BINARY = os.path.abspath(options.chrome)
731  else:
732    _CHROME_BINARY = None
733
734  global _ANDROID_PACKAGE
735  _ANDROID_PACKAGE = options.android_package
736
737  if options.filter == '*':
738    if _ANDROID_PACKAGE:
739      negative_filter = _ANDROID_NEGATIVE_FILTER[_ANDROID_PACKAGE]
740    else:
741      negative_filter = _GetDesktopNegativeFilter(options.chrome_version)
742    options.filter = '*-' + ':__main__.'.join([''] + negative_filter)
743
744  all_tests_suite = unittest.defaultTestLoader.loadTestsFromModule(
745      sys.modules[__name__])
746  tests = unittest_util.FilterTestSuite(all_tests_suite, options.filter)
747  ChromeDriverTest.GlobalSetUp()
748  result = unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run(tests)
749  ChromeDriverTest.GlobalTearDown()
750  sys.exit(len(result.failures) + len(result.errors))
751