Skip to content

Commit 032e371

Browse files
authored
Selenium options in Open Browser keyword (robotframework#1393)
Adds support for Selenium options in Open Browser keyword.
1 parent f09b365 commit 032e371

15 files changed

+736
-58
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
*** Settings ***
2+
Suite Teardown Close All Browsers
3+
Library ../resources/testlibs/get_selenium_options.py
4+
Resource resource.robot
5+
Documentation Creating test which would work on all browser is not possible. When testing with other
6+
... browser than Chrome it is OK that these test will fail. SeleniumLibrary CI is run with Chrome only
7+
... and therefore there is tests for Chrome only.
8+
9+
*** Test Cases ***
10+
Chrome Browser With Selenium Options As String
11+
[Documentation]
12+
... LOG 1:2 DEBUG GLOB: *"goog:chromeOptions"*
13+
... LOG 1:2 DEBUG GLOB: *args": ["--disable-dev-shm-usage"?*
14+
Open Browser ${FRONT PAGE} ${BROWSER} remote_url=${REMOTE_URL}
15+
... desired_capabilities=${DESIRED_CAPABILITIES} options=add_argument("--disable-dev-shm-usage")
16+
17+
Chrome Browser With Selenium Options As String With Attirbute As True
18+
[Documentation]
19+
... LOG 1:2 DEBUG GLOB: *"goog:chromeOptions"*
20+
... LOG 1:2 DEBUG GLOB: *args": ["--disable-dev-shm-usage"?*
21+
... LOG 1:2 DEBUG GLOB: *"--headless"*
22+
Open Browser ${FRONT PAGE} ${BROWSER} remote_url=${REMOTE_URL}
23+
... desired_capabilities=${DESIRED_CAPABILITIES} options=add_argument ( "--disable-dev-shm-usage" ) ; headless = True
24+
25+
Chrome Browser With Selenium Options Object
26+
[Documentation]
27+
... LOG 2:2 DEBUG GLOB: *"goog:chromeOptions"*
28+
... LOG 2:2 DEBUG GLOB: *args": ["--disable-dev-shm-usage"?*
29+
${options} = Get Chrome Options
30+
Open Browser ${FRONT PAGE} ${BROWSER} remote_url=${REMOTE_URL}
31+
... desired_capabilities=${DESIRED_CAPABILITIES} options=${options}
32+
33+
Chrome Browser With Selenium Options Invalid Method
34+
Run Keyword And Expect Error AttributeError: 'Options' object has no attribute 'not_here_method'
35+
... Open Browser ${FRONT PAGE} ${BROWSER} remote_url=${REMOTE_URL}
36+
... desired_capabilities=${DESIRED_CAPABILITIES} options=not_here_method("arg1")
37+
38+
39+
Chrome Browser With Selenium Options Argument With Semicolon
40+
[Documentation]
41+
... LOG 1:2 DEBUG GLOB: *"goog:chromeOptions"*
42+
... LOG 1:2 DEBUG GLOB: *["has;semicolon"*
43+
Open Browser ${FRONT PAGE} ${BROWSER} remote_url=${REMOTE_URL}
44+
... desired_capabilities=${DESIRED_CAPABILITIES} options=add_argument("has;semicolon")
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from selenium import webdriver
2+
3+
4+
def get_chrome_options():
5+
options = webdriver.ChromeOptions()
6+
options.add_argument('--disable-dev-shm-usage')
7+
return options

src/SeleniumLibrary/keywords/browsermanagement.py

Lines changed: 84 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def close_browser(self):
5858
@keyword
5959
def open_browser(self, url, browser='firefox', alias=None,
6060
remote_url=False, desired_capabilities=None,
61-
ff_profile_dir=None, service_log_path=None):
61+
ff_profile_dir=None, options=None, service_log_path=None):
6262
"""Opens a new browser instance to the given ``url``.
6363
6464
The ``browser`` argument specifies which browser to use, and the
@@ -119,6 +119,71 @@ def open_browser(self, url, browser='firefox', alias=None,
119119
``ff_profile_dir`` can also be instance of the
120120
[https://seleniumhq.github.io/selenium/docs/api/py/webdriver_firefox/selenium.webdriver.firefox.firefox_profile.html?highlight=firefoxprofile#selenium.webdriver.firefox.firefox_profile.FirefoxProfile|selenium.webdriver.FirefoxProfile].
121121
122+
Optional ``options`` argument allows to define browser specific
123+
Selenium options. Example for Chrome, the ``options`` argument
124+
allows defining the following
125+
[https://seleniumhq.github.io/selenium/docs/api/py/webdriver_chrome/selenium.webdriver.chrome.options.html#selenium.webdriver.chrome.options.Options|methods and attributes]
126+
and for Firefox these
127+
[https://seleniumhq.github.io/selenium/docs/api/py/webdriver_firefox/selenium.webdriver.firefox.options.html?highlight=firefox#selenium.webdriver.firefox.options.Options|methods and attributes]
128+
are available. Please note that not all browsers supported by the
129+
SeleniumLibrary have Selenium options available. Therefore please
130+
consult the Selenium documentation which browsers do support
131+
the Selenium options. If ``browser`` argument is `android` then
132+
[https://seleniumhq.github.io/selenium/docs/api/py/webdriver_chrome/selenium.webdriver.chrome.options.html#selenium.webdriver.chrome.options.Options|Chrome options]
133+
is used. Selenium options are also supported, when ``remote_url``
134+
argument is used.
135+
136+
The SeleniumLibrary ``options`` argument accepts Selenium
137+
options in two different formats: as a string and as Python object
138+
which is an instance of the Selenium options class.
139+
140+
The string format allows to define Selenium options methods
141+
or attributes and their arguments in Robot Framework test data.
142+
The method and attributes names are case and space sensitive and
143+
must match to the Selenium options methods and attributes names.
144+
When defining a method, is must defined in similar way as in
145+
python: method name, opening parenthesis, zero to many arguments
146+
and closing parenthesis. If there is need to define multiple
147+
arguments for a single method, arguments must be separated with
148+
comma, just like in Python. Example: `add_argument("--headless")`
149+
or `add_experimental_option("key", "value")`. Attributes are
150+
defined in similar way as in Python: attribute name, equal sing
151+
and attribute value. Example, `headless=True`. Multiple methods
152+
and attributes must separated by a semicolon, example:
153+
`add_argument("--headless");add_argument("--start-maximized")`.
154+
155+
Arguments allow defining Python data types and arguments are
156+
evaluated by using Python
157+
[https://docs.python.org/3/library/ast.html#ast.literal_eval|ast.literal_eval].
158+
Strings must be quoted with single or double quotes, example "value"
159+
or 'value'. It is also possible define other Python builtin
160+
data types, example `True` or `None`, by not using quotes
161+
around the arguments.
162+
163+
The string format is space friendly and usually spaces do not alter
164+
the defining the methods or attributes. There are two exceptions.
165+
In some Robot Framework test data formats, two or more spaces are
166+
considered as cell separator and instead of defining a single
167+
argument, two or more arguments may be defined. Spaces in string
168+
arguments are not removed and are left as is. Example
169+
`add_argument ( "--headless" )` is same as
170+
`add_argument("--headless")`. But `add_argument(" --headless ")` is
171+
not same same as `add_argument ( "--headless" )`, because
172+
spaces inside of quotes are not removed.
173+
174+
As last format ``options`` argument also support receiving
175+
the Selenium options as Python class instance. In this case, the
176+
instance is used as is and the SeleniumLibrary will not convert
177+
the instance to other formats.
178+
For example, if the following code return value is saved to
179+
`${options}` variable in the Robot Framework data:
180+
| options = webdriver.ChromeOptions()
181+
| options.add_argument('--disable-dev-shm-usage')
182+
| return options
183+
184+
Then the `${options}` variable can be used as argument to
185+
``options``.
186+
122187
Optional ``service_log_path`` argument defines the name of the
123188
file where to write the browser driver logs. If the
124189
``service_log_path`` argument contain a marker ``{index}``, it
@@ -142,6 +207,13 @@ def open_browser(self, url, browser='firefox', alias=None,
142207
| Should Be Equal | ${1_index} | ${4_index} | | | |
143208
| Should Be Equal | ${2_index} | ${2} | | | |
144209
210+
Example when using
211+
[https://seleniumhq.github.io/selenium/docs/api/py/webdriver_chrome/selenium.webdriver.chrome.options.html#selenium.webdriver.chrome.options.Options|Chrome options]
212+
method:
213+
| `Open Browser` | http://example.com | Chrome | options=add_argument("--disable-popup-blocking"); add_argument("--ignore-certificate-errors") | # Sting format |
214+
| ${options} = | Get Options | | | # Selenium options instance |
215+
| `Open Browser` | http://example.com | Chrome | options=${options 2} | |
216+
145217
If the provided configuration options are not enough, it is possible
146218
to use `Create Webdriver` to customize browser initialization even
147219
more.
@@ -150,10 +222,10 @@ def open_browser(self, url, browser='firefox', alias=None,
150222
new in SeleniumLibrary 3.1.
151223
152224
Using ``alias`` to decide, is the new browser opened is new
153-
in SeleniumLibrary 4.0. Also the ``service_log_path`` is new
154-
in SeleniumLibrary 4.0. Support for ``ff_profile_dir`` accepting
155-
instance of the `selenium.webdriver.FirefoxProfile` is new in
156-
SeleniumLibrary 4.0.
225+
in SeleniumLibrary 4.0. The ``options`` and ``service_log_path``
226+
are new in SeleniumLibrary 4.0. Support for ``ff_profile_dir``
227+
accepting instance of the `selenium.webdriver.FirefoxProfile`
228+
is new in SeleniumLibrary 4.0.
157229
"""
158230
index = self.drivers.get_index(alias)
159231
if index:
@@ -163,19 +235,19 @@ def open_browser(self, url, browser='firefox', alias=None,
163235
return index
164236
return self._make_new_browser(url, browser, alias, remote_url,
165237
desired_capabilities, ff_profile_dir,
166-
service_log_path)
238+
options, service_log_path)
167239

168240
def _make_new_browser(self, url, browser='firefox', alias=None,
169241
remote_url=False, desired_capabilities=None,
170-
ff_profile_dir=None, service_log_path=None):
242+
ff_profile_dir=None, options=None, service_log_path=None):
171243
if is_truthy(remote_url):
172244
self.info("Opening browser '%s' to base url '%s' through "
173245
"remote server at '%s'." % (browser, url, remote_url))
174246
else:
175247
self.info("Opening browser '%s' to base url '%s'." % (browser, url))
176248
driver = self._make_driver(browser, desired_capabilities,
177249
ff_profile_dir, remote_url,
178-
service_log_path)
250+
options, service_log_path)
179251
driver = self._wrap_event_firing_webdriver(driver)
180252
try:
181253
driver.get(url)
@@ -504,11 +576,11 @@ def set_browser_implicit_wait(self, value):
504576
"""
505577
self.driver.implicitly_wait(timestr_to_secs(value))
506578

507-
def _make_driver(self, browser, desired_capabilities=None,
508-
profile_dir=None, remote=None, service_log_path=None):
579+
def _make_driver(self, browser, desired_capabilities=None, profile_dir=None,
580+
remote=None, options=None, service_log_path=None):
509581
driver = WebDriverCreator(self.log_dir).create_driver(
510-
browser=browser, desired_capabilities=desired_capabilities,
511-
remote_url=remote, profile_dir=profile_dir, service_log_path=service_log_path)
582+
browser=browser, desired_capabilities=desired_capabilities, remote_url=remote,
583+
profile_dir=profile_dir, options=options, service_log_path=service_log_path)
512584
driver.set_script_timeout(self.ctx.timeout)
513585
driver.implicitly_wait(self.ctx.implicit_wait)
514586
if self.ctx.speed:

0 commit comments

Comments
 (0)