test: mock-based integration tests for post-game refractor hook (#148) #158

Merged
cal merged 1 commits from issue/148-test-mock-based-integration-tests-for-post-game-re into main 2026-04-08 14:26:07 +00:00
Collaborator

Closes #148

Summary

Extracted the post-game refractor block from complete_game() into a standalone _run_post_game_refractor_hook(db_game_id, channel) helper, then added 13 mock-based integration tests that exercise the real production code path without requiring a live game.

Changes

command_logic/logic_gameplay.py

  • Added _run_post_game_refractor_hook(db_game_id, channel) — contains the try/except block that was previously inline in complete_game() at lines 4374–4387
  • complete_game() now calls the helper (await _run_post_game_refractor_hook(db_game["id"], interaction.channel)) — no behaviour change

tests/test_post_game_refractor_hook.py (new, 13 tests)

  • TestEndpointOrder — both endpoints called, season-stats before evaluate, game ID interpolated correctly
  • TestTierUpNotifications — one call per tier-up, correct channel forwarded, no calls on empty/absent tier_ups
  • TestVariantRenderTriggers — full tier_ups list passed to _trigger_variant_renders, not called on empty list, notifications fire before render trigger
  • TestNonFatalErrors — season-stats raise, evaluate raise, None evaluate response — all non-fatal

Test results

13 passed in 0.52s

Other observations

tests/test_complete_game_hook.py contains an _run_hook helper that duplicates the hook code inline rather than calling the production function. Now that _run_post_game_refractor_hook is extractable, those tests could be simplified to call it directly — but that's out of scope for this issue.

Closes #148 ## Summary Extracted the post-game refractor block from `complete_game()` into a standalone `_run_post_game_refractor_hook(db_game_id, channel)` helper, then added 13 mock-based integration tests that exercise the real production code path without requiring a live game. ## Changes **`command_logic/logic_gameplay.py`** - Added `_run_post_game_refractor_hook(db_game_id, channel)` — contains the `try/except` block that was previously inline in `complete_game()` at lines 4374–4387 - `complete_game()` now calls the helper (`await _run_post_game_refractor_hook(db_game["id"], interaction.channel)`) — no behaviour change **`tests/test_post_game_refractor_hook.py`** (new, 13 tests) - `TestEndpointOrder` — both endpoints called, season-stats before evaluate, game ID interpolated correctly - `TestTierUpNotifications` — one call per tier-up, correct channel forwarded, no calls on empty/absent tier_ups - `TestVariantRenderTriggers` — full tier_ups list passed to `_trigger_variant_renders`, not called on empty list, notifications fire before render trigger - `TestNonFatalErrors` — season-stats raise, evaluate raise, None evaluate response — all non-fatal ## Test results ``` 13 passed in 0.52s ``` ## Other observations `tests/test_complete_game_hook.py` contains an `_run_hook` helper that duplicates the hook code inline rather than calling the production function. Now that `_run_post_game_refractor_hook` is extractable, those tests could be simplified to call it directly — but that's out of scope for this issue.
Claude added 1 commit 2026-04-08 13:35:09 +00:00
test: mock-based integration tests for post-game refractor hook (#148)
All checks were successful
Ruff Lint / lint (pull_request) Successful in 28s
eb022c3d66
Extract _run_post_game_refractor_hook() from complete_game() so the hook
logic can be tested directly without a live game session. Add 13 tests
covering endpoint ordering, tier-up notification dispatch, variant render
triggers, and non-fatal error handling.

Closes #148

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude added the
ai-reviewing
label 2026-04-08 13:45:50 +00:00
Claude reviewed 2026-04-08 13:48:07 +00:00
Claude left a comment
Author
Collaborator

AI Code Review

Files Reviewed

  • command_logic/logic_gameplay.py (modified — extraction + call site update)
  • tests/test_post_game_refractor_hook.py (added — 13 tests)

Findings

Correctness

No issues found. The extraction is mechanical — the try/except block is moved verbatim into _run_post_game_refractor_hook, with db_game['id']db_game_id and interaction.channelchannel as expected parameter substitutions. Call site passes the same values. logger is in scope at module level (line 80). notify_tier_completion is already imported from helpers.refractor_notifs. No behavior change.

Security

No issues found.

Style & Conventions

  • Leading underscore on _run_post_game_refractor_hook correctly signals a private module-level function, consistent with the existing _trigger_variant_renders pattern.
  • Docstring explains non-fatal semantics clearly.
  • Type annotation db_game_id: int added; channel left unannotated (consistent with surrounding code).

Test quality

  • asyncio_mode = auto in pytest.ini handles async test methods — no @pytest.mark.asyncio decorators needed. ✓
  • patch() on async targets (notify_tier_completion, _trigger_variant_renders) auto-selects AsyncMock in Python 3.8+ — the two tests in TestVariantRenderTriggers that use bare patch(..., side_effect=async_fn) are correct. ✓
  • test_no_notify_when_tier_ups_key_absent correctly exercises the if evo_result and ... guard — {} is falsy, so the condition short-circuits. ✓
  • test_nonfatal_when_season_stats_raises uses side_effect=Exception(...) (an instance, not a callable) — AsyncMock raises it on the first await, which the outer try/except catches. ✓
  • Call-order test (test_notifications_before_render_trigger) tracks execution sequence via a shared list — solid approach for ordering assertions.
  • 13 tests across 4 classes cover: endpoint order, game-ID interpolation, notification dispatch, render trigger, and all three non-fatal error paths. No obvious gaps.

Suggestions

  • The PR body already acknowledges it: tests/test_complete_game_hook.py's inline _run_hook helper could eventually be replaced with a direct call to _run_post_game_refractor_hook, but that's a separate cleanup and not a blocker.

Verdict: APPROVED

Clean extraction with no behavior change, comprehensive test coverage, and correct mock usage throughout. Ready to merge.


Automated review by Claude PR Reviewer

## AI Code Review ### Files Reviewed - `command_logic/logic_gameplay.py` (modified — extraction + call site update) - `tests/test_post_game_refractor_hook.py` (added — 13 tests) ### Findings #### Correctness No issues found. The extraction is mechanical — the try/except block is moved verbatim into `_run_post_game_refractor_hook`, with `db_game['id']` → `db_game_id` and `interaction.channel` → `channel` as expected parameter substitutions. Call site passes the same values. `logger` is in scope at module level (line 80). `notify_tier_completion` is already imported from `helpers.refractor_notifs`. No behavior change. #### Security No issues found. #### Style & Conventions - Leading underscore on `_run_post_game_refractor_hook` correctly signals a private module-level function, consistent with the existing `_trigger_variant_renders` pattern. - Docstring explains non-fatal semantics clearly. - Type annotation `db_game_id: int` added; `channel` left unannotated (consistent with surrounding code). #### Test quality - `asyncio_mode = auto` in `pytest.ini` handles async test methods — no `@pytest.mark.asyncio` decorators needed. ✓ - `patch()` on async targets (`notify_tier_completion`, `_trigger_variant_renders`) auto-selects `AsyncMock` in Python 3.8+ — the two tests in `TestVariantRenderTriggers` that use bare `patch(..., side_effect=async_fn)` are correct. ✓ - `test_no_notify_when_tier_ups_key_absent` correctly exercises the `if evo_result and ...` guard — `{}` is falsy, so the condition short-circuits. ✓ - `test_nonfatal_when_season_stats_raises` uses `side_effect=Exception(...)` (an instance, not a callable) — `AsyncMock` raises it on the first await, which the outer try/except catches. ✓ - Call-order test (`test_notifications_before_render_trigger`) tracks execution sequence via a shared list — solid approach for ordering assertions. - 13 tests across 4 classes cover: endpoint order, game-ID interpolation, notification dispatch, render trigger, and all three non-fatal error paths. No obvious gaps. #### Suggestions - The PR body already acknowledges it: `tests/test_complete_game_hook.py`'s inline `_run_hook` helper could eventually be replaced with a direct call to `_run_post_game_refractor_hook`, but that's a separate cleanup and not a blocker. ### Verdict: APPROVED Clean extraction with no behavior change, comprehensive test coverage, and correct mock usage throughout. Ready to merge. --- *Automated review by Claude PR Reviewer*
Claude added
ai-reviewed
and removed
ai-reviewing
labels 2026-04-08 13:48:25 +00:00
cal approved these changes 2026-04-08 14:25:50 +00:00
cal left a comment
Owner

Approved via pd-pr

Approved via pd-pr
cal merged commit bd6c387902 into main 2026-04-08 14:26:07 +00:00
cal deleted branch issue/148-test-mock-based-integration-tests-for-post-game-re 2026-04-08 14:26:08 +00:00
Sign in to join this conversation.
No reviewers
cal
No Milestone
No project
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: cal/paper-dynasty-discord#158
No description provided.