# ABOUTME: Tests for the reference data seeder. # ABOUTME: Validates that seeding populates correct data and is idempotent. import pytest from animaltrack.db import get_db from animaltrack.migrations import run_migrations from animaltrack.models.reference import ProductUnit, UserRole from animaltrack.repositories import ( FeedTypeRepository, LocationRepository, ProductRepository, SpeciesRepository, UserRepository, ) from animaltrack.seeds import run_seeds @pytest.fixture def migrated_db(tmp_path): """Create a database with migrations applied.""" db_path = str(tmp_path / "test.db") run_migrations(db_path, "migrations", verbose=False) return get_db(db_path) class TestSeedCounts: """Tests that seeding creates the correct number of records.""" def test_seeds_three_users(self, migrated_db): """Seeding creates 3 users.""" run_seeds(migrated_db) repo = UserRepository(migrated_db) assert len(repo.list_all()) == 3 def test_seeds_eight_locations(self, migrated_db): """Seeding creates 8 locations.""" run_seeds(migrated_db) repo = LocationRepository(migrated_db) assert len(repo.list_all()) == 8 def test_seeds_three_species(self, migrated_db): """Seeding creates 3 species.""" run_seeds(migrated_db) repo = SpeciesRepository(migrated_db) assert len(repo.list_all()) == 3 def test_seeds_seven_products(self, migrated_db): """Seeding creates 7 products.""" run_seeds(migrated_db) repo = ProductRepository(migrated_db) assert len(repo.list_all()) == 7 def test_seeds_three_feed_types(self, migrated_db): """Seeding creates 3 feed types.""" run_seeds(migrated_db) repo = FeedTypeRepository(migrated_db) assert len(repo.list_all()) == 3 class TestSeedIdempotency: """Tests that seeding is idempotent.""" def test_seeding_twice_same_user_count(self, migrated_db): """Seeding twice produces same number of users.""" run_seeds(migrated_db) run_seeds(migrated_db) repo = UserRepository(migrated_db) assert len(repo.list_all()) == 3 def test_seeding_twice_same_location_count(self, migrated_db): """Seeding twice produces same number of locations.""" run_seeds(migrated_db) run_seeds(migrated_db) repo = LocationRepository(migrated_db) assert len(repo.list_all()) == 8 def test_seeding_twice_same_species_count(self, migrated_db): """Seeding twice produces same number of species.""" run_seeds(migrated_db) run_seeds(migrated_db) repo = SpeciesRepository(migrated_db) assert len(repo.list_all()) == 3 def test_seeding_twice_same_product_count(self, migrated_db): """Seeding twice produces same number of products.""" run_seeds(migrated_db) run_seeds(migrated_db) repo = ProductRepository(migrated_db) assert len(repo.list_all()) == 7 def test_seeding_twice_same_feed_type_count(self, migrated_db): """Seeding twice produces same number of feed types.""" run_seeds(migrated_db) run_seeds(migrated_db) repo = FeedTypeRepository(migrated_db) assert len(repo.list_all()) == 3 class TestUserSeedData: """Tests for correct user seed data.""" def test_ppetru_is_admin(self, migrated_db): """User ppetru has admin role.""" run_seeds(migrated_db) repo = UserRepository(migrated_db) user = repo.get("ppetru") assert user is not None assert user.role == UserRole.ADMIN assert user.active is True def test_ines_is_admin(self, migrated_db): """User ines has admin role.""" run_seeds(migrated_db) repo = UserRepository(migrated_db) user = repo.get("ines") assert user is not None assert user.role == UserRole.ADMIN def test_guest_is_recorder(self, migrated_db): """User guest has recorder role.""" run_seeds(migrated_db) repo = UserRepository(migrated_db) user = repo.get("guest") assert user is not None assert user.role == UserRole.RECORDER class TestLocationSeedData: """Tests for correct location seed data.""" def test_strip_locations_exist(self, migrated_db): """All 4 strip locations exist.""" run_seeds(migrated_db) repo = LocationRepository(migrated_db) for i in range(1, 5): location = repo.get_by_name(f"Strip {i}") assert location is not None, f"Strip {i} not found" assert location.active is True def test_nursery_locations_exist(self, migrated_db): """All 4 nursery locations exist.""" run_seeds(migrated_db) repo = LocationRepository(migrated_db) for i in range(1, 5): location = repo.get_by_name(f"Nursery {i}") assert location is not None, f"Nursery {i} not found" assert location.active is True def test_location_ids_are_valid_ulids(self, migrated_db): """All location IDs are 26 characters (ULID format).""" run_seeds(migrated_db) repo = LocationRepository(migrated_db) for location in repo.list_all(): assert len(location.id) == 26 class TestSpeciesSeedData: """Tests for correct species seed data.""" def test_duck_is_active(self, migrated_db): """Species duck is active.""" run_seeds(migrated_db) repo = SpeciesRepository(migrated_db) species = repo.get("duck") assert species is not None assert species.name == "Duck" assert species.active is True def test_goose_is_active(self, migrated_db): """Species goose is active.""" run_seeds(migrated_db) repo = SpeciesRepository(migrated_db) species = repo.get("goose") assert species is not None assert species.name == "Goose" assert species.active is True def test_sheep_is_inactive(self, migrated_db): """Species sheep is inactive.""" run_seeds(migrated_db) repo = SpeciesRepository(migrated_db) species = repo.get("sheep") assert species is not None assert species.name == "Sheep" assert species.active is False class TestProductSeedData: """Tests for correct product seed data.""" def test_egg_duck_product(self, migrated_db): """Product egg.duck has correct attributes.""" run_seeds(migrated_db) repo = ProductRepository(migrated_db) product = repo.get("egg.duck") assert product is not None assert product.name == "Duck Egg" assert product.unit == ProductUnit.PIECE assert product.collectable is True assert product.sellable is True def test_meat_products_use_kg(self, migrated_db): """All meat-related products use kg unit.""" run_seeds(migrated_db) repo = ProductRepository(migrated_db) kg_products = ["meat", "offal", "fat", "bones", "feathers", "down"] for code in kg_products: product = repo.get(code) assert product is not None, f"Product {code} not found" assert product.unit == ProductUnit.KG, f"Product {code} should use kg" class TestFeedTypeSeedData: """Tests for correct feed type seed data.""" def test_starter_feed_type(self, migrated_db): """Feed type starter has correct attributes.""" run_seeds(migrated_db) repo = FeedTypeRepository(migrated_db) feed_type = repo.get("starter") assert feed_type is not None assert feed_type.name == "Starter Feed" assert feed_type.default_bag_size_kg == 20 def test_grower_feed_type(self, migrated_db): """Feed type grower has correct attributes.""" run_seeds(migrated_db) repo = FeedTypeRepository(migrated_db) feed_type = repo.get("grower") assert feed_type is not None assert feed_type.name == "Grower Feed" assert feed_type.default_bag_size_kg == 20 def test_layer_feed_type(self, migrated_db): """Feed type layer has correct attributes.""" run_seeds(migrated_db) repo = FeedTypeRepository(migrated_db) feed_type = repo.get("layer") assert feed_type is not None assert feed_type.name == "Layer Feed" assert feed_type.default_bag_size_kg == 20