"""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