Skip to content

Commit

Permalink
feat: add Chrome options property to add additional config (#327)
Browse files Browse the repository at this point in the history
  • Loading branch information
rgonalo committed Apr 3, 2023
1 parent ffde0b0 commit 3c78cfb
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 61 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ v3.0.0
- Now `gecko_driver_path`, `chrome_driver_path`, `explorer_driver_path` and `edge_driver_path` config properties
in [Driver] section are optional, due to new SeleniumManager feature, that downloads drivers automatically
- New optional config property `safari_driver_path` in [Driver] section to configure Safari driver
- New optional config property `options` in [Chromer] section to configure Chrome options instead of using old
property `goog:chromeOptions` in [Capabilities] section.
- Update [RANDOM_PHONE_NUMBER] replacement using new `DataGenerator` class

v2.7.0
Expand Down
43 changes: 13 additions & 30 deletions docs/browser_configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,17 +117,6 @@ For example, to open firefox in a private browsing mode::
Chrome
~~~~~~

**Chrome section**

When Chrome is installed in a non-default location, configure the Chrome binary path in *[Chrome]* configuration
section::

[Driver]
type: chrome

[Chrome]
binary: /usr/local/chrome_beta/chrome

**ChromePreferences section**

To configure `Chrome preferences <https://cs.chromium.org/chromium/src/chrome/common/pref_names.cc>`_, create a
Expand Down Expand Up @@ -194,32 +183,26 @@ replacing ':' with '___' in the key name::

[Capabilities]
goog___loggingPrefs: {'performance': 'ALL', 'browser': 'ALL', 'driver': 'ALL'}
goog___chromeOptions: {'excludeSwitches': ['enable-automation'], 'useAutomationExtension': False}

In fact, all the settings in above Chrome sections can be also configured in *goog___chromeOptions*:

- Chrome section::

[Capabilities]
goog___chromeOptions: {'binary': '/usr/local/chrome_beta/chrome'}

- ChromePreferences section::
**Chrome section**

[Capabilities]
goog___chromeOptions: {'prefs': {'download.default_directory': 'C:\tmp'}}
Additional `Chrome Options <https://chromedriver.chromium.org/capabilities#h.p_ID_102>`_ can be configured in
*[Chrome]* configuration section::

- ChromeArguments section::
[Driver]
type: chrome

[Capabilities]
goog___chromeOptions: {'args': {'user-data-dir': 'C:\Users\USERNAME\AppData\Local\Google\Chrome\User Data'}}
[Chrome]
options: {'excludeSwitches': ['enable-automation'], 'perfLoggingPrefs': {'enableNetwork': True}}

- ChromeMobileEmulation section::
When Chrome is installed in a non-default location, configure the Chrome binary path in *[Chrome]* configuration
section::

[Capabilities]
goog___chromeOptions: {'mobileEmulation': {'deviceName': 'Google Nexus 5'}}
[Driver]
type: chrome

In case of defining the same setting both in its dedicated section and in the capabilities section, the dedicated
section value will be used.
[Chrome]
binary: /usr/local/chrome_beta/chrome

Driver Download
---------------
Expand Down
23 changes: 15 additions & 8 deletions docs/tests_result_analysis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ nose, pytest, behave, ...). But Toolium provides some useful features to analyze
Logs
----

Toolium internal logs are written in *output/toolium.log*. Your tests logs can be also written in the same file using the
already existing logger instance:
Toolium internal logs are written in *output/toolium.log*. Your tests logs can be also written in the same file using
the already existing logger instance:

.. code-block:: python
Expand Down Expand Up @@ -62,24 +62,31 @@ the driver type, the webdriver will contain different log types, for instance, *
*performance*, *profiler*, *logcat*, *bugreport*, etc.

By default, when a test fails, toolium will download all log types available in current webdriver. But it can be also
configured to download only a set of log types setting the property `log_types <https://toolium.readthedocs.io/en/latest/remote_configuration.html#log-types>`_
in *[Server]* section in properties.cfg file ::
configured to download only a set of log types setting the property
`log_types <https://toolium.readthedocs.io/en/latest/remote_configuration.html#log-types>`_ in *[Server]* section in
properties.cfg file ::

[Server]
log_types: client,server

Notice that if using Chrome, log types can be enabled in *capabilities* section ::
Notice that if using Chrome, log types can be enabled in *[Capabilities]* section and performance log can be configured
in *[Chrome]* section::

[Capabilities]
goog___loggingPrefs: {'browser':'ALL', 'driver': 'ALL', 'performance': 'ALL'}

