move resolve locator (#472)
This commit is contained in:
@@ -6,16 +6,15 @@ from typing import Any, Awaitable, Callable, List
|
|||||||
|
|
||||||
import structlog
|
import structlog
|
||||||
from deprecation import deprecated
|
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 (
|
from skyvern.exceptions import (
|
||||||
ImaginaryFileUrl,
|
ImaginaryFileUrl,
|
||||||
InvalidElementForTextInput,
|
InvalidElementForTextInput,
|
||||||
MissingElement,
|
MissingElement,
|
||||||
MissingFileUrl,
|
MissingFileUrl,
|
||||||
MultipleElementsFound,
|
MultipleElementsFound,
|
||||||
SkyvernException,
|
|
||||||
)
|
)
|
||||||
from skyvern.forge import app
|
from skyvern.forge import app
|
||||||
from skyvern.forge.prompts import prompt_engine
|
from skyvern.forge.prompts import prompt_engine
|
||||||
@@ -42,6 +41,7 @@ from skyvern.webeye.actions.actions import (
|
|||||||
from skyvern.webeye.actions.responses import ActionFailure, ActionResult, ActionSuccess
|
from skyvern.webeye.actions.responses import ActionFailure, ActionResult, ActionSuccess
|
||||||
from skyvern.webeye.browser_factory import BrowserState
|
from skyvern.webeye.browser_factory import BrowserState
|
||||||
from skyvern.webeye.scraper.scraper import ScrapedPage
|
from skyvern.webeye.scraper.scraper import ScrapedPage
|
||||||
|
from skyvern.webeye.utils.dom import resolve_locator
|
||||||
|
|
||||||
LOG = structlog.get_logger()
|
LOG = structlog.get_logger()
|
||||||
TEXT_INPUT_DELAY = 10 # 10ms between each character input
|
TEXT_INPUT_DELAY = 10 # 10ms between each character input
|
||||||
@@ -996,31 +996,6 @@ async def click_listbox_option(
|
|||||||
return False
|
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:
|
async def get_input_value(locator: Locator) -> str | None:
|
||||||
tag_name = await get_tag_name_lowercase(locator)
|
tag_name = await get_tag_name_lowercase(locator)
|
||||||
if tag_name in COMMON_INPUT_TAGS:
|
if tag_name in COMMON_INPUT_TAGS:
|
||||||
|
|||||||
@@ -2,23 +2,49 @@ import typing
|
|||||||
from enum import StrEnum
|
from enum import StrEnum
|
||||||
|
|
||||||
import structlog
|
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 (
|
from skyvern.exceptions import (
|
||||||
ElementIsNotLabel,
|
ElementIsNotLabel,
|
||||||
MissingElement,
|
MissingElement,
|
||||||
MissingElementDict,
|
MissingElementDict,
|
||||||
MissingElementInIframe,
|
MissingElementInIframe,
|
||||||
MultipleElementsFound,
|
MultipleElementsFound,
|
||||||
|
SkyvernException,
|
||||||
)
|
)
|
||||||
from skyvern.forge.sdk.settings_manager import SettingsManager
|
from skyvern.forge.sdk.settings_manager import SettingsManager
|
||||||
from skyvern.webeye.actions.handler import resolve_locator
|
|
||||||
from skyvern.webeye.scraper.scraper import ScrapedPage
|
from skyvern.webeye.scraper.scraper import ScrapedPage
|
||||||
|
|
||||||
LOG = structlog.get_logger()
|
LOG = structlog.get_logger()
|
||||||
TEXT_INPUT_DELAY = 10
|
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):
|
class InteractiveElement(StrEnum):
|
||||||
INPUT = "input"
|
INPUT = "input"
|
||||||
SELECT = "select"
|
SELECT = "select"
|
||||||
|
|||||||
Reference in New Issue
Block a user