-
Notifications
You must be signed in to change notification settings - Fork 13
[Req-81] Playwright-Selenium Dual-Driver Implementation #670
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
base: playwright-async
Are you sure you want to change the base?
Changes from all commits
e2255a7
151c2ab
4095923
7bf65e1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -59,6 +59,30 @@ def _get_frame_locator(): | |
| # Variable doesn't exist yet | ||
| return None | ||
|
|
||
|
|
||
| def connect_selenium_to_playwright(port=9222): | ||
| """Connect Selenium to Playwright browser via CDP""" | ||
| try: | ||
| from selenium import webdriver | ||
| from selenium.webdriver.chrome.options import Options | ||
|
|
||
| options = Options() | ||
| options.add_experimental_option("debuggerAddress", f"127.0.0.1:{port}") | ||
|
|
||
| driver = webdriver.Chrome(options=options) | ||
|
|
||
| from Framework.Built_In_Automation.Web.Selenium import BuiltInFunctions as SeleniumBuiltInFunctions | ||
| SeleniumBuiltInFunctions.selenium_driver = driver | ||
|
|
||
| sr.Set_Shared_Variables("selenium_driver", driver) | ||
|
|
||
| CommonUtil.ExecLog("connect_selenium_to_playwright", "Connected Selenium to Playwright", 1) | ||
| return "passed" | ||
|
|
||
| except Exception as e: | ||
| CommonUtil.ExecLog("connect_selenium_to_playwright", f"Failed to connect Selenium to Playwright: {e}", 3) | ||
| return "zeuz_failed" | ||
|
|
||
| ######################### | ||
| # # | ||
| # Global Variables # | ||
|
|
@@ -195,8 +219,11 @@ async def Open_Browser(step_data): | |
| "slow_mo": slow_mo, | ||
| "devtools": devtools, | ||
| } | ||
| if args: | ||
| launch_options["args"] = args | ||
|
|
||
| # Add remote debugging port for CDP connection | ||
| all_args = args + ["--remote-debugging-port=9222"] | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Using a fixed Useful? React with 👍 / 👎. |
||
| if all_args: | ||
| launch_options["args"] = all_args | ||
| if downloads_path: | ||
| launch_options["downloads_path"] = downloads_path | ||
|
|
||
|
|
@@ -265,6 +292,9 @@ async def Open_Browser(step_data): | |
| # Set screenshot variables for CommonUtil.TakeScreenShot() | ||
| CommonUtil.set_screenshot_vars(sr.Shared_Variable_Export()) | ||
|
|
||
| # Connect Selenium to Playwright via CDP | ||
| connect_selenium_to_playwright(port=9222) | ||
|
|
||
| CommonUtil.ExecLog(sModuleInfo, f"Browser opened successfully (page_id: {page_id})", 1) | ||
| return "passed" | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -71,6 +71,8 @@ | |
| from Framework.AI.NLP import binary_classification | ||
| from .utils import ChromeForTesting, ChromeExtensionDownloader | ||
|
|
||
| from playwright.async_api import async_playwright | ||
|
|
||
| ######################### | ||
| # # | ||
| # Global Variables # | ||
|
|
@@ -656,8 +658,24 @@ def headless(): | |
| return options | ||
|
|
||
|
|
||
| async def connect_playwright_to_selenium(port=9222): | ||
| playwright_instance = await async_playwright().start() | ||
| browser = await playwright_instance.chromium.connect_over_cdp(f"http://localhost:{port}") | ||
| context = browser.contexts[0] | ||
| page = context.pages[0] | ||
|
|
||
| from Framework.Built_In_Automation.Web.Playwright import BuiltInFunctions as PlaywrightBuiltInFunctions | ||
| PlaywrightBuiltInFunctions.current_page = page | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This bridge only sets Useful? React with 👍 / 👎. |
||
|
|
||
| Shared_Resources.Set_Shared_Variables("playwright_context", context) | ||
| Shared_Resources.Set_Shared_Variables("playwright_browser", browser) | ||
| Shared_Resources.Set_Shared_Variables("playwright_page", page) | ||
|
|
||
| return "passed" | ||
|
|
||
|
|
||
| @logger | ||
| def Open_Browser(browser, browser_options: BrowserOptions): | ||
| async def Open_Browser(browser, browser_options: BrowserOptions): | ||
| """Launch browser from options and service object""" | ||
| try: | ||
| global selenium_driver | ||
|
|
@@ -687,6 +705,9 @@ def Open_Browser(browser, browser_options: BrowserOptions): | |
|
|
||
| options = generate_options(browser, browser_options) | ||
|
|
||
| # Enable remote debugging / CDP | ||
| options.add_argument("--remote-debugging-port=9222") | ||
|
|
||
| if browser in ("android", "chrome", "chromeheadless"): | ||
| from selenium.webdriver.chrome.service import Service | ||
|
|
||
|
|
@@ -756,6 +777,13 @@ def Open_Browser(browser, browser_options: BrowserOptions): | |
| ) | ||
| return "zeuz_failed" | ||
|
|
||
| # Connect Playwright to Selenium via CDP | ||
| try: | ||
| await connect_playwright_to_selenium(port=9222) | ||
| CommonUtil.ExecLog(sModuleInfo, "Connected Playwright to Selenium", 1) | ||
| except Exception as e: | ||
| CommonUtil.ExecLog(sModuleInfo, f"Failed to connect Playwright to Selenium: {e}", 3) | ||
|
|
||
| CommonUtil.ExecLog(sModuleInfo, f"Started {browser} browser", 1) | ||
| Shared_Resources.Set_Shared_Variables("selenium_driver", selenium_driver) | ||
| CommonUtil.set_screenshot_vars(Shared_Resources.Shared_Variable_Export()) | ||
|
|
@@ -915,7 +943,7 @@ def parse_and_verify_datatype(left: str, right: str, chrome_version=None): | |
|
|
||
|
|
||
| @logger | ||
| def Go_To_Link(dataset: Dataset) -> ReturnType: | ||
| async def Go_To_Link(dataset: Dataset) -> ReturnType: | ||
| try: | ||
| sModuleInfo = inspect.currentframe().f_code.co_name + " : " + MODULE_NAME | ||
| window_size_X = None | ||
|
|
@@ -1117,7 +1145,7 @@ def Go_To_Link(dataset: Dataset) -> ReturnType: | |
| sModuleInfo, "Browser not previously opened, doing so now", 1 | ||
| ) | ||
|
|
||
| if Open_Browser(dependency["Browser"], browser_options) == "zeuz_failed": | ||
| if await Open_Browser(dependency["Browser"], browser_options) == "zeuz_failed": | ||
| return "zeuz_failed" | ||
|
|
||
| if ConfigModule.get_config_value( | ||
|
|
@@ -1191,7 +1219,7 @@ def Go_To_Link(dataset: Dataset) -> ReturnType: | |
| # If the browser is closed but selenium instance is on, relaunch selenium_driver | ||
| if Shared_Resources.Test_Shared_Variables("dependency"): | ||
| dependency = Shared_Resources.Get_Shared_Variables("dependency") | ||
| result = Open_Browser(dependency["Browser"], browser_options) | ||
| result = await Open_Browser(dependency["Browser"], browser_options) | ||
| else: | ||
| result = "zeuz_failed" | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The routing check accepts
BROWSER_DRIVERcase-insensitively, but this assignment uses the raw runtime value, so inputs likePlaywrightorseleniumbecomePlaywright action/selenium actionand then fail module resolution inget_module_and_function(which matches module tokens exactly). This makes the new runtime override intermittently break based on capitalization/spacing even though the validation path explicitly treats those values as valid.Useful? React with 👍 / 👎.