Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -2327,6 +2327,62 @@ def compare_variable_names(set, dataset):
CommonUtil.compare_action_varnames = {"left": "Left", "right": "Right"}


def get_browser_driver_routing(action_subfield, data_set):
"""
Check if browser driver optional parameter is present and route to appropriate driver.

Args:
action_subfield (str): The original action subfield (e.g., "selenium action", "playwright action")
data_set (list): The data set containing optional parameters

Returns:
str: Updated action_subfield based on browser driver parameter

This function checks if there is a "browser driver" optional parameter in the data set or a BROWSER_DRIVER in runtime parameters.
If any of them are present, it updates the action_subfield to the value specified.
If both are present, it uses the action-level optional parameter.
If neither are present, it returns the original action_subfield.
"""
sModuleInfo = inspect.currentframe().f_code.co_name + " : " + MODULE_NAME

# If the action subfield is not for playwright or selenium, return as is
if action_subfield not in ("playwright action", "selenium action"):
return action_subfield

# Initialize the updated action subfield with the original action subfield
updated_action_subfield = action_subfield

# Get the runtime parameter for browser driver preference
browser_driver_runtime_parameter = sr.shared_variables.get("BROWSER_DRIVER")

# If runtime parameter is present and valid, update the action subfield
if browser_driver_runtime_parameter and browser_driver_runtime_parameter.strip().lower() in ("playwright", "selenium"):
CommonUtil.ExecLog(sModuleInfo, "Runtime parameter for browser driver preference detected", 5)
updated_action_subfield = browser_driver_runtime_parameter + " action"

# Check if there is an optional parameter for browser driver in the data set
for left, mid, right in data_set:
# If optional parameter is present and valid, update the action subfield
if (mid.strip().lower().startswith("optional")
and left.strip().lower() == "browser driver"
and right.strip().lower() in ("playwright", "selenium")):

# If runtime parameter is also present, action-level optional parameter will take precedence
if browser_driver_runtime_parameter:
# log a warning for browser driver preference in two places
CommonUtil.ExecLog(sModuleInfo, "Both runtime parameter and optional parameter for browser driver detected, using optional parameter", 2)
else:
CommonUtil.ExecLog(sModuleInfo, "Optional parameter for browser driver preference detected in action", 5)
updated_action_subfield = right.strip().lower() + " action"
break

# If the action subfield has changed, log the change
if action_subfield != updated_action_subfield:
CommonUtil.ExecLog(sModuleInfo, "Browser action changed from %s to %s" % (action_subfield, updated_action_subfield), 1)

return updated_action_subfield


async def Action_Handler(_data_set, action_row, _bypass_bug=True):
""" Finds the appropriate function for the requested action in the step data and executes it """

Expand All @@ -2337,6 +2393,9 @@ async def Action_Handler(_data_set, action_row, _bypass_bug=True):
action_name = action_row[0]
action_subfield = action_row[1]

# Apply browser driver routing if applicable
action_subfield = get_browser_driver_routing(action_subfield, _data_set)

if str(action_name).startswith("%|"): # if shared variable
action_name = sr.get_previous_response_variables_in_strings(action_name)

Expand Down
34 changes: 32 additions & 2 deletions Framework/Built_In_Automation/Web/Playwright/BuiltInFunctions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 #
Expand Down Expand Up @@ -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"]
if all_args:
launch_options["args"] = all_args
if downloads_path:
launch_options["downloads_path"] = downloads_path

Expand Down Expand Up @@ -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"

Expand Down
36 changes: 32 additions & 4 deletions Framework/Built_In_Automation/Web/Selenium/BuiltInFunctions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 #
Expand Down Expand Up @@ -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

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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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"

Expand Down
Loading