"""Tests for the 2026-05-28 reaper fixes: 1. The reaper used to read ``instance.get("instance_status")`` — but ``GET /approval/v4/instances/{code}`` returns its status under ``status``, NOT ``instance_status``. Every status-based branch was a silent no-op since PR #164 launched the reaper. Only the fetch-error hard-expire branch actually fired. 2. The reaper's COMPLETED branch was an explicit ``# else COMPLETED — leave alone, callback should land``. When Feishu's at-most-once webhook delivery drops the event, the callback never lands and the row sits ``pending`` forever. The reaper now replays the missed callback via ``ApprovalService.replay_callback_from_feishu``. These tests pin the bugfix at the source-inspection level (so a future refactor cannot silently regress to the wrong key) AND the behavioural level (a pending row + a Feishu-COMPLETED response → replay invocation). """ from __future__ import annotations import inspect def test_reaper_reads_status_key_not_instance_status_key() -> None: """Source-level guard: the reaper must inspect ``status`` from the Feishu instance payload, never ``instance_status``. The latter is a different shape on a different endpoint and the original wiring silently broke every status check. """ from app.scheduled_jobs import feishu_handlers src = inspect.getsource(feishu_handlers.run_approval_pending_reaper) # Positive: must read the documented Feishu key assert 'instance.get("status")' in src # Negative: must not regress to the broken key. We allow it to # appear in comments / docstrings so future code-review notes # explaining the old bug survive — but it must not appear as a # ``.get(...)`` argument string. assert 'instance.get("instance_status")' not in src def test_reaper_replays_completed_via_service() -> None: """Source-level guard: the reaper's terminal-state branches must delegate to ``service.replay_callback_from_feishu`` (the idempotent replay path), NOT mutate ``req.status`` directly. Direct mutation would leave the per-domain child row (DnsRecordRequest, ScopeRequest, ApiKeyAssignment, AssetEmployeeRequest, …) orphaned in ``pending`` even though the parent flipped to ``approved``. The terminal-state list lives at module level (``_TERMINAL_FEISHU_STATUSES_FOR_REPLAY``); we assert against that constant rather than scanning the function body for literals so a future refactor that moves the list elsewhere still trips the test. """ from app.scheduled_jobs import feishu_handlers src = inspect.getsource(feishu_handlers.run_approval_pending_reaper) assert "service.replay_callback_from_feishu(" in src assert "_TERMINAL_FEISHU_STATUSES_FOR_REPLAY" in src terminal = feishu_handlers._TERMINAL_FEISHU_STATUSES_FOR_REPLAY # Approved + Cancelled both go through the same replay branch. assert "APPROVED" in terminal assert "COMPLETED" in terminal assert "CANCELED" in terminal assert "REJECTED" in terminal def test_reaper_does_not_short_circuit_completed_state() -> None: """The reaper used to drop COMPLETED on the floor with ``# else COMPLETED — leave alone, callback should land``. Pin that the "leave alone" branch is gone from the function body so a future refactor doesn't accidentally reinstate the silent drop. The docstring legitimately references the historical comment when describing the 2026-05-28 fix, so we scope the assertion to "branch comment in the loop body" by requiring the literal phrase appears at most ONCE (in the docstring) and the surrounding branch comment ``# else COMPLETED`` is gone. """ from app.scheduled_jobs import feishu_handlers src = inspect.getsource(feishu_handlers.run_approval_pending_reaper) assert "# else COMPLETED — leave alone" not in src assert "# else COMPLETED" not in src