You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

173 lines
5.6 KiB
Python

"""Tests for the role gate (title classification) and candidate logs."""
from datetime import date, timedelta
from gimme_job.proactive import roles
from gimme_job.proactive.plan import ProactivePlan
from gimme_job.proactive.roles import (
NON_CLINICAL,
OTHER_SPECIALTY,
SUPPORT,
TARGET,
UNKNOWN,
classify_role,
effective_role_terms,
is_role_excluded,
normalize_title,
prune_candidate_logs,
read_role_candidates,
record_role_candidate,
)
# ── normalize ────────────────────────────────────────────────────────────────
def test_normalize_title_strips_prefix_company_location_ids():
assert (
normalize_title(
"Job Application for Dental Assistant at Anthem Pediatric Dentistry "
"at Specialty Dental Brands"
)
== "Dental Assistant"
)
assert normalize_title("Orthodontist - Phoenix, AZ") == "Orthodontist"
assert normalize_title("Dentist | Requisition #12345") == "Dentist"
assert normalize_title(" Orthodontist ") == "Orthodontist"
# ── classify ─────────────────────────────────────────────────────────────────
def test_target_titles():
for title in (
"Orthodontist",
"Orthodontist Job in Phoenix, AZ at Smile Doctors",
"Staff Dentist",
"Dentist II (Orthodontics)",
"Staff Dental Officer",
"Specialty Dentist",
"Dental Specialist",
):
role, _ = classify_role(title)
assert role == TARGET, title
def test_support_titles():
for title in (
"Dental Assistant at Anthem Pediatric Dentistry",
"Orthodontic Assistant",
"Registered Dental Hygienist",
"Orthodontic Technician",
"Treatment Coordinator",
"Front Desk Receptionist",
"Orthodontic Clinician I",
):
role, _ = classify_role(title)
assert role == SUPPORT, title
def test_non_clinical_titles():
for title in (
"Account Payable Specialist at Specialty Dental Brands",
"Staff Accountant",
"Payroll Clerk",
"Director of Operations",
"Regional Manager",
"Marketing Manager",
"HR Generalist",
):
role, _ = classify_role(title)
assert role == NON_CLINICAL, title
def test_other_specialty_titles():
"""Explicit non-ortho specialties are filtered even though they say "dentist"."""
for title in (
"Job Application for Pediatric Dentist - Associate at Specialty Dental Brands",
"Pediatric Dentist",
"Pediatric Dentistry Associate",
"Endodontist",
"Periodontist",
"Prosthodontist",
"Oral Surgeon",
"General Dentist",
"Public Health Dentist",
):
role, _ = classify_role(title)
assert role == OTHER_SPECIALTY, title
def test_orthodontist_variants_stay_target():
for title in (
"Pediatric Orthodontist",
"Orthodontist",
"Orthodontic Specialist",
"Staff Dentist",
"Dentist II (Orthodontics)",
):
role, _ = classify_role(title)
assert role == TARGET, title
def test_unknown_titles():
for title in ("Clinical Lead", "Dental Program Specialist", ""):
role, _ = classify_role(title)
assert role == UNKNOWN, title
def test_target_beats_support_on_compound_titles():
role, _ = classify_role("Orthodontist and Clinical Assistant")
assert role == TARGET
def test_is_role_excluded():
assert is_role_excluded("Dental Assistant")[0] == SUPPORT
assert is_role_excluded("Payroll Clerk")[0] == NON_CLINICAL
assert is_role_excluded("Pediatric Dentist")[0] == OTHER_SPECIALTY
assert is_role_excluded("Orthodontist") is None
assert is_role_excluded("Clinical Lead") is None
def test_effective_role_terms_merges_plan_additions():
plan = ProactivePlan()
plan.verification.role_terms = {"support": ["surgical tech"]}
terms = effective_role_terms(plan)
assert "surgical tech" in terms["support"]
assert "assistant" in terms["support"]
assert classify_role("Surgical Tech", plan)[0] == SUPPORT
# ── candidate log ────────────────────────────────────────────────────────────
def test_record_read_and_prune_candidate_logs():
today = date(2026, 9, 12)
record_role_candidate(
"Dental Assistant", "https://x/j/1", "greenhouse", SUPPORT, "matched", run_date=today
)
record_role_candidate(
"Orthodontic Clinician", "https://x/j/2", "workday", UNKNOWN, "no keyword", run_date=today
)
record_role_candidate(
"Orthodontist", "https://x/j/3", "lever", TARGET, "target", run_date=today
)
entries = read_role_candidates(today)
assert len(entries) == 2 # target is not logged
assert entries[0]["title"] == "Dental Assistant"
assert entries[0]["role"] == SUPPORT
old = today - timedelta(days=31)
record_role_candidate("Old", "https://x/old", "lever", UNKNOWN, "old", run_date=old)
removed = prune_candidate_logs(30, now=today)
assert removed == 1
assert {e["title"] for e in read_role_candidates(today)} == {
"Dental Assistant",
"Orthodontic Clinician",
}
assert read_role_candidates(old) == []
def test_candidate_log_path_shape():
path = roles.candidates_log_path(date(2026, 1, 2))
assert path.name == "2026-01-02.roles.jsonl"