diff --git a/apps/Frontend/src/components/claims/claim-form.tsx b/apps/Frontend/src/components/claims/claim-form.tsx
index a9e09d08..087b90a7 100755
--- a/apps/Frontend/src/components/claims/claim-form.tsx
+++ b/apps/Frontend/src/components/claims/claim-form.tsx
@@ -1537,6 +1537,8 @@ export function ClaimForm({
insuranceProvider: "United Ucard",
appointmentId: appointmentIdToUse,
insuranceSiteKey: "UNITED_UCARD",
+ firstName: patient?.firstName ?? "",
+ lastName: patient?.lastName ?? "",
claimId: createdClaim.id,
claimFiles: claimFilesMeta,
});
diff --git a/apps/SeleniumService/selenium_UnitedUcard_claimSubmitWorker.py b/apps/SeleniumService/selenium_UnitedUcard_claimSubmitWorker.py
index 2105e1f8..aeeb5941 100644
--- a/apps/SeleniumService/selenium_UnitedUcard_claimSubmitWorker.py
+++ b/apps/SeleniumService/selenium_UnitedUcard_claimSubmitWorker.py
@@ -16,7 +16,7 @@ service lines / attach files / submit / save confirmation PDF) are left as
TODO stubs — fill these in once we know the exact DOM for the claim
submission flow on the UHC Dental provider dashboard.
"""
-from selenium.common.exceptions import WebDriverException, TimeoutException
+from selenium.common.exceptions import WebDriverException, TimeoutException, NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
@@ -382,12 +382,12 @@ class AutomationUnitedUcardClaimSubmit:
def step3_fill_patient_information(self):
"""
- Fill the Patient Information step: Date of Service, Subscriber ID,
- Date of Birth, then click Search to look up the member.
+ Fill the Patient Information step: Date of Service, choose the
+ First Name + Last Name + DOB search, then First/Last Name, Date of Birth, then click Search to look up the member.
Confirmed against the live site (2026-09-13):
-
+ /
"""
@@ -402,12 +402,30 @@ class AutomationUnitedUcardClaimSubmit:
return "ERROR: Date of Service field not found on Patient Information step"
try:
- subscriber_id_field = self.driver.find_element(By.CSS_SELECTOR, "input.subscriber-id")
- subscriber_id_field.clear()
- subscriber_id_field.send_keys(self.memberId)
- print(f"[UnitedUcard Claim] Entered Subscriber ID: {self.memberId}")
+ name_radio = WebDriverWait(self.driver, 10).until(
+ EC.presence_of_element_located((By.CSS_SELECTOR, "input.searchname[name='member-search'][value='name']"))
+ )
+ self.driver.execute_script("arguments[0].scrollIntoView({block:'center'});", name_radio)
+ try:
+ name_radio.click()
+ except Exception:
+ self.driver.execute_script("arguments[0].click();", name_radio)
+ print("[UnitedUcard Claim] Selected 'First Name + Last Name + DOB' search")
+ except TimeoutException:
+ return "ERROR: 'First Name + Last Name + DOB' radio not found on Patient Information step"
+
+ try:
+ fname_field = WebDriverWait(self.driver, 10).until(
+ EC.element_to_be_clickable((By.CSS_SELECTOR, "input.member-fname"))
+ )
+ fname_field.clear()
+ fname_field.send_keys(self.firstName)
+ lname_field = self.driver.find_element(By.CSS_SELECTOR, "input.member-lname")
+ lname_field.clear()
+ lname_field.send_keys(self.lastName)
+ print(f"[UnitedUcard Claim] Entered name: {self.firstName} {self.lastName}")
except Exception as e:
- return f"ERROR: Subscriber ID field not found on Patient Information step: {e}"
+ return f"ERROR: First/Last Name fields not found on Patient Information step: {e}"
try:
dob_field = self.driver.find_element(By.CSS_SELECTOR, "input.date-of-birth")
@@ -646,6 +664,16 @@ class AutomationUnitedUcardClaimSubmit:
except TimeoutException:
return "ERROR: 'Add a Procedure' button not found"
+ def _wait_visible(self, element_id, timeout=10):
+ """Return the element once visible, or None if it never appears
+ (the portal only shows tooth fields for certain procedure codes)."""
+ try:
+ return WebDriverWait(self.driver, timeout).until(
+ lambda d: next((e for e in d.find_elements(By.ID, element_id) if e.is_displayed()), None)
+ )
+ except TimeoutException:
+ return None
+
def _fill_and_save_procedure(self, line: dict, idx: int):
"""
Fill one procedure row (Procedure Code, Date of Service, Procedure
@@ -690,6 +718,28 @@ class AutomationUnitedUcardClaimSubmit:
except Exception as e:
return f"ERROR: Procedure Fee field not found for line {idx + 1}: {e}"
+ # Tooth Number / Surface are driven by the app's claim data: only wait
+ # for and fill them when the service line actually has a value.
+ tooth = str(line.get("toothNumber") or line.get("tooth") or "").strip()
+ if tooth:
+ tooth_field = self._wait_visible("toothNum")
+ if tooth_field:
+ tooth_field.clear()
+ tooth_field.send_keys(tooth)
+ print(f"[UnitedUcard Claim] Entered Tooth Number: {tooth}")
+ else:
+ print(f"[UnitedUcard Claim] Tooth Number field did not appear for {procedure_code}; skipped")
+
+ surface = str(line.get("toothSurface") or line.get("surface") or "").strip().upper()
+ if surface:
+ surface_field = self._wait_visible("toothSurf")
+ if surface_field:
+ surface_field.clear()
+ surface_field.send_keys(surface)
+ print(f"[UnitedUcard Claim] Entered Tooth Surface: {surface}")
+ else:
+ print(f"[UnitedUcard Claim] Tooth Surface field did not appear for {procedure_code}; skipped")
+
try:
save_btn = WebDriverWait(self.driver, 10).until(
EC.element_to_be_clickable((By.XPATH, "//*[@onclick='saveProcCode()']"))