diff --git a/Browser/gen_stub.py b/Browser/gen_stub.py index 88199fc4b..e691508e8 100644 --- a/Browser/gen_stub.py +++ b/Browser/gen_stub.py @@ -69,7 +69,7 @@ def parse_kw_stubs(): from Browser.utils .data_types import ( MouseButton, KeyboardModifier, ScrollBehavior, ScrollBehavior, DialogAction, MouseButtonAction, NotSet, Dimensions, SizeFields, AreaFields, BoundingBoxFields, SelectionStrategy, ElementRole, AriaSnapshotReturnType, - KeyboardInputAction, KeyAction + KeyboardInputAction, KeyAction, TextType ) from Browser.utils.types import Secret """ diff --git a/Browser/keywords/evaluation.py b/Browser/keywords/evaluation.py index 0361bbb4d..69be6700d 100644 --- a/Browser/keywords/evaluation.py +++ b/Browser/keywords/evaluation.py @@ -20,7 +20,13 @@ from ..base import LibraryComponent from ..generated.playwright_pb2 import Request -from ..utils import DownloadInfo, HighlightMode, keyword, logger +from ..utils import ( + ROBOT_FRAMEWORK_BROWSER_NO_SET, + DownloadInfo, + HighlightMode, + keyword, + logger, +) class Evaluation(LibraryComponent): @@ -117,7 +123,7 @@ def highlight_elements( Request().ElementSelectorWithDuration( selector=self.resolve_selector(selector) if selector - else "ROBOT_FRAMEWORK_BROWSER_NO_ELEMENT", + else ROBOT_FRAMEWORK_BROWSER_NO_SET, duration=int(self.convert_timeout(duration)), width=width, style=style, diff --git a/Browser/keywords/getters.py b/Browser/keywords/getters.py index e0277e17c..9df8786e2 100644 --- a/Browser/keywords/getters.py +++ b/Browser/keywords/getters.py @@ -38,6 +38,7 @@ from ..generated.playwright_pb2 import Request from ..utils import keyword, logger from ..utils.data_types import ( + ROBOT_FRAMEWORK_BROWSER_NO_SET, AreaFields, AriaSnapshotReturnType, BoundingBox, @@ -52,6 +53,7 @@ SelectionStrategy, SelectOptions, SizeFields, + TextType, ViewportDimensions, ) @@ -228,36 +230,49 @@ def get_text( assertion_operator: AssertionOperator | None = None, assertion_expected: Any | None = None, message: str | None = None, - ) -> str: + *, + text_type: TextType | None = None, + ) -> str | list[str]: """Returns text attribute of the element found by ``selector``. - Keyword can also return `input` or `textarea` value property text. + Keyword can also return `input` or `textarea` value property text. See the `Finding elements` section for details about the selectors. - | =Arguments= | =Description= | - | ``assertion_operator`` | See `Assertions` for further details. Defaults to None. | - | ``assertion_expected`` | Expected value for the state | - | ``message`` | overrides the default error message for assertion. | + | =Arguments= | =Description= | + | ``assertion_operator`` | See `Assertions` for further details. Defaults to None. | + | ``assertion_expected`` | Expected value for the state | + | ``message`` | overrides the default error message for assertion. | + | ``text_type`` | How text is returned. Possible values are ``allInnerTexts``, ``allTextContents``, ``innerText``, ``inputValue``, and ``innerHTML``. | - Keyword uses strict mode, see `Finding elements` for more details about strict mode. + Keyword uses strict mode, see `Finding elements` for more details about strict mode. + The ``text_type`` argument determines how text is returned. The ``allInnerTexts`` and + ``allTextContents`` will return a list of strings, while other types return a single + string. - Optionally asserts that the text matches the specified assertion. See `Assertions` - for further details for the assertion arguments. By default, assertion is not done. + Optionally asserts that the text matches the specified assertion. See `Assertions` + for further details for the assertion arguments. By default, assertion is not done. - Example: - | ${text} = `Get Text` id=important # Returns element text without assertion. - | ${text} = `Get Text` id=important == Important text # Returns element text with assertion. - | ${text} = `Get Text` //input == root # Returns input element text with assertion. + Example: + | ${text} = `Get Text` id=important # Returns element text without assertion. + | ${text} = `Get Text` id=important == Important text # Returns element text with assertion. + | ${text} = `Get Text` //input == root # Returns input element text with assertion. + | ${text} = `Get Text` id=important text_type=innerHTML # Returns element inner HTML. + | ${text} = `Get Text` id=important text_type=allInnerTexts # Returns element inner text as list of strings. - [https://forum.robotframework.org/t//4285|Comment >>] + [https://forum.robotframework.org/t//4285|Comment >>] """ selector = self.presenter_mode(selector, self.strict_mode) - response = self._get_text(selector) + response = self._get_text(selector, text_type) logger.debug(response.log) - logger.info(f"Text: {response.body!r}") + is_all_type = text_type in (TextType.allInnerTexts, TextType.allTextContents) + if is_all_type: + value = [str(item) for item in response.items] + else: + value = [str(response.items[0])] + logger.info(f"Text: {value!r}") formatter = self.get_assertion_formatter("Get Text") return verify_assertion( - response.body, + value[0] if not is_all_type else value, assertion_operator, assertion_expected, "Text", @@ -265,10 +280,17 @@ def get_text( formatter, ) - def _get_text(self, selector: str): # To ease unit testing + def _get_text( + self, selector: str, text_type: TextType | None + ): # To ease unit testing + text_type_value = ( + str(text_type.name) if text_type else ROBOT_FRAMEWORK_BROWSER_NO_SET + ) with self.playwright.grpc_channel() as stub: return stub.GetText( - Request().ElementSelector(selector=selector, strict=self.strict_mode) + Request().ElementSelectorWithTextType( + selector=selector, strict=self.strict_mode, textType=text_type_value + ) ) @keyword(tags=("Getter", "Assertion", "PageContent")) diff --git a/Browser/utils/__init__.py b/Browser/utils/__init__.py index 3e5b6ab0e..04d20abb5 100644 --- a/Browser/utils/__init__.py +++ b/Browser/utils/__init__.py @@ -63,8 +63,10 @@ SelectionType, ServiceWorkersPermissions, SupportedBrowsers, + TextType, ViewportDimensions, convert_typed_dict, + ROBOT_FRAMEWORK_BROWSER_NO_SET, ) from .js_utilities import get_abs_scroll_coordinates, get_rel_scroll_coordinates from .meta_python import find_by_id, locals_to_params diff --git a/Browser/utils/data_types.py b/Browser/utils/data_types.py index 37d640035..f7e438bb7 100644 --- a/Browser/utils/data_types.py +++ b/Browser/utils/data_types.py @@ -1483,6 +1483,27 @@ class TracingGroupMode(Enum): Playwright = auto() +class TextType(Enum): + """Defines which Playwright method is used to get the text of an element. + + ``allInnerTexts``: Returns a list of `node.innerText` values for all matching nodes. + + ``allTextContents``: Returns a list of `node.textContent` values for all matching nodes. + + ``innerText``: Returns the element node.innerText value, which represents the rendered text content of a node and its descendants. + + ``inputValue``: Returns the value for the matching or