Skip to content

Commit 05970f0

Browse files
committed
Added support for iframe context switching in all Playwright actions
1 parent c26b182 commit 05970f0

File tree

2 files changed

+60
-42
lines changed

2 files changed

+60
-42
lines changed

Framework/Built_In_Automation/Web/Playwright/BuiltInFunctions.py

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@
4646
from Framework.Utilities.CommonUtil import passed_tag_list, failed_tag_list
4747
from . import locator as PlaywrightLocator
4848

49+
def _get_frame_locator():
50+
"""Helper function to get current frame locator from shared variables."""
51+
frame_locator = sr.Get_Shared_Variables("playwright_frame")
52+
if frame_locator in failed_tag_list:
53+
return None
54+
return frame_locator
55+
4956
#########################
5057
# #
5158
# Global Variables #
@@ -495,7 +502,7 @@ async def Click_Element(step_data):
495502
right_click = True
496503

497504
# Get element
498-
locator = await PlaywrightLocator.Get_Element(step_data, current_page)
505+
locator = await PlaywrightLocator.Get_Element(step_data, current_page, frame_locator=_get_frame_locator())
499506
if locator == "zeuz_failed":
500507
CommonUtil.ExecLog(sModuleInfo, "Element not found", 3)
501508
return "zeuz_failed"
@@ -609,7 +616,7 @@ async def Hover_Over_Element(step_data):
609616
elif left_l == "timeout":
610617
timeout = int(float(right_v) * 1000)
611618

612-
locator = await PlaywrightLocator.Get_Element(step_data, current_page)
619+
locator = await PlaywrightLocator.Get_Element(step_data, current_page, frame_locator=_get_frame_locator())
613620
if locator == "zeuz_failed":
614621
CommonUtil.ExecLog(sModuleInfo, "Element not found", 3)
615622
return "zeuz_failed"
@@ -686,7 +693,7 @@ async def Enter_Text_In_Text_Box(step_data):
686693
elif left_l == "timeout":
687694
timeout = int(float(right.strip()) * 1000)
688695

689-
locator = await PlaywrightLocator.Get_Element(step_data, current_page)
696+
locator = await PlaywrightLocator.Get_Element(step_data, current_page, frame_locator=_get_frame_locator())
690697
if locator == "zeuz_failed":
691698
CommonUtil.ExecLog(sModuleInfo, "Element not found", 3)
692699
return "zeuz_failed"
@@ -830,7 +837,7 @@ async def Keystroke_For_Element(step_data):
830837
key = key_map.get(key, keystroke_value)
831838

832839
if has_element:
833-
locator = await PlaywrightLocator.Get_Element(step_data, current_page)
840+
locator = await PlaywrightLocator.Get_Element(step_data, current_page, frame_locator=_get_frame_locator())
834841
if locator == "zeuz_failed":
835842
CommonUtil.ExecLog(sModuleInfo, "Element not found", 3)
836843
return "zeuz_failed"
@@ -853,7 +860,7 @@ async def Keystroke_For_Element(step_data):
853860
type_options["delay"] = int(delay * 1000)
854861

855862
if has_element:
856-
locator = await PlaywrightLocator.Get_Element(step_data, current_page)
863+
locator = await PlaywrightLocator.Get_Element(step_data, current_page, frame_locator=_get_frame_locator())
857864
if locator == "zeuz_failed":
858865
CommonUtil.ExecLog(sModuleInfo, "Element not found", 3)
859866
return "zeuz_failed"
@@ -930,7 +937,7 @@ async def Validate_Text(step_data):
930937
if left_l == "timeout":
931938
timeout = int(float(right_v) * 1000)
932939

933-
locator = await PlaywrightLocator.Get_Element(step_data, current_page)
940+
locator = await PlaywrightLocator.Get_Element(step_data, current_page, frame_locator=_get_frame_locator())
934941
if locator == "zeuz_failed":
935942
CommonUtil.ExecLog(sModuleInfo, "Element not found", 3)
936943
return "zeuz_failed"
@@ -995,7 +1002,7 @@ async def if_element_exists(step_data):
9951002
if mid_l == "optional parameter" and left_l == "timeout":
9961003
timeout = int(float(right_v) * 1000)
9971004

998-
locator = await PlaywrightLocator.Get_Element(step_data, current_page, element_wait=timeout/1000)
1005+
locator = await PlaywrightLocator.Get_Element(step_data, current_page, element_wait=timeout/1000, frame_locator=_get_frame_locator())
9991006

