From b40e162dabdcbc2bc25aa95d469f44b0dcc9c4ea Mon Sep 17 00:00:00 2001 From: ZeuZ Agent Date: Sat, 23 May 2026 08:10:09 +0000 Subject: [PATCH 1/4] docs: update instruction files to reflect recent changes Co-Authored-By: ZeuZ Agent --- CLAUDE.md | 2 + .../Web/Selenium/BuiltInFunctions.py | 77 ++++++++++--------- 2 files changed, 42 insertions(+), 37 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index c6c2af41..a58ca821 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -146,6 +146,8 @@ Variables use `%|variable_name|%` syntax: "%|user["name"]|%" # Dictionary access ``` +Some Selenium actions, including `copy image into browser`, accept a single input row that can contain either a literal path or a `%|...|%` reference because the framework resolves it before the action runs. + ### Element Location The unified `LocateElement.Get_Element()` supports: - Selenium WebDriver diff --git a/Framework/Built_In_Automation/Web/Selenium/BuiltInFunctions.py b/Framework/Built_In_Automation/Web/Selenium/BuiltInFunctions.py index 55797f58..ae1354e2 100644 --- a/Framework/Built_In_Automation/Web/Selenium/BuiltInFunctions.py +++ b/Framework/Built_In_Automation/Web/Selenium/BuiltInFunctions.py @@ -5155,17 +5155,12 @@ def if_element_exists(data_set): @logger def copy_image_into_browser(data_set): """ - This action will copy an image from path or a variable into browser, and later you can paste via ctrl+v or cmd+v. + This action will copy an image from path or a shared variable into browser, and later you can paste via ctrl+v or cmd+v. Supported formats: PNG, SVG - Example 1: - Field Sub Field Value - image file input parameter %| image.png |% - copy image into browser selenium action copy image into browser - - Example 2: + Example: Field Sub Field Value - image variable input parameter %| image_var |% + image file input parameter %| image_var |% copy image into browser selenium action copy image into browser """ sModuleInfo = inspect.currentframe().f_code.co_name + " : " + MODULE_NAME @@ -5174,7 +5169,6 @@ def copy_image_into_browser(data_set): try: image_data = None image_path = "" - variable_name = "" mime_type = "image/png" # Parse @@ -5184,35 +5178,36 @@ def copy_image_into_browser(data_set): right = right.strip() if left == "imagefile": - if os.path.exists(right): - image_path = right - else: - image_path = CommonUtil.path_parser(right) + image_path = right - elif left == "imagevariable": - if os.path.exists(right): - image_path = right - else: - variable_name = right + if not image_path: + CommonUtil.ExecLog( + sModuleInfo, "Must provide 'image file' for copy image into browser", 3 + ) + return "zeuz_failed" - if image_path: - if not os.path.exists(image_path): - CommonUtil.ExecLog( - sModuleInfo, f"Image file not found: {image_path}", 3 - ) - return "zeuz_failed" - elif variable_name: - image_path = Shared_Resources.Get_Shared_Variables(variable_name) - if not image_path: - CommonUtil.ExecLog( - sModuleInfo, - f"Image path not found in variable: {variable_name}. Make sure you must be use '%| |%' syntax for any variable or attachment.", - 3, - ) - return "zeuz_failed" - else: + image_path = CommonUtil.path_parser(image_path) + if not image_path: CommonUtil.ExecLog( - sModuleInfo, "Must provide either 'image file' or 'image variable'", 3 + sModuleInfo, + "Image path resolved to an empty value. Check the 'image file' input.", + 3, + ) + return "zeuz_failed" + + if not os.path.exists(image_path): + CommonUtil.ExecLog( + sModuleInfo, + f"Image file not found or unreadable: {image_path}", + 3, + ) + return "zeuz_failed" + + if not os.path.isfile(image_path): + CommonUtil.ExecLog( + sModuleInfo, + f"Image path is not a file: {image_path}", + 3, ) return "zeuz_failed" @@ -5228,8 +5223,16 @@ def copy_image_into_browser(data_set): ) return "zeuz_failed" - with open(image_path, "rb") as image_file: - image_data = image_file.read() + try: + with open(image_path, "rb") as image_file: + image_data = image_file.read() + except OSError as exc: + CommonUtil.ExecLog( + sModuleInfo, + f"Unable to read image file '{image_path}': {exc}", + 3, + ) + return "zeuz_failed" # Convert image_b64 = base64.b64encode(image_data).decode("utf-8") From c5a96b389ed730b54d1a99157241520f96f8b47e Mon Sep 17 00:00:00 2001 From: ZeuZ Agent Date: Sat, 23 May 2026 08:16:20 +0000 Subject: [PATCH 2/4] docs: update instruction files to reflect recent changes Co-Authored-By: ZeuZ Agent --- CLAUDE.md | 2 +- .../Web/Selenium/BuiltInFunctions.py | 21 +++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index a58ca821..977734ef 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -146,7 +146,7 @@ Variables use `%|variable_name|%` syntax: "%|user["name"]|%" # Dictionary access ``` -Some Selenium actions, including `copy image into browser`, accept a single input row that can contain either a literal path or a `%|...|%` reference because the framework resolves it before the action runs. +Some Selenium actions, including `copy image into browser`, use a single `image file` row whose value can be a literal path or a `%|...|%` expression such as `%|var|%/whatever.png` because the framework resolves it before the action runs. ### Element Location The unified `LocateElement.Get_Element()` supports: diff --git a/Framework/Built_In_Automation/Web/Selenium/BuiltInFunctions.py b/Framework/Built_In_Automation/Web/Selenium/BuiltInFunctions.py index ae1354e2..c1839ae3 100644 --- a/Framework/Built_In_Automation/Web/Selenium/BuiltInFunctions.py +++ b/Framework/Built_In_Automation/Web/Selenium/BuiltInFunctions.py @@ -1434,8 +1434,6 @@ def parse_status_codes(code_str): "method_filter": [], "include_body": False, } - - # Parse for left, mid, right in step_data: left = left.lower().strip() if left == "capture network log": @@ -5155,23 +5153,21 @@ def if_element_exists(data_set): @logger def copy_image_into_browser(data_set): """ - This action will copy an image from path or a shared variable into browser, and later you can paste via ctrl+v or cmd+v. + This action will copy an image from path or a shared-variable expression into the browser, + and later you can paste via ctrl+v or cmd+v. Supported formats: PNG, SVG Example: Field Sub Field Value - image file input parameter %| image_var |% - copy image into browser selenium action copy image into browser + copy image into browser selenium action %|var|%/whatever.png """ sModuleInfo = inspect.currentframe().f_code.co_name + " : " + MODULE_NAME global selenium_driver try: - image_data = None image_path = "" mime_type = "image/png" - # Parse for left, mid, right in data_set: left = left.lower().replace(" ", "") mid = mid.lower().replace(" ", "") @@ -5179,6 +5175,13 @@ def copy_image_into_browser(data_set): if left == "imagefile": image_path = right + elif left in {"imagevariable", "imagevar"}: + CommonUtil.ExecLog( + sModuleInfo, + "Use only the 'image file' row for copy image into browser.", + 3, + ) + return "zeuz_failed" if not image_path: CommonUtil.ExecLog( @@ -5190,7 +5193,7 @@ def copy_image_into_browser(data_set): if not image_path: CommonUtil.ExecLog( sModuleInfo, - "Image path resolved to an empty value. Check the 'image file' input.", + "Image file resolved to an empty value. Check the 'image file' input.", 3, ) return "zeuz_failed" @@ -5206,7 +5209,7 @@ def copy_image_into_browser(data_set): if not os.path.isfile(image_path): CommonUtil.ExecLog( sModuleInfo, - f"Image path is not a file: {image_path}", + f"Image file is not a file: {image_path}", 3, ) return "zeuz_failed" From 0bb52f0522a98311f4eba47f75b666441a722e79 Mon Sep 17 00:00:00 2001 From: ZeuZ Agent Date: Sat, 23 May 2026 10:27:23 +0000 Subject: [PATCH 3/4] docs: update instruction files to reflect recent changes Co-Authored-By: ZeuZ Agent --- .../Web/Selenium/BuiltInFunctions.py | 58 ++++++++----------- tests/test_copy_image_into_browser.py | 48 +++++++++++++++ 2 files changed, 72 insertions(+), 34 deletions(-) create mode 100644 tests/test_copy_image_into_browser.py diff --git a/Framework/Built_In_Automation/Web/Selenium/BuiltInFunctions.py b/Framework/Built_In_Automation/Web/Selenium/BuiltInFunctions.py index 55797f58..b5316bd6 100644 --- a/Framework/Built_In_Automation/Web/Selenium/BuiltInFunctions.py +++ b/Framework/Built_In_Automation/Web/Selenium/BuiltInFunctions.py @@ -5155,17 +5155,12 @@ def if_element_exists(data_set): @logger def copy_image_into_browser(data_set): """ - This action will copy an image from path or a variable into browser, and later you can paste via ctrl+v or cmd+v. + This action will copy an image from a single image file input into browser, and later you can paste via ctrl+v or cmd+v. Supported formats: PNG, SVG - Example 1: - Field Sub Field Value - image file input parameter %| image.png |% - copy image into browser selenium action copy image into browser - - Example 2: + Example: Field Sub Field Value - image variable input parameter %| image_var |% + image file input parameter %|var|%/whatever.png copy image into browser selenium action copy image into browser """ sModuleInfo = inspect.currentframe().f_code.co_name + " : " + MODULE_NAME @@ -5174,7 +5169,6 @@ def copy_image_into_browser(data_set): try: image_data = None image_path = "" - variable_name = "" mime_type = "image/png" # Parse @@ -5184,35 +5178,31 @@ def copy_image_into_browser(data_set): right = right.strip() if left == "imagefile": - if os.path.exists(right): + image_path = CommonUtil.path_parser(right) if right else "" + if not image_path and right: image_path = right - else: - image_path = CommonUtil.path_parser(right) - elif left == "imagevariable": - if os.path.exists(right): - image_path = right - else: - variable_name = right + if not image_path: + CommonUtil.ExecLog( + sModuleInfo, "Must provide a value for 'image file'", 3 + ) + return "zeuz_failed" - if image_path: - if not os.path.exists(image_path): - CommonUtil.ExecLog( - sModuleInfo, f"Image file not found: {image_path}", 3 - ) - return "zeuz_failed" - elif variable_name: - image_path = Shared_Resources.Get_Shared_Variables(variable_name) - if not image_path: - CommonUtil.ExecLog( - sModuleInfo, - f"Image path not found in variable: {variable_name}. Make sure you must be use '%| |%' syntax for any variable or attachment.", - 3, - ) - return "zeuz_failed" - else: + if not os.path.exists(image_path): + CommonUtil.ExecLog( + sModuleInfo, f"Image file not found: {image_path}", 3 + ) + return "zeuz_failed" + + if not os.path.isfile(image_path): + CommonUtil.ExecLog( + sModuleInfo, f"Image path is not a file: {image_path}", 3 + ) + return "zeuz_failed" + + if not os.access(image_path, os.R_OK): CommonUtil.ExecLog( - sModuleInfo, "Must provide either 'image file' or 'image variable'", 3 + sModuleInfo, f"Image file is not readable: {image_path}", 3 ) return "zeuz_failed" diff --git a/tests/test_copy_image_into_browser.py b/tests/test_copy_image_into_browser.py new file mode 100644 index 00000000..29e94845 --- /dev/null +++ b/tests/test_copy_image_into_browser.py @@ -0,0 +1,48 @@ +import unittest +from unittest.mock import MagicMock, mock_open, patch + +from Framework.Built_In_Automation.Web.Selenium.BuiltInFunctions import ( + copy_image_into_browser, +) + + +class CopyImageIntoBrowserTests(unittest.TestCase): + @patch("Framework.Built_In_Automation.Web.Selenium.BuiltInFunctions.selenium_driver") + @patch("Framework.Built_In_Automation.Web.Selenium.BuiltInFunctions.CommonUtil.ExecLog") + @patch("Framework.Built_In_Automation.Web.Selenium.BuiltInFunctions.CommonUtil.path_parser") + @patch("Framework.Built_In_Automation.Web.Selenium.BuiltInFunctions.os.access", return_value=True) + @patch("Framework.Built_In_Automation.Web.Selenium.BuiltInFunctions.os.path.isfile", return_value=True) + @patch("Framework.Built_In_Automation.Web.Selenium.BuiltInFunctions.os.path.exists", return_value=True) + @patch("Framework.Built_In_Automation.Web.Selenium.BuiltInFunctions.open", new_callable=mock_open, read_data=b"fakepng") + def test_accepts_single_image_file_row_with_mixed_variable_path( + self, + mock_open_file, + mock_exists, + mock_isfile, + mock_access, + mock_path_parser, + mock_exec_log, + mock_driver, + ): + mock_path_parser.return_value = "/resolved/image.png" + mock_driver.capabilities = {"browserName": "chrome"} + mock_driver.execute_cdp_cmd = MagicMock() + + result = copy_image_into_browser( + [("image file", "input parameter", "%|var|%/whatever.png")] + ) + + self.assertEqual(result, "passed") + mock_path_parser.assert_called_once_with("%|var|%/whatever.png") + mock_driver.execute_cdp_cmd.assert_called_once() + mock_exec_log.assert_any_call( + "copy_image_into_browser : selenium", "Image copied to clipboard via CDP: /resolved/image.png", 1 + ) + + @patch("Framework.Built_In_Automation.Web.Selenium.BuiltInFunctions.CommonUtil.ExecLog") + def test_rejects_missing_image_file_value(self, mock_exec_log): + result = copy_image_into_browser([]) + + self.assertEqual(result, "zeuz_failed") + mock_exec_log.assert_called_once() + self.assertIn("image file", mock_exec_log.call_args.args[1]) From 502da96e87db24d209e5b0c0bb660a1dbe8fd782 Mon Sep 17 00:00:00 2001 From: ZeuZ Agent Date: Sun, 24 May 2026 08:58:13 +0000 Subject: [PATCH 4/4] docs: update instruction files to reflect recent changes Co-Authored-By: ZeuZ Agent --- .../Web/Selenium/BuiltInFunctions.py | 212 ------------------ tests/test_copy_image_into_browser.py | 32 +++ 2 files changed, 32 insertions(+), 212 deletions(-) diff --git a/Framework/Built_In_Automation/Web/Selenium/BuiltInFunctions.py b/Framework/Built_In_Automation/Web/Selenium/BuiltInFunctions.py index cdcd685f..2378ea25 100644 --- a/Framework/Built_In_Automation/Web/Selenium/BuiltInFunctions.py +++ b/Framework/Built_In_Automation/Web/Selenium/BuiltInFunctions.py @@ -5151,215 +5151,3 @@ def if_element_exists(data_set): @logger -def copy_image_into_browser(data_set): - """ -<<<<<<< HEAD - This action will copy an image from a single image file input into browser, and later you can paste via ctrl+v or cmd+v. -======= - This action will copy an image from path or a shared-variable expression into the browser, - and later you can paste via ctrl+v or cmd+v. ->>>>>>> origin/zeuz-REQ-75 - Supported formats: PNG, SVG - - Example: - Field Sub Field Value -<<<<<<< HEAD - image file input parameter %|var|%/whatever.png - copy image into browser selenium action copy image into browser -======= - copy image into browser selenium action %|var|%/whatever.png ->>>>>>> origin/zeuz-REQ-75 - """ - sModuleInfo = inspect.currentframe().f_code.co_name + " : " + MODULE_NAME - global selenium_driver - - try: - image_path = "" - mime_type = "image/png" - - for left, mid, right in data_set: - left = left.lower().replace(" ", "") - mid = mid.lower().replace(" ", "") - right = right.strip() - - if left == "imagefile": -<<<<<<< HEAD - image_path = CommonUtil.path_parser(right) if right else "" - if not image_path and right: - image_path = right - - if not image_path: - CommonUtil.ExecLog( - sModuleInfo, "Must provide a value for 'image file'", 3 -======= - image_path = right - elif left in {"imagevariable", "imagevar"}: - CommonUtil.ExecLog( - sModuleInfo, - "Use only the 'image file' row for copy image into browser.", - 3, - ) - return "zeuz_failed" - - if not image_path: - CommonUtil.ExecLog( - sModuleInfo, "Must provide 'image file' for copy image into browser", 3 - ) - return "zeuz_failed" - - image_path = CommonUtil.path_parser(image_path) - if not image_path: - CommonUtil.ExecLog( - sModuleInfo, - "Image file resolved to an empty value. Check the 'image file' input.", - 3, ->>>>>>> origin/zeuz-REQ-75 - ) - return "zeuz_failed" - - if not os.path.exists(image_path): - CommonUtil.ExecLog( -<<<<<<< HEAD - sModuleInfo, f"Image file not found: {image_path}", 3 -======= - sModuleInfo, - f"Image file not found or unreadable: {image_path}", - 3, ->>>>>>> origin/zeuz-REQ-75 - ) - return "zeuz_failed" - - if not os.path.isfile(image_path): - CommonUtil.ExecLog( -<<<<<<< HEAD - sModuleInfo, f"Image path is not a file: {image_path}", 3 - ) - return "zeuz_failed" - - if not os.access(image_path, os.R_OK): - CommonUtil.ExecLog( - sModuleInfo, f"Image file is not readable: {image_path}", 3 -======= - sModuleInfo, - f"Image file is not a file: {image_path}", - 3, ->>>>>>> origin/zeuz-REQ-75 - ) - return "zeuz_failed" - - if image_path.lower().endswith(".svg"): - mime_type = "image/svg+xml" - elif image_path.lower().endswith(".png"): - mime_type = "image/png" - else: - CommonUtil.ExecLog( - sModuleInfo, - "Unsupported file format. You can copy only PNG or SVG image.", - 2, - ) - return "zeuz_failed" - - try: - with open(image_path, "rb") as image_file: - image_data = image_file.read() - except OSError as exc: - CommonUtil.ExecLog( - sModuleInfo, - f"Unable to read image file '{image_path}': {exc}", - 3, - ) - return "zeuz_failed" - - # Convert - image_b64 = base64.b64encode(image_data).decode("utf-8") - - browser_name = selenium_driver.capabilities.get("browserName", "").lower() - if browser_name in ("chrome", "microsoft edge", "edge"): - try: - selenium_driver.execute_cdp_cmd( - "Browser.setClipboard", {"data": image_b64, "type": mime_type} - ) - CommonUtil.ExecLog( - sModuleInfo, f"Image copied to clipboard via CDP: {image_path}", 1 - ) - return "passed" - except Exception as e: - CommonUtil.ExecLog( - sModuleInfo, f"CDP failed ({str(e)}). Trying fallback method", 2 - ) - - try: - # Grant clipboard permissions via CDP if possible - try: - from urllib.parse import urlparse - - parsed_uri = urlparse(selenium_driver.current_url) - origin = f"{parsed_uri.scheme}://{parsed_uri.netloc}" - selenium_driver.execute_cdp_cmd( - "Browser.grantPermissions", - { - "origin": origin, - "permissions": [ - "clipboardReadWrite", - "clipboardSanitizedWrite", - ], - }, - ) - except: - pass - - async_script = """ - const [base64Data, mimeType, callback] = arguments; - const byteCharacters = atob(base64Data); - const byteArrays = []; - - for (let offset = 0; offset < byteCharacters.length; offset += 512) { - const slice = byteCharacters.slice(offset, offset + 512); - const byteNumbers = new Array(slice.length); - - for (let i = 0; i < slice.length; i++) { - byteNumbers[i] = slice.charCodeAt(i); - } - - byteArrays.push(new Uint8Array(byteNumbers)); - } - - const blob = new Blob(byteArrays, {type: mimeType}); - const item = new ClipboardItem({ [mimeType]: blob }); - - window.focus(); - navigator.clipboard.write([item]) - .then(() => { - console.log('Successfully copied image to clipboard.'); - callback(true); - }) - .catch(err => { - console.log('Failed to copy image to clipboard', err); - callback(false); - }); - """ - - selenium_driver.switch_to.window(selenium_driver.current_window_handle) - selenium_driver.execute_script("window.focus();") - - success = selenium_driver.execute_async_script( - async_script, image_b64, mime_type - ) - if success: - CommonUtil.ExecLog( - sModuleInfo, f"Image copied to clipboard: {image_path}", 1 - ) - return "passed" - CommonUtil.ExecLog( - sModuleInfo, - f"Document is not focused. Failed to copy image to clipboard: {image_path}", - 3, - ) - return "zeuz_failed" - - except Exception as e: - CommonUtil.ExecLog(sModuleInfo, f"Fallback method failed: {str(e)}", 3) - return "zeuz_failed" - - except Exception: - return CommonUtil.Exception_Handler(sys.exc_info()) diff --git a/tests/test_copy_image_into_browser.py b/tests/test_copy_image_into_browser.py index 29e94845..e931808b 100644 --- a/tests/test_copy_image_into_browser.py +++ b/tests/test_copy_image_into_browser.py @@ -39,6 +39,38 @@ def test_accepts_single_image_file_row_with_mixed_variable_path( "copy_image_into_browser : selenium", "Image copied to clipboard via CDP: /resolved/image.png", 1 ) + @patch("Framework.Built_In_Automation.Web.Selenium.BuiltInFunctions.selenium_driver") + @patch("Framework.Built_In_Automation.Web.Selenium.BuiltInFunctions.CommonUtil.ExecLog") + @patch("Framework.Built_In_Automation.Web.Selenium.BuiltInFunctions.CommonUtil.path_parser") + @patch("Framework.Built_In_Automation.Web.Selenium.BuiltInFunctions.os.access", return_value=True) + @patch("Framework.Built_In_Automation.Web.Selenium.BuiltInFunctions.os.path.isfile", return_value=True) + @patch("Framework.Built_In_Automation.Web.Selenium.BuiltInFunctions.os.path.exists", return_value=True) + @patch("Framework.Built_In_Automation.Web.Selenium.BuiltInFunctions.open", new_callable=mock_open, read_data=b"fakepng") + def test_accepts_single_literal_image_path_row( + self, + mock_open_file, + mock_exists, + mock_isfile, + mock_access, + mock_path_parser, + mock_exec_log, + mock_driver, + ): + mock_path_parser.side_effect = lambda value: value + mock_driver.capabilities = {"browserName": "chrome"} + mock_driver.execute_cdp_cmd = MagicMock() + + result = copy_image_into_browser( + [("image file", "input parameter", "/tmp/whatever.png")] + ) + + self.assertEqual(result, "passed") + mock_path_parser.assert_called_once_with("/tmp/whatever.png") + mock_driver.execute_cdp_cmd.assert_called_once() + mock_exec_log.assert_any_call( + "copy_image_into_browser : selenium", "Image copied to clipboard via CDP: /tmp/whatever.png", 1 + ) + @patch("Framework.Built_In_Automation.Web.Selenium.BuiltInFunctions.CommonUtil.ExecLog") def test_rejects_missing_image_file_value(self, mock_exec_log): result = copy_image_into_browser([])