Skip to content

Commit 30bd196

Browse files
mcherifclaude
andcommitted
Fix employment history crash and school combobox fill
- _parse_date: guard against IndexError when date string is empty (triggered when date_to == "present" is passed as "" to _parse_date) - _select_combobox_option: when combobox root is a div/button (is_input=False), look for a revealed inner <input> search field after clicking and type into it so school/university dropdowns that require typing to filter are handled - Native SELECT partial match: make bidirectional so "University of British Columbia" option matches value "The University of British Columbia" Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 0abc313 commit 30bd196

2 files changed

Lines changed: 23 additions & 3 deletions

File tree

utils/form_filler.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -682,9 +682,12 @@ def _is_anonymous_text(f: dict) -> bool:
682682
opt_texts = [o["t"] for o in option_data]
683683
opt_vals = [o["v"] for o in option_data]
684684
chosen_val = None
685-
# 1. Simple partial match (e.g. "male" in "Male").
685+
# 1. Bidirectional partial match (e.g. "male" in "Male",
686+
# or option "University of British Columbia" inside
687+
# value "The University of British Columbia").
688+
_vl = value.lower()
686689
for t, v in zip(opt_texts, opt_vals):
687-
if value.lower() in t.lower():
690+
if _vl in t.lower() or t.lower() in _vl:
688691
chosen_val = v
689692
break
690693
# 2. Demographic synonym match (gender, disability, veteran, etc.)
@@ -1951,6 +1954,23 @@ def _query_opts(listbox_id: str) -> str:
19511954
aria_controls = await el.get_attribute("aria-controls") or ""
19521955
opts = await page.evaluate(_query_opts(aria_controls), aria_controls)
19531956

1957+
# Some comboboxes are div/button wrappers (is_input=False) that reveal an
1958+
# inner <input> search field when opened (e.g. Greenhouse school selector).
1959+
# When no options appeared after clicking, try to find and type into that
1960+
# inner input — then fall through to the normal fallback-terms logic.
1961+
if not opts and not is_input:
1962+
try:
1963+
inner = page.locator("input[type='search']:visible, input[type='text']:visible").last
1964+
if await inner.count() > 0 and await inner.is_visible(timeout=1000):
1965+
el = inner
1966+
is_input = True
1967+
await el.fill(value)
1968+
await asyncio.sleep(0.5)
1969+
aria_controls = await el.get_attribute("aria-controls") or ""
1970+
opts = await page.evaluate(_query_opts(aria_controls), aria_controls)
1971+
except Exception:
1972+
pass
1973+
19541974
# If typing the full value produced no options, retry with shorter search
19551975
# terms so the dropdown has something to filter on. Strategy:
19561976
# - Comma-separated ("Tunis, Tunisia"): try country part, then city.

utils/form_prefill.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,7 @@ async def _fill_select_last(pattern: re.Pattern, value: str) -> bool:
617617
def _parse_date(date_str: str):
618618
parts = date_str.split()
619619
month = parts[0] if len(parts) >= 1 else ""
620-
year = parts[1] if len(parts) >= 2 else parts[0] if parts[0].isdigit() else ""
620+
year = parts[1] if len(parts) >= 2 else (parts[0] if len(parts) >= 1 and parts[0].isdigit() else "")
621621
return month, year
622622

623623
from_month, from_year = _parse_date(date_from)

0 commit comments

Comments
 (0)