Skip to content

Commit

Permalink
selector_synchronizer.py web tests and small fixes / improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
VladimirPodolian committed Jan 28, 2025
1 parent 21ee06c commit 6e80ac9
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 29 deletions.
10 changes: 7 additions & 3 deletions mops/playwright/play_element.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
from PIL.Image import Image
from mops.keyboard_keys import KeyboardKeys
from mops.mixins.objects.scrolls import ScrollTo, ScrollTypes
from playwright.sync_api import TimeoutError as PlayTimeoutError
from playwright.sync_api import TimeoutError as PlayTimeoutError, Error
from playwright.sync_api import Page as PlaywrightPage
from playwright.sync_api import Locator, Page, Browser, BrowserContext

from mops.mixins.objects.size import Size
from mops.mixins.objects.location import Location
from mops.utils.selector_synchronizer import get_platform_locator, set_playwright_locator
from mops.abstraction.element_abc import ElementABC
from mops.exceptions import TimeoutException
from mops.exceptions import TimeoutException, InvalidSelectorException
from mops.utils.logs import Logging
from mops.shared_utils import cut_log_data, get_image
from mops.utils.internal_utils import (
Expand Down Expand Up @@ -435,7 +435,11 @@ def is_displayed(self, silent: bool = False) -> bool:
if not silent:
self.log(f'Check visibility of "{self.name}"')

return self._first_element.is_visible()
try:
return self._first_element.is_visible()
except Error as exc:
raise InvalidSelectorException(exc.message) from None


def is_hidden(self, silent: bool = False) -> bool:
"""
Expand Down
5 changes: 4 additions & 1 deletion mops/selenium/core/core_element.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,10 @@ def is_available(self) -> bool:
:return: :class:`bool` - :obj:`True` if present in DOM
"""
element = safe_call(self._find_element, wait_parent=False)
try:
element = safe_call(self._find_element, wait_parent=False)
except SeleniumInvalidSelectorException as exc:
raise InvalidSelectorException(exc.msg) from None

return bool(element)

Expand Down
20 changes: 11 additions & 9 deletions mops/utils/selector_synchronizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def set_selenium_selector(obj: Any):
elif " " in locator:
obj.locator = f'//*[contains(text(), "{locator}")]'
obj.locator_type = By.XPATH
obj.log_locator = f'{LocatorType.XPATH}={locator}'
obj.log_locator = f'{LocatorType.XPATH}={obj.locator}'

# Default to ID if nothing else matches

Expand All @@ -108,33 +108,35 @@ def set_playwright_locator(obj: Any):
Sets playwright locator & locator type
"""
locator = obj.locator.strip()
obj.log_locator = locator

# Checking the supported locators

if locator.startswith(DEFAULT_MATCH):
pass
obj.locator_type = locator.partition('=')[0]
return

# Checking the regular locators

elif locator.startswith(XPATH_MATCH):
obj.locator = f"{LocatorType.XPATH}={locator}"
obj.locator_type = LocatorType.XPATH

elif locator.startswith(CSS_MATCH) or re.search(CSS_REGEXP, locator):
obj.locator = f"{LocatorType.CSS}={locator}"
obj.locator_type = LocatorType.CSS

elif locator in all_tags:
obj.locator = f'{LocatorType.CSS}={locator}'
elif locator in all_tags or all(tag in all_tags for tag in locator.split()):
obj.locator_type = LocatorType.CSS

elif " " in locator:
obj.locator = f"{LocatorType.TEXT}={locator}"
obj.locator_type = LocatorType.TEXT

# Default to ID if nothing else matches

else:
obj.locator = f"{LocatorType.ID}={locator}"
obj.locator_type = LocatorType.ID

obj.locator = f'{obj.locator_type}={locator}'
obj.log_locator = obj.locator
obj.locator_type = None


def set_appium_selector(obj: Any):
Expand Down
31 changes: 16 additions & 15 deletions tests/static_tests/unit/test_selector_synchronizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
("/html/body/div", "/html/body/div", By.XPATH, "xpath=/html/body/div"),
("#my_element", "#my_element", By.CSS_SELECTOR, "css=#my_element"),
("button", "button", By.CSS_SELECTOR, "css=button"),
("div span", "div span", By.CSS_SELECTOR, "css=div span"),
("tbody tr td span", "tbody tr td span", By.CSS_SELECTOR, "css=tbody tr td span"),
("textarea", "textarea", By.CSS_SELECTOR, "css=textarea"),
("Some text", '//*[contains(text(), "Some text")]', By.XPATH, "xpath=Some text"),
("[href='/some/url']", "[href='/some/url']", By.CSS_SELECTOR, "css=[href='/some/url']"),
],
Expand All @@ -30,24 +31,24 @@ def test_set_selenium_selector(locator_input, expected_locator, expected_locator


@pytest.mark.parametrize(
"locator_input, expected_locator, expected_log_locator",
"locator_input, expected_locator",
[
("xpath=//div", "xpath=//div", "xpath=//div"),
("text=Hello", "text=Hello", "text=Hello"),
("css=.class", "css=.class", "css=.class"),
("id=my_id", "id=my_id", "id=my_id"),
("/html/body/div", "xpath=/html/body/div", "xpath=/html/body/div"),
("#my_element", "css=#my_element", "css=#my_element"),
("button", "css=button", "css=button"),
("div span", "text=div span", "text=div span"),
("Some text", "text=Some text", "text=Some text"),
("[href='/some/url']", "css=[href='/some/url']", "css=[href='/some/url']"),
("", "id=", "id="),
("xpath=//div", "xpath=//div"),
("text=Hello", "text=Hello"),
("css=.class", "css=.class"),
("id=my_id", "id=my_id"),
("/html/body/div", "xpath=/html/body/div"),
("#my_element", "css=#my_element"),
("button", "css=button"),
("tbody tr td span", "css=tbody tr td span"),
("Some text", "text=Some text"),
("[href='/some/url']", "css=[href='/some/url']"),
],
)
def test_set_playwright_locator(locator_input, expected_locator, expected_log_locator):
def test_set_playwright_locator(locator_input, expected_locator):
mock_obj = SimpleNamespace()
mock_obj.locator = locator_input
set_playwright_locator(mock_obj)
assert mock_obj.locator == expected_locator
assert mock_obj.log_locator == expected_log_locator
assert mock_obj.log_locator == expected_locator
assert mock_obj.locator_type == expected_locator.partition('=')[0]
57 changes: 56 additions & 1 deletion tests/web_tests/test_element.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import contextlib
import random

import pytest

from mops.base.element import Element
from mops.mixins.internal_mixin import get_element_info
from tests.adata.pages.expected_condition_page import WaitValueCardBroken
from mops.exceptions import NoSuchElementException, NoSuchParentException
from mops.exceptions import NoSuchElementException, NoSuchParentException, InvalidSelectorException
from tests.adata.pages.keyboard_page import KeyboardPage


Expand Down Expand Up @@ -157,3 +159,56 @@ def test_element_execute_script(forms_page, driver_wrapper):
new_text = 'driver wrapper automation'
forms_page.controls_form.german_slider.execute_script('arguments[0].textContent = arguments[1];', new_text)
assert forms_page.controls_form.german_slider.text == new_text

def test_element_locator_check(mouse_event_page, driver_wrapper):
# Let's keep Elements here, for encapsulation purposes
# Reformat test if any trouble occur
locators = (
'.card.text-center',
'[class *= card][class *= text-center]',
'#footer',
'[href*="https://www.linkedin.com/in"]'
)
invalid_prefixes = ('xpath', 'text', 'id')

for locator in locators:
assert Element(locator).is_displayed()
assert Element(f'css={locator}').is_displayed()
for invalid_prefix in invalid_prefixes:
with contextlib.suppress(InvalidSelectorException):
assert not Element(f'{invalid_prefix}={locator}').is_displayed()

locators = ('//*[contains(@class, "card")]', '//body/div')
invalid_prefixes = ('css', 'text', 'id')
for locator in locators:
assert Element(locator).is_displayed()
assert Element(f'xpath={locator}').is_displayed()
for invalid_prefix in invalid_prefixes:
with contextlib.suppress(InvalidSelectorException):
assert not Element(f'{invalid_prefix}={locator}').is_displayed()

locators = ('drop_target', 'drag_source')
invalid_prefixes = ('css', 'xpath', 'text')
for locator in locators:
assert Element(locator).is_displayed()
assert Element(f'id={locator}').is_displayed()

for invalid_prefix in invalid_prefixes:
with contextlib.suppress(InvalidSelectorException):
assert not Element(f'{invalid_prefix}={locator}').is_displayed()

choose_lang_button_name = 'Choose Language'
locators = (choose_lang_button_name, )
invalid_prefixes = ('css', 'xpath', 'id')
for locator in locators:
breakpoint()
assert Element(locator).is_displayed()
assert Element(f'text={locator}').is_displayed()
if locator == choose_lang_button_name: # Move to separate test
assert not Element('.dropdown-content').is_displayed()
Element(locator).scroll_into_view().click()
Element('.dropdown-content').wait_visibility()

for invalid_prefix in invalid_prefixes:
with contextlib.suppress(InvalidSelectorException):
assert not Element(f'{invalid_prefix}={locator}').is_displayed()

0 comments on commit 6e80ac9

Please sign in to comment.