Repository: robotframework/SeleniumLibrary

Issue:
Open Browser keyword in 3.2 (and most likely 3.1 too) does not work with chromium-browser, but 3.0 works with chromium-browser. 
# Steps to reproduce the issue

```
| Open Browser | http://google.com | Chrome | # In Linux with chromium-browser |
```
# Error messages and additional information

```
Message:    WebDriverException: Message: unknown error: Chrome failed to start: exited abnormally
 (unknown error: DevToolsActivePort file doesn't exist)
 (The process started from chrome location /usr/lib/chromium-browser/chromium-browser is no longer running, so ChromeDriver is assuming that Chrome has crashed.)
 (Driver info: chromedriver=2.44.609551 (5d576e9a44fe4c5b6a07e568f1ebc753f1214634),platform=Linux 3.10.0-693.17.1.el7.x86_64 x86_64)
00:00:01.994KEYWORD Open Google
Start / End / Elapsed:    20181122 11:52:11.601 / 20181122 11:52:13.595 / 00:00:01.994
00:00:01.993KEYWORD SeleniumLibrary . Open Browser http://google.com, Chrome
Documentation:    
Opens a new browser instance to the given url.

Start / End / Elapsed:    20181122 11:52:11.601 / 20181122 11:52:13.594 / 00:00:01.993
00:00:00.001KEYWORD SeleniumLibrary . Capture Page Screenshot
11:52:11.602    TRACE    Arguments: [ 'http://google.com' | 'Chrome' ]    
11:52:11.602    INFO    Opening browser 'Chrome' to base url 'http://google.com'.    
11:52:13.525    DEBUG    POST http://127.0.0.1:52399/session {"capabilities": {"alwaysMatch": {"browserName": "chrome", "platformName": "any"}, "firstMatch": [{}]}, "desiredCapabilities": {"platform": "ANY", "browserName": "chrome", "version": ""}}    
11:52:13.526    DEBUG    Starting new HTTP connection (1): 127.0.0.1:52399    
11:52:13.587    DEBUG    http://127.0.0.1:52399 "POST /session HTTP/1.1" 200 496    
11:52:13.587    DEBUG    Finished Request    
11:52:13.594    FAIL    WebDriverException: Message: unknown error: Chrome failed to start: exited abnormally
 (unknown error: DevToolsActivePort file doesn't exist)
 (The process started from chrome location /usr/lib/chromium-browser/chromium-browser is no longer running, so ChromeDriver is assuming that Chrome has crashed.)
 (Driver info: chromedriver=2.44.609551 (5d576e9a44fe4c5b6a07e568f1ebc753f1214634),platform=Linux 3.10.0-693.17.1.el7.x86_64 x86_64)
11:52:13.594    DEBUG    Traceback (most recent call last):
 File "/usr/local/lib/python2.7/dist-packages/SeleniumLibrary/__init__.py", line 369, in run_keyword
   return DynamicCore.run_keyword(self, name, args, kwargs)
 File "/usr/local/lib/python2.7/dist-packages/SeleniumLibrary/base/robotlibcore.py", line 102, in run_keyword
   return self.keywords[name](*args, **kwargs)
 File "/usr/local/lib/python2.7/dist-packages/SeleniumLibrary/keywords/browsermanagement.py", line 131, in open_browser
   ff_profile_dir, remote_url)
 File "/usr/local/lib/python2.7/dist-packages/SeleniumLibrary/keywords/browsermanagement.py", line 456, in _make_driver
   remote_url=remote, profile_dir=profile_dir)
 File "/usr/local/lib/python2.7/dist-packages/SeleniumLibrary/keywords/webdrivertools.py", line 58, in create_driver
   return creation_method(desired_capabilities, remote_url)
 File "/usr/local/lib/python2.7/dist-packages/SeleniumLibrary/keywords/webdrivertools.py", line 85, in create_chrome
   options=options)
 File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/chrome/webdriver.py", line 81, in __init__
   desired_capabilities=desired_capabilities)
 File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py", line 157, in __init__
   self.start_session(capabilities, browser_profile)
 File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py", line 252, in start_session
   response = self.execute(Command.NEW_SESSION, parameters)
 File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
   self.error_handler.check_response(response)
 File "/usr/local/lib/python2.7/dist-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
   raise exception_class(message, screen, stacktrace
```
## Expected behavior and actual behavior

