99 lines
3.4 KiB
Python
99 lines
3.4 KiB
Python
"""Pure-logic tests for the dashboard's applications-per-job aggregate.
|
|
|
|
No DB: the SQL group-bys live on the models, but every decision this endpoint
|
|
makes — summing the two sources, zero-filling open reqs without resurrecting
|
|
dead postings, ordering, capping — is in _merge_job_counts and the serializer,
|
|
which is what the dashboard's numbers stand on.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from types import SimpleNamespace
|
|
from uuid import uuid4
|
|
|
|
from analytics.serializers import serialize_job_application_count
|
|
from analytics.views import _merge_job_counts
|
|
|
|
|
|
def _job(title="Backend Engineer", status="open", **overrides):
|
|
fields = {
|
|
"id": uuid4(),
|
|
"title": title,
|
|
"department": "Engineering",
|
|
"requisition_status": status,
|
|
"vacancies": 2,
|
|
"is_active": True,
|
|
}
|
|
fields.update(overrides)
|
|
return SimpleNamespace(**fields)
|
|
|
|
|
|
# ---------------------------------------------------------------- serializer
|
|
|
|
def test_serializer_coerces_and_stringifies():
|
|
job = _job(vacancies=None, department=None)
|
|
row = serialize_job_application_count(job, None)
|
|
assert row["job_post_id"] == str(job.id)
|
|
assert row["count"] == 0
|
|
assert row["vacancies"] == 0
|
|
assert row["department"] == ""
|
|
assert row["is_active"] is True
|
|
|
|
|
|
# ---------------------------------------------------------------- merge
|
|
|
|
def test_merge_sums_both_sources():
|
|
job = _job()
|
|
key = str(job.id)
|
|
rows = _merge_job_counts({key: 3}, {key: 2}, [job], [], 10)
|
|
assert len(rows) == 1
|
|
assert rows[0]["count"] == 5
|
|
|
|
|
|
def test_merge_includes_zero_application_open_reqs():
|
|
starving = _job(title="Unloved Role")
|
|
rows = _merge_job_counts({}, {}, [], [starving], 10)
|
|
assert len(rows) == 1
|
|
assert rows[0]["count"] == 0
|
|
assert rows[0]["title"] == "Unloved Role"
|
|
|
|
|
|
def test_merge_never_resurrects_closed_jobs_without_counts():
|
|
# A closed job appears only when it actually received applications:
|
|
# it arrives via job_rows (it had counts), never via the open-req fill.
|
|
closed_with_apps = _job(title="Closed But Applied", status="closed", is_active=False)
|
|
rows = _merge_job_counts({str(closed_with_apps.id): 4}, {}, [closed_with_apps], [], 10)
|
|
assert [r["title"] for r in rows] == ["Closed But Applied"]
|
|
|
|
# No counts and not open -> absent entirely (it is in neither input).
|
|
rows = _merge_job_counts({}, {}, [], [], 10)
|
|
assert rows == []
|
|
|
|
|
|
def test_merge_drops_counts_for_unknown_jobs():
|
|
# A count whose job row could not be loaded must not crash or emit a row.
|
|
rows = _merge_job_counts({str(uuid4()): 7}, {}, [], [], 10)
|
|
assert rows == []
|
|
|
|
|
|
def test_merge_orders_by_count_desc_then_title_and_caps():
|
|
a = _job(title="Alpha")
|
|
b = _job(title="beta")
|
|
c = _job(title="Zeta")
|
|
d = _job(title="Delta")
|
|
counts = {str(a.id): 1, str(c.id): 5, str(d.id): 1}
|
|
rows = _merge_job_counts(counts, {}, [a, c, d], [b], 3)
|
|
# count desc; ties by title case-insensitively; zero rows last; capped at 3.
|
|
assert [r["title"] for r in rows] == ["Zeta", "Alpha", "Delta"]
|
|
|
|
rows = _merge_job_counts(counts, {}, [a, c, d], [b], 10)
|
|
assert [r["title"] for r in rows] == ["Zeta", "Alpha", "Delta", "beta"]
|
|
|
|
|
|
def test_merge_top_survives_garbage():
|
|
job = _job()
|
|
rows = _merge_job_counts({str(job.id): 1}, {}, [job], [], None)
|
|
assert len(rows) == 1
|
|
rows = _merge_job_counts({str(job.id): 1}, {}, [job], [], 0)
|
|
assert len(rows) == 1
|