Repository: robotframework/SeleniumLibrary

Issue:
Headless Firefox and Chrome not working over selenium grid
 I was trying to run headless firefox with custom firefox profile over a selenium grid, But the browser does not open is headless mode.  It opens in the GUI mode

Launch Firefox Grid
    Set Download Directory
    ${profile path}=  set_firefox_profile  ${DOWNLOAD_DIR}
    log  ${profile path}
    ${dict}    Create Dictionary    seleniumProtocol=WebDriver  maxInstances=5  environment=firefox
    Open Browser  about:blank  headlessfirefox  None  http://192.168.99.100:4444/wd/hub    desired_capabilities=${dict}  ff_profile_dir=${profile path}
    Maximize Browser Window

The firefox profile was created like this:
`def set_firefox_profile(download_dir):
    fp = FirefoxProfile()
    fp.set_preference("browser.download.folderList", 2)
    fp.set_preference("browser.download.manager.showWhenStarting", False)
    fp.set_preference("browser.download.dir", download_dir)
    fp.set_preference("browser.manager.closeWhenDone", True)
    fp.set_preference("browser.download.manager.showAlertOnComplete", False)
    fp.set_preference("browser.helperApps.neverAsk.saveToDisk", "text/plan")
    fp.update_preferences()
    return fp.path`

I have 3.11.0 version of selenium and 3.1.1 version of SeleniumLibrary in my environment



Discussion:

Patch:
diff --git a/src/SeleniumLibrary/keywords/webdrivertools.py b/src/SeleniumLibrary/keywords/webdrivertools.py
index f5969526..3aa14dc8 100644
--- a/src/SeleniumLibrary/keywords/webdrivertools.py
+++ b/src/SeleniumLibrary/keywords/webdrivertools.py
@@ -77,7 +77,8 @@ class WebDriverCreator(object):
     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)
+            return self._remote(default, desired_capabilities, remote_url,
+                                options=options)
         capabilities = self._combine_capabilites(default, desired_capabilities)
         if SELENIUM_VERSION.major >= 3 and SELENIUM_VERSION.minor >= 8:
             return webdriver.Chrome(desired_capabilities=capabilities,
@@ -97,7 +98,8 @@ class WebDriverCreator(object):
         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, profile)
+            return self._remote(default, desired_capabilities, remote_url,
+                                profile, options)
         capabilities = self._combine_capabilites(default, desired_capabilities)
         if SELENIUM_VERSION.major >= 3 and SELENIUM_VERSION.minor >= 8:
             return webdriver.Firefox(capabilities=capabilities, options=options,
@@ -180,10 +182,14 @@ class WebDriverCreator(object):
         return self._remote(default, desired_capabilities, remote_url)
 
     def _remote(self, default_capabilities, user_capabilities, remote_url,
-                profile_dir=None):
+                profile_dir=None, options=None):
         remote_url = str(remote_url)
         capabilities = self._combine_capabilites(default_capabilities,
                                                  user_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)
         return webdriver.Remote(command_executor=remote_url,
                                 desired_capabilities=capabilities,
                                 browser_profile=profile_dir)


Test patch:
diff --git a/utest/test/keywords/test_webdrivercreator.py b/utest/test/keywords/test_webdrivercreator.py
index c59ad757..e37b2274 100644
--- a/utest/test/keywords/test_webdrivercreator.py
+++ b/utest/test/keywords/test_webdrivercreator.py
@@ -69,7 +69,8 @@ class WebDriverCreatorTests(unittest.TestCase):
         caps = webdriver.DesiredCapabilities.CHROME
         when(webdriver).Remote(command_executor=url,
                                desired_capabilities=caps,
-                               browser_profile=None).thenReturn(expected_webdriver)
+                               browser_profile=None,
+                               options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_chrome({}, url)
         self.assertEqual(driver, expected_webdriver)
 
@@ -90,6 +91,19 @@ class WebDriverCreatorTests(unittest.TestCase):
             verify(options, times=0).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)
+        driver = self.creator.create_headless_chrome({}, remote_url)
+        verify(options).set_headless()
+        self.assertEqual(driver, expected_webdriver)
+
     def test_firefox(self):
         expected_webdriver = mock()
         profile = mock()
@@ -116,7 +130,8 @@ class WebDriverCreatorTests(unittest.TestCase):
         caps = webdriver.DesiredCapabilities.FIREFOX
         when(webdriver).Remote(command_executor=url,
                                desired_capabilities=caps,
-                               browser_profile=profile).thenReturn(expected_webdriver)
+                               browser_profile=profile,
+                               options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_firefox({}, url, None)
         self.assertEqual(driver, expected_webdriver)
 