Chromium browser does not open, but it should open with SeleniumLibrary 3.2. Chromium browser 

## Additional information
If this is done
```
from selenium import webdriver

capabilities = webdriver.DesiredCapabilities.CHROME
driver = webdriver.Chrome(desired_capabilities=capabilities, options=None)
driver.get("http://www.python.org")
assert "Python" in driver.title
driver.close()
```
Same error is received, but if this is done
```
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("http://www.python.org")
assert "Python" in driver.title
driver.close()
```
Error is not received. 

The former is what SL 3.2 `Open Browser` keyword does and later is what SL 3.0 `Open Browser` keyword does. Because of the errors with chromium-browser, we should restore the functionality SL 3.0 with opening browser. 

Also Selenium will set the desired capabilities for local browsers if SL does not define desired capabilities. But for remote browsers, there is small change that feature is backwards incompatible.

Discussion:
aaltat: Tested with different browsers and also with grid. All looks OK and now it is ready for to be merged.

Patch:
diff --git a/src/SeleniumLibrary/keywords/webdrivertools.py b/src/SeleniumLibrary/keywords/webdrivertools.py
index 3aa14dc8..e6da3016 100644
--- a/src/SeleniumLibrary/keywords/webdrivertools.py
+++ b/src/SeleniumLibrary/keywords/webdrivertools.py
@@ -50,7 +50,7 @@ class WebDriverCreator(object):
     def create_driver(self, browser, desired_capabilities, remote_url,
                       profile_dir=None):
         creation_method = self._get_creator_method(browser)
