""" Shared test fixtures for the Paper Dynasty database test suite. Provides dummy PostgreSQL credentials so PooledPostgresqlDatabase can be instantiated during test collection without a real database connection. Each test module is responsible for binding models to its own test database. """ import os import pytest import psycopg2 from peewee import SqliteDatabase # Provide dummy credentials so PooledPostgresqlDatabase can be instantiated # without raising a configuration error (it will not actually be used). os.environ.setdefault("POSTGRES_PASSWORD", "test-dummy") from app.db_engine import ( Rarity, Event, Cardset, MlbPlayer, Player, Team, PackType, Pack, Card, Roster, RosterSlot, StratGame, StratPlay, Decision, BattingSeasonStats, PitchingSeasonStats, ProcessedGame, BattingCard, PitchingCard, RefractorTrack, RefractorCardState, RefractorBoostAudit, ScoutOpportunity, ScoutClaim, ) _test_db = SqliteDatabase(":memory:", pragmas={"foreign_keys": 1}) # All models in dependency order (parents before children) so that # create_tables and drop_tables work without FK violations. _TEST_MODELS = [ Rarity, Event, Cardset, MlbPlayer, Player, Team, PackType, Pack, Card, Roster, RosterSlot, StratGame, StratPlay, Decision, BattingSeasonStats, PitchingSeasonStats, ProcessedGame, ScoutOpportunity, ScoutClaim, RefractorTrack, RefractorCardState, BattingCard, PitchingCard, RefractorBoostAudit, ] @pytest.fixture(autouse=True) def setup_test_db(): """Bind all models to in-memory SQLite and create tables. The fixture is autouse so every test automatically gets a fresh, isolated database schema without needing to request it explicitly. Tables are dropped in reverse dependency order after each test to keep the teardown clean and to catch any accidental FK reference direction bugs early. """ _test_db.bind(_TEST_MODELS) _test_db.connect() _test_db.create_tables(_TEST_MODELS) yield _test_db _test_db.drop_tables(list(reversed(_TEST_MODELS)), safe=True) _test_db.close() # --------------------------------------------------------------------------- # Minimal shared fixtures — create just enough data for FK dependencies # --------------------------------------------------------------------------- @pytest.fixture def rarity(): """A single Common rarity row used as FK seed for Player rows.""" return Rarity.create(value=1, name="Common", color="#ffffff") @pytest.fixture def player(rarity): """A minimal Player row with all required (non-nullable) columns filled. Player.p_name is the real column name (not 'name'). All FK and non-nullable varchar fields are provided so SQLite's NOT NULL constraints are satisfied even with foreign_keys=ON. """ cardset = Cardset.create( name="Test Set", description="Test cardset", total_cards=100, ) return Player.create( p_name="Test Player", rarity=rarity, cardset=cardset, set_num=1, pos_1="1B", image="https://example.com/image.png", mlbclub="TST", franchise="TST", description="A test player", ) @pytest.fixture def team(): """A minimal Team row. Team uses abbrev/lname/sname/gmid/gmname/gsheet/wallet/team_value/ collection_value — not the 'name'/'user_id' shorthand described in the spec, which referred to the real underlying columns by simplified names. """ return Team.create( abbrev="TST", sname="Test", lname="Test Team", gmid=100000001, gmname="testuser", gsheet="https://docs.google.com/spreadsheets/test", wallet=500, team_value=1000, collection_value=1000, season=11, is_ai=False, ) @pytest.fixture def track(): """A minimal RefractorTrack for batter cards.""" return RefractorTrack.create( name="Batter Track", card_type="batter", formula="pa + tb * 2", t1_threshold=37, t2_threshold=149, t3_threshold=448, t4_threshold=896, ) # --------------------------------------------------------------------------- # PostgreSQL integration fixture (used by test_refractor_*_api.py) # --------------------------------------------------------------------------- @pytest.fixture(scope="session") def pg_conn(): """Open a psycopg2 connection to the PostgreSQL instance for integration tests. Reads connection parameters from the standard POSTGRES_* env vars that the CI workflow injects when a postgres service container is running. Skips the entire session (via pytest.skip) when POSTGRES_HOST is not set, keeping local runs clean. The connection is shared for the whole session (scope="session") because the integration test modules use module-scoped fixtures that rely on it; creating a new connection per test would break those module-scoped fixtures. Teardown: the connection is closed once all tests have finished. """ host = os.environ.get("POSTGRES_HOST") if not host: pytest.skip("POSTGRES_HOST not set — PostgreSQL integration tests skipped") conn = psycopg2.connect( host=host, port=int(os.environ.get("POSTGRES_PORT", "5432")), dbname=os.environ.get("POSTGRES_DB", "paper_dynasty"), user=os.environ.get("POSTGRES_USER", "postgres"), password=os.environ.get("POSTGRES_PASSWORD", ""), ) conn.autocommit = False yield conn conn.close()