Also take into account that, to enable logs in GGR, the following capability must be configured ::
[Chrome]
options: {'perfLoggingPrefs': {'enableNetwork': True}}

Also take into account that, to enable logs in GGR, the following capability must be configured in *[Capabilities]*
section ::

[Capabilities]
selenoid___options: {'enableLog': True}

In order to download webdriver logs even if the test passes, configure the property `logs_enabled <https://toolium.readthedocs.io/en/latest/remote_configuration.html#logs-enabled>`_
in *[Server]* section in properties.cfg file ::
In order to download webdriver logs even if the test passes, configure the property
`logs_enabled <https://toolium.readthedocs.io/en/latest/remote_configuration.html#logs-enabled>`_ in *[Server]* section
in properties.cfg file ::

[Server]
logs_enabled: true
2 changes: 1 addition & 1 deletion docs/visual_testing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ Toolium properties related to Visual Testing are stored in properties.cfg as ::
| Some examples of baseline_name values are:
- *{Driver_type}*: depending on the value of *type* property, baseline_name might take one of these values: firefox, iexplore, chrome... This is the value by default.
- *{Driver_type}-{Capabilities_version}-{Capabilities_platform}*: baseline_name might take one of these values: iexplore-11-WIN8, safari-9.0-YOSEMITE...
- *{Driver_type}-{Capabilities_browserVersion}-{Capabilities_platformName}*: baseline_name might take one of these values: iexplore-11-windows, safari-9.0-mac...
- *{AppiumCapabilities_deviceName}-{AppiumCapabilities_platformVersion}*: baseline_name might take one of these values: iPhone_6-8.3, iPhone_6-9.1, iPhone_6s-9.1...
- *{PlatformVersion}*: baseline_name will take the value of the mobile platform version, instead of the platformVersion configuration property
- *{Version}*: baseline_name will take the value of version capability, although it is not configured
Expand Down
21 changes: 19 additions & 2 deletions toolium/config_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ def _get_chrome_options(self, capabilities={}):
# Add Chrome preferences, arguments, extensions and mobile emulation options
self._add_chrome_options(options, 'prefs')
self._add_chrome_options(options, 'mobileEmulation')
self._add_chrome_additional_options(options)
self._add_chrome_arguments(options)
self._add_chrome_extensions(options)

Expand All @@ -364,8 +365,10 @@ def _add_chrome_options(self, options, option_name):
:param options: Chrome options object
:param option_name: Chrome option name
"""
options_conf = {'prefs': {'section': 'ChromePreferences', 'message': 'preference'},
'mobileEmulation': {'section': 'ChromeMobileEmulation', 'message': 'mobile emulation option'}}
options_conf = {
'prefs': {'section': 'ChromePreferences', 'message': 'preference'},
'mobileEmulation': {'section': 'ChromeMobileEmulation', 'message': 'mobile emulation option'}
}
option_value = dict()
try:
for key, value in dict(self.config.items(options_conf[option_name]['section'])).items():
Expand All @@ -376,6 +379,20 @@ def _add_chrome_options(self, options, option_name):
except NoSectionError:
pass

def _add_chrome_additional_options(self, options):
"""Add Chrome additional options from properties file
:param options: Chrome options object
"""
chrome_options = self.config.get_optional('Chrome', 'options')
if options:
try:
for key, value in ast.literal_eval(chrome_options).items():
self.logger.debug("Added Chrome additional option: %s = %s", key, value)
options.add_experimental_option(key, value)
except Exception as exc:
self.logger.warning(f'Chrome options "{chrome_options}" can not be added: {exc}')

def _add_chrome_arguments(self, options):
"""Add Chrome arguments from properties file
Expand Down
4 changes: 2 additions & 2 deletions toolium/config_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,9 +173,9 @@ def get_config_from_file(conf_properties_files):

# Overwrite ConfigParser methods to allow colon in options names
# To set a config property with colon in name
# goog:loggingPrefs = "{'performance': 'ALL', 'browser': 'ALL', 'driver': 'ALL'}"
# selenoid:options = "{'enableVideo': True}"
# configure properties.cfg with:
# goog___loggingPrefs: {'performance': 'ALL', 'browser': 'ALL', 'driver': 'ALL'}
# selenoid___options: {'enableVideo': True}

def _encode_option(self, option):
return option.replace(':', '___')
Expand Down
4 changes: 2 additions & 2 deletions toolium/test/conf/properties.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ complete_report: true
baseline_name: {Driver_type}

[Capabilities]
goog___loggingPrefs: {'performance': 'ALL', 'browser': 'ALL', 'driver': 'ALL'}
goog___chromeOptions: {'excludeSwitches': ['enable-automation'], 'useAutomationExtension': False}
selenoid___options: {'enableVNC': True, 'enableVideo': True}
cloud___options: {'name': 'test'}

