Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Chrome options property to add additional config #327

Merged
merged 1 commit into from
Apr 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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