10001007
if locator == "zeuz_failed":
10011008
CommonUtil.ExecLog(sModuleInfo, "Element does not exist", 1)
@@ -1069,7 +1076,7 @@ async def Save_Attribute(step_data):
10691076
CommonUtil.ExecLog(sModuleInfo, "No save variable specified", 3)
10701077
return "zeuz_failed"
10711078

1072-
locator = await PlaywrightLocator.Get_Element(step_data, current_page)
1079+
locator = await PlaywrightLocator.Get_Element(step_data, current_page, frame_locator=_get_frame_locator())
10731080
if locator == "zeuz_failed":
10741081
CommonUtil.ExecLog(sModuleInfo, "Element not found", 3)
10751082
return "zeuz_failed"
@@ -1131,7 +1138,7 @@ async def get_element_info(step_data):
11311138
if mid.strip().lower() == "save parameter":
11321139
save_variable = left.strip()
11331140

1134-
locator = await PlaywrightLocator.Get_Element(step_data, current_page)
1141+
locator = await PlaywrightLocator.Get_Element(step_data, current_page, frame_locator=_get_frame_locator())
11351142
if locator == "zeuz_failed":
11361143
CommonUtil.ExecLog(sModuleInfo, "Element not found", 3)
11371144
return "zeuz_failed"
@@ -1363,7 +1370,7 @@ async def scroll_to_element(step_data):
13631370
elif left_l == "align to top":
13641371
align_to_top = right_v.lower() in ("true", "yes", "1")
13651372

1366-
locator = await PlaywrightLocator.Get_Element(step_data, current_page)
1373+
locator = await PlaywrightLocator.Get_Element(step_data, current_page, frame_locator=_get_frame_locator())
13671374
if locator == "zeuz_failed":
13681375
CommonUtil.ExecLog(sModuleInfo, "Element not found", 3)
13691376
return "zeuz_failed"
@@ -1443,7 +1450,7 @@ async def Select_Deselect(step_data):
14431450
CommonUtil.ExecLog(sModuleInfo, "No selection value provided", 3)
14441451
return "zeuz_failed"
14451452

1446-
locator = await PlaywrightLocator.Get_Element(step_data, current_page)
1453+
locator = await PlaywrightLocator.Get_Element(step_data, current_page, frame_locator=_get_frame_locator())
14471454
if locator == "zeuz_failed":
14481455
CommonUtil.ExecLog(sModuleInfo, "Element not found", 3)
14491456
return "zeuz_failed"
@@ -1521,7 +1528,7 @@ async def check_uncheck(step_data):
15211528
if left_l == "use js":
15221529
use_js = right_v in ("true", "yes", "1")
15231530

1524-
locator = await PlaywrightLocator.Get_Element(step_data, current_page)
1531+
locator = await PlaywrightLocator.Get_Element(step_data, current_page, frame_locator=_get_frame_locator())
15251532
if locator == "zeuz_failed":
15261533
CommonUtil.ExecLog(sModuleInfo, "Element not found", 3)
15271534
return "zeuz_failed"
@@ -1758,7 +1765,7 @@ def close_tab(step_data):
17581765
#########################
17591766