[AppiumCapabilities]
automationName: Appium
Expand Down
23 changes: 23 additions & 0 deletions toolium/test/test_config_driver_chrome.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,29 @@ def test_get_chrome_options_binary(config, utils):
assert options.binary_location == expected_binary_location


def test_get_chrome_options_additional(config, utils):
config.add_section('Chrome')
config.set('Chrome', 'options',
"{'excludeSwitches': ['enable-automation'], 'perfLoggingPrefs': {'enableNetwork': True}}")
config_driver = ConfigDriver(config, utils)
expected_arguments = []
expected_capabilities = DEFAULT_CAPABILITIES
expected_experimental_options = {
'excludeSwitches': ['enable-automation'],
'perfLoggingPrefs': {'enableNetwork': True}
}
expected_extensions_len = 0
expected_binary_location = ''

options = config_driver._get_chrome_options()

assert options.arguments == expected_arguments
assert options.capabilities == expected_capabilities
assert options.experimental_options == expected_experimental_options
assert len(options.extensions) == expected_extensions_len
assert options.binary_location == expected_binary_location


def test_get_chrome_options_headless(config, utils):
config.set('Driver', 'headless', 'true')
config_driver = ConfigDriver(config, utils)
Expand Down
31 changes: 15 additions & 16 deletions toolium/test/test_config_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,16 @@ def test_get(config):

def test_get_with_colon_in_option(config):
section = 'Capabilities'
option = 'goog:loggingPrefs'
value = "{'performance': 'ALL', 'browser': 'ALL', 'driver': 'ALL'}"
option = 'selenoid:options'
value = "{'enableVNC': True, 'enableVideo': True}"
assert value == config.get(section, option)


def test_set_with_colon_in_option(config):
section = 'Capabilities'
option = 'goog:loggingPrefs'
orig_value = "{'performance': 'ALL', 'browser': 'ALL', 'driver': 'ALL'}"
new_value = "{'performance': 'ALL', 'browser': 'ALL'}"
option = 'selenoid:options'
orig_value = "{'enableVNC': True, 'enableVideo': True}"
new_value = "{'enableVNC': False}"

# Check previous value
assert orig_value == config.get(section, option)
Expand All @@ -121,31 +121,30 @@ def test_set_with_colon_in_option(config):

def test_options_with_colon_in_option(config):
section = 'Capabilities'
options = ['goog:loggingPrefs', 'goog:chromeOptions']
options = ['selenoid:options', 'cloud:options']
assert options == config.options(section)


def test_has_option_with_colon_in_option(config):
section = 'Capabilities'
option = 'goog:loggingPrefs'
wrong_option = 'goog:loggingPrefsWrong'
option = 'selenoid:options'
wrong_option = 'selenoid:optionsWrong'
assert config.has_option(section, option) is True
assert config.has_option(section, wrong_option) is False


def test_remove_option_with_colon_in_option(config):
section = 'Capabilities'
option = 'goog:loggingPrefs'
wrong_option = 'goog:loggingPrefsWrong'
option = 'selenoid:options'
wrong_option = 'selenoid:optionsWrong'
assert config.remove_option(section, option) is True
assert config.remove_option(section, wrong_option) is False
assert config.get_optional(section, option, default=None) is None


def test_items_with_colon_in_option(config):
section = 'Capabilities'
items = [('goog:loggingPrefs', "{'performance': 'ALL', 'browser': 'ALL', 'driver': 'ALL'}"),
('goog:chromeOptions', "{'excludeSwitches': ['enable-automation'], 'useAutomationExtension': False}")]
items = [('selenoid:options', "{'enableVNC': True, 'enableVideo': True}"), ('cloud:options', "{'name': 'test'}")]
assert items == config.items(section)


Expand Down Expand Up @@ -175,10 +174,10 @@ def test_deepcopy(config):

def test_deepcopy_and_modify_option_with_colon(config):
section = 'Capabilities'
configured_option = 'goog___loggingPrefs'
option = 'goog:loggingPrefs'
orig_value = "{'performance': 'ALL', 'browser': 'ALL', 'driver': 'ALL'}"
new_value = "{'performance': 'ALL', 'browser': 'ALL'}"
configured_option = 'selenoid___options'
option = 'selenoid:options'
orig_value = "{'enableVNC': True, 'enableVideo': True}"
new_value = "{'enableVNC': False}"

# Check previous value
assert orig_value == config.get(section, option)
Expand Down

0 comments on commit 3c78cfb

Please sign in to comment.