Skip to content

Commit

Permalink
Topic/argument docs (#2308)
Browse files Browse the repository at this point in the history
### News & Changes:

#### Following should be backwards compatible:

- [x] Deprecation of positional arguments for `Library Import` and `New Context`
- [x] Deprecated positional arguments except the first few of `New Browser` and `New Persistent Context`
- [x] Reordered named-only arguments alphabetically
- [x] Updated all argument docs to be tables.
- [x] Fixed some bad docs.
- [x] New data type for switching and selecting browser, context and page. Now supports ``CURRENT`` == ``ACTIVE`` and ``ALL`` == ``ANY``. Not longer case sensitive.

#### Backwards INCOMPATIBLE changes:

- [x] Changed arguments for the expected assertion argument from `expected_value` or `expected_state` to `assertion_expected` as on all other getters for the following keywords:
  - [x] `Get Checkbox State`
  - [x] `Get Element Count`
  - [x] `Get Table Cell Index`
  - [x] `Get Table Row Index`
- [x] `Keyboard Input` has now a `timedelta` as type for the  `delay` argument. Before it was integer in milliseconds
- [x] `Mouse Button` has now a `timedelta` as type for the  `delay` argument. Before it was integer in milliseconds

#### Bugfixes:

- [x] `New Persistent Context` could not use `timeout` argument set to `0`
- [x] `New Context` `viewport` argument can now be `${None}` to be able to open full screen browsers. #2054
  • Loading branch information
Snooz82 authored Sep 20, 2022
1 parent 781d470 commit ccf92c8
Show file tree
Hide file tree
Showing 20 changed files with 1,078 additions and 1,179 deletions.
113 changes: 78 additions & 35 deletions Browser/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from robot.errors import DataError # type: ignore
from robot.libraries.BuiltIn import EXECUTION_CONTEXTS, BuiltIn # type: ignore
from robot.running.arguments import PythonArgumentParser # type: ignore
from robot.running.arguments.typeconverters import TypeConverter # type: ignore
from robot.utils import secs_to_timestr, timestr_to_secs # type: ignore
from robotlibcore import DynamicCore # type: ignore

Expand Down Expand Up @@ -692,43 +693,69 @@ class Browser(DynamicCore):
_context_cache = ContextCache()
_suite_cleanup_done = False

old_init_args = {
"timeout": timedelta,
"enable_playwright_debug": bool,
"auto_closing_level": AutoClosingLevel,
"retry_assertions_for": timedelta,
"run_on_failure": str,
"external_browser_executable": Optional[Dict[SupportedBrowsers, str]],
"jsextension": Optional[str],
"enable_presenter_mode": Union[HighLightElement, bool],
"playwright_process_port": Optional[int],
"strict": bool,
"show_keyword_call_banner": Optional[bool],
}

def __init__(
self,
timeout: timedelta = timedelta(seconds=10),
enable_playwright_debug: bool = False,
*deprecated_pos_args,
auto_closing_level: AutoClosingLevel = AutoClosingLevel.TEST,
retry_assertions_for: timedelta = timedelta(seconds=1),
run_on_failure: str = "Take Screenshot fail-screenshot-{index}",
enable_playwright_debug: bool = False,
enable_presenter_mode: Union[HighLightElement, bool] = False,
external_browser_executable: Optional[Dict[SupportedBrowsers, str]] = None,
jsextension: Optional[str] = None,
enable_presenter_mode: Union[HighLightElement, bool] = False,
playwright_process_port: Optional[int] = None,
strict: bool = True,
retry_assertions_for: timedelta = timedelta(seconds=1),
run_on_failure: str = "Take Screenshot fail-screenshot-{index}",
show_keyword_call_banner: Optional[bool] = None,
strict: bool = True,
timeout: timedelta = timedelta(seconds=10),
):
"""Browser library can be taken into use with optional arguments:
| ``timeout`` | <str> Timeout for keywords that operate on elements. The keywords will wait for this time for the element to appear into the page. Defaults to "10s" => 10 seconds. |
| ``enable_playwright_debug`` | <bool> Enable low level debug information from the playwright tool. Mainly Useful for the library developers and for debugging purposes. |
| ``auto_closing_level`` | < ``TEST`` or ``SUITE`` or ``MANUAL`` > Configure context and page automatic closing. Default is ``TEST``, for more details, see `AutoClosingLevel` |
| ``retry_assertions_for`` | <str> Timeout for retrying assertions on keywords before failing the keywords. This timeout starts counting from the first failure. Global ``timeout`` will still be in effect. This allows stopping execution faster to assertion failure when element is found fast. |
| ``run_on_failure`` | <str> Sets the keyword to execute in case of a failing Browser keyword. It can be the name of any keyword. If the keyword has arguments those must be separated with two spaces for example ``My keyword \\ arg1 \\ arg2``. If no extra action should be done after a failure, set it to ``None`` or any other robot falsy value. Run on failure is not applied when library methods are executed directly from Python. |
| ``external_browser_executable`` | <Dict <SupportedBrowsers, Path>> Dict mapping name of browser to path of executable of a browser. Will make opening new browsers of the given type use the set executablePath. Currently only configuring of `chromium` to a separate executable (chrome, chromium and Edge executables all work with recent versions) works. |
| ``jsextension`` | <str> Path to Javascript module exposed as extra keywords. The module must be in CommonJS. |
| ``enable_presenter_mode`` | <bool or dict> Automatic highlights to interacted components, slowMo and a small pause at the end. Can be enabled by giving True or can be customized by giving a dictionary: `{"duration": "2 seconds", "width": "2px", "style": "dotted", "color": "blue"}` Where `duration` is time format in Robot Framework format, defaults to 2 seconds. `width` is width of the marker in pixels, defaults the `2px`. `style` is the style of border, defaults to `dotted`. `color` is the color of the marker, defaults to `blue`. |
| ``strict`` | <bool> If keyword selector points multiple elements and keywords should interact with one element, keyword will fail if ``strict`` mode is true. Strict mode can be changed individually in keywords or by ```et Strict Mode`` keyword. |
| ``show_keyword_call_banner`` | <bool or None> If set to ``True``, will show a banner with the keyword name and arguments before the keyword is executed at the bottom of the page. If set to ``False``, will not show the banner. If set to None, which is the default, will show the banner only if the presenter mode is enabled. `Get Page Source` and `Take Screenshot` will not show the banner, because that could negatively affect your test cases/tasks. This feature may be super helpful when you are debugging your tests and using tracing from `New Context` or `Video recording` features. |
| =Argument= | =Description= |
| ``*deprecated_pos_args`` | Positional arguments are deprecated for Library import. Please use named arguments instead. We will remove positional arguments after RoboCon 2023 Online in March. Old positional order was: ``timeout``, ``enable_playwright_debug``, ``auto_closing_level``, ``retry_assertions_for``, ``run_on_failure``, ``external_browser_executable``, ``jsextension``, ``enable_presenter_mode``, ``playwright_process_port``, ``strict``, ``show_keyword_call_banner``. |
| ``auto_closing_level`` | Configure context and page automatic closing. Default is ``TEST``, for more details, see `AutoClosingLevel` |
| ``enable_playwright_debug`` | Enable low level debug information from the playwright tool. Mainly Useful for the library developers and for debugging purposes. |
| ``enable_presenter_mode`` | Automatic highlights to interacted components, slowMo and a small pause at the end. Can be enabled by giving True or can be customized by giving a dictionary: `{"duration": "2 seconds", "width": "2px", "style": "dotted", "color": "blue"}` Where `duration` is time format in Robot Framework format, defaults to 2 seconds. `width` is width of the marker in pixels, defaults the `2px`. `style` is the style of border, defaults to `dotted`. `color` is the color of the marker, defaults to `blue`. |
| ``external_browser_executable`` | Dict mapping name of browser to path of executable of a browser. Will make opening new browsers of the given type use the set executablePath. Currently only configuring of `chromium` to a separate executable (chrome, chromium and Edge executables all work with recent versions) works. |
| ``jsextension`` | Path to Javascript module exposed as extra keywords. The module must be in CommonJS. |
| ``playwright_process_port`` | Experimental reusing of playwright process. ``playwright_process_port`` is preferred over environment variable ``ROBOT_FRAMEWORK_BROWSER_NODE_PORT``. See `Experimental: Re-using same node process` for more details. |
| ``retry_assertions_for`` | Timeout for retrying assertions on keywords before failing the keywords. This timeout starts counting from the first failure. Global ``timeout`` will still be in effect. This allows stopping execution faster to assertion failure when element is found fast. |
| ``run_on_failure`` | Sets the keyword to execute in case of a failing Browser keyword. It can be the name of any keyword. If the keyword has arguments those must be separated with two spaces for example ``My keyword \\ arg1 \\ arg2``. If no extra action should be done after a failure, set it to ``None`` or any other robot falsy value. Run on failure is not applied when library methods are executed directly from Python. |
| ``show_keyword_call_banner`` | If set to ``True``, will show a banner with the keyword name and arguments before the keyword is executed at the bottom of the page. If set to ``False``, will not show the banner. If set to None, which is the default, will show the banner only if the presenter mode is enabled. `Get Page Source` and `Take Screenshot` will not show the banner, because that could negatively affect your test cases/tasks. This feature may be super helpful when you are debugging your tests and using tracing from `New Context` or `Video recording` features. |
| ``strict`` | If keyword selector points multiple elements and keywords should interact with one element, keyword will fail if ``strict`` mode is true. Strict mode can be changed individually in keywords or by ```et Strict Mode`` keyword. |
| ``timeout`` | Timeout for keywords that operate on elements. The keywords will wait for this time for the element to appear into the page. Defaults to "10s" => 10 seconds. |
"""
self.timeout = self.convert_timeout(timeout)
self.retry_assertions_for = self.convert_timeout(retry_assertions_for)
self.ROBOT_LIBRARY_LISTENER = self
self._execution_stack: List[dict] = []
self._running_on_failure_keyword = False
self._pause_on_failure: Set["Browser"] = set()
self.external_browser_executable: Dict[SupportedBrowsers, str] = (
external_browser_executable or {}
)
self._unresolved_promises: Set[Future] = set()

old_args_list = list(self.old_init_args.items())
pos_params = {}
for index, pos_arg in enumerate(deprecated_pos_args):
argument_name = old_args_list[index][0]
argument_type = old_args_list[index][1]
converted_pos = TypeConverter.converter_for(argument_type).convert(
argument_name, pos_arg
)
pos_params[argument_name] = converted_pos
if pos_params:
logger.warn(
"Deprecated positional arguments are used in 'Library import of Browser library'. Please use named arguments instead."
)
params = dict(locals())
params = {**pos_params, **params}

self._playwright_state = PlaywrightState(self)
libraries = [
self._playwright_state,
Expand All @@ -747,22 +774,38 @@ def __init__(
Waiter(self),
WebAppState(self),
]

self.timeout = self.convert_timeout(params["timeout"])
self.playwright = Playwright(
self, enable_playwright_debug, playwright_process_port
self, params["enable_playwright_debug"], playwright_process_port
)
self._auto_closing_level: AutoClosingLevel = params["auto_closing_level"]
self.retry_assertions_for = self.convert_timeout(params["retry_assertions_for"])
# Parsing needs keywords to be discovered.
self.external_browser_executable: Dict[SupportedBrowsers, str] = (
params["external_browser_executable"] or {}
)
self._auto_closing_level = auto_closing_level
if params["jsextension"] is not None:
libraries.append(self._initialize_jsextension(params["jsextension"]))
self.presenter_mode: Union[HighLightElement, bool] = params[
"enable_presenter_mode"
]
self.strict_mode = params["strict"]
self.show_keyword_call_banner = params["show_keyword_call_banner"]

self._execution_stack: List[dict] = []
self._running_on_failure_keyword = False
self.pause_on_failure: Set[str] = set()
self._unresolved_promises: Set[Future] = set()
self.current_arguments = ()
if jsextension is not None:
libraries.append(self._initialize_jsextension(jsextension))
self.presenter_mode = enable_presenter_mode
self.strict_mode = strict
self.show_keyword_call_banner = show_keyword_call_banner
self.keyword_call_banner_add_style: str = ""
self._keyword_formatters: dict = {}
self._current_loglevel: Optional[str] = None

DynamicCore.__init__(self, libraries)
# Parsing needs keywords to be discovered.
self.run_on_failure_keyword = self._parse_run_on_failure_keyword(run_on_failure)
self.run_on_failure_keyword = self._parse_run_on_failure_keyword(
params["run_on_failure"]
)

def _parse_run_on_failure_keyword(
self, keyword_name: Union[str, None]
Expand Down Expand Up @@ -995,7 +1038,7 @@ def run_keyword(self, name, args, kwargs=None):
except AssertionError as e:
self.keyword_error()
e.args = self._alter_keyword_error(e.args)
if self._pause_on_failure:
if self.pause_on_failure:
sys.__stdout__.write(f"\n[ FAIL ] {e}")
sys.__stdout__.write(
"\n[Paused on failure] Press Enter to continue..\n"
Expand Down
Loading

0 comments on commit ccf92c8

Please sign in to comment.