-        desired_capabilities = self._parse_capabilities(desired_capabilities)
+        desired_capabilities = self._parse_capabilities(desired_capabilities, browser)
         if (creation_method == self.create_firefox
                 or creation_method == self.create_headless_firefox):
             return creation_method(desired_capabilities, remote_url,
@@ -63,7 +63,7 @@ class WebDriverCreator(object):
             return getattr(self, 'create_{}'.format(self.browser_names[browser]))
         raise ValueError('{} is not a supported browser.'.format(browser))
 
-    def _parse_capabilities(self, capabilities):
+    def _parse_capabilities(self, capabilities, browser=None):
         if isinstance(capabilities, dict):
             return capabilities
         desired_capabilities = {}
@@ -72,18 +72,21 @@ class WebDriverCreator(object):
         for part in capabilities.split(','):
             key, value = part.split(':')
             desired_capabilities[key.strip()] = value.strip()
-        return desired_capabilities
+        browser_alias = {'googlechrome': "chrome", 'gc': "chrome",
+                         'headlesschrome': 'chrome', 'ff': 'firefox',
+                         'headlessfirefox': 'firefox',
+                         'internetexplorer': 'ie'}
+        browser = browser_alias.get(browser, browser)
+        if browser in ['ie', 'firefox', 'edge']:
+            return {'capabilities': desired_capabilities}
+        return {'desired_capabilities': desired_capabilities}
 
     def create_chrome(self, desired_capabilities, remote_url, options=None):
-        default = webdriver.DesiredCapabilities.CHROME
         if is_truthy(remote_url):
-            return self._remote(default, desired_capabilities, remote_url,
-                                options=options)
-        capabilities = self._combine_capabilites(default, desired_capabilities)
+            return self._remote(desired_capabilities, remote_url, options=options)
         if SELENIUM_VERSION.major >= 3 and SELENIUM_VERSION.minor >= 8:
-            return webdriver.Chrome(desired_capabilities=capabilities,
-                                    options=options)
-        return webdriver.Chrome(desired_capabilities=capabilities)
+            return webdriver.Chrome(options=options, **desired_capabilities)
+        return webdriver.Chrome(**desired_capabilities)
 
     def create_headless_chrome(self, desired_capabilities, remote_url):
         if SELENIUM_VERSION.major >= 3 and SELENIUM_VERSION.minor >= 8:
@@ -95,19 +98,16 @@ class WebDriverCreator(object):
 
     def create_firefox(self, desired_capabilities, remote_url, ff_profile_dir,
                        options=None):
-        default = webdriver.DesiredCapabilities.FIREFOX
         profile = self._get_ff_profile(ff_profile_dir)
         if is_truthy(remote_url):
-            return self._remote(default, desired_capabilities, remote_url,
+            return self._remote(desired_capabilities, remote_url,
                                 profile, options)
-        capabilities = self._combine_capabilites(default, desired_capabilities)
+        desired_capabilities.update(self._geckodriver_log)
         if SELENIUM_VERSION.major >= 3 and SELENIUM_VERSION.minor >= 8:
-            return webdriver.Firefox(capabilities=capabilities, options=options,
-                                     firefox_profile=profile,
-                                     **self._geckodriver_log)
-        return webdriver.Firefox(capabilities=capabilities,
-                                 firefox_profile=profile,
-                                 **self._geckodriver_log)
+            return webdriver.Firefox(options=options, firefox_profile=profile,
+                                     **desired_capabilities)
+        return webdriver.Firefox(firefox_profile=profile,
+                                 **desired_capabilities)
 
     def _get_ff_profile(self, ff_profile_dir):
         if is_falsy(ff_profile_dir):
@@ -131,73 +131,54 @@ class WebDriverCreator(object):
                                    ff_profile_dir, options)
 
     def create_ie(self, desired_capabilities, remote_url):
-        default = webdriver.DesiredCapabilities.INTERNETEXPLORER
         if is_truthy(remote_url):
-            return self._remote(default, desired_capabilities, remote_url)
-        capabilities = self._combine_capabilites(default, desired_capabilities)
-        return webdriver.Ie(capabilities=capabilities)
+            return self._remote(desired_capabilities, remote_url)
+        return webdriver.Ie(**desired_capabilities)
 
     def create_edge(self, desired_capabilities, remote_url):
-        default = webdriver.DesiredCapabilities.EDGE
         if is_truthy(remote_url):
-            return self._remote(default, desired_capabilities, remote_url)
-        capabilities = self._combine_capabilites(default, desired_capabilities)
-        return webdriver.Edge(capabilities=capabilities)
+            return self._remote(desired_capabilities, remote_url)
+        return webdriver.Edge(**desired_capabilities)
 
     def create_opera(self, desired_capabilities, remote_url):
-        default = webdriver.DesiredCapabilities.OPERA
         if is_truthy(remote_url):
-            return self._remote(default, desired_capabilities, remote_url)
-        capabilities = self._combine_capabilites(default, desired_capabilities)
-        return webdriver.Opera(desired_capabilities=capabilities)
+            return self._remote(desired_capabilities, remote_url)
+        return webdriver.Opera(**desired_capabilities)
 
     def create_safari(self, desired_capabilities, remote_url):
-        default = webdriver.DesiredCapabilities.SAFARI
         if is_truthy(remote_url):
-            return self._remote(default, desired_capabilities, remote_url)
-        capabilities = self._combine_capabilites(default, desired_capabilities)
-        return webdriver.Safari(desired_capabilities=capabilities)
+            return self._remote(desired_capabilities, remote_url)
+        return webdriver.Safari(**desired_capabilities)
 
     def create_phantomjs(self, desired_capabilities, remote_url):
-        default = webdriver.DesiredCapabilities.PHANTOMJS
         if is_truthy(remote_url):
-            return self._remote(default, desired_capabilities, remote_url)
-        capabilities = self._combine_capabilites(default, desired_capabilities)
-        return webdriver.PhantomJS(desired_capabilities=capabilities)
+            return self._remote(desired_capabilities, remote_url)
+        return webdriver.PhantomJS(**desired_capabilities)
 
     def create_htmlunit(self, desired_capabilities, remote_url):
-        default = webdriver.DesiredCapabilities.HTMLUNIT
-        return self._remote(default, desired_capabilities, remote_url)
+        return self._remote(desired_capabilities, remote_url)
 
     def create_htmlunit_with_js(self, desired_capabilities, remote_url):
-        default = webdriver.DesiredCapabilities.HTMLUNITWITHJS
-        return self._remote(default, desired_capabilities, remote_url)
+        return self._remote(desired_capabilities, remote_url)
 
     def create_android(self, desired_capabilities, remote_url):
-        default = webdriver.DesiredCapabilities.ANDROID
-        return self._remote(default, desired_capabilities, remote_url)
+        return self._remote(desired_capabilities, remote_url)
 
     def create_iphone(self, desired_capabilities, remote_url):
-        default = webdriver.DesiredCapabilities.IPHONE
-        return self._remote(default, desired_capabilities, remote_url)
+        return self._remote(desired_capabilities, remote_url)
 
-    def _remote(self, default_capabilities, user_capabilities, remote_url,
+    def _remote(self, desired_capabilities, remote_url,
                 profile_dir=None, options=None):
         remote_url = str(remote_url)
-        capabilities = self._combine_capabilites(default_capabilities,
-                                                 user_capabilities)
+        if 'capabilities' in desired_capabilities:
+            desired_capabilities['desired_capabilities'] = desired_capabilities.pop('capabilities')
         if SELENIUM_VERSION.major >= 3 and SELENIUM_VERSION.minor >= 8:
             return webdriver.Remote(command_executor=remote_url,
-                                    desired_capabilities=capabilities,
-                                    browser_profile=profile_dir, options=options)
+                                    browser_profile=profile_dir, options=options,
+                                    **desired_capabilities)
         return webdriver.Remote(command_executor=remote_url,
-                                desired_capabilities=capabilities,
-                                browser_profile=profile_dir)
-
-    def _combine_capabilites(self, default, user):
-        default = default.copy()
-        default.update(user)
-        return default
+                                browser_profile=profile_dir,
+                                **desired_capabilities)
 
 
 class WebDriverCache(ConnectionCache):


