keep applicant count fix surgical
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
"""Dashboard stats — pure-helper and RQ Score client contract tests."""
|
||||
|
||||
import asyncio
|
||||
|
||||
import httpx
|
||||
@@ -11,71 +10,34 @@ from app.db.repo import _activity_score
|
||||
|
||||
|
||||
def test_posted_date_per_board():
|
||||
assert (
|
||||
_posted_date({"createdDate": "2026-06-18T10:37:17Z"}) == "2026-06-18T10:37:17Z"
|
||||
) # Naukri
|
||||
assert (
|
||||
_posted_date({"postedDate": "2026-06-18T12:46:39Z"}) == "2026-06-18T12:46:39Z"
|
||||
) # LinkedIn
|
||||
assert (
|
||||
_posted_date({"date_posted": "2026-06-17T17:38:14Z"}) == "2026-06-17T17:38:14Z"
|
||||
) # Foundit
|
||||
assert (
|
||||
_posted_date({"jobDetails": {"createdDate": "2026-06-18T00:00:00Z"}})
|
||||
is not None
|
||||
) # nested
|
||||
assert _posted_date({"createdDate": "2026-06-18T10:37:17Z"}) == "2026-06-18T10:37:17Z" # Naukri
|
||||
assert _posted_date({"postedDate": "2026-06-18T12:46:39Z"}) == "2026-06-18T12:46:39Z" # LinkedIn
|
||||
assert _posted_date({"date_posted": "2026-06-17T17:38:14Z"}) == "2026-06-17T17:38:14Z" # Foundit
|
||||
assert _posted_date({"jobDetails": {"createdDate": "2026-06-18T00:00:00Z"}}) is not None # nested
|
||||
assert _posted_date({"nope": "x"}) is None
|
||||
|
||||
|
||||
def test_match_scores_and_histogram():
|
||||
opps = [{"match": {"score": 84}}, {"matchScore": 72}, {"match": {"score": 0}}, {}]
|
||||
scores = S._match_scores(opps)
|
||||
assert sorted(scores) == [72, 84] # 0 and missing dropped
|
||||
assert sorted(scores) == [72, 84] # 0 and missing dropped
|
||||
h = S._histogram(scores)
|
||||
assert sum(h) == 2 and len(h) == 11
|
||||
|
||||
|
||||
def test_scout_stats_accepts_numeric_applicant_strings(monkeypatch):
|
||||
feed = {
|
||||
"opportunities": [
|
||||
{"applicants": "10"},
|
||||
{"applicants": 30},
|
||||
{"applicants": "unknown"},
|
||||
]
|
||||
}
|
||||
feed = {"opportunities": [{"applicants": "10"}, {"applicants": 30}, {"applicants": "unknown"}]}
|
||||
activity = {
|
||||
"matches": 3,
|
||||
"viewed": 0,
|
||||
"saved": 0,
|
||||
"applied": 0,
|
||||
"tailored": 0,
|
||||
"searches": 1,
|
||||
"percentile": None,
|
||||
"cohort_size": 1,
|
||||
"matches": 3, "viewed": 0, "saved": 0, "applied": 0, "tailored": 0,
|
||||
"searches": 1, "percentile": None, "cohort_size": 1,
|
||||
}
|
||||
monkeypatch.setattr(
|
||||
S._repo, "get_feed", lambda _user_id: asyncio.sleep(0, result=feed)
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
S._repo,
|
||||
"get_activity_stats",
|
||||
lambda _user_id: asyncio.sleep(0, result=activity),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
S._repo, "get_active_window", lambda _user_id: asyncio.sleep(0, result={})
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
S._repo, "get_salary_band", lambda _user_id: asyncio.sleep(0, result=None)
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
S._clients, "fetch_qx", lambda _user_uuid: asyncio.sleep(0, result=None)
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
S._clients, "fetch_qx_trend", lambda _user_uuid: asyncio.sleep(0, result=None)
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
S._clients, "fetch_streak", lambda _user_id: asyncio.sleep(0, result=None)
|
||||
)
|
||||
monkeypatch.setattr(S._repo, "get_feed", lambda _user_id: asyncio.sleep(0, result=feed))
|
||||
monkeypatch.setattr(S._repo, "get_activity_stats", lambda _user_id: asyncio.sleep(0, result=activity))
|
||||
monkeypatch.setattr(S._repo, "get_active_window", lambda _user_id: asyncio.sleep(0, result={}))
|
||||
monkeypatch.setattr(S._repo, "get_salary_band", lambda _user_id: asyncio.sleep(0, result=None))
|
||||
monkeypatch.setattr(S._clients, "fetch_qx", lambda _user_uuid: asyncio.sleep(0, result=None))
|
||||
monkeypatch.setattr(S._clients, "fetch_qx_trend", lambda _user_uuid: asyncio.sleep(0, result=None))
|
||||
monkeypatch.setattr(S._clients, "fetch_streak", lambda _user_id: asyncio.sleep(0, result=None))
|
||||
|
||||
result = asyncio.run(S.build_scout_stats("user-1"))
|
||||
|
||||
@@ -85,26 +47,13 @@ def test_scout_stats_accepts_numeric_applicant_strings(monkeypatch):
|
||||
def test_apply_window_freshness():
|
||||
# all None when no posting dates (honest — never fabricated)
|
||||
assert S._apply_window([{}, {"posted_date": None}])["urgency"] is None
|
||||
w = S._apply_window(
|
||||
[
|
||||
{"posted_date": "2026-06-19T00:00:00Z"},
|
||||
{"posted_date": "2026-06-15T00:00:00Z"},
|
||||
]
|
||||
)
|
||||
assert (
|
||||
w["dated"] == 2
|
||||
and w["median_age_days"] is not None
|
||||
and w["urgency"] in ("high", "medium", "low")
|
||||
)
|
||||
w = S._apply_window([{"posted_date": "2026-06-19T00:00:00Z"}, {"posted_date": "2026-06-15T00:00:00Z"}])
|
||||
assert w["dated"] == 2 and w["median_age_days"] is not None and w["urgency"] in ("high", "medium", "low")
|
||||
|
||||
|
||||
def test_activity_score_weighting():
|
||||
# applies weighted highest, then saves, views, searches
|
||||
assert (
|
||||
_activity_score(0, 0, 1, 0)
|
||||
> _activity_score(0, 1, 0, 0)
|
||||
> _activity_score(1, 0, 0, 0)
|
||||
)
|
||||
assert _activity_score(0, 0, 1, 0) > _activity_score(0, 1, 0, 0) > _activity_score(1, 0, 0, 0)
|
||||
assert _activity_score(0, 0, 0, 0) == 0
|
||||
|
||||
|
||||
@@ -153,9 +102,7 @@ def test_fetch_qx_treats_malformed_payload_as_absent(monkeypatch):
|
||||
|
||||
def test_fetch_qx_trend_ignores_malformed_and_absent_points(monkeypatch):
|
||||
async def _get(_self, _url, **_kwargs):
|
||||
return _Response(
|
||||
{"points": [None, {"rq_score": "bad"}, {"rq_score": 35}, {"rq_score": 40}]}
|
||||
)
|
||||
return _Response({"points": [None, {"rq_score": "bad"}, {"rq_score": 35}, {"rq_score": 40}]})
|
||||
|
||||
monkeypatch.setattr(httpx.AsyncClient, "get", _get)
|
||||
|
||||
@@ -164,15 +111,13 @@ def test_fetch_qx_trend_ignores_malformed_and_absent_points(monkeypatch):
|
||||
|
||||
def test_fetch_qx_trend_reads_strict_rq_score_points(monkeypatch):
|
||||
async def _get(_self, _url, **_kwargs):
|
||||
return _Response(
|
||||
{
|
||||
"points": [
|
||||
{"rq_score": 35, "q_score": 91},
|
||||
{"rq_score": 44.16, "q_score": 92},
|
||||
{"q_score": 93},
|
||||
]
|
||||
}
|
||||
)
|
||||
return _Response({
|
||||
"points": [
|
||||
{"rq_score": 35, "q_score": 91},
|
||||
{"rq_score": 44.16, "q_score": 92},
|
||||
{"q_score": 93},
|
||||
]
|
||||
})
|
||||
|
||||
monkeypatch.setattr(httpx.AsyncClient, "get", _get)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user