Compare commits
2
Commits
90f587ac9d
...
8c0fcb4267
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c0fcb4267 | ||
|
|
ef919a2a2f |
@@ -343,6 +343,20 @@ class AutomationCCAClaimSubmit:
|
|||||||
if not verified:
|
if not verified:
|
||||||
return "ERROR: 'Verify Eligibility' button not found"
|
return "ERROR: 'Verify Eligibility' button not found"
|
||||||
|
|
||||||
|
# Multiple records popup: pick the first member (top Select)
|
||||||
|
try:
|
||||||
|
sel_btn = WebDriverWait(self.driver, 12).until(
|
||||||
|
EC.element_to_be_clickable((By.ID, "buttonSelectMember0"))
|
||||||
|
)
|
||||||
|
print("[CCA Claim step2] Multiple records popup — clicking top Select")
|
||||||
|
try:
|
||||||
|
sel_btn.click()
|
||||||
|
except Exception:
|
||||||
|
self.driver.execute_script("arguments[0].click();", sel_btn)
|
||||||
|
time.sleep(2)
|
||||||
|
except TimeoutException:
|
||||||
|
print("[CCA Claim step2] No multiple-records popup")
|
||||||
|
|
||||||
# Wait for eligibility result
|
# Wait for eligibility result
|
||||||
print("[CCA Claim step2] Waiting for eligibility result...")
|
print("[CCA Claim step2] Waiting for eligibility result...")
|
||||||
try:
|
try:
|
||||||
@@ -449,11 +463,43 @@ class AutomationCCAClaimSubmit:
|
|||||||
# Extract Encounter ID from the FIRST row (newest claim is at the top)
|
# Extract Encounter ID from the FIRST row (newest claim is at the top)
|
||||||
claim_number = None
|
claim_number = None
|
||||||
|
|
||||||
# Try table cells first (Encounter ID is the first column)
|
# Pick the latest claim for this member: rows matching DOB, highest Encounter ID
|
||||||
for sel in [
|
try:
|
||||||
|
def _variants(d):
|
||||||
|
d = self._format_dob(d) if d else ""
|
||||||
|
if not d:
|
||||||
|
return []
|
||||||
|
m, dd, y = d.split("/")
|
||||||
|
return list({d, f"{int(m)}/{int(dd)}/{y}", f"{m}/{dd}/{y[-2:]}"})
|
||||||
|
dos_v = _variants(self.serviceDate)
|
||||||
|
dob_v = _variants(self.dateOfBirth)
|
||||||
|
rows = self.driver.execute_script("""
|
||||||
|
return Array.from(document.querySelectorAll('table tbody tr')).map(function(tr){
|
||||||
|
return Array.from(tr.querySelectorAll('td')).map(function(td){return td.innerText.trim();});
|
||||||
|
}).filter(function(c){return c.length;});
|
||||||
|
""") or []
|
||||||
|
# Rows for this member (by DOB); the largest Encounter ID is the latest claim
|
||||||
|
id_rows = [c for c in rows if re.match(r'\d{10,}', c[0])]
|
||||||
|
dob_rows = [c for c in id_rows if any(v in " | ".join(c) for v in dob_v)]
|
||||||
|
if not dob_rows:
|
||||||
|
# DOB not shown/matched — fall back to the service date
|
||||||
|
dob_rows = [c for c in id_rows if any(v in " | ".join(c) for v in dos_v)]
|
||||||
|
if dob_rows:
|
||||||
|
best = max(dob_rows, key=lambda c: int(re.match(r'\d+', c[0]).group(0)))
|
||||||
|
claim_number = re.match(r'\d+', best[0]).group(0)
|
||||||
|
print(f"[CCA Claim step4] Encounter ID {claim_number} = latest of "
|
||||||
|
f"{len(dob_rows)} row(s) for DOB {dob_v[:1]}: {best}")
|
||||||
|
else:
|
||||||
|
print(f"[CCA Claim step4] No row matched DOB={dob_v} or DOS={dos_v}; "
|
||||||
|
f"falling back to top row. Rows seen: {rows[:6]}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[CCA Claim step4] Row matching failed: {e!r}")
|
||||||
|
|
||||||
|
# Fallback: top row (Encounter ID is the first column)
|
||||||
|
for sel in ([] if claim_number else [
|
||||||
(By.XPATH, "//table//tbody//tr[1]/td[1]"),
|
(By.XPATH, "//table//tbody//tr[1]/td[1]"),
|
||||||
(By.XPATH, "//*[contains(@class,'wbx-table-results')]//tr[1]/td[1]"),
|
(By.XPATH, "//*[contains(@class,'wbx-table-results')]//tr[1]/td[1]"),
|
||||||
]:
|
]):
|
||||||
try:
|
try:
|
||||||
cell = WebDriverWait(self.driver, 8).until(
|
cell = WebDriverWait(self.driver, 8).until(
|
||||||
EC.presence_of_element_located(sel))
|
EC.presence_of_element_located(sel))
|
||||||
@@ -806,27 +852,56 @@ class AutomationCCAClaimSubmit:
|
|||||||
print(f"[CCA Claim grid] Filled {input_id}={value!r}")
|
print(f"[CCA Claim grid] Filled {input_id}={value!r}")
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[CCA Claim grid] Fill {input_id} failed: {e}")
|
print(f"[CCA Claim grid] Fill {input_id} failed: {e!r}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def click_cell_and_fill_retry(col_expr, input_id, value, attempts=3):
|
||||||
|
"""Retry when the editor input doesn't appear after the cell click
|
||||||
|
(the grid sometimes hasn't finished committing the previous row)."""
|
||||||
|
from selenium.webdriver.common.action_chains import ActionChains
|
||||||
|
for attempt in range(1, attempts + 1):
|
||||||
|
if click_cell_and_fill(col_expr, input_id, value):
|
||||||
|
return True
|
||||||
|
print(f"[CCA Claim grid] {input_id} attempt {attempt}/{attempts} failed")
|
||||||
|
time.sleep(1.5)
|
||||||
|
if attempt >= 2:
|
||||||
|
# Escape any stray popup/editor and try a double-click on the cell
|
||||||
|
try:
|
||||||
|
ActionChains(self.driver).send_keys(Keys.ESCAPE).perform()
|
||||||
|
cell = self.driver.find_element(
|
||||||
|
By.XPATH,
|
||||||
|
f"(//div[contains(@class,'e-gridcontent')]//tr)[{row_num}]/td[{col_expr}]")
|
||||||
|
ActionChains(self.driver).double_click(cell).perform()
|
||||||
|
time.sleep(0.5)
|
||||||
|
field = self.driver.find_element(By.ID, input_id)
|
||||||
|
field.send_keys(Keys.CONTROL + "a")
|
||||||
|
field.send_keys(Keys.DELETE)
|
||||||
|
field.send_keys(str(value))
|
||||||
|
print(f"[CCA Claim grid] Filled {input_id}={value!r} via double-click")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[CCA Claim grid] Double-click fallback failed: {e!r}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# CODE
|
# CODE
|
||||||
code_ok = click_cell_and_fill(col_map["CODE"], "ServicesCODE", code)
|
code_ok = click_cell_and_fill_retry(col_map["CODE"], "ServicesCODE", code)
|
||||||
|
time.sleep(1.0) # let the grid finish its code lookup before the next cell
|
||||||
|
|
||||||
# TOOTH — skip if empty
|
# TOOTH — skip if empty
|
||||||
tooth_ok = True
|
tooth_ok = True
|
||||||
if tooth:
|
if tooth:
|
||||||
tooth_ok = click_cell_and_fill(col_map["TOOTH"], "ServicesTOOTH", tooth)
|
tooth_ok = click_cell_and_fill_retry(col_map["TOOTH"], "ServicesTOOTH", tooth)
|
||||||
|
|
||||||
# Surfaces — skip if empty
|
# Surfaces — skip if empty
|
||||||
if surface_chars:
|
if surface_chars:
|
||||||
surf_ids = ["ServicesSURF1","ServicesSURF2","ServicesSURF3",
|
surf_ids = ["ServicesSURF1","ServicesSURF2","ServicesSURF3",
|
||||||
"ServicesSURF4","ServicesSURF5"]
|
"ServicesSURF4","ServicesSURF5"]
|
||||||
for si, char in enumerate(surface_chars[:5]):
|
for si, char in enumerate(surface_chars[:5]):
|
||||||
click_cell_and_fill(col_map[f"SURF{si+1}"], surf_ids[si], char)
|
click_cell_and_fill_retry(col_map[f"SURF{si+1}"], surf_ids[si], char)
|
||||||
|
|
||||||
# Billed Amount
|
# Billed Amount
|
||||||
# QTY and Service Date auto-fill after CODE is entered and this cell is clicked
|
# QTY and Service Date auto-fill after CODE is entered and this cell is clicked
|
||||||
billed_ok = click_cell_and_fill(col_map["BILLED_AMOUNT"], "ServicesBILLED_AMOUNT", billed_str)
|
billed_ok = click_cell_and_fill_retry(col_map["BILLED_AMOUNT"], "ServicesBILLED_AMOUNT", billed_str)
|
||||||
|
|
||||||
if not (code_ok and tooth_ok and billed_ok):
|
if not (code_ok and tooth_ok and billed_ok):
|
||||||
missing = [name for name, ok in
|
missing = [name for name, ok in
|
||||||
@@ -954,23 +1029,36 @@ class AutomationCCAClaimSubmit:
|
|||||||
|
|
||||||
# ---- Handle confirmation modal popup ----
|
# ---- Handle confirmation modal popup ----
|
||||||
print("[CCA Claim step3] Waiting for confirmation modal...")
|
print("[CCA Claim step3] Waiting for confirmation modal...")
|
||||||
time.sleep(1.5)
|
|
||||||
modal_confirmed = False
|
modal_confirmed = False
|
||||||
for sel in [
|
modal_selectors = [
|
||||||
# Most specific: Submit/Confirm/Yes button inside an active modal
|
# Most specific: Submit/Confirm/Yes button inside an active modal
|
||||||
(By.XPATH, "//div[contains(@class,'modal') and contains(@class,'in')]//button[contains(text(),'Submit') or contains(text(),'Confirm') or contains(text(),'Yes')]"),
|
(By.XPATH, "//div[contains(@class,'modal') and contains(@class,'in')]//button[contains(text(),'Submit') or contains(text(),'Confirm') or contains(text(),'Yes')]"),
|
||||||
(By.XPATH, "//div[@class='modal-footer']//button[contains(text(),'Submit') or contains(text(),'Confirm') or contains(text(),'Yes')]"),
|
(By.XPATH, "//div[@class='modal-footer']//button[contains(text(),'Submit') or contains(text(),'Confirm') or contains(text(),'Yes')]"),
|
||||||
(By.XPATH, "//button[@ng-click and (contains(@ng-click,'confirm') or contains(@ng-click,'Confirm') or contains(@ng-click,'submit') or contains(@ng-click,'Submit'))]"),
|
(By.XPATH, "//button[@ng-click and (contains(@ng-click,'confirm') or contains(@ng-click,'Confirm') or contains(@ng-click,'submit') or contains(@ng-click,'Submit'))]"),
|
||||||
(By.XPATH, "//div[contains(@class,'modal')]//button[not(contains(@class,'cancel')) and not(contains(text(),'Cancel')) and not(contains(text(),'No'))]"),
|
(By.XPATH, "//div[contains(@class,'modal')]//button[not(contains(@class,'cancel')) and not(contains(text(),'Cancel')) and not(contains(text(),'No'))]"),
|
||||||
]:
|
]
|
||||||
|
# Poll for the modal's own button first (patterns 1-2). The looser patterns (3-4)
|
||||||
|
# also match the page's own "Submit Claim" button behind the popup, so they are
|
||||||
|
# only tried after the modal-specific ones have had time to appear.
|
||||||
|
start = time.monotonic()
|
||||||
|
while time.monotonic() - start < 8 and not modal_confirmed:
|
||||||
|
active = modal_selectors[:2] if time.monotonic() - start < 5 else modal_selectors
|
||||||
|
for sel in active:
|
||||||
try:
|
try:
|
||||||
btn = WebDriverWait(self.driver, 5).until(EC.element_to_be_clickable(sel))
|
btn = next((b for b in self.driver.find_elements(*sel)
|
||||||
|
if b.is_displayed() and b.is_enabled()), None)
|
||||||
|
if btn:
|
||||||
btn.click()
|
btn.click()
|
||||||
modal_confirmed = True
|
modal_confirmed = True
|
||||||
print(f"[CCA Claim step3] Clicked modal confirm via {sel}")
|
print(f"[CCA Claim step3] Clicked modal confirm via {sel}")
|
||||||
break
|
break
|
||||||
except Exception:
|
except Exception:
|
||||||
continue
|
continue
|
||||||
|
if not modal_confirmed:
|
||||||
|
time.sleep(0.3)
|
||||||
|
|
||||||
|
if not modal_confirmed:
|
||||||
|
time.sleep(0.3)
|
||||||
|
|
||||||
if not modal_confirmed:
|
if not modal_confirmed:
|
||||||
print("[CCA Claim step3] No confirmation modal found — may have auto-submitted")
|
print("[CCA Claim step3] No confirmation modal found — may have auto-submitted")
|
||||||
@@ -978,7 +1066,7 @@ class AutomationCCAClaimSubmit:
|
|||||||
# Wait for final confirmation page
|
# Wait for final confirmation page
|
||||||
print("[CCA Claim step3] Waiting for submission confirmation...")
|
print("[CCA Claim step3] Waiting for submission confirmation...")
|
||||||
try:
|
try:
|
||||||
WebDriverWait(self.driver, 30).until(
|
WebDriverWait(self.driver, 10).until(
|
||||||
lambda d: any(x in d.find_element(By.TAG_NAME, "body").text.lower() for x in [
|
lambda d: any(x in d.find_element(By.TAG_NAME, "body").text.lower() for x in [
|
||||||
"claim submitted", "claim number", "confirmation", "success",
|
"claim submitted", "claim number", "confirmation", "success",
|
||||||
"has been submitted", "claim id", "assigned the number",
|
"has been submitted", "claim id", "assigned the number",
|
||||||
|
|||||||
@@ -291,15 +291,15 @@ class AutomationMassHealthClaimsLogin:
|
|||||||
(By.XPATH, "//input[@name='dateInput' and @placeholder='mm/dd/yyyy' and @ng-model='date']")
|
(By.XPATH, "//input[@name='dateInput' and @placeholder='mm/dd/yyyy' and @ng-model='date']")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
time.sleep(1)
|
time.sleep(0.3)
|
||||||
|
|
||||||
# Use JavaScript to set the value directly to avoid date picker interference
|
# Use JavaScript to set the value directly to avoid date picker interference
|
||||||
self.driver.execute_script(f"arguments[0].value = '{formatted_dob}'; arguments[0].dispatchEvent(new Event('input', {{ bubbles: true }})); arguments[0].dispatchEvent(new Event('change', {{ bubbles: true }}));", dob_input)
|
self.driver.execute_script(f"arguments[0].value = '{formatted_dob}'; arguments[0].dispatchEvent(new Event('input', {{ bubbles: true }})); arguments[0].dispatchEvent(new Event('change', {{ bubbles: true }}));", dob_input)
|
||||||
time.sleep(1)
|
time.sleep(0.3)
|
||||||
|
|
||||||
# Press Tab to move to next field and ensure the date is set
|
# Press Tab to move to next field and ensure the date is set
|
||||||
dob_input.send_keys(Keys.TAB)
|
dob_input.send_keys(Keys.TAB)
|
||||||
time.sleep(1)
|
time.sleep(0.3)
|
||||||
|
|
||||||
# Step 2: Fill Member Number
|
# Step 2: Fill Member Number
|
||||||
if self.memberId:
|
if self.memberId:
|
||||||
@@ -309,15 +309,15 @@ class AutomationMassHealthClaimsLogin:
|
|||||||
(By.XPATH, "//input[@placeholder='Member Number' and @ng-model='vm.number']")
|
(By.XPATH, "//input[@placeholder='Member Number' and @ng-model='vm.number']")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
time.sleep(1)
|
time.sleep(0.3)
|
||||||
member_input.click()
|
member_input.click()
|
||||||
time.sleep(1)
|
time.sleep(0.3)
|
||||||
member_input.clear()
|
member_input.clear()
|
||||||
time.sleep(1)
|
time.sleep(0.3)
|
||||||
member_input.send_keys(self.memberId)
|
member_input.send_keys(self.memberId)
|
||||||
time.sleep(1)
|
time.sleep(0.3)
|
||||||
member_input.send_keys(Keys.TAB)
|
member_input.send_keys(Keys.TAB)
|
||||||
time.sleep(1)
|
time.sleep(0.3)
|
||||||
|
|
||||||
# Step 3: Fill First Name and Last Name
|
# Step 3: Fill First Name and Last Name
|
||||||
# if self.firstName:
|
# if self.firstName:
|
||||||
@@ -383,12 +383,12 @@ class AutomationMassHealthClaimsLogin:
|
|||||||
(By.XPATH, "//input[@ng-model='serviceLine.procedure' and @placeholder='Code']")
|
(By.XPATH, "//input[@ng-model='serviceLine.procedure' and @placeholder='Code']")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
time.sleep(1)
|
time.sleep(0.3)
|
||||||
|
|
||||||
# Step 2: Type the procedure code to trigger typeahead
|
# Step 2: Type the procedure code to trigger typeahead
|
||||||
procedure_input.clear()
|
procedure_input.clear()
|
||||||
procedure_input.send_keys(self.procedureCode)
|
procedure_input.send_keys(self.procedureCode)
|
||||||
time.sleep(3) # Wait for typeahead to load
|
time.sleep(0.5) # brief debounce; the dropdown wait below does the real waiting
|
||||||
|
|
||||||
# Step 3: Look for the typeahead dropdown and select the first option
|
# Step 3: Look for the typeahead dropdown and select the first option
|
||||||
# The dropdown appears as ul with class 'dropdown-menu'
|
# The dropdown appears as ul with class 'dropdown-menu'
|
||||||
@@ -405,13 +405,13 @@ class AutomationMassHealthClaimsLogin:
|
|||||||
if first_option:
|
if first_option:
|
||||||
print("DEBUG: Found first option in procedure dropdown, clicking...")
|
print("DEBUG: Found first option in procedure dropdown, clicking...")
|
||||||
first_option.click()
|
first_option.click()
|
||||||
time.sleep(2)
|
time.sleep(0.5)
|
||||||
return "Success"
|
return "Success"
|
||||||
except:
|
except:
|
||||||
# If no dropdown appears, just press Tab to move to next field
|
# If no dropdown appears, just press Tab to move to next field
|
||||||
print("DEBUG: No procedure dropdown found, pressing Tab")
|
print("DEBUG: No procedure dropdown found, pressing Tab")
|
||||||
procedure_input.send_keys(Keys.TAB)
|
procedure_input.send_keys(Keys.TAB)
|
||||||
time.sleep(1)
|
time.sleep(0.3)
|
||||||
return "Success"
|
return "Success"
|
||||||
|
|
||||||
return "Success"
|
return "Success"
|
||||||
@@ -433,16 +433,16 @@ class AutomationMassHealthClaimsLogin:
|
|||||||
(By.XPATH, "//input[@ng-model='serviceLine.toothCode' and @placeholder='Tooth']")
|
(By.XPATH, "//input[@ng-model='serviceLine.toothCode' and @placeholder='Tooth']")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
time.sleep(1)
|
time.sleep(0.3)
|
||||||
|
|
||||||
# Step 2: Type the tooth number
|
# Step 2: Type the tooth number
|
||||||
tooth_input.clear()
|
tooth_input.clear()
|
||||||
tooth_input.send_keys(tooth_value.upper()) # Convert to uppercase as per onkeyup
|
tooth_input.send_keys(tooth_value.upper()) # Convert to uppercase as per onkeyup
|
||||||
time.sleep(2)
|
time.sleep(0.5)
|
||||||
|
|
||||||
# Press Tab to move to next field
|
# Press Tab to move to next field
|
||||||
tooth_input.send_keys(Keys.TAB)
|
tooth_input.send_keys(Keys.TAB)
|
||||||
time.sleep(1)
|
time.sleep(0.3)
|
||||||
|
|
||||||
return "Success"
|
return "Success"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -463,16 +463,16 @@ class AutomationMassHealthClaimsLogin:
|
|||||||
(By.XPATH, "//input[@ng-model='serviceLine.surface' and @placeholder='Surface']")
|
(By.XPATH, "//input[@ng-model='serviceLine.surface' and @placeholder='Surface']")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
time.sleep(1)
|
time.sleep(0.3)
|
||||||
|
|
||||||
# Step 2: Type the tooth surface (convert to uppercase)
|
# Step 2: Type the tooth surface (convert to uppercase)
|
||||||
surface_input.clear()
|
surface_input.clear()
|
||||||
surface_input.send_keys(surface_value.upper())
|
surface_input.send_keys(surface_value.upper())
|
||||||
time.sleep(2)
|
time.sleep(0.5)
|
||||||
|
|
||||||
# Press Tab to move to next field
|
# Press Tab to move to next field
|
||||||
surface_input.send_keys(Keys.TAB)
|
surface_input.send_keys(Keys.TAB)
|
||||||
time.sleep(1)
|
time.sleep(0.3)
|
||||||
|
|
||||||
return "Success"
|
return "Success"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -491,12 +491,12 @@ class AutomationMassHealthClaimsLogin:
|
|||||||
(By.XPATH, "//select[@ng-model='serviceLine.quadrant']")
|
(By.XPATH, "//select[@ng-model='serviceLine.quadrant']")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
time.sleep(1)
|
time.sleep(0.3)
|
||||||
|
|
||||||
# Step 2: Use Select class to choose Upper Right
|
# Step 2: Use Select class to choose Upper Right
|
||||||
select = Select(quadrant_dropdown)
|
select = Select(quadrant_dropdown)
|
||||||
select.select_by_visible_text("Upper Right")
|
select.select_by_visible_text("Upper Right")
|
||||||
time.sleep(2)
|
time.sleep(0.5)
|
||||||
|
|
||||||
return "Success"
|
return "Success"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -515,12 +515,12 @@ class AutomationMassHealthClaimsLogin:
|
|||||||
(By.XPATH, "//select[@ng-model='serviceLine.arch']")
|
(By.XPATH, "//select[@ng-model='serviceLine.arch']")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
time.sleep(1)
|
time.sleep(0.3)
|
||||||
|
|
||||||
# Step 2: Use Select class to choose Entire Oral Cavity
|
# Step 2: Use Select class to choose Entire Oral Cavity
|
||||||
select = Select(arch_dropdown)
|
select = Select(arch_dropdown)
|
||||||
select.select_by_visible_text("Entire Oral Cavity")
|
select.select_by_visible_text("Entire Oral Cavity")
|
||||||
time.sleep(2)
|
time.sleep(0.5)
|
||||||
|
|
||||||
return "Success"
|
return "Success"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -541,16 +541,16 @@ class AutomationMassHealthClaimsLogin:
|
|||||||
(By.XPATH, "//input[@ng-model='serviceLine.authorizationNumber' and @placeholder='No.']")
|
(By.XPATH, "//input[@ng-model='serviceLine.authorizationNumber' and @placeholder='No.']")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
time.sleep(1)
|
time.sleep(0.3)
|
||||||
|
|
||||||
# Step 2: Type the authorization number
|
# Step 2: Type the authorization number
|
||||||
auth_input.clear()
|
auth_input.clear()
|
||||||
auth_input.send_keys(auth_number)
|
auth_input.send_keys(auth_number)
|
||||||
time.sleep(2)
|
time.sleep(0.5)
|
||||||
|
|
||||||
# Press Tab to move to next field
|
# Press Tab to move to next field
|
||||||
auth_input.send_keys(Keys.TAB)
|
auth_input.send_keys(Keys.TAB)
|
||||||
time.sleep(1)
|
time.sleep(0.3)
|
||||||
|
|
||||||
return "Success"
|
return "Success"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
Reference in New Issue
Block a user