17601767
@logger
1761-
def switch_iframe(step_data):
1768+
async def switch_iframe(step_data):
17621769
"""
17631770
Switch to an iframe or back to main content.
17641771
@@ -1806,6 +1813,7 @@ def switch_iframe(step_data):
18061813
if switch_to_default:
18071814
# In Playwright, we work with the main page directly
18081815
# Store a flag or reset frame locator
1816+
sr.Set_Shared_Variables("playwright_frame", None)
18091817
CommonUtil.ExecLog(sModuleInfo, "Switched to default content", 1)
18101818
return "passed"
18111819

@@ -1974,13 +1982,13 @@ async def drag_and_drop(step_data):
19741982
source_param = left.strip()
19751983

19761984
# Get source element
1977-
source_locator = await PlaywrightLocator.Get_Element(source_param, current_page)
1985+
source_locator = await PlaywrightLocator.Get_Element(source_param, current_page, frame_locator=_get_frame_locator())
19781986
if source_locator == "zeuz_failed":
19791987
CommonUtil.ExecLog(sModuleInfo, "Source element not found", 3)
19801988
return "zeuz_failed"
19811989

19821990
# Get target element
1983-
target_locator = await PlaywrightLocator.Get_Element(target_param, current_page)
1991+
target_locator = await PlaywrightLocator.Get_Element(target_param, current_page, frame_locator=_get_frame_locator())
19841992
if target_locator == "zeuz_failed":
19851993
CommonUtil.ExecLog(sModuleInfo, "Target element not found", 3)
19861994
return "zeuz_failed"
@@ -2053,7 +2061,7 @@ async def take_screenshot_playwright(step_data):
20532061

20542062
# Take screenshot
20552063
if has_element:
2056-
locator = await PlaywrightLocator.Get_Element(step_data, current_page)
2064+
locator = await PlaywrightLocator.Get_Element(step_data, current_page, frame_locator=_get_frame_locator())
20572065
if locator == "zeuz_failed":
20582066
CommonUtil.ExecLog(sModuleInfo, "Element not found", 3)
20592067
return "zeuz_failed"
@@ -2123,7 +2131,7 @@ async def execute_javascript(step_data):
21232131

21242132
# Execute JS
21252133
if has_element:
2126-
locator = await PlaywrightLocator.Get_Element(step_data, current_page)
2134+
locator = await PlaywrightLocator.Get_Element(step_data, current_page, frame_locator=_get_frame_locator())
21272135
if locator == "zeuz_failed":
21282136
CommonUtil.ExecLog(sModuleInfo, "Element not found", 3)
21292137
return "zeuz_failed"
@@ -2193,7 +2201,7 @@ async def upload_file(step_data):
21932201
CommonUtil.ExecLog(sModuleInfo, f"File not found: {file_path}", 3)
21942202
return "zeuz_failed"
21952203

2196-
locator = await PlaywrightLocator.Get_Element(step_data, current_page)
2204+
locator = await PlaywrightLocator.Get_Element(step_data, current_page, frame_locator=_get_frame_locator())
21972205
if locator == "zeuz_failed":
21982206
CommonUtil.ExecLog(sModuleInfo, "Element not found", 3)
21992207
return "zeuz_failed"
@@ -2320,7 +2328,7 @@ async def Wait_For_Element(step_data):
23202328
if timeout:
23212329
await asyncio.sleep(timeout)
23222330

2323-
locator = await PlaywrightLocator.Get_Element(step_data, current_page)
2331+
locator = await PlaywrightLocator.Get_Element(step_data, current_page, frame_locator=_get_frame_locator())
23242332

23252333
if locator == "zeuz_failed":
23262334
# For hidden/detached states, element not found is actually success
@@ -2539,7 +2547,7 @@ async def Extract_Table_Data(step_data):
25392547
elif left_l == "column":
25402548
col_filter = right_v
25412549

2542-
locator = await PlaywrightLocator.Get_Element(step_data, current_page)
2550+
locator = await PlaywrightLocator.Get_Element(step_data, current_page, frame_locator=_get_frame_locator())
25432551
if locator == "zeuz_failed":
25442552
CommonUtil.ExecLog(sModuleInfo, "Table element not found", 3)
25452553
return "zeuz_failed"

Framework/Built_In_Automation/Web/Playwright/locator.py

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
MODULE_NAME = inspect.getmodulename(__file__)
2626

2727

28-
async def Get_Element(step_data, page, return_all=False, element_wait=None):
28+
async def Get_Element(step_data, page, return_all=False, element_wait=None, frame_locator=None):
2929
"""
3030
Get element using Playwright's native Locator API.
3131
@@ -38,6 +38,7 @@ async def Get_Element(step_data, page, return_all=False, element_wait=None):
3838
page: Playwright Page object
3939
return_all: If True, return list of all matching ElementHandles
4040
element_wait: Override default wait timeout (in seconds)
41+
frame_locator: Optional frame locator for iframe context
4142
4243
Returns:
4344
Locator | List[ElementHandle] | "zeuz_failed"
@@ -75,7 +76,7 @@ async def Get_Element(step_data, page, return_all=False, element_wait=None):
7576
return "zeuz_failed"
7677

7778
# Build the locator
78-
locator = _build_locator(page, step_data, params)
79+
locator = _build_locator(page, step_data, params, frame_locator)
7980

8081
if locator is None:
8182
CommonUtil.ExecLog(sModuleInfo, "Could not build locator from step data", 3)
@@ -230,23 +231,32 @@ def _parse_element_params(step_data):
230231
return params
231232

232233

