test: refractor system comprehensive test coverage #117

Merged
cal merged 1 commits from test/refractor-comprehensive into main 2026-03-24 21:06:14 +00:00
Owner

Summary

  • 23 new test cases covering critical, high, and medium priority gaps in the Discord bot's Refractor integration
  • Tier 1 (Critical): tier_up dict shape mismatch exposing WP-14 latent bug, TIER_NAMES duplication divergence check, TIER_BADGES format consistency between cog and helpers
  • Tier 2 (High): notify_tier_completion with None channel, filter combination tier=4 + progress="close" behavior
  • Tier 3 (Medium): Malformed API response handling, progress bar boundary precision, RP formula label, unknown card_type fallback

Test plan

  • All 112 tests pass (89 pre-existing + 23 new), 0 failures
  • Ruff lint passed on all files
  • No new test files created — all added to existing files

Notable findings

  • T1-5 (WP-14 bug confirmed): build_tier_up_embed uses bare tier_up["player_name"] dict access — the minimal stub shape from the post-game hook will KeyError in production when WP-14 wires in the real function
  • T1-7: TIER_BADGES format split is intentional (bare in helpers/main, bracketed in cogs/refractor) — test validates the conversion relationship

🤖 Generated with Claude Code

## Summary - 23 new test cases covering critical, high, and medium priority gaps in the Discord bot's Refractor integration - **Tier 1 (Critical)**: tier_up dict shape mismatch exposing WP-14 latent bug, TIER_NAMES duplication divergence check, TIER_BADGES format consistency between cog and helpers - **Tier 2 (High)**: notify_tier_completion with None channel, filter combination tier=4 + progress="close" behavior - **Tier 3 (Medium)**: Malformed API response handling, progress bar boundary precision, RP formula label, unknown card_type fallback ## Test plan - [x] All 112 tests pass (89 pre-existing + 23 new), 0 failures - [x] Ruff lint passed on all files - [x] No new test files created — all added to existing files ## Notable findings - **T1-5 (WP-14 bug confirmed)**: `build_tier_up_embed` uses bare `tier_up["player_name"]` dict access — the minimal stub shape from the post-game hook will KeyError in production when WP-14 wires in the real function - T1-7: TIER_BADGES format split is intentional (bare in helpers/main, bracketed in cogs/refractor) — test validates the conversion relationship 🤖 Generated with [Claude Code](https://claude.com/claude-code)
cal added 1 commit 2026-03-24 21:02:48 +00:00
test: add comprehensive refractor test cases (T1-5 through T3-5)
All checks were successful
Ruff Lint / lint (pull_request) Successful in 22s
b34dcc390c
Implements all gap tests identified by PO agents across three existing
test files. No new files created — tests added to existing modules.

T1-5 (test_refractor_notifs): Expose WP-14 integration bug — minimal
stub dict {player_id, old_tier, new_tier} causes KeyError in
build_tier_up_embed because player_name/track_name use bare dict access.
Documents the bug contract so WP-14 implementers know what to fix.

T1-6 (test_refractor_commands): Divergence tripwire — imports TIER_NAMES
from both cogs.refractor and helpers.refractor_notifs and asserts deep
equality. Will fail the moment the two copies fall out of sync.

T1-7 (test_card_embed_refractor): TIER_BADGES format contract — asserts
that wrapping helpers.main badge values in brackets produces cogs.refractor
badge values (e.g. "BC" -> "[BC]") for all tiers.

T2-7 (test_refractor_notifs): notify_tier_completion with None channel
must not raise — the try/except absorbs AttributeError from None.send().

T2-8 (test_refractor_commands): All-T4 apply_close_filter returns empty
list. Documents intended behaviour for tier=4 + progress="close" combo.

T3-2 (test_refractor_commands): Malformed API response handling —
format_refractor_entry must use fallbacks ("Unknown", 0) for missing keys.

T3-3 (test_refractor_commands): Progress bar boundary precision — 1/100,
99/100, 0/100, and negative current values.

T3-4 (test_refractor_commands): RP formula label — card_type="rp" shows
"IP+K" (previously only "sp" was tested).

T3-5 (test_refractor_commands): Unknown card_type falls back to raw string
as the formula label without crashing.

112 tests pass (23 new, 89 pre-existing).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
cal reviewed 2026-03-24 21:04:44 +00:00
cal left a comment
Author
Owner

AI Code Review

Files Reviewed

  • tests/test_card_embed_refractor.py (modified — added TestTierBadgesFormatConsistency)
  • tests/test_refractor_commands.py (modified — added TestTierNamesDivergenceCheck, TestApplyCloseFilterWithAllT4Cards, TestFormatRefractorEntryMalformedInput, TestRenderProgressBarBoundaryPrecision, TestRPFormulaLabel, TestUnknownCardTypeFallback)
  • tests/test_refractor_notifs.py (modified — added TestTierUpDictShapeMismatch, TestNotifyTierCompletionNoneChannel)