@@ -157,6 +172,21 @@ class WebDriverCreatorTests(unittest.TestCase):
         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,
+                               browser_profile=profile,).thenReturn(expected_webdriver)
+        driver = self.creator.create_headless_firefox({}, remote_url, None)
+        verify(options).set_headless()
+        self.assertEqual(driver, expected_webdriver)
+
     def test_ie(self):
         expected_webdriver = mock()
         caps = webdriver.DesiredCapabilities.INTERNETEXPLORER
@@ -170,7 +200,8 @@ class WebDriverCreatorTests(unittest.TestCase):
         caps = webdriver.DesiredCapabilities.INTERNETEXPLORER
         when(webdriver).Remote(command_executor=url,
                                desired_capabilities=caps,
-                               browser_profile=None).thenReturn(expected_webdriver)
+                               browser_profile=None,
+                               options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_ie({}, url)
         self.assertEqual(driver, expected_webdriver)
 
@@ -187,7 +218,8 @@ class WebDriverCreatorTests(unittest.TestCase):
         caps = webdriver.DesiredCapabilities.EDGE
         when(webdriver).Remote(command_executor=url,
                                desired_capabilities=caps,
-                               browser_profile=None).thenReturn(expected_webdriver)
+                               browser_profile=None,
+                               options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_edge({}, url)
         self.assertEqual(driver, expected_webdriver)
 
@@ -204,7 +236,8 @@ class WebDriverCreatorTests(unittest.TestCase):
         caps = webdriver.DesiredCapabilities.OPERA
         when(webdriver).Remote(command_executor=url,
                                desired_capabilities=caps,
-                               browser_profile=None).thenReturn(expected_webdriver)
+                               browser_profile=None,
+                               options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_opera({}, url)
         self.assertEqual(driver, expected_webdriver)
 
@@ -221,7 +254,8 @@ class WebDriverCreatorTests(unittest.TestCase):
         caps = webdriver.DesiredCapabilities.SAFARI
         when(webdriver).Remote(command_executor=url,
                                desired_capabilities=caps,
-                               browser_profile=None).thenReturn(expected_webdriver)
+                               browser_profile=None,
+                               options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_safari({}, url)
         self.assertEqual(driver, expected_webdriver)
 
@@ -238,7 +272,8 @@ class WebDriverCreatorTests(unittest.TestCase):
         caps = webdriver.DesiredCapabilities.PHANTOMJS
         when(webdriver).Remote(command_executor=url,
                                desired_capabilities=caps,
-                               browser_profile=None).thenReturn(expected_webdriver)
+                               browser_profile=None,
+                               options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_phantomjs({}, url)
         self.assertEqual(driver, expected_webdriver)
 
@@ -247,7 +282,8 @@ class WebDriverCreatorTests(unittest.TestCase):
         caps = webdriver.DesiredCapabilities.HTMLUNIT
         when(webdriver).Remote(command_executor='None',
                                desired_capabilities=caps,
-                               browser_profile=None).thenReturn(expected_webdriver)
+                               browser_profile=None,
+                               options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_htmlunit({}, None)
         self.assertEqual(driver, expected_webdriver)
 
@@ -256,7 +292,8 @@ class WebDriverCreatorTests(unittest.TestCase):
         caps = webdriver.DesiredCapabilities.HTMLUNITWITHJS
         when(webdriver).Remote(command_executor='None',
                                desired_capabilities=caps,
-                               browser_profile=None).thenReturn(expected_webdriver)
+                               browser_profile=None,
+                               options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_htmlunit_with_js({}, None)
         self.assertEqual(driver, expected_webdriver)
 
@@ -265,7 +302,8 @@ class WebDriverCreatorTests(unittest.TestCase):
         caps = webdriver.DesiredCapabilities.ANDROID
         when(webdriver).Remote(command_executor='None',
                                desired_capabilities=caps,
-                               browser_profile=None).thenReturn(expected_webdriver)
+                               browser_profile=None,
+                               options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_android({}, None)
         self.assertEqual(driver, expected_webdriver)
 
@@ -274,7 +312,8 @@ class WebDriverCreatorTests(unittest.TestCase):
         caps = webdriver.DesiredCapabilities.IPHONE
         when(webdriver).Remote(command_executor='None',
                                desired_capabilities=caps,
-                               browser_profile=None).thenReturn(expected_webdriver)
+                               browser_profile=None,
+                               options=None).thenReturn(expected_webdriver)
         driver = self.creator.create_iphone({}, None)
         self.assertEqual(driver, expected_webdriver)