Test patch:
diff --git a/atest/run.py b/atest/run.py
index 60af2658..23ad3ca3 100755
--- a/atest/run.py
+++ b/atest/run.py
@@ -158,7 +158,7 @@ def get_sauce_conf(browser, sauce_username, sauce_key):
             sauce_username, sauce_key
         ),
         '--variable',
-        'DESIRED_CAPABILITIES:build:{0}-{1},tunnel-identifier:{0}'.format(
+        'DESIRED_CAPABILITIES:build:{0}-{1},tunnel-identifier:{0},browserName:{1}'.format(
             TRAVIS_JOB_NUMBER, browser
         )
     ]
diff --git a/utest/test/keywords/test_browsermanagement.py b/utest/test/keywords/test_browsermanagement.py
index 19473a00..e92c9a12 100644
--- a/utest/test/keywords/test_browsermanagement.py
+++ b/utest/test/keywords/test_browsermanagement.py
@@ -59,12 +59,7 @@ class BrowserManagementTests(unittest.TestCase):
         ctx = mock()
         ctx.speed = 5.0
         browser = mock()
-        caps = webdriver.DesiredCapabilities.CHROME
-        if SELENIUM_VERSION.major >= 3 and SELENIUM_VERSION.minor >= 8:
-            when(webdriver).Chrome(desired_capabilities=caps,
-                                   options=None).thenReturn(browser)
-        else:
-            when(webdriver).Chrome(desired_capabilities=caps).thenReturn(browser)
+        when(webdriver).Chrome(options=None).thenReturn(browser)
         bm = BrowserManagementKeywords(ctx)
         bm.open_browser('http://robotframework.org/', 'chrome')
         self.assertEqual(browser._speed, 5.0)
@@ -74,12 +69,7 @@ class BrowserManagementTests(unittest.TestCase):
         ctx = mock()
         ctx.speed = 0.0
         browser = mock()