Source files read for verification: cogs/refractor.py, helpers/refractor_notifs.py, helpers/main.py


Findings

Correctness

All assertions were verified against the actual source implementations.

T1-5 (TestTierUpDictShapeMismatch): build_tier_up_embed uses bare tier_up["player_name"] and tier_up["track_name"] (confirmed at helpers/refractor_notifs.py lines 50, 52). test_minimal_stub_shape_raises_key_error correctly documents the real KeyError. The companion test_full_shape_does_not_raise uses make_tier_up which supplies all required keys — correct.

T1-6 (TestTierNamesDivergenceCheck): Both cogs/refractor.py and helpers/refractor_notifs.py define identical TIER_NAMES dicts (T0-T4). The tripwire pattern (equality + key set + per-value) is sound. Call-time imports avoid monkeypatch interference as noted.

T1-7 (TestTierBadgesFormatConsistency): Confirmed helpers/main.py uses bare strings ({1: "BC", 2: "R", 3: "GR", 4: "SF"}) and cogs/refractor.py uses bracket strings ({1: "[BC]", 2: "[R]", ...}). The bracket-wrapping relationship is real. The four per-tier spot checks are redundant with the parametric test but low-cost and useful as documentation.

T2-7 (TestNotifyTierCompletionNoneChannel): notify_tier_completion wraps its entire body in try/except Exception, which catches the AttributeError from None.send(). The test correctly expects no raise.

T2-8 (TestApplyCloseFilterWithAllT4Cards): The current_tier >= 4 or not next_threshold guard in apply_close_filter excludes all T4 cards regardless of formula_value. Both test methods assert correct behavior.

T3-2 (TestFormatRefractorEntryMalformedInput): All four assertions verified. format_refractor_entry uses .get() with fallbacks for all fields. The empty-dict test correctly produces two lines because the next_threshold defaults to None via .get(), triggering the FULLY EVOLVED branch.

T3-3 (TestRenderProgressBarBoundaryPrecision): The negative value test correctly expects 0 filled segments. One note: the docstring attributes the behavior to the min(..., 1.0) clamp, but it is actually round() that truncates the small negative ratio to 0. The test result is correct regardless.

T3-4 (TestRPFormulaLabel): FORMULA_LABELS maps "rp" to "IP+K". Assertion is correct. Closes the gap where only "sp" was previously tested.

T3-5 (TestUnknownCardTypeFallback): FORMULA_LABELS.get(card_type, card_type) falls back to the raw string. Both "util" and "dh" are absent from FORMULA_LABELS, so both tests assert correctly.

Security

No issues found. Tests only import from internal modules with no new external dependencies or I/O.

Style & Conventions

  • Section header comment blocks follow the existing # ----------- pattern throughout all three files.
  • Docstrings follow the "what + why" format used in the existing test suite.
  • All new classes follow the TestFooBar naming convention.
  • New tests construct inline state dicts rather than adding fixtures, matching the existing style for simple inputs.
  • The two blank-line removals in test_refractor_commands.py are valid cleanup.

Suggestions

  • The docstring for test_negative_current_does_not_overflow_bar says "the min(..., 1.0) clamp in render_progress_bar should handle this." This is slightly inaccurate — negative values pass through the clamp (since -0.05 < 1.0) and the zero result comes from round() truncating the negative. Not a correctness issue, but worth a follow-up docstring fix to avoid misleading anyone who later modifies render_progress_bar.
  • TestTierNamesDivergenceCheck.test_tier_names_have_same_keys and test_tier_names_have_same_values are fully subsumed by test_tier_names_are_identical_across_modules. They are not wrong, and the pattern is consistent with how TestTierBadgesFormatConsistency handles the same concern.

Verdict: APPROVED

All 23 new test cases correctly assert against the actual source implementations. The WP-14 bug documentation test uses pytest.raises(KeyError) correctly — intent is clearly stated and the test will fail (become green-then-red) exactly when WP-14 fixes the underlying issue, at which point it should be converted to a positive assertion. Cross-module divergence tripwires target a real duplication risk. No pattern violations, no incorrect assertions found.


Automated review by Claude PR Reviewer

