Skip to content

Commit

Permalink
documentation fixes (#409)
Browse files Browse the repository at this point in the history
* documentation fixes
  • Loading branch information
cgarmor authored Jan 14, 2025
1 parent 8f3b145 commit 71b4174
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 133 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,8 @@ v1.2.0

| If it's false, the WebElement is searched whenever is needed (default value)
| If it's true, the WebElement is saved in PageElement to avoid searching for the same element multiple times. Useful
in mobile testing when searching for an element can take a long time.
in mobile testing when searching for an element can take a long time.
- New config property 'restart_driver_fail' in [Driver] section to restart the driver when the test fails even though
the value of *reuse_driver* property is *true*
- System property 'Config_environment' is used to select config files, e.g., to read android-properties.cfg file:
Expand Down
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@
# texinfo_no_detailmenu = False

# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'http://docs.python.org/': None}
intersphinx_mapping = {'python': ('https://docs.python.org/3', None)}


def remove_module_docstring(app, what, name, obj, options, lines):
Expand Down
2 changes: 1 addition & 1 deletion docs/page_objects.rst
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ If this default behaviour is not valid for our app (for example has more than on
following optional parameters to define a custom logic that is executed at runtime:

- webview_context_selection_callback: Method provided to select the desired webview context if
automatic_context_selection is enabled. Must return a tuple (context, window_handle) for android, and a context for ios.
automatic_context_selection is enabled. Must return a tuple (context, window_handle) for android, and a context for ios.
- webview_csc_args: arguments list for webview_context_selection_callback.

To use this functionality appium version must be greater or equal to 1.17. (where mobile:getContexts functionality was
Expand Down
2 changes: 1 addition & 1 deletion docs/toolium.utils.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ driver_utils
driver_wait_utils
-----------------

.. automodule:: toolium.utils.driver_utils
.. automodule:: toolium.utils.driver_wait_utils
:members:
:undoc-members:
:show-inheritance:
Expand Down
112 changes: 58 additions & 54 deletions toolium/selenoid.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,62 +132,66 @@ def is_the_session_still_active(self):
"""
Is the GGR session still active? Associated to a browser and the sessionId
Example of GGR status:
{
"browsers": {
"MicrosoftEdge": {
"latest": {}
},
"android": {
"8.1": {}
},
"chrome": {
"70.0": {},
"latest": {
"test_tef": {
"count": 1,
"sessions": [
{
"caps": {
"browserName": "chrome",
"enableVNC": true,
"enableVideo": true,
"platformName": "ANY",
"screenResolution": "1280x1024x24",
'browserVersion': "latest",
"videoName": "selenoide952e551bb9395e16d060f28c54e5d31.mp4",
"videoScreenSize": "1280x1024"
},
"container": "8489205e28c9781472e99c3921a6240de3894a3603ed9e187ad6360b6b013b8b",
"containerInfo": {
"id": "8489205e28c9781472e99c3921a6240de3894a3603ed9e187ad6360b6b013b8b",
"ip": "172.17.0.4"
},
"id": "1345506093dfed8dbcef610da476911a228ca315978e5464ae49fb1142bbc49b",
"screen": "1280x1024x24",
"vnc": true
.. code-block:: json
{
"browsers": {
"MicrosoftEdge": {
"latest": {}
},
"android": {
"8.1": {}
},
"chrome": {
"70.0": {},
"latest": {
"test_tef": {
"count": 1,
"sessions": [
{
"caps": {
"browserName": "chrome",
"enableVNC": true,
"enableVideo": true,
"platformName": "ANY",
"screenResolution": "1280x1024x24",
"browserVersion": "latest",
"videoName": "selenoide952e551bb9395e16d060f28c54e5d31.mp4",
"videoScreenSize": "1280x1024"
},
"container": "8489205e28c9781472e99c3921a6240de3894a3603ed9e187ad6360b6b013b8b",
"containerInfo": {
"id": "8489205e28c9781472e99c3921a6240de3894a3603ed9e187ad6360b6b013b8b",
"ip": "172.17.0.4"
},
"id": "1345506093dfed8dbcef610da476911a228ca315978e5464ae49fb1142bbc49b",
"screen": "1280x1024x24",
"vnc": true
}
]
}
]
}
}
},
"firefox": {
"59.0": {},
"63.0": {},
"64.0": {},
"latest": {}
},
"internet explorer": {
"11": {}
},
"firefox": {
"59.0": {},
"63.0": {},
"64.0": {},
"latest": {}
},
"internet explorer": {
"11": {}
},
"safari": {
"latest": {}
}
},
"safari": {
"latest": {}
"pending": 0,
"queued": 0,
"total": 30,
"used": 1
}
},
"pending": 0,
"queued": 0,
"total": 30,
"used": 1
}
:return boolean (although in case of error in the request will be returned None)
"""
server_url_splitted = self.server_url.split(':')
Expand Down Expand Up @@ -224,7 +228,7 @@ def download_session_video(self, scenario_name, timeout=5):
"""
download the execution video file if the scenario fails or the video is enabled,
renaming the file to scenario name and removing the video file in the server.
GGR request: http://<username>:<password>@<ggr_host>:<ggr_port>/video/<session_id>
GGR request: http://<username>:<password>@<ggr_host>:<ggr_port>/video/<session_id>
selenoid request: http://<username>:<password>@<ggr_host>:<ggr_port>/video/<session_id>.mp4
:param scenario_name: scenario name
:param timeout: threshold until the video file is downloaded
Expand All @@ -249,7 +253,7 @@ def download_session_log(self, scenario_name, timeout=5):
"""
download the session log file from remote selenoid,
renaming the file to scenario name and removing the log file in the server.
GGR request: http://<username>:<password>@<ggr_host>:<ggr_port>/logs/<ggr_session_id>
GGR request: http://<username>:<password>@<ggr_host>:<ggr_port>/logs/<ggr_session_id>
selenoid request: http://<username>:<password>@<ggr_host>:<ggr_port>/logs/<ggr_session_id>.log
:param scenario_name: scenario name
:param timeout: threshold until the log file is downloaded
Expand Down
38 changes: 26 additions & 12 deletions toolium/test/utils/test_dataset_replace_param.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import datetime
from uuid import UUID

import pytest

from toolium.utils import dataset
from toolium.utils.dataset import replace_param

Expand Down Expand Up @@ -333,18 +335,30 @@ def test_replace_param_now_offsets_with_and_without_format_and_more():
assert param == f'The date {offset_date} was yesterday and I have an appointment at {offset_datetime}'


def test_replace_param_round_with_type_inference():
param = replace_param('[ROUND:7.5::2]')
assert param == 7.5
param = replace_param('[ROUND:3.33333333::3]')
assert param == 3.333


def test_replace_param_round_without_type_inference():
param = replace_param('[ROUND:7.500::2]', infer_param_type=False)
assert param == '7.50'
param = replace_param('[ROUND:3.33333333::3]', infer_param_type=False)
assert param == '3.333'
@pytest.mark.parametrize('in_param, number_of_digits_in_fractional_part, out_param',
[['7.5', '2', 7.5],
['3.33333333', '3', 3.333],
['123', '5', 123.0],
['0.001', '2', 0.0],
['0.4', '0', 0],
['0.6', '0', 1]
])
def test_replace_param_round_with_type_inference(in_param, number_of_digits_in_fractional_part, out_param):
param = replace_param(f'[ROUND:{in_param}::{number_of_digits_in_fractional_part}]')
assert param == out_param


@pytest.mark.parametrize('in_param, number_of_digits_in_fractional_part, out_param',
[['7.5', '2', '7.50'],
['3.33333333', '3', '3.333'],
['123', '5', '123.00000'],
['0.001', '2', '0.00'],
['0.4', '0', '0'],
['0.6', '0', '1']
])
def test_replace_param_round_without_type_inference(in_param, number_of_digits_in_fractional_part, out_param):
param = replace_param(f'[ROUND:{in_param}::{number_of_digits_in_fractional_part}]', infer_param_type=False)
assert param == out_param


def test_replace_param_str_int():
Expand Down
131 changes: 69 additions & 62 deletions toolium/utils/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,41 +56,43 @@ def replace_param(param, language='es', infer_param_type=True):
"""
Apply transformations to the given param based on specific patterns.
Available replacements:
[STRING_WITH_LENGTH_XX] Generates a fixed length string
[INTEGER_WITH_LENGTH_XX] Generates a fixed length integer
[STRING_ARRAY_WITH_LENGTH_XX] Generates a fixed length array of strings
[INTEGER_ARRAY_WITH_LENGTH_XX] Generates a fixed length array of integers
[JSON_WITH_LENGTH_XX] Generates a fixed length JSON
[MISSING_PARAM] Generates a None object
[NULL] Generates a None object
[TRUE] Generates a boolean True
[FALSE] Generates a boolean False
[EMPTY] Generates an empty string
[B] Generates a blank space
[UUID] Generates a v4 UUID
[RANDOM] Generates a random value
[RANDOM_PHONE_NUMBER] Generates a random phone number for language and country configured in dataset.language
and dataset.country
[TIMESTAMP] Generates a timestamp from the current time
[DATETIME] Generates a datetime from the current time
[NOW] Similar to DATETIME without milliseconds; the format depends on the language
[NOW(%Y-%m-%dT%H:%M:%SZ)] Same as NOW but using an specific format by the python strftime function of the
datetime module
[NOW + 2 DAYS] Similar to NOW but two days later
[NOW - 1 MINUTES] Similar to NOW but one minute earlier
[NOW(%Y-%m-%dT%H:%M:%SZ) - 7 DAYS] Similar to NOW but seven days before and with the indicated format
[TODAY] Similar to NOW without time; the format depends on the language
[TODAY + 2 DAYS] Similar to NOW, but two days later
[ROUND:xxxx::y] Generates a string from a float number (xxxx) with the indicated number of decimals (y)
[STR:xxxx] Cast xxxx to a string
[INT:xxxx] Cast xxxx to an int
[FLOAT:xxxx] Cast xxxx to a float
[LIST:xxxx] Cast xxxx to a list
[DICT:xxxx] Cast xxxx to a dict
[UPPER:xxxx] Converts xxxx to upper case
[LOWER:xxxx] Converts xxxx to lower case
[REPLACE:xxxxx::yy::zz] Replace elements in string. Example: [REPLACE:[CONTEXT:some_url]::https::http]
[TITLE:xxxxx] Apply .title() to string value. Example: [TITLE:the title]
- [STRING_WITH_LENGTH_XX] Generates a fixed length string
- [INTEGER_WITH_LENGTH_XX] Generates a fixed length integer
- [STRING_ARRAY_WITH_LENGTH_XX] Generates a fixed length array of strings
- [INTEGER_ARRAY_WITH_LENGTH_XX] Generates a fixed length array of integers
- [JSON_WITH_LENGTH_XX] Generates a fixed length JSON
- [MISSING_PARAM] Generates a None object
- [NULL] Generates a None object
- [TRUE] Generates a boolean True
- [FALSE] Generates a boolean False
- [EMPTY] Generates an empty string
- [B] Generates a blank space
- [UUID] Generates a v4 UUID
- [RANDOM] Generates a random value
- [RANDOM_PHONE_NUMBER] Generates a random phone number for language and country configured
in dataset.language and dataset.country
- [TIMESTAMP] Generates a timestamp from the current time
- [DATETIME] Generates a datetime from the current time
- [NOW] Similar to DATETIME without milliseconds; the format depends on the language
- [NOW(%Y-%m-%dT%H:%M:%SZ)] Same as NOW but using an specific format by the python strftime function of
the datetime module
- [NOW + 2 DAYS] Similar to NOW but two days later
- [NOW - 1 MINUTES] Similar to NOW but one minute earlier
- [NOW(%Y-%m-%dT%H:%M:%SZ) - 7 DAYS] Similar to NOW but seven days before and with the indicated format
- [TODAY] Similar to NOW without time; the format depends on the language
- [TODAY + 2 DAYS] Similar to NOW, but two days later
- [ROUND:xxxx::y] Generates a string from a float number (xxxx) with the indicated number of decimals (y)
- [STR:xxxx] Cast xxxx to a string
- [INT:xxxx] Cast xxxx to an int
- [FLOAT:xxxx] Cast xxxx to a float
- [LIST:xxxx] Cast xxxx to a list
- [DICT:xxxx] Cast xxxx to a dict
- [UPPER:xxxx] Converts xxxx to upper case
- [LOWER:xxxx] Converts xxxx to lower case
- [REPLACE:xxxxx::yy::zz] Replace elements in string. Example: [REPLACE:[CONTEXT:some_url]::https::http]
- [TITLE:xxxxx] Apply .title() to string value. Example: [TITLE:the title]
If infer_param_type is True and the result of the replacement process is a string,
this function also tries to infer and cast the result to the most appropriate data type,
attempting first the direct conversion to a Python built-in data type and then,
Expand Down Expand Up @@ -437,18 +439,19 @@ def map_one_param(param):
"""
Analyze the pattern in the given string and find out its transformed value.
Available tags and replacement values:
[CONF:xxxx] Value from the config dict in project_config global variable for the key xxxx (dot notation is used
for keys, e.g. key_1.key_2.0.key_3)
[LANG:xxxx] String from the texts dict in language_terms global variable for the key xxxx, using the language
specified in language global variable (dot notation is used for keys, e.g. button.label)
[POE:xxxx] Definition(s) from the POEditor terms list in poeditor_terms global variable for the term xxxx
[TOOLIUM:xxxx] Value from the toolium config in toolium_config global variable for the key xxxx (key format is
section_option, e.g. Driver_type)
[CONTEXT:xxxx] Value from the behave context storage dict in behave_context global variable for the key xxxx, or
value of the behave context attribute xxxx, if the former does not exist
[ENV:xxxx] Value of the OS environment variable xxxx
[FILE:xxxx] String with the content of the file in the path xxxx
[BASE64:xxxx] String with the base64 representation of the file content in the path xxxx
- [CONF:xxxx] Value from the config dict in project_config global variable for the key xxxx (dot notation is used
for keys, e.g. key_1.key_2.0.key_3)
- [LANG:xxxx] String from the texts dict in language_terms global variable for the key xxxx, using the language
specified in language global variable (dot notation is used for keys, e.g. button.label)
- [POE:xxxx] Definition(s) from the POEditor terms list in poeditor_terms global variable for the term xxxx
- [TOOLIUM:xxxx] Value from the toolium config in toolium_config global variable for the key xxxx (key format is
section_option, e.g. Driver_type)
- [CONTEXT:xxxx] Value from the behave context storage dict in behave_context global variable for the key xxxx, or
value of the behave context attribute xxxx, if the former does not exist
- [ENV:xxxx] Value of the OS environment variable xxxx
- [FILE:xxxx] String with the content of the file in the path xxxx
- [BASE64:xxxx] String with the base64 representation of the file content in the path xxxx
:param param: string parameter
:return: transformed value or the original string if no transformation could be applied
Expand Down Expand Up @@ -525,19 +528,22 @@ def map_json_param(param, config, copy=True):
"""
Find the value of the given param using it as a key in the given dictionary. Dot notation is used,
so for example "service.vamps.user" could be used to retrieve the email in the following config example:
{
"services":{
"vamps":{
"user": "[email protected]",
"password": "MyPassword"
.. code-block:: json
{
"services":{
"vamps":{
"user": "[email protected]",
"password": "MyPassword"
}
}
}
}
:param param: key to be searched (dot notation is used, e.g. "service.vamps.user").
:param config: configuration dictionary
:param copy: boolean value to indicate whether to work with a copy of the given dictionary or not,
in which case, the dictionary content might be changed by this function (True by default)
in which case, the dictionary content might be changed by this function (True by default)
:return: mapped value
"""
properties_list = param.split(".")
Expand Down Expand Up @@ -630,18 +636,19 @@ def get_value_from_context(param, context):
If the resolved element at one of the tokens is a list and the next token is a key=value expression, then the
element in the list that matches the key=value expression is selected, e.g. "list.key=value" returns the element
in the list "list" that has the value for key attribute. So, for example, if the list is:
[
{"key": "value1", "attr": "attr1"},
{"key": "value2", "attr": "attr2"}
]
.. code-block:: json
[
{"key": "value1", "attr": "attr1"},
{"key": "value2", "attr": "attr2"}
]
then "list.key=value2" returns the second element in the list. Also does "list.'key'='value2'",
"list.'key'=\"value2\"", "list.\"key\"='value2'" or "list.\"key\"=\"value2\"".
There is not limit in the nested levels of dotted tokens, so a key like a.b.c.d will be tried to be resolved as:
context.storage['a'].b.c.d
or
context.a.b.c.d
context.storage['a'].b.c.d or context.a.b.c.d
:param param: key to be searched (e.g. "last_request_result" / "last_request.result")
:param context: behave context
Expand Down
Loading

0 comments on commit 71b4174

Please sign in to comment.