233-
def _build_locator(page, step_data, params):
234+
def _build_locator(page, step_data, params, frame_locator=None):
234235
"""
235236
Build a Playwright Locator from step data.
236237
237238
Attempts these strategies in order:
238239
1. Playwright-native selectors (test-id, role, text, etc.) - fastest
239240
2. Direct xpath/css if provided
240241
3. Build xpath from element parameters using existing logic
242+
243+
Args:
244+
page: Playwright Page object
245+
step_data: Step data for building xpath
246+
params: Parsed element parameters
247+
frame_locator: Optional frame locator for iframe context
241248
"""
242249

250+
# Use frame locator if provided, otherwise use page
251+
base_locator = frame_locator if frame_locator else page
252+
243253
# Strategy 1: Check for Playwright-native selectors (fastest path)
244254
for left, right in params['element_params']:
245255
left_lower = left.lower()
246256

247257
# Test ID selectors
248258
if left_lower in ("test-id", "testid", "data-testid", "data-test-id"):
249-
return page.get_by_test_id(right)
259+
return base_locator.get_by_test_id(right)
250260

251261
# Role selector
252262
if left_lower == "role":
@@ -257,54 +267,54 @@ def _build_locator(page, step_data, params):
257267
name = r
258268
break
259269
if name:
260-
return page.get_by_role(right, name=name)
261-
return page.get_by_role(right)
270+
return base_locator.get_by_role(right, name=name)
271+
return base_locator.get_by_role(right)
262272

263273
# Text selectors
264274
if left_lower == "text":
265-
return page.get_by_text(right, exact=True)
275+
return base_locator.get_by_text(right, exact=True)
266276
if left_lower == "*text":
267-
return page.get_by_text(right, exact=False)
277+
return base_locator.get_by_text(right, exact=False)
268278
if left_lower == "**text":
269279
# Case-insensitive partial match
270-
return page.get_by_text(re.compile(re.escape(right), re.IGNORECASE))
280+
return base_locator.get_by_text(re.compile(re.escape(right), re.IGNORECASE))
271281

272282
# Label selector
273283
if left_lower == "label":
274-
return page.get_by_label(right)
284+
return base_locator.get_by_label(right)
275285

276286
# Placeholder selector
277287
if left_lower == "placeholder":
278-
return page.get_by_placeholder(right)
288+
return base_locator.get_by_placeholder(right)
279289

280290
# Alt text selector
281291
if left_lower in ("alt", "alt text", "alt-text"):
282-
return page.get_by_alt_text(right)
292+
return base_locator.get_by_alt_text(right)
283293

284294
# Title selector
285295
if left_lower == "title" and "parameter" not in params.get('mid', ''):
286-
return page.get_by_title(right)
296+
return base_locator.get_by_title(right)
287297

288298
# Direct xpath
289299
if left_lower == "xpath":
290-
return page.locator(f"xpath={right}")
300+
return base_locator.locator(f"xpath={right}")
291301

292302
# Direct CSS selector
293303
if left_lower in ("css", "css selector", "css_selector"):
294-
return page.locator(right)
304+
return base_locator.locator(right)
295305

296306
# Strategy 2: Check for unique parameters
297307
for left, right in params['unique_params']:
298308
left_lower = left.lower()
299309

300310
if left_lower == "id":
301-
return page.locator(f"#{right}")
311+
return base_locator.locator(f"#{right}")
302312
elif left_lower == "name":
303-
return page.locator(f"[name='{right}']")
313+
return base_locator.locator(f"[name='{right}']")
304314
elif left_lower == "class":
305-
return page.locator(f".{right}")
315+
return base_locator.locator(f".{right}")
306316
elif left_lower == "tag":
307-
return page.locator(right)
317+
return base_locator.locator(right)
308318

309319
# Strategy 3: Build xpath from element/parent/child parameters
310320
xpath = _build_xpath_from_params(step_data, params)
@@ -314,7 +324,7 @@ def _build_locator(page, step_data, params):
314324
f"Built xpath from parameters: {xpath}",
315325
5
316326
)
317-
return page.locator(f"xpath={xpath}")
327+
return base_locator.locator(f"xpath={xpath}")
318328

319329
# Strategy 4: Simple element parameters as xpath
320330
if params['element_params']:
@@ -348,9 +358,9 @@ def _build_locator(page, step_data, params):
348358

349359
if xpath_parts:
350360
xpath = f"//{tag}[{' and '.join(xpath_parts)}]"
351-
return page.locator(f"xpath={xpath}")
361+
return base_locator.locator(f"xpath={xpath}")
352362
elif tag != "*":
353-
return page.locator(tag)
363+
return base_locator.locator(tag)
354364

355365
return None
356366

0 commit comments

Comments
 (0)