## AI Code Review ### Files Reviewed - `tests/test_card_embed_refractor.py` (modified — added `TestTierBadgesFormatConsistency`) - `tests/test_refractor_commands.py` (modified — added `TestTierNamesDivergenceCheck`, `TestApplyCloseFilterWithAllT4Cards`, `TestFormatRefractorEntryMalformedInput`, `TestRenderProgressBarBoundaryPrecision`, `TestRPFormulaLabel`, `TestUnknownCardTypeFallback`) - `tests/test_refractor_notifs.py` (modified — added `TestTierUpDictShapeMismatch`, `TestNotifyTierCompletionNoneChannel`) Source files read for verification: `cogs/refractor.py`, `helpers/refractor_notifs.py`, `helpers/main.py` --- ### Findings #### Correctness All assertions were verified against the actual source implementations. **T1-5 (`TestTierUpDictShapeMismatch`):** `build_tier_up_embed` uses bare `tier_up["player_name"]` and `tier_up["track_name"]` (confirmed at `helpers/refractor_notifs.py` lines 50, 52). `test_minimal_stub_shape_raises_key_error` correctly documents the real `KeyError`. The companion `test_full_shape_does_not_raise` uses `make_tier_up` which supplies all required keys — correct. **T1-6 (`TestTierNamesDivergenceCheck`):** Both `cogs/refractor.py` and `helpers/refractor_notifs.py` define identical `TIER_NAMES` dicts (T0-T4). The tripwire pattern (equality + key set + per-value) is sound. Call-time imports avoid monkeypatch interference as noted. **T1-7 (`TestTierBadgesFormatConsistency`):** Confirmed `helpers/main.py` uses bare strings (`{1: "BC", 2: "R", 3: "GR", 4: "SF"}`) and `cogs/refractor.py` uses bracket strings (`{1: "[BC]", 2: "[R]", ...}`). The bracket-wrapping relationship is real. The four per-tier spot checks are redundant with the parametric test but low-cost and useful as documentation. **T2-7 (`TestNotifyTierCompletionNoneChannel`):** `notify_tier_completion` wraps its entire body in `try/except Exception`, which catches the `AttributeError` from `None.send()`. The test correctly expects no raise. **T2-8 (`TestApplyCloseFilterWithAllT4Cards`):** The `current_tier >= 4 or not next_threshold` guard in `apply_close_filter` excludes all T4 cards regardless of formula_value. Both test methods assert correct behavior. **T3-2 (`TestFormatRefractorEntryMalformedInput`):** All four assertions verified. `format_refractor_entry` uses `.get()` with fallbacks for all fields. The empty-dict test correctly produces two lines because the `next_threshold` defaults to `None` via `.get()`, triggering the FULLY EVOLVED branch. **T3-3 (`TestRenderProgressBarBoundaryPrecision`):** The negative value test correctly expects 0 filled segments. One note: the docstring attributes the behavior to the `min(..., 1.0)` clamp, but it is actually `round()` that truncates the small negative ratio to 0. The test result is correct regardless. **T3-4 (`TestRPFormulaLabel`):** `FORMULA_LABELS` maps `"rp"` to `"IP+K"`. Assertion is correct. Closes the gap where only `"sp"` was previously tested. **T3-5 (`TestUnknownCardTypeFallback`):** `FORMULA_LABELS.get(card_type, card_type)` falls back to the raw string. Both `"util"` and `"dh"` are absent from `FORMULA_LABELS`, so both tests assert correctly. #### Security No issues found. Tests only import from internal modules with no new external dependencies or I/O. #### Style & Conventions - Section header comment blocks follow the existing `# -----------` pattern throughout all three files. - Docstrings follow the "what + why" format used in the existing test suite. - All new classes follow the `TestFooBar` naming convention. - New tests construct inline state dicts rather than adding fixtures, matching the existing style for simple inputs. - The two blank-line removals in `test_refractor_commands.py` are valid cleanup. #### Suggestions - The docstring for `test_negative_current_does_not_overflow_bar` says "the `min(..., 1.0)` clamp in `render_progress_bar` should handle this." This is slightly inaccurate — negative values pass through the clamp (since `-0.05 < 1.0`) and the zero result comes from `round()` truncating the negative. Not a correctness issue, but worth a follow-up docstring fix to avoid misleading anyone who later modifies `render_progress_bar`. - `TestTierNamesDivergenceCheck.test_tier_names_have_same_keys` and `test_tier_names_have_same_values` are fully subsumed by `test_tier_names_are_identical_across_modules`. They are not wrong, and the pattern is consistent with how `TestTierBadgesFormatConsistency` handles the same concern. ### Verdict: APPROVED All 23 new test cases correctly assert against the actual source implementations. The WP-14 bug documentation test uses `pytest.raises(KeyError)` correctly — intent is clearly stated and the test will fail (become green-then-red) exactly when WP-14 fixes the underlying issue, at which point it should be converted to a positive assertion. Cross-module divergence tripwires target a real duplication risk. No pattern violations, no incorrect assertions found. --- *Automated review by Claude PR Reviewer*
cal merged commit 8c0c2eb21a into main 2026-03-24 21:06:14 +00:00
cal deleted branch test/refractor-comprehensive 2026-03-24 21:06:15 +00:00
Sign in to join this conversation.
No reviewers
No Milestone
No project
No Assignees
1 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#117
No description provided.