Skip to content
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: 1 addition & 1 deletion Browser/gen_stub.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
"""
Expand Down
10 changes: 8 additions & 2 deletions Browser/keywords/evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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,
Expand Down
60 changes: 41 additions & 19 deletions Browser/keywords/getters.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -52,6 +53,7 @@
SelectionStrategy,
SelectOptions,
SizeFields,
TextType,
ViewportDimensions,
)

Expand Down Expand Up @@ -228,47 +230,67 @@ 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",
message,
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"))
Expand Down
2 changes: 2 additions & 0 deletions Browser/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 24 additions & 0 deletions Browser/utils/data_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 <input> or <textarea> or <select> element.

``innerHTML``: Returns the element node.innerHTML value, which is the HTML markup contained within the element, omitting any shadow roots.
"""

allInnerTexts = auto()
allTextContents = auto()
innerText = auto()
inputValue = auto()
innerHTML = auto()


InstallableBrowser = Enum(
"InstallableBrowser",
{
Expand Down Expand Up @@ -1522,3 +1543,6 @@ class TracingGroupMode(Enum):
"only-shell": "only install headless shell when installing chromium",
"no-shell": "do not install chromium headless shell",
}


ROBOT_FRAMEWORK_BROWSER_NO_SET = "ROBOT_FRAMEWORK_BROWSER_NO_SET"
39 changes: 6 additions & 33 deletions atest/test/02_Content_Keywords/basic_getters.robot
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Resource imports.resource
Library ../../library/presenter_mode.py

Suite Setup Setup
Suite Setup Setup Basic Getters
Suite Teardown Set Retry Assertions For ${assert_timeout}
Test Setup Ensure Location ${LOGIN_URL}

Expand All @@ -11,33 +11,6 @@ ${UserNameLabel} = label[for="username_field"]
${InputUsername} = id=username_field

*** Test Cases ***
Get Text
${h1} = Get Text h1
Should Be Equal ${h1} Login Page

Get Text Disabled
[Setup] Go To ${ELEMENT_STATE_URL}
presenter_mode.Set Presenter Mode {"color": "red", "duration": "1s", "style": "solid"}
${text} = Get Text //input[@name="readonly_with_equals_only"]
[Teardown] presenter_mode.Set Presenter Mode False

Get Text And Assert ==
Get Text ${UserNameLabel} == User Name:

Get Text And Assert !=
Get Text ${UserNameLabel} !=

Get Text Assert Validate
Get Text h1 validate value.startswith('Login')

Get Text With Nonmatching Selector
[Tags] no-iframe
Set Browser Timeout 50ms
Run Keyword And Expect Error
... *Error: locator.elementHandle: Timeout 50ms exceeded.*waiting for locator('notamatch')*
... Get Text notamatch
[Teardown] Set Browser Timeout ${PLAYWRIGHT_TIMEOUT}

Get Property And Assert
Get Property h1 innerText == Login Page
Get Property h1 innerText != ${None}
Expand Down Expand Up @@ -148,20 +121,20 @@ Get Element Count
${count} = Get Element Count h1
Should Be Equal ${count} ${1}
${count} = Get Element Count label
Should Be Equal ${count} ${13}
Should Be Equal ${count} ${14}
${count} = Get Element Count not-existing
Should Be Equal ${count} ${0}

Get Element Count And Assert
[Setup] Ensure Location ${LOGIN_URL}
Get Element Count h1 == 1
Get Element Count h1 == ${1}
Get Element Count label validate value == 13
Get Element Count label validate value == 14
Get Element Count label > 1
Get Element Count not-existing ==
${promise} = Promise To Get Element Count label
${count} = Wait For ${promise}
Should Be Equal ${count} ${13}
Should Be Equal ${count} ${14}

Get Style And Assert
Get Style h1 ALL *= align-content
Expand Down Expand Up @@ -353,7 +326,7 @@ Get Element States Return Flags
Should Be Equal ${input_state} ${pwd_state}

Get Console Log Test
[Setup] Setup
[Setup] Setup Basic Getters
${first} = Get Console Log then len(value)
Click With Options "Click with Options" left ALT SHIFT
# Sometimes test app emist React Router Future Flag Warning: React Router ...
Expand Down Expand Up @@ -395,7 +368,7 @@ Get Console Log Test
... $now - datetime.datetime.strptime($first_log['time'], '%Y-%m-%dT%H:%M:%S.%f%z') < datetime.timedelta(seconds=0.5)

*** Keywords ***
Setup
Setup Basic Getters
Close Page ALL
Ensure Open Page ${LOGIN_URL}
${assert_timeout} = Set Retry Assertions For 2 sec
Expand Down
98 changes: 98 additions & 0 deletions atest/test/02_Content_Keywords/basic_getters_get_text.robot
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
*** Settings ***
Resource imports.resource
Library ../../library/presenter_mode.py

Suite Setup Setup Get Text
Suite Teardown Set Retry Assertions For ${assert_timeout}
Test Setup Ensure Location ${LOGIN_URL}

*** Variables ***
${USERNAMELABEL} = label[for="username_field"]
${INPUTUSERNAME} = id=username_field

*** Test Cases ***
Get Text
${h1} = Get Text h1
Should Be Equal ${h1} Login Page

Get Text Disabled
[Setup] Go To ${ELEMENT_STATE_URL}
presenter_mode.Set Presenter Mode {"color": "red", "duration": "1s", "style": "solid"}
${text} = Get Text //input[@name="readonly_with_equals_only"]
[Teardown] presenter_mode.Set Presenter Mode False

Get Text And Assert ==
Get Text ${USERNAMELABEL} == User Name:

Get Text And Assert !=
Get Text ${USERNAMELABEL} !=

Get Text No Text Type And Input Field
Type Text ${INPUTUSERNAME} MyUserName
Get Text ${INPUTUSERNAME} == MyUserName

Get Text Text Type As InputValue And Input Field
Type Text ${INPUTUSERNAME} MyUserName
Get Text ${INPUTUSERNAME} == MyUserName text_type=inputValue

Get Text No Text Type And Select Element
Select Options By id=pet-select value dog
Get Text id=pet-select == dog

Get Text Text Type As InputValue And Select Element
Select Options By id=pet-select value dog
Get Text id=pet-select == dog text_type=inputValue

Get Text Assert Validate
Get Text h1 validate value.startswith('Login')

Get Text With No Matching Selector
[Tags] no-iframe
Set Browser Timeout 50ms
Run Keyword And Expect Error
... *TimeoutError: locator.evaluate: Timeout 50ms exceeded.*
... Get Text notamatch
[Teardown] Set Browser Timeout ${PLAYWRIGHT_TIMEOUT}

Get Text With Text Type As InnerHTML
${text} = Get Text h1 == Login Page text_type=innerHTML
Should Be Equal ${text} Login Page
${text} = Get Text [name="login_form"] text_type=innerHTML
Should Contain ${text} <label for="username_field">User Name:</label>
Should Contain ${text} <label for="password_field">Password:</label>

Get Text With Text Type As InnerText
${text} = Get Text h1 == Login Page text_type=innerText
Should Be Equal ${text} Login Page
${text} = Get Text ${USERNAMELABEL} text_type=innerText
Should Be Equal ${text} User Name:

Get Text With Text Type As All InnerTexts
${texts} = Get Text //option text_type=allInnerTexts
VAR @{expected} = --Please choose an option-- Dog Cat Hamster Parrot Spider Goldfish
Lists Should Be Equal ${texts} ${expected}

Get Text With Text Type As All InnerTexts On Single Element With Multiple Text
${texts} = Get Text [name="login_form"] text_type=allInnerTexts
Should Contain ${texts[0]} User Name:
Should Contain ${texts[0]} Password:
Length Should Be ${texts} 1

Get Text With Text Type As All TextContents With Multiple Text
${texts} = Get Text //option text_type=allTextContents
VAR @{expected} = --Please choose an option-- Dog Cat Hamster Parrot Spider Goldfish
Lists Should Be Equal ${texts} ${expected}

Text Area Access And No Text Type
Get Text id=textarea51 == Some initial text
Type Text id=textarea51 Area 51
Get Text id=textarea51 == Area 51
Type Text id=textarea51 Ufo detected
Get Text id=textarea51 == Ufo detected text_type=inputValue

*** Keywords ***
Setup Get Text
Close Page ALL
Ensure Open Page ${LOGIN_URL}
${assert_timeout} = Set Retry Assertions For 2 sec
VAR ${assert_timeout} = ${assert_timeout} scope=SUITE
7 changes: 0 additions & 7 deletions atest/test/02_Content_Keywords/text_keywords.robot
Original file line number Diff line number Diff line change
Expand Up @@ -331,13 +331,6 @@ Get Text Custom Error
... Get Text css=input#username_field == username Tidii
[Teardown] Set Retry Assertions For 1s

Text Area Access
Get Text id=textarea51 == Some initial text
Type Text id=textarea51 Area 51
Get Text id=textarea51 == Area 51
Type Text id=textarea51 Ufo detected
Get Text id=textarea51 == Ufo detected

Type Secret With CryptoLibrary
Type Secret
... input#username_field
Expand Down
12 changes: 12 additions & 0 deletions node/dynamic-test-app/src/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,18 @@ export default function Site() {
</tbody>
</table>

<label id="pet-select-label">Choose a pet:</label>
<select name="pets" id="pet-select">
<option value="">--Please choose an option--</option>
<option value="dog">Dog</option>
<option value="cat">Cat</option>
<option value="hamster">Hamster</option>
<option value="parrot">Parrot</option>
<option value="spider">Spider</option>
<option value="goldfish">Goldfish</option>
</select>
<br></br>

<input
type="file"
id="file_chooser"
Expand Down
Loading
Loading