fix: complete remaining evolution→refractor renames from review

- Rename route /{team_id}/evolutions → /{team_id}/refractors
- Rename function initialize_card_evolution → initialize_card_refractor
- Rename index names in migration SQL
- Update all test references

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Cal Corum 2026-03-23 14:17:03 -05:00
parent b7dec3f231
commit 500a8f3848
6 changed files with 40 additions and 36 deletions

View File

@ -16,7 +16,7 @@ from ..db_engine import (
DoesNotExist,
)
from ..dependencies import oauth2_scheme, valid_token
from ..services.refractor_init import _determine_card_type, initialize_card_evolution
from ..services.refractor_init import _determine_card_type, initialize_card_refractor
router = APIRouter(prefix="/api/v2/cards", tags=["cards"])
@ -227,7 +227,7 @@ async def v1_cards_post(cards: CardModel, token: str = Depends(oauth2_scheme)):
try:
this_player = Player.get_by_id(x.player_id)
card_type = _determine_card_type(this_player)
initialize_card_evolution(x.player_id, x.team_id, card_type)
initialize_card_refractor(x.player_id, x.team_id, card_type)
except Exception:
logging.exception(
"refractor hook: unexpected error for player_id=%s team_id=%s",

View File

@ -1530,8 +1530,8 @@ async def delete_team(team_id, token: str = Depends(oauth2_scheme)):
raise HTTPException(status_code=500, detail=f"Team {team_id} was not deleted")
@router.get("/{team_id}/evolutions")
async def list_team_evolutions(
@router.get("/{team_id}/refractors")
async def list_team_refractors(
team_id: int,
card_type: Optional[str] = Query(default=None),
tier: Optional[int] = Query(default=None),

View File

@ -3,7 +3,7 @@ WP-10: Pack opening hook — refractor_card_state initialization.
Public API
----------
initialize_card_evolution(player_id, team_id, card_type)
initialize_card_refractor(player_id, team_id, card_type)
Get-or-create a RefractorCardState for the (player_id, team_id) pair.
Returns the state instance on success, or None if initialization fails
(missing track, integrity error, etc.). Never raises.
@ -53,7 +53,7 @@ def _determine_card_type(player) -> str:
return "batter"
def initialize_card_evolution(
def initialize_card_refractor(
player_id: int,
team_id: int,
card_type: str,

View File

@ -13,3 +13,7 @@ ALTER TABLE evolution_track RENAME TO refractor_track;
ALTER TABLE evolution_card_state RENAME TO refractor_card_state;
ALTER TABLE evolution_tier_boost RENAME TO refractor_tier_boost;
ALTER TABLE evolution_cosmetic RENAME TO refractor_cosmetic;
-- Rename indexes to match new table names
ALTER INDEX IF EXISTS evolution_card_state_player_team_uniq RENAME TO refractor_card_state_player_team_uniq;
ALTER INDEX IF EXISTS evolution_tier_boost_track_tier_type_target_uniq RENAME TO refractor_tier_boost_track_tier_type_target_uniq;

View File

@ -1,7 +1,7 @@
"""
Tests for WP-10: refractor_card_state initialization on pack opening.
Covers `app/services/refractor_init.py` the `initialize_card_evolution`
Covers `app/services/refractor_init.py` the `initialize_card_refractor`
function that creates an RefractorCardState row when a card is first acquired.
Test strategy:
@ -30,7 +30,7 @@ from app.db_engine import (
RefractorTrack,
Player,
)
from app.services.refractor_init import _determine_card_type, initialize_card_evolution
from app.services.refractor_init import _determine_card_type, initialize_card_refractor
# ---------------------------------------------------------------------------
@ -154,12 +154,12 @@ class TestDetermineCardType:
# ---------------------------------------------------------------------------
# Integration tests — initialize_card_evolution
# Integration tests — initialize_card_refractor
# ---------------------------------------------------------------------------
class TestInitializeCardEvolution:
"""Integration tests for initialize_card_evolution against in-memory SQLite.
"""Integration tests for initialize_card_refractor against in-memory SQLite.
Each test relies on the conftest autouse fixture to get a clean database.
We create tracks for all three card types so the function can always find
@ -170,7 +170,7 @@ class TestInitializeCardEvolution:
def seed_tracks(self):
"""Create one RefractorTrack per card_type before each test.
initialize_card_evolution does a DB lookup for a track matching the
initialize_card_refractor does a DB lookup for a track matching the
card_type. If no track exists the function must not crash (it should
log and return None), but having tracks present lets us verify the
happy path for all three types without repeating setup in every test.
@ -189,7 +189,7 @@ class TestInitializeCardEvolution:
- track matches the player's card_type (batter here)
"""
player = _make_player(rarity, "2B")
state = initialize_card_evolution(player.player_id, team.id, "batter")
state = initialize_card_refractor(player.player_id, team.id, "batter")
assert state is not None
assert state.player_id == player.player_id
@ -208,7 +208,7 @@ class TestInitializeCardEvolution:
"""
player = _make_player(rarity, "SS")
# First call creates the state
state1 = initialize_card_evolution(player.player_id, team.id, "batter")
state1 = initialize_card_refractor(player.player_id, team.id, "batter")
assert state1 is not None
# Simulate partial evolution progress
@ -217,7 +217,7 @@ class TestInitializeCardEvolution:
state1.save()
# Second call (duplicate card) must not reset progress
state2 = initialize_card_evolution(player.player_id, team.id, "batter")
state2 = initialize_card_refractor(player.player_id, team.id, "batter")
assert state2 is not None
# Exactly one row in the database
@ -246,8 +246,8 @@ class TestInitializeCardEvolution:
player_a = _make_player(rarity, "LF")
player_b = _make_player(rarity, "RF")
state_a = initialize_card_evolution(player_a.player_id, team.id, "batter")
state_b = initialize_card_evolution(player_b.player_id, team.id, "batter")
state_a = initialize_card_refractor(player_a.player_id, team.id, "batter")
state_b = initialize_card_refractor(player_b.player_id, team.id, "batter")
assert state_a is not None
assert state_b is not None
@ -264,7 +264,7 @@ class TestInitializeCardEvolution:
state links to the sp track, not the batter track.
"""
player = _make_player(rarity, "SP")
state = initialize_card_evolution(player.player_id, team.id, "sp")
state = initialize_card_refractor(player.player_id, team.id, "sp")
assert state is not None
assert state.track_id == self.sp_track.id
@ -272,7 +272,7 @@ class TestInitializeCardEvolution:
def test_rp_card_gets_rp_track(self, rarity, team):
"""A relief pitcher (RP or CP) is assigned the 'rp' RefractorTrack."""
player = _make_player(rarity, "RP")
state = initialize_card_evolution(player.player_id, team.id, "rp")
state = initialize_card_refractor(player.player_id, team.id, "rp")
assert state is not None
assert state.track_id == self.rp_track.id
@ -291,7 +291,7 @@ class TestInitializeCardEvolution:
# Delete the sp track to simulate missing seed data
self.sp_track.delete_instance()
result = initialize_card_evolution(player.player_id, team.id, "sp")
result = initialize_card_refractor(player.player_id, team.id, "sp")
assert result is None
def test_card_type_from_pos1_batter(self, rarity, team):
@ -302,7 +302,7 @@ class TestInitializeCardEvolution:
"""
player = _make_player(rarity, "3B")
card_type = _determine_card_type(player)
state = initialize_card_evolution(player.player_id, team.id, card_type)
state = initialize_card_refractor(player.player_id, team.id, card_type)
assert state is not None
assert state.track_id == self.batter_track.id
@ -311,7 +311,7 @@ class TestInitializeCardEvolution:
"""_determine_card_type is wired correctly for a starting pitcher."""
player = _make_player(rarity, "SP")
card_type = _determine_card_type(player)
state = initialize_card_evolution(player.player_id, team.id, card_type)
state = initialize_card_refractor(player.player_id, team.id, card_type)
assert state is not None
assert state.track_id == self.sp_track.id
@ -320,7 +320,7 @@ class TestInitializeCardEvolution:
"""_determine_card_type correctly routes CP to the rp track."""
player = _make_player(rarity, "CP")
card_type = _determine_card_type(player)
state = initialize_card_evolution(player.player_id, team.id, card_type)
state = initialize_card_refractor(player.player_id, team.id, card_type)
assert state is not None
assert state.track_id == self.rp_track.id

View File

@ -1,7 +1,7 @@
"""Integration tests for the refractor card state API endpoints (WP-07).
Tests cover:
GET /api/v2/teams/{team_id}/evolutions
GET /api/v2/teams/{team_id}/refractors
GET /api/v2/refractor/cards/{card_id}
All tests require a live PostgreSQL connection (POSTGRES_HOST env var) and
@ -24,7 +24,7 @@ Object graph built by fixtures
Test matrix
-----------
test_list_team_evolutions -- baseline: returns count + items for a team
test_list_team_refractors -- baseline: returns count + items for a team
test_list_filter_by_card_type -- card_type query param filters by track.card_type
test_list_filter_by_tier -- tier query param filters by current_tier
test_list_pagination -- page/per_page params slice results correctly
@ -288,19 +288,19 @@ def client():
# ---------------------------------------------------------------------------
# Tests: GET /api/v2/teams/{team_id}/evolutions
# Tests: GET /api/v2/teams/{team_id}/refractors
# ---------------------------------------------------------------------------
@_skip_no_pg
def test_list_team_evolutions(client, seeded_data):
"""GET /teams/{id}/evolutions returns count=1 and one item for the seeded state.
def test_list_team_refractors(client, seeded_data):
"""GET /teams/{id}/refractors returns count=1 and one item for the seeded state.
Verifies the basic list response shape: a dict with 'count' and 'items',
and that the single item contains player_id, team_id, and current_tier.
"""
team_id = seeded_data["team_id"]
resp = client.get(f"/api/v2/teams/{team_id}/evolutions", headers=AUTH_HEADER)
resp = client.get(f"/api/v2/teams/{team_id}/refractors", headers=AUTH_HEADER)
assert resp.status_code == 200
data = resp.json()
assert data["count"] == 1
@ -337,7 +337,7 @@ def test_list_filter_by_card_type(client, seeded_data, pg_conn):
team_id = seeded_data["team_id"]
resp_batter = client.get(
f"/api/v2/teams/{team_id}/evolutions?card_type=batter", headers=AUTH_HEADER
f"/api/v2/teams/{team_id}/refractors?card_type=batter", headers=AUTH_HEADER
)
assert resp_batter.status_code == 200
batter_data = resp_batter.json()
@ -345,7 +345,7 @@ def test_list_filter_by_card_type(client, seeded_data, pg_conn):
assert batter_data["items"][0]["player_id"] == seeded_data["player_id"]
resp_sp = client.get(
f"/api/v2/teams/{team_id}/evolutions?card_type=sp", headers=AUTH_HEADER
f"/api/v2/teams/{team_id}/refractors?card_type=sp", headers=AUTH_HEADER
)
assert resp_sp.status_code == 200
sp_data = resp_sp.json()
@ -377,13 +377,13 @@ def test_list_filter_by_tier(client, seeded_data, pg_conn):
team_id = seeded_data["team_id"]
resp_t1 = client.get(
f"/api/v2/teams/{team_id}/evolutions?tier=1", headers=AUTH_HEADER
f"/api/v2/teams/{team_id}/refractors?tier=1", headers=AUTH_HEADER
)
assert resp_t1.status_code == 200
assert resp_t1.json()["count"] == 0
resp_t2 = client.get(
f"/api/v2/teams/{team_id}/evolutions?tier=2", headers=AUTH_HEADER
f"/api/v2/teams/{team_id}/refractors?tier=2", headers=AUTH_HEADER
)
assert resp_t2.status_code == 200
t2_data = resp_t2.json()
@ -426,14 +426,14 @@ def test_list_pagination(client, seeded_data, pg_conn):
team_id = seeded_data["team_id"]
resp1 = client.get(
f"/api/v2/teams/{team_id}/evolutions?page=1&per_page=1", headers=AUTH_HEADER
f"/api/v2/teams/{team_id}/refractors?page=1&per_page=1", headers=AUTH_HEADER
)
assert resp1.status_code == 200
data1 = resp1.json()
assert len(data1["items"]) == 1
resp2 = client.get(
f"/api/v2/teams/{team_id}/evolutions?page=2&per_page=1", headers=AUTH_HEADER
f"/api/v2/teams/{team_id}/refractors?page=2&per_page=1", headers=AUTH_HEADER
)
assert resp2.status_code == 200
data2 = resp2.json()
@ -596,13 +596,13 @@ def test_auth_required(client, seeded_data):
"""Both endpoints return 401 when no Bearer token is provided.
Verifies that the valid_token dependency is enforced on:
GET /api/v2/teams/{id}/evolutions
GET /api/v2/teams/{id}/refractors
GET /api/v2/refractor/cards/{id}
"""
team_id = seeded_data["team_id"]
card_id = seeded_data["card_id"]
resp_list = client.get(f"/api/v2/teams/{team_id}/evolutions")
resp_list = client.get(f"/api/v2/teams/{team_id}/refractors")
assert resp_list.status_code == 401
resp_card = client.get(f"/api/v2/refractor/cards/{card_id}")