-        caps = webdriver.DesiredCapabilities.CHROME
-        if SELENIUM_VERSION.major >= 3 and SELENIUM_VERSION.minor >= 8:
-            when(webdriver).Chrome(desired_capabilities=caps,
-                                   options=None).thenReturn(browser)
-        else:
-            when(webdriver).Chrome(desired_capabilities=caps).thenReturn(browser)
+        when(webdriver).Chrome(options=None).thenReturn(browser)
         bm = BrowserManagementKeywords(ctx)
         bm.open_browser('http://robotframework.org/', 'chrome')
         verify(browser, times=0).__call__('_speed')
diff --git a/utest/test/keywords/test_webdrivercreator.py b/utest/test/keywords/test_webdrivercreator.py
index d19e9e3c..7d7bea45 100644
--- a/utest/test/keywords/test_webdrivercreator.py
+++ b/utest/test/keywords/test_webdrivercreator.py
@@ -4,7 +4,6 @@ import unittest
 from mockito import mock, verify, when, unstub
 from selenium import webdriver
 
-from SeleniumLibrary.utils import SELENIUM_VERSION
 from SeleniumLibrary.keywords import WebDriverCreator
 
 
@@ -33,17 +32,31 @@ class WebDriverCreatorTests(unittest.TestCase):
 
     def test_parse_capabilities(self):
         caps = self.creator._parse_capabilities('key1:value1,key2:value2')
-        expected = {'key1': 'value1', 'key2': 'value2'}
+        expected = {'desired_capabilities': {'key1': 'value1', 'key2': 'value2'}}
+        self.assertDictEqual(caps, expected)
+
+        caps = self.creator._parse_capabilities('key1:value1,key2:value2', 'ie')
+        expected = {'capabilities': {'key1': 'value1', 'key2': 'value2'}}
+        self.assertDictEqual(caps, expected)
+
+        caps = self.creator._parse_capabilities('key1:value1,key2:value2', 'firefox')
+        self.assertDictEqual(caps, expected)
+
+        caps = self.creator._parse_capabilities('key1:value1,key2:value2', 'ff')
+        self.assertDictEqual(caps, expected)
+
+        caps = self.creator._parse_capabilities('key1:value1,key2:value2', 'edge')
         self.assertDictEqual(caps, expected)
 
         caps = self.creator._parse_capabilities(expected)
         self.assertDictEqual(caps, expected)
 
         caps = self.creator._parse_capabilities('key1 : value1 , key2: value2')
+        expected = {'desired_capabilities': {'key1': 'value1', 'key2': 'value2'}}
         self.assertDictEqual(caps, expected)
 
         caps = self.creator._parse_capabilities(' key 1 : value 1 , key2:value2')
-        expected = {'key 1': 'value 1', 'key2': 'value2'}
+        expected = {'desired_capabilities': {'key 1': 'value 1', 'key2': 'value2'}}
         self.assertDictEqual(caps, expected)
 
         caps = self.creator._parse_capabilities('')
