Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

optimize react select #654

Merged
merged 1 commit into from
Jul 29, 2024
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
30 changes: 29 additions & 1 deletion skyvern/webeye/scraper/domUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,9 @@ async function getSelect2Options(element) {
}

async function getReactSelectOptionElements(element) {
var scrollLeft = window.scrollX;
var scrollTop = window.scrollY;

let optionList = [];
// wait for 2s until the element is updated with `aria-controls`
console.log("wait 2s for the dropdown being updated.");
Expand All @@ -714,7 +717,7 @@ async function getReactSelectOptionElements(element) {
// sometimes need more time to load the options
console.log("wait 5s to load all options");
await sleep(5000); // wait 5s
optionList = dropdownDiv.querySelectorAll("div[role='option']");
optionList = dropdownDiv.querySelectorAll("div[class*='select__option']");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change from div[role='option'] to div[class*='select__option'] needs clarification on its necessity and impact. Ensure it doesn't affect existing functionalities that might rely on the previous selector. This comment applies to all similar changes in this PR.

if (optionList.length === 0) {
break;
}
Expand Down Expand Up @@ -750,6 +753,12 @@ async function getReactSelectOptionElements(element) {
);
}

// scroll back to the original place
window.scroll({
top: scrollTop,
left: scrollLeft,
behavior: "instant",
});
return optionList;
}

Expand Down Expand Up @@ -887,6 +896,12 @@ async function buildTreeFromBody(frame = "main.frame", open_select = false) {
view: window,
}),
);
element.dispatchEvent(
new MouseEvent("mousedown", {
bubbles: true,
view: window,
}),
);

selectOptions = await getReactSelectOptions(element);

Expand All @@ -897,6 +912,19 @@ async function buildTreeFromBody(frame = "main.frame", open_select = false) {
view: window,
}),
);
element.dispatchEvent(
new MouseEvent("mousedown", {
bubbles: true,
view: window,
}),
);
element.dispatchEvent(
new KeyboardEvent("keydown", {
keyCode: 27,
bubbles: true,
key: "Escape",
}),
);
} else if (open_select && isComboboxDropdown(element)) {
// open combobox dropdown to get options
element.click();
Expand Down
11 changes: 6 additions & 5 deletions skyvern/webeye/utils/dom.py
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ def __find_input_locator(self) -> Locator:
locator = self.skyvern_element.get_locator()

if tag_name == InteractiveElement.BUTTON:
return locator.locator("..").locator("..").locator("input[class~='select__input']")
return locator.locator("..").locator("..").locator("input[class*='select__input']")

return locator

Expand All @@ -461,17 +461,18 @@ def name(self) -> str:
return "react-select"

async def open(self, timeout: float = SettingsManager.get_settings().BROWSER_ACTION_TIMEOUT_MS) -> None:
await self.skyvern_element.get_locator().click(timeout=timeout)
await self.skyvern_element.get_locator().focus(timeout=timeout)
await self.skyvern_element.get_locator().press(key="ArrowDown", timeout=timeout)
await self.__find_anchor(timeout=timeout)

async def close(self, timeout: float = SettingsManager.get_settings().BROWSER_ACTION_TIMEOUT_MS) -> None:
await self.__find_anchor(timeout=timeout)
await self.skyvern_element.get_locator().click(timeout=timeout)
await self.skyvern_element.get_locator().press(key="Escape", timeout=timeout)

async def get_current_value(self, timeout: float = SettingsManager.get_settings().BROWSER_ACTION_TIMEOUT_MS) -> str:
input_locator = self.__find_input_locator()
# TODO: only support single value now
value_locator = input_locator.locator("..").locator("..").locator("div[class~='select__single-value']")
value_locator = input_locator.locator("..").locator("..").locator("div[class*='select__single-value']")
if await value_locator.count() == 0:
return ""
try:
Expand All @@ -491,7 +492,7 @@ async def select_by_index(
self, index: int, timeout: float = SettingsManager.get_settings().BROWSER_ACTION_TIMEOUT_MS
) -> None:
anchor = await self.__find_anchor(timeout=timeout)
options = anchor.locator("div[role='option']")
options = anchor.locator("div[class*='select__option']")
await options.nth(index).click(timeout=timeout)


Expand Down
Loading