Skip to content

Commit

Permalink
move resolve locator (#472)
Browse files Browse the repository at this point in the history
  • Loading branch information
LawyZheng committed Jun 14, 2024
1 parent 08c3fe1 commit 9c2be13
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 30 deletions.
31 changes: 3 additions & 28 deletions skyvern/webeye/actions/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,15 @@

import structlog
from deprecation import deprecated
from playwright.async_api import FrameLocator, Locator, Page, TimeoutError
from playwright.async_api import Locator, Page, TimeoutError

from skyvern.constants import REPO_ROOT_DIR, SKYVERN_ID_ATTR
from skyvern.constants import REPO_ROOT_DIR
from skyvern.exceptions import (
ImaginaryFileUrl,
InvalidElementForTextInput,
MissingElement,
MissingFileUrl,
MultipleElementsFound,
SkyvernException,
)
from skyvern.forge import app
from skyvern.forge.prompts import prompt_engine
Expand All @@ -42,6 +41,7 @@
from skyvern.webeye.actions.responses import ActionFailure, ActionResult, ActionSuccess
from skyvern.webeye.browser_factory import BrowserState
from skyvern.webeye.scraper.scraper import ScrapedPage
from skyvern.webeye.utils.dom import resolve_locator

LOG = structlog.get_logger()
TEXT_INPUT_DELAY = 10 # 10ms between each character input
Expand Down Expand Up @@ -996,31 +996,6 @@ async def click_listbox_option(
return False


def resolve_locator(scrape_page: ScrapedPage, page: Page, frame: str, xpath: str) -> Locator:
iframe_path: list[str] = []

while frame != "main.frame":
iframe_path.append(frame)

frame_element = scrape_page.id_to_element_dict.get(frame)
if frame_element is None:
raise MissingElement(element_id=frame)

parent_frame = frame_element.get("frame")
if not parent_frame:
raise SkyvernException(f"element without frame: {frame_element}")

LOG.info(f"{frame} is a child frame of {parent_frame}")
frame = parent_frame

current_page: Page | FrameLocator = page
while len(iframe_path) > 0:
child_frame = iframe_path.pop()
current_page = current_page.frame_locator(f"[{SKYVERN_ID_ATTR}='{child_frame}']")

return current_page.locator(f"xpath={xpath}")


async def get_input_value(locator: Locator) -> str | None:
tag_name = await get_tag_name_lowercase(locator)
if tag_name in COMMON_INPUT_TAGS:
Expand Down
30 changes: 28 additions & 2 deletions skyvern/webeye/utils/dom.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,49 @@
from enum import StrEnum

import structlog
from playwright.async_api import Locator, Page
from playwright.async_api import FrameLocator, Locator, Page

from skyvern.constants import SKYVERN_ID_ATTR
from skyvern.exceptions import (
ElementIsNotLabel,
MissingElement,
MissingElementDict,
MissingElementInIframe,
MultipleElementsFound,
SkyvernException,
)
from skyvern.forge.sdk.settings_manager import SettingsManager
from skyvern.webeye.actions.handler import resolve_locator
from skyvern.webeye.scraper.scraper import ScrapedPage

LOG = structlog.get_logger()
TEXT_INPUT_DELAY = 10


def resolve_locator(scrape_page: ScrapedPage, page: Page, frame: str, xpath: str) -> Locator:
iframe_path: list[str] = []

while frame != "main.frame":
iframe_path.append(frame)

frame_element = scrape_page.id_to_element_dict.get(frame)
if frame_element is None:
raise MissingElement(element_id=frame)

parent_frame = frame_element.get("frame")
if not parent_frame:
raise SkyvernException(f"element without frame: {frame_element}")

LOG.info(f"{frame} is a child frame of {parent_frame}")
frame = parent_frame

current_page: Page | FrameLocator = page
while len(iframe_path) > 0:
child_frame = iframe_path.pop()
current_page = current_page.frame_locator(f"[{SKYVERN_ID_ATTR}='{child_frame}']")

return current_page.locator(f"xpath={xpath}")


class InteractiveElement(StrEnum):
INPUT = "input"
SELECT = "select"
Expand Down

0 comments on commit 9c2be13

Please sign in to comment.