|
82 | 82 | selenium_details = {} |
83 | 83 | default_x, default_y = 1920, 1080 |
84 | 84 |
|
| 85 | +# JavaScript for collecting First Contentful Paint value. |
| 86 | +JS_FCP = ''' |
| 87 | +return performance.getEntriesByName("first-contentful-paint")[0].startTime |
| 88 | +''' |
| 89 | + |
| 90 | +# JavaScript for collecting Largest Contentful Paint value. |
| 91 | +JS_LCP = ''' |
| 92 | +var args = arguments; |
| 93 | +const po = new PerformanceObserver(list => { |
| 94 | + const entries = list.getEntries(); |
| 95 | + const entry = entries[entries.length - 1]; |
| 96 | + // Process entry as the latest LCP candidate |
| 97 | + // LCP is accurate when the renderTime is available. |
| 98 | + // Try to avoid this being false by adding Timing-Allow-Origin headers! |
| 99 | + const accurateLCP = entry.renderTime ? true : false; |
| 100 | + // Use startTime as the LCP timestamp. It will be renderTime if available, or loadTime otherwise. |
| 101 | + const largestPaintTime = entry.startTime; |
| 102 | + // Send the LCP information for processing. |
| 103 | +
|
| 104 | + console.log("[ZeuZ Node] Largest Contentful Paint: ", largestPaintTime); |
| 105 | + args[0](largestPaintTime); |
| 106 | +}); |
| 107 | +po.observe({ type: 'largest-contentful-paint', buffered: true }); |
| 108 | +''' |
| 109 | + |
85 | 110 | # if Shared_Resources.Test_Shared_Variables('selenium_driver'): # Check if driver is already set in shared variables |
86 | 111 | # selenium_driver = Shared_Resources.Get_Shared_Variables('selenium_driver') # Retreive appium driver |
87 | 112 |
|
@@ -387,6 +412,7 @@ def get_performance_metrics(dataset): |
387 | 412 | metrics = selenium_details[driver_id]["driver"].execute_cdp_cmd('Performance.getMetrics', {}) |
388 | 413 | perf_json_data = {data["name"]: data["value"] for data in metrics["metrics"]} |
389 | 414 | Shared_Resources.Set_Shared_Variables(var_name,perf_json_data) |
| 415 | + CommonUtil.browser_perf[current_driver_id].append(perf_json_data) |
390 | 416 | return "passed" |
391 | 417 | except: |
392 | 418 | return CommonUtil.Exception_Handler(sys.exc_info()) |
@@ -975,15 +1001,28 @@ def Go_To_Link(step_data, page_title=False): |
975 | 1001 | except Exception: |
976 | 1002 | ErrorMessage = "failed to open your link: %s" % (web_link) |
977 | 1003 | return CommonUtil.Exception_Handler(sys.exc_info(), None, ErrorMessage) |
| 1004 | + |
| 1005 | + # Collect custom performance metrics |
978 | 1006 | try: |
979 | 1007 | if current_driver_id not in CommonUtil.browser_perf: |
980 | 1008 | metrics = selenium_driver.execute_cdp_cmd('Performance.getMetrics', {}) |
981 | 1009 | metrics_dict = {data["name"]: data["value"] for data in metrics["metrics"]} |
| 1010 | + |
| 1011 | + # FCP - First Contentful Paint |
982 | 1012 | try: |
983 | | - metrics_dict["first-contentful-paint"] = selenium_driver.execute_script('return performance.getEntriesByName("first-contentful-paint")[0].startTime') |
| 1013 | + metrics_dict["first-contentful-paint"] = selenium_driver.execute_script(JS_FCP) |
984 | 1014 | except: |
985 | 1015 | metrics_dict["first-contentful-paint"] = 0 |
| 1016 | + |
| 1017 | + # LCP - Largest Contenful Paint |
| 1018 | + try: |
| 1019 | + metrics_dict["largest-contentful-paint"] = selenium_driver.execute_async_script(JS_LCP) |
| 1020 | + except: |
| 1021 | + metrics_dict["largest-contentful-paint"] = 0 |
| 1022 | + |
986 | 1023 | CommonUtil.browser_perf[current_driver_id] = [metrics_dict] |
| 1024 | + |
| 1025 | + # CommonUtil.prettify(key="metrics", val=metrics_dict) |
987 | 1026 | return "passed" |
988 | 1027 | except: |
989 | 1028 | return CommonUtil.Exception_Handler(sys.exc_info()) |
@@ -1167,7 +1206,7 @@ def Enter_Text_In_Text_Box(step_data): |
1167 | 1206 | selenium_driver.execute_script("arguments[0].click();", Element) |
1168 | 1207 | else: |
1169 | 1208 | try: |
1170 | | - handle_clickability_and_click(step_data, Element) |
| 1209 | + Element = handle_clickability_and_click(step_data, Element) |
1171 | 1210 | except: |
1172 | 1211 | CommonUtil.ExecLog(sModuleInfo, "Entering text without clicking the element", 2) |
1173 | 1212 | if clear: |
@@ -1358,28 +1397,38 @@ def execute_javascript(data_set): |
1358 | 1397 |
|
1359 | 1398 | def handle_clickability_and_click(dataset, Element:selenium.webdriver.remote.webelement.WebElement): |
1360 | 1399 | sModuleInfo = inspect.currentframe().f_code.co_name + " : " + MODULE_NAME |
1361 | | - wait_clickable = 0 |
1362 | | - for left, mid, right in dataset: |
1363 | | - if mid.strip().lower() == "option": |
1364 | | - left = left.strip().lower() |
1365 | | - if "wait" in left and "clickable" in left: |
1366 | | - wait_clickable = int(right.strip()) |
1367 | | - if not wait_clickable: |
1368 | | - Element.click() # no need of try except here. we need to return the exact exception upto this point |
1369 | | - else: |
1370 | | - log_flag = True |
1371 | | - start = time.time() |
1372 | | - while True: |
1373 | | - try: |
1374 | | - Element.click() |
1375 | | - break |
1376 | | - except ElementClickInterceptedException: |
1377 | | - if log_flag: |
1378 | | - CommonUtil.ExecLog(sModuleInfo, "The Element is overlapped. Waiting %s seconds max for the element to become clickable" % wait_clickable, 2) |
1379 | | - log_flag = False |
1380 | | - if time.time() > start + wait_clickable: |
1381 | | - raise Exception # not ElementClickInterceptedException. we dont want js to perform click |
1382 | | - |
| 1400 | + wait_clickable = Shared_Resources.Get_Shared_Variables("element_wait") |
| 1401 | + # for left, mid, right in dataset: |
| 1402 | + # if mid.strip().lower() == "option": |
| 1403 | + # left = left.strip().lower() |
| 1404 | + # if "wait" in left and "clickable" in left: |
| 1405 | + # wait_clickable = int(right.strip()) |
| 1406 | + # if not wait_clickable: |
| 1407 | + # Element.click() # no need of try except here. we need to return the exact exception upto this point |
| 1408 | + # else: |
| 1409 | + log_flag = True |
| 1410 | + log_flag2 = True |
| 1411 | + start = time.perf_counter() |
| 1412 | + stale_i = 0 |
| 1413 | + while True: |
| 1414 | + try: |
| 1415 | + Element.click() |
| 1416 | + CommonUtil.ExecLog(sModuleInfo, "Element has become clickable after %s seconds" % round(time.perf_counter() - start, 2), 2) |
| 1417 | + return Element |
| 1418 | + except ElementClickInterceptedException: |
| 1419 | + if log_flag: |
| 1420 | + CommonUtil.ExecLog(sModuleInfo, "Click is Intercepted. Waiting %s seconds max for the element to become clickable" % wait_clickable, 2) |
| 1421 | + log_flag = False |
| 1422 | + except StaleElementReferenceException: |
| 1423 | + if log_flag2: |
| 1424 | + CommonUtil.ExecLog(sModuleInfo, "Element is stale. Waiting %s seconds max for the element to become clickable" % wait_clickable, 2) |
| 1425 | + log_flag2 = False |
| 1426 | + Element = LocateElement.Get_Element(dataset, selenium_driver) # Element may need to be relocated in stale |
| 1427 | + if stale_i == 0: |
| 1428 | + stale_i += 1 |
| 1429 | + continue |
| 1430 | + if time.perf_counter() > start + wait_clickable: |
| 1431 | + raise Exception # not StaleElementReferenceException. we don't want js to perform click |
1383 | 1432 |
|
1384 | 1433 | # Method to click on element; step data passed on by the user |
1385 | 1434 | @logger |
|
0 commit comments