"""Tests for the evolution track seed data fixture (WP-03). Unit tests verify the JSON fixture is correctly formed without touching any database. The integration test binds a minimal in-memory EvolutionTrack model (mirroring the schema WP-01 will add to db_engine) to an in-memory SQLite database, calls seed(), and verifies idempotency. """ import pytest from peewee import CharField, IntegerField, Model, SqliteDatabase from app.seed.evolution_tracks import load_tracks, seed # --------------------------------------------------------------------------- # Fixtures # --------------------------------------------------------------------------- _test_db = SqliteDatabase(":memory:") class EvolutionTrackStub(Model): """Minimal EvolutionTrack model for integration tests. Mirrors the schema that WP-01 will add to db_engine so the integration test can run without WP-01 being merged. """ name = CharField() card_type = CharField(unique=True) formula = CharField() t1 = IntegerField() t2 = IntegerField() t3 = IntegerField() t4 = IntegerField() class Meta: database = _test_db table_name = "evolution_track" @pytest.fixture(autouse=True) def _db(): """Bind and create the stub table; drop it after each test.""" _test_db.connect(reuse_if_open=True) _test_db.create_tables([EvolutionTrackStub]) yield _test_db.drop_tables([EvolutionTrackStub]) # --------------------------------------------------------------------------- # Unit tests — JSON fixture only, no database # --------------------------------------------------------------------------- def test_three_tracks_in_seed_data(): """load_tracks() must return exactly 3 evolution tracks.""" assert len(load_tracks()) == 3 def test_card_types_are_exactly_batter_sp_rp(): """The set of card_type values must be exactly {'batter', 'sp', 'rp'}.""" types = {t["card_type"] for t in load_tracks()} assert types == {"batter", "sp", "rp"} def test_all_thresholds_positive_and_ascending(): """Each track must have t1 < t2 < t3 < t4, all positive.""" for track in load_tracks(): assert track["t1"] > 0 assert track["t1"] < track["t2"] < track["t3"] < track["t4"] def test_all_tracks_have_non_empty_formula(): """Every track must have a non-empty formula string.""" for track in load_tracks(): assert isinstance(track["formula"], str) and track["formula"].strip() def test_tier_thresholds_match_locked_values(): """Threshold values must exactly match the locked design spec.""" tracks = {t["card_type"]: t for t in load_tracks()} assert tracks["batter"]["t1"] == 37 assert tracks["batter"]["t2"] == 149 assert tracks["batter"]["t3"] == 448 assert tracks["batter"]["t4"] == 896 assert tracks["sp"]["t1"] == 10 assert tracks["sp"]["t2"] == 40 assert tracks["sp"]["t3"] == 120 assert tracks["sp"]["t4"] == 240 assert tracks["rp"]["t1"] == 3 assert tracks["rp"]["t2"] == 12 assert tracks["rp"]["t3"] == 35 assert tracks["rp"]["t4"] == 70 # --------------------------------------------------------------------------- # Integration test — uses the stub model + in-memory SQLite # --------------------------------------------------------------------------- def test_seed_is_idempotent(): """Calling seed() twice must not create duplicate rows (get_or_create). First call: all three tracks created (created=True for each). Second call: all three already exist (created=False for each). Both calls succeed without error. """ results_first = seed(model_class=EvolutionTrackStub) assert len(results_first) == 3 assert all(created for _, created in results_first) results_second = seed(model_class=EvolutionTrackStub) assert len(results_second) == 3 assert not any(created for _, created in results_second) assert EvolutionTrackStub.select().count() == 3