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.
300 lines
9.3 KiB
Python
300 lines
9.3 KiB
Python
"""Tests for the proactive verifier classification logic."""
|
|
from gimme_job.proactive.plan import ProactivePlan
|
|
from gimme_job.proactive.verifier import (
|
|
ACTIVE,
|
|
CLOSED,
|
|
FILTERED,
|
|
STALE,
|
|
VERIFY,
|
|
PageEvidence,
|
|
classify_lead,
|
|
detect_ats,
|
|
extract_fte,
|
|
extract_license,
|
|
extract_salary,
|
|
has_apply_path,
|
|
has_closed_markers,
|
|
has_credential_signal,
|
|
has_deprioritized,
|
|
has_ortho_signal,
|
|
is_aggregator,
|
|
)
|
|
|
|
|
|
def _plan() -> ProactivePlan:
|
|
return ProactivePlan.load()
|
|
|
|
|
|
def test_detect_ats():
|
|
plan = _plan()
|
|
patterns = plan.verification.ats_patterns
|
|
assert detect_ats("https://wd5.myworkdayjobs.com/en-US/org/job/123", patterns) == "workday"
|
|
assert detect_ats("https://careers-org.icims.com/jobs/123", patterns) == "icims"
|
|
assert detect_ats("https://www.governmentjobs.com/careers/az", patterns) == "govtjobs"
|
|
assert detect_ats("https://org.org/jobs/123", patterns) is None
|
|
|
|
|
|
def test_is_aggregator():
|
|
plan = _plan()
|
|
aggregators = plan.verification.aggregator_domains
|
|
assert is_aggregator("https://www.indeed.com/viewjob?jk=123", aggregators)
|
|
assert is_aggregator("https://www.linkedin.com/jobs/view/123", aggregators)
|
|
assert not is_aggregator("https://careers.gilariver.org/jobs/123", aggregators)
|
|
|
|
|
|
def test_has_apply_path():
|
|
assert has_apply_path("Click here to Apply Now for this position", ["apply now"])
|
|
assert not has_apply_path("We are hiring a dentist", ["apply now"])
|
|
|
|
|
|
def test_has_closed_markers():
|
|
assert has_closed_markers(
|
|
"This position has been filled. Thank you.", ["position has been filled"]
|
|
)
|
|
assert not has_closed_markers("We are actively hiring", ["position has been filled"])
|
|
|
|
|
|
def test_open_federal_boilerplate_is_not_closed():
|
|
"""USAJOBS open announcements say "until the position is filled"."""
|
|
plan = _plan()
|
|
open_text = (
|
|
"Applications will be referred every 2 weeks until the position is filled. "
|
|
"This job is open to the public."
|
|
)
|
|
assert not has_closed_markers(open_text, plan.verification.closed_keywords)
|
|
|
|
|
|
def test_has_ortho_signal():
|
|
assert has_ortho_signal(
|
|
"Dentist II", "This role includes orthodontic treatment of children", ["orthodontic"]
|
|
)
|
|
assert not has_ortho_signal("Dentist II", "General restorative dentistry", ["orthodontic"])
|
|
|
|
|
|
def _ev(**kw) -> PageEvidence:
|
|
defaults = dict(
|
|
url="https://employer.org/jobs/1",
|
|
final_url="https://employer.org/jobs/1",
|
|
title="Orthodontist",
|
|
body_text="Full time orthodontist position. Apply Now.",
|
|
http_ok=True,
|
|
apply_found=True,
|
|
closed_found=False,
|
|
ortho_signal=True,
|
|
job_signal=True,
|
|
program_signal=False,
|
|
is_aggregator=False,
|
|
employer_type="government",
|
|
employer_type_reason="host test.gov",
|
|
)
|
|
defaults.update(kw)
|
|
return PageEvidence(**defaults)
|
|
|
|
|
|
def test_employer_ats_apply_ortho_is_active():
|
|
plan = _plan()
|
|
ev = _ev(title="Orthodontist", body_text="Apply now for this orthodontics role")
|
|
status, reason = classify_lead(ev, plan)
|
|
assert status == ACTIVE
|
|
|
|
|
|
def test_school_program_page_is_filtered():
|
|
"""ATSU-style school page: APPLY button + program content, no job signal."""
|
|
plan = _plan()
|
|
ev = _ev(
|
|
title="ASDOH - Dental Clinics",
|
|
body_text=(
|
|
"Admissions Curriculum Residency program Tuition Apply Now "
|
|
"A.T. Still University dental school"
|
|
),
|
|
job_signal=False,
|
|
program_signal=True,
|
|
)
|
|
status, reason = classify_lead(ev, plan)
|
|
assert status == FILTERED
|
|
assert "program" in reason
|
|
|
|
|
|
def test_employer_apply_without_job_signal_is_verify():
|
|
"""Apply path on employer site but no job wording → not confirmable."""
|
|
plan = _plan()
|
|
ev = _ev(
|
|
body_text="Orthodontics department information. Contact us to learn more.",
|
|
job_signal=False,
|
|
)
|
|
status, _ = classify_lead(ev, plan)
|
|
assert status == VERIFY
|
|
|
|
|
|
def test_aggregator_even_with_apply_is_verify():
|
|
plan = _plan()
|
|
ev = _ev(
|
|
url="https://www.indeed.com/viewjob?jk=1",
|
|
final_url="https://www.indeed.com/viewjob?jk=1",
|
|
body_text="Apply now orthodontist",
|
|
is_aggregator=True,
|
|
)
|
|
status, reason = classify_lead(ev, plan)
|
|
assert status == VERIFY
|
|
|
|
|
|
def test_employer_no_apply_is_verify():
|
|
plan = _plan()
|
|
ev = _ev(body_text="We are looking for an orthodontist", apply_found=False)
|
|
status, _ = classify_lead(ev, plan)
|
|
assert status == VERIFY
|
|
|
|
|
|
def test_closed_markers_win():
|
|
plan = _plan()
|
|
ev = _ev(body_text="Orthodontist position has been filled", closed_found=True)
|
|
status, _ = classify_lead(ev, plan)
|
|
assert status == CLOSED
|
|
|
|
|
|
def test_load_failure_is_stale():
|
|
plan = _plan()
|
|
ev = _ev(http_ok=False, load_error="net::ERR_NAME_NOT_RESOLVED")
|
|
status, _ = classify_lead(ev, plan)
|
|
assert status == STALE
|
|
|
|
|
|
def test_no_ortho_signal_is_filtered():
|
|
plan = _plan()
|
|
ev = _ev(
|
|
title="Registered Nurse",
|
|
body_text="Apply now for nursing position",
|
|
ortho_signal=False,
|
|
)
|
|
status, _ = classify_lead(ev, plan)
|
|
assert status == FILTERED
|
|
|
|
|
|
def test_support_role_filtered_even_with_ortho_signal():
|
|
"""Real false positive: Dental Assistant page mentions the ortho team."""
|
|
plan = _plan()
|
|
ev = _ev(
|
|
title="Dental Assistant at Anthem Pediatric Dentistry",
|
|
body_text="Work with the orthodontic team. Apply now.",
|
|
ortho_signal=True,
|
|
)
|
|
status, reason = classify_lead(ev, plan)
|
|
assert status == FILTERED
|
|
assert "role filter" in reason and "support" in reason
|
|
|
|
|
|
def test_non_clinical_role_filtered():
|
|
plan = _plan()
|
|
ev = _ev(
|
|
title="Account Payable Specialist at Specialty Dental Brands",
|
|
body_text="Orthodontics company. Apply now.",
|
|
ortho_signal=True,
|
|
)
|
|
status, reason = classify_lead(ev, plan)
|
|
assert status == FILTERED
|
|
assert "non_clinical" in reason
|
|
|
|
|
|
def test_non_ortho_specialty_filtered():
|
|
"""Pediatric Dentist is a different specialty — not an orthodontist job."""
|
|
plan = _plan()
|
|
ev = _ev(
|
|
title="Job Application for Pediatric Dentist - Associate at Specialty Dental Brands",
|
|
body_text="Pediatric dentistry role with orthodontic referrals. Apply now.",
|
|
ortho_signal=True,
|
|
)
|
|
status, reason = classify_lead(ev, plan)
|
|
assert status == FILTERED
|
|
assert "other_specialty" in reason
|
|
|
|
|
|
def test_private_company_filtered():
|
|
"""Real false positive: for-profit DSO posting an actual ortho job."""
|
|
plan = _plan()
|
|
ev = _ev(
|
|
title="Job Application for Orthodontist at Specialty Dental Brands",
|
|
employer_type="private",
|
|
employer_type_reason="profile is for-profit DSO",
|
|
)
|
|
status, reason = classify_lead(ev, plan)
|
|
assert status == FILTERED
|
|
assert "employer scope" in reason and "private" in reason
|
|
|
|
|
|
def test_unknown_employer_filtered():
|
|
"""Default-deny: a mission-driven signal is required to keep a lead."""
|
|
plan = _plan()
|
|
ev = _ev(title="Orthodontist", employer_type="unknown")
|
|
status, reason = classify_lead(ev, plan)
|
|
assert status == FILTERED
|
|
assert "employer scope" in reason
|
|
|
|
|
|
def test_unknown_title_requires_credential():
|
|
plan = _plan()
|
|
ev = _ev(
|
|
title="Clinical Lead",
|
|
ats_platform="greenhouse",
|
|
credential_signal=False,
|
|
)
|
|
status, reason = classify_lead(ev, plan)
|
|
assert status == VERIFY
|
|
assert "credential" in reason
|
|
|
|
ev = _ev(
|
|
title="Clinical Lead",
|
|
ats_platform="greenhouse",
|
|
credential_signal=True,
|
|
)
|
|
status, _ = classify_lead(ev, plan)
|
|
assert status == ACTIVE
|
|
|
|
|
|
def test_has_credential_signal():
|
|
assert has_credential_signal("Requires a DDS or DMD degree", [])
|
|
assert has_credential_signal("Must hold a valid dental license", [])
|
|
assert not has_credential_signal("No degree mentioned", [])
|
|
assert has_credential_signal("custom credential", ["custom credential"])
|
|
|
|
|
|
def test_workday_apply_is_active():
|
|
plan = _plan()
|
|
ev = _ev(
|
|
url="https://wd5.myworkdayjobs.com/org/job/123",
|
|
final_url="https://wd5.myworkdayjobs.com/org/job/123",
|
|
body_text="Orthodontist apply now",
|
|
ats_platform="workday",
|
|
apply_found=True,
|
|
)
|
|
status, reason = classify_lead(ev, plan)
|
|
assert status == ACTIVE
|
|
assert "workday" in reason
|
|
|
|
|
|
def test_locum_deprioritized():
|
|
plan = _plan()
|
|
ev = _ev(body_text="Locum tenens orthodontist position", deprioritized=True)
|
|
status, reason = classify_lead(ev, plan)
|
|
assert status == FILTERED
|
|
assert "deprioritized" in reason
|
|
|
|
|
|
def test_extract_salary_range():
|
|
assert extract_salary("Salary $180,000 - $220,000 per year") == "$180,000 - $220,000"
|
|
assert extract_salary("Location: Phoenix") is None
|
|
|
|
|
|
def test_extract_fte():
|
|
assert extract_fte("This is a 0.8 FTE position") == "0.8 FTE"
|
|
assert extract_fte("Full-time orthodontist") == "Full-time"
|
|
assert extract_fte("Some text without fte") is None
|
|
|
|
|
|
def test_extract_license():
|
|
assert extract_license("Requires a valid state license or eligibility") is not None
|
|
assert extract_license("No requirements listed") is None
|
|
|
|
|
|
def test_has_deprioritized():
|
|
assert has_deprioritized("Per diem orthodontist", ["per diem", "locum"])
|
|
assert not has_deprioritized("Full-time orthodontist", ["per diem", "locum"]) |