# tests/conftest.py import os import pytest # ---------------------------------------------------------------------- # Import the concrete classes from your backend package. # Adjust the import path if your package layout differs. # ---------------------------------------------------------------------- from backend.db import DatabaseConnection from backend.repositories import ( MemberRepository, ClassificationRepository, ServiceTypeRepository, ServiceAvailabilityRepository, ) # ---------------------------------------------------------------------- # Path to the full schema (DDL) that creates every table, including # ServiceAvailability. # ---------------------------------------------------------------------- @pytest.fixture(scope="session") def schema_path() -> str: """Absolute path to the SQL file that creates the test schema.""" return os.path.abspath( os.path.join(os.path.dirname(__file__), "..", "schema.sql") ) # ---------------------------------------------------------------------- # Fresh in‑memory SQLite DB with the full schema applied. # ---------------------------------------------------------------------- @pytest.fixture def db_connection(schema_path: str) -> DatabaseConnection: conn = DatabaseConnection(":memory:") # Load the DDL. with open(schema_path, "r", encoding="utf-8") as f: ddl = f.read() conn._conn.executescript(ddl) # apply the whole schema conn._conn.commit() yield conn conn.close() # ---------------------------------------------------------------------- # Seed lookup tables that have foreign‑key relationships. # ---------------------------------------------------------------------- @pytest.fixture def seed_lookup_tables(db_connection: DatabaseConnection): """ Insert rows into lookup tables that other tables reference. Currently we need: • Classifications – for Member tests • ServiceTypes – for ServiceTypeRepository tests • ServiceAvailability – for the repo we are testing now """ # ---- Classifications ------------------------------------------------- classifications = [ ("Soprano",), # ClassificationId = 1 ("Alto / Mezzo",), # ClassificationId = 2 ("Tenor",), # ClassificationId = 3 ("Baritone",), # ClassificationId = 4 ] for name in classifications: db_connection.execute( "INSERT INTO Classifications (ClassificationName) VALUES (?)", name, ) # ---- ServiceTypes ---------------------------------------------------- # These are the three time‑slot examples you asked for. service_types = [("9AM",), ("11AM",), ("6PM",)] for name in service_types: db_connection.execute( "INSERT INTO ServiceTypes (TypeName) VALUES (?)", name, ) # ---- ServiceAvailability --------------------------------------------- # We need a couple of members first, otherwise the FK constraints will # reject the inserts. We'll create two dummy members (Alice = 1, # Bob = 2) and then map them to the three slots. # # NOTE: In a real test suite you would probably use the MemberRepository # to create these rows, but inserting directly keeps the fixture fast and # independent of the Member repo implementation. dummy_members = [ ("Alice", "Smith", "alice@example.com", None, None, 1, None, 1), ("Bob", "Jones", "bob@example.com", None, None, 2, None, 1), ] for ( fn, ln, email, phone, notes, classification_id, is_active, member_id_placeholder, ) in dummy_members: # The MemberId column is AUTOINCREMENT, so we omit it. db_connection.execute( """ INSERT INTO Members (FirstName, LastName, Email, PhoneNumber, Notes, ClassificationId, IsActive) VALUES (?, ?, ?, ?, ?, ?, ?) """, (fn, ln, email, phone, notes, classification_id, is_active), ) # At this point SQLite has assigned MemberIds 1 and 2. # Map them to the three service‑type slots: # Alice → 9AM (id = 1) and 6PM (id = 3) # Bob → 11AM (id = 2) and 6PM (id = 3) availability = [ (1, 1), # Alice – 9AM (1, 3), # Alice – 6PM (2, 2), # Bob – 11AM (2, 3), # Bob – 6PM ] for member_id, service_type_id in availability: db_connection.execute( """ INSERT INTO ServiceAvailability (MemberId, ServiceTypeId) VALUES (?, ?) """, (member_id, service_type_id), ) # Commit everything so downstream fixtures see the data. db_connection._conn.commit() # ---------------------------------------------------------------------- # Repository factories – each receives the same fresh DB that already has # the lookup data seeded. # ---------------------------------------------------------------------- @pytest.fixture def member_repo( db_connection: DatabaseConnection, seed_lookup_tables, ) -> MemberRepository: return MemberRepository(db_connection) @pytest.fixture def classification_repo( db_connection: DatabaseConnection, seed_lookup_tables, ) -> ClassificationRepository: return ClassificationRepository(db_connection) @pytest.fixture def service_type_repo( db_connection: DatabaseConnection, seed_lookup_tables, ) -> ServiceTypeRepository: return ServiceTypeRepository(db_connection) @pytest.fixture def service_availability_repo( db_connection: DatabaseConnection, seed_lookup_tables, ) -> ServiceAvailabilityRepository: return ServiceAvailabilityRepository(db_connection)