@@ -54,43 +67,41 @@ class WebDriverCreatorTests(unittest.TestCase):
 
     def test_chrome(self):
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.CHROME
-        when(webdriver).Chrome(desired_capabilities=caps,
-                               options=None).thenReturn(expected_webdriver)
+        when(webdriver).Chrome(options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_chrome({}, None)
         self.assertEqual(driver, expected_webdriver)
 
+    def test_chrome_with_desired_capabilities(self):
+        expected_webdriver = mock()
+        when(webdriver).Chrome(desired_capabilities={'key': 'value'}, options=None).thenReturn(expected_webdriver)
+        driver = self.creator.create_chrome({'desired_capabilities': {'key': 'value'}}, None)
+        self.assertEqual(driver, expected_webdriver)
+
     def test_chrome_remote(self):
         url = 'http://localhost:4444/wd/hub'
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.CHROME
         when(webdriver).Remote(command_executor=url,
-                               desired_capabilities=caps,
                                browser_profile=None,
                                options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_chrome({}, url)
         self.assertEqual(driver, expected_webdriver)
 
     def test_chrome_healdless(self):
-        caps = webdriver.DesiredCapabilities.CHROME
         expected_webdriver = mock()
         options = mock()
         when(webdriver).ChromeOptions().thenReturn(options)
-        when(webdriver).Chrome(desired_capabilities=caps,
-                               options=options).thenReturn(expected_webdriver)
+        when(webdriver).Chrome(options=options).thenReturn(expected_webdriver)
         driver = self.creator.create_headless_chrome({}, None)
         verify(options).set_headless()
         self.assertEqual(driver, expected_webdriver)
 
     def test_chrome_healdless_with_grid(self):
-        caps = webdriver.DesiredCapabilities.CHROME
         expected_webdriver = mock()
         options = mock()
         when(webdriver).ChromeOptions().thenReturn(options)
         remote_url = 'localhost:4444'
         when(webdriver).Remote(command_executor=remote_url,
-                               desired_capabilities=caps, options=options,
-                               browser_profile=None,).thenReturn(expected_webdriver)
+                               options=options, browser_profile=None).thenReturn(expected_webdriver)
         driver = self.creator.create_headless_chrome({}, remote_url)
         verify(options).set_headless()
         self.assertEqual(driver, expected_webdriver)
@@ -99,9 +110,8 @@ class WebDriverCreatorTests(unittest.TestCase):
         expected_webdriver = mock()
         profile = mock()
         when(webdriver).FirefoxProfile().thenReturn(profile)
-        caps = webdriver.DesiredCapabilities.FIREFOX
         log_file = self.get_geckodriver_log()
-        when(webdriver).Firefox(capabilities=caps, options=None,
+        when(webdriver).Firefox(options=None,
                                 firefox_profile=profile,
                                 log_path=log_file).thenReturn(expected_webdriver)
         driver = self.creator.create_firefox({}, None, None)
@@ -113,9 +123,7 @@ class WebDriverCreatorTests(unittest.TestCase):
         profile = mock()
         when(webdriver).FirefoxProfile().thenReturn(profile)
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.FIREFOX
         when(webdriver).Remote(command_executor=url,
-                               desired_capabilities=caps,
                                browser_profile=profile,
                                options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_firefox({}, url, None)
@@ -126,56 +134,58 @@ class WebDriverCreatorTests(unittest.TestCase):
         profile = mock()
         profile_dir = '/profile/dir'
         when(webdriver).FirefoxProfile(profile_dir).thenReturn(profile)
-        caps = webdriver.DesiredCapabilities.FIREFOX
         log_file = self.get_geckodriver_log()
-        when(webdriver).Firefox(capabilities=caps, options=None,
-                                log_path=log_file,
+        when(webdriver).Firefox(options=None, log_path=log_file,
                                 firefox_profile=profile).thenReturn(expected_webdriver)
         driver = self.creator.create_firefox({}, None, profile_dir)
         self.assertEqual(driver, expected_webdriver)
 
     def test_firefox_headless(self):
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.FIREFOX
         profile = mock()
         when(webdriver).FirefoxProfile().thenReturn(profile)
         options = mock()
         when(webdriver).FirefoxOptions().thenReturn(options)
         log_file = self.get_geckodriver_log()
-        when(webdriver).Firefox(capabilities=caps, options=options,
-                                log_path=log_file,
+        when(webdriver).Firefox(options=options, log_path=log_file,
                                 firefox_profile=profile).thenReturn(expected_webdriver)
         driver = self.creator.create_headless_firefox({}, None, None)
         self.assertEqual(driver, expected_webdriver)
 
     def test_firefox_healdless_with_grid(self):
-        caps = webdriver.DesiredCapabilities.FIREFOX
         expected_webdriver = mock()
         options = mock()
         when(webdriver).FirefoxOptions().thenReturn(options)
         profile = mock()
         when(webdriver).FirefoxProfile().thenReturn(profile)
         remote_url = 'localhost:4444'
-        when(webdriver).Remote(command_executor=remote_url,
-                               desired_capabilities=caps, options=options,
+        when(webdriver).Remote(command_executor=remote_url, options=options,
+                               desired_capabilities={'key': 'value'},
                                browser_profile=profile,).thenReturn(expected_webdriver)
-        driver = self.creator.create_headless_firefox({}, remote_url, None)
+        driver = self.creator.create_headless_firefox({'capabilities': {'key': 'value'}}, remote_url, None)
         verify(options).set_headless()
         self.assertEqual(driver, expected_webdriver)
 
+        when(webdriver).Remote(command_executor=remote_url, options=options,
+                               browser_profile=profile, ).thenReturn(expected_webdriver)
+        driver = self.creator.create_headless_firefox({}, remote_url, None)
+        self.assertEqual(driver, expected_webdriver)
+        verify(options, times=2).set_headless()
+
     def test_ie(self):
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.INTERNETEXPLORER
-        when(webdriver).Ie(capabilities=caps).thenReturn(expected_webdriver)
+        when(webdriver).Ie().thenReturn(expected_webdriver)
         driver = self.creator.create_ie({}, None)
         self.assertEqual(driver, expected_webdriver)
 
+        when(webdriver).Ie(capabilities={'key': 'value'}).thenReturn(expected_webdriver)
+        driver = self.creator.create_ie({'capabilities': {'key': 'value'}}, None)
+        self.assertEqual(driver, expected_webdriver)
+
     def test_ie_remote(self):
         url = 'http://localhost:4444/wd/hub'
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.INTERNETEXPLORER
         when(webdriver).Remote(command_executor=url,
-                               desired_capabilities=caps,
                                browser_profile=None,
                                options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_ie({}, url)
@@ -183,17 +193,14 @@ class WebDriverCreatorTests(unittest.TestCase):
 
     def test_edge(self):
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.EDGE
-        when(webdriver).Edge(capabilities=caps).thenReturn(expected_webdriver)
+        when(webdriver).Edge().thenReturn(expected_webdriver)
         driver = self.creator.create_edge({}, None)
         self.assertEqual(driver, expected_webdriver)
 
     def test_edge_remote(self):
         url = 'http://localhost:4444/wd/hub'
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.EDGE
         when(webdriver).Remote(command_executor=url,
-                               desired_capabilities=caps,
                                browser_profile=None,
                                options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_edge({}, url)
@@ -201,17 +208,14 @@ class WebDriverCreatorTests(unittest.TestCase):
 
     def test_opera(self):
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.OPERA
-        when(webdriver).Opera(desired_capabilities=caps).thenReturn(expected_webdriver)
+        when(webdriver).Opera().thenReturn(expected_webdriver)
         driver = self.creator.create_opera({}, None)
         self.assertEqual(driver, expected_webdriver)
 
     def test_opera_remote(self):
         url = 'http://localhost:4444/wd/hub'
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.OPERA
         when(webdriver).Remote(command_executor=url,
-                               desired_capabilities=caps,
                                browser_profile=None,
                                options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_opera({}, url)
@@ -219,17 +223,14 @@ class WebDriverCreatorTests(unittest.TestCase):
 
     def test_safari(self):
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.SAFARI
-        when(webdriver).Safari(desired_capabilities=caps).thenReturn(expected_webdriver)
+        when(webdriver).Safari().thenReturn(expected_webdriver)
         driver = self.creator.create_safari({}, None)
         self.assertEqual(driver, expected_webdriver)
 
     def test_safari_remote(self):
         url = 'http://localhost:4444/wd/hub'
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.SAFARI
         when(webdriver).Remote(command_executor=url,
-                               desired_capabilities=caps,
                                browser_profile=None,
                                options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_safari({}, url)
@@ -237,17 +238,14 @@ class WebDriverCreatorTests(unittest.TestCase):
 
     def test_phantomjs(self):
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.PHANTOMJS
-        when(webdriver).PhantomJS(desired_capabilities=caps).thenReturn(expected_webdriver)
+        when(webdriver).PhantomJS().thenReturn(expected_webdriver)
         driver = self.creator.create_phantomjs({}, None)
         self.assertEqual(driver, expected_webdriver)
 
     def test_phantomjs_remote(self):
         url = 'http://localhost:4444/wd/hub'
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.PHANTOMJS
         when(webdriver).Remote(command_executor=url,
-                               desired_capabilities=caps,
                                browser_profile=None,
                                options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_phantomjs({}, url)
@@ -255,9 +253,7 @@ class WebDriverCreatorTests(unittest.TestCase):
 
     def test_htmlunit(self):
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.HTMLUNIT
         when(webdriver).Remote(command_executor='None',
-                               desired_capabilities=caps,
                                browser_profile=None,
                                options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_htmlunit({}, None)
@@ -265,9 +261,7 @@ class WebDriverCreatorTests(unittest.TestCase):
 
     def test_htmlunit_with_js(self):
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.HTMLUNITWITHJS
         when(webdriver).Remote(command_executor='None',
-                               desired_capabilities=caps,
                                browser_profile=None,
                                options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_htmlunit_with_js({}, None)
@@ -275,9 +269,7 @@ class WebDriverCreatorTests(unittest.TestCase):
 
     def test_android(self):
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.ANDROID
         when(webdriver).Remote(command_executor='None',
-                               desired_capabilities=caps,
                                browser_profile=None,
                                options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_android({}, None)
@@ -285,9 +277,7 @@ class WebDriverCreatorTests(unittest.TestCase):
 
     def test_iphone(self):
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.IPHONE
         when(webdriver).Remote(command_executor='None',
-                               desired_capabilities=caps,
                                browser_profile=None,
                                options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_iphone({}, None)
@@ -295,9 +285,7 @@ class WebDriverCreatorTests(unittest.TestCase):
 
     def test_create_driver_chrome(self):
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.CHROME
-        when(webdriver).Chrome(desired_capabilities=caps,
-                                   options=None).thenReturn(expected_webdriver)
+        when(webdriver).Chrome(options=None).thenReturn(expected_webdriver)
         for browser in ['chrome', 'googlechrome', 'gc']:
             driver = self.creator.create_driver(browser, None, None)
             self.assertEqual(driver, expected_webdriver)
@@ -306,10 +294,8 @@ class WebDriverCreatorTests(unittest.TestCase):
         expected_webdriver = mock()
         profile = mock()
         when(webdriver).FirefoxProfile().thenReturn(profile)
-        caps = webdriver.DesiredCapabilities.FIREFOX
         log_file = self.get_geckodriver_log()
-        when(webdriver).Firefox(capabilities=caps, options=None,
-                                log_path=log_file,
+        when(webdriver).Firefox(options=None, log_path=log_file,
                                 firefox_profile=profile).thenReturn(expected_webdriver)
         for browser in ['ff', 'firefox']:
             driver = self.creator.create_driver(browser, None, None, None)
@@ -317,31 +303,10 @@ class WebDriverCreatorTests(unittest.TestCase):
 
     def test_create_driver_ie(self):
         expected_webdriver = mock()
-        caps = webdriver.DesiredCapabilities.INTERNETEXPLORER
-        when(webdriver).Ie(capabilities=caps).thenReturn(expected_webdriver)
+        when(webdriver).Ie().thenReturn(expected_webdriver)
         for browser in ['ie', 'Internet Explorer']:
             driver = self.creator.create_driver(browser, None, None)
             self.assertEqual(driver, expected_webdriver)
 
-    def test_combine_capabilites(self):
-        default = webdriver.DesiredCapabilities.CHROME.copy()
-        user = {'platform': 'Linux'}
-        combined = self.creator._combine_capabilites(default, user)
-        expected = default.copy()
-        expected['platform'] = 'Linux'
-        self.assertDictEqual(combined, expected)
-
-        combined = self.creator._combine_capabilites(default, {})
-        self.assertDictEqual(combined, default)
-
-        combined = self.creator._combine_capabilites({}, {})
-        self.assertDictEqual(combined, {})
-
-        with self.assertRaises(AttributeError):
-            self.creator._combine_capabilites('foo', 'bar')
-
-        with self.assertRaises(ValueError):
-            self.creator._combine_capabilites({}, 'bar')
-
     def get_geckodriver_log(self):
         return os.path.join(self.log_dir, 'geckodriver.log')