""" Unit tests for Cardset model using proper testing patterns. Tests data validation, field constraints, and model behavior with transaction rollback for test isolation and factories for unique data. """ import pytest from pydantic import ValidationError from sqlmodel import select from app.models.cardset import Cardset, CardsetBase from tests.factories import CardsetFactory class TestCardsetBaseValidation: """Test CardsetBase model validation (no database needed).""" def test_create_with_defaults(self): """Test creating Cardset with default values.""" cardset = CardsetFactory.build() assert cardset.name.startswith("Cardset") assert cardset.ranked_legal is False assert cardset.id is not None def test_create_with_custom_values(self): """Test creating Cardset with custom values.""" cardset = CardsetFactory.build( name="Custom Season", ranked_legal=True ) assert cardset.name == "Custom Season" assert cardset.ranked_legal is True def test_create_with_explicit_id(self): """Test creating Cardset with explicit ID.""" cardset = CardsetFactory.build( id=12345, name="Specific ID Set" ) assert cardset.id == 12345 assert cardset.name == "Specific ID Set" def test_required_name_field(self): """Test that name field is required.""" with pytest.raises(ValidationError) as exc_info: CardsetBase() assert "Field required" in str(exc_info.value) def test_empty_name_validation(self): """Test that empty name is not allowed.""" with pytest.raises(ValidationError) as exc_info: CardsetBase(name="") assert "Name cannot be empty" in str(exc_info.value) def test_whitespace_only_name_validation(self): """Test that whitespace-only name is not allowed.""" with pytest.raises(ValidationError) as exc_info: CardsetBase(name=" ") assert "Name cannot be empty" in str(exc_info.value) def test_none_name_not_allowed(self): """Test that None name is not allowed.""" with pytest.raises(ValidationError) as exc_info: CardsetBase(name=None) assert "Input should be a valid string" in str(exc_info.value) def test_boolean_validation_for_ranked_legal(self): """Test that ranked_legal field validates boolean values.""" # Valid boolean values cardset_true = CardsetFactory.build(ranked_legal=True) cardset_false = CardsetFactory.build(ranked_legal=False) assert cardset_true.ranked_legal is True assert cardset_false.ranked_legal is False def test_field_descriptions(self): """Test that field descriptions are properly set.""" fields = CardsetBase.model_fields assert "Name of the card set" in str(fields['name']) assert "Whether this cardset is legal for ranked play" in str(fields['ranked_legal']) def test_id_field_accepts_none(self): """Test that ID field can be None.""" cardset = CardsetFactory.build(id=None) assert cardset.id is None class TestCardsetDatabaseOperations: """Test Cardset database operations with transaction rollback.""" def test_create_and_save(self, db_session): """Test creating and saving Cardset to database.""" cardset = CardsetFactory.create( db_session, name="Database Test Set", ranked_legal=True ) assert cardset.id is not None assert cardset.name == "Database Test Set" assert cardset.ranked_legal is True def test_retrieve_from_database(self, db_session): """Test retrieving Cardset from database.""" # Create and save original = CardsetFactory.create( db_session, name="Retrieval Test", ranked_legal=False ) # Retrieve by ID retrieved = db_session.get(Cardset, original.id) assert retrieved is not None assert retrieved.name == "Retrieval Test" assert retrieved.ranked_legal is False assert retrieved.id == original.id def test_update_values(self, db_session): """Test updating Cardset values.""" cardset = CardsetFactory.create(db_session, name="Update Test") # Update values cardset.ranked_legal = True cardset.name = "Updated Name" db_session.flush() # Verify updates (no commit needed due to rollback) assert cardset.name == "Updated Name" assert cardset.ranked_legal is True def test_multiple_instances(self, db_session): """Test creating multiple Cardset instances.""" cardsets = CardsetFactory.create_batch( db_session, 3, ranked_legal=True ) # Verify all saved with unique IDs ids = [c.id for c in cardsets] assert len(set(ids)) == 3 # All IDs are unique assert all(c.ranked_legal is True for c in cardsets) def test_query_operations(self, db_session): """Test querying Cardset records.""" # Create test data ranked_sets = CardsetFactory.create_batch( db_session, 2, ranked_legal=True ) casual_sets = CardsetFactory.create_batch( db_session, 3, ranked_legal=False ) # Query for ranked legal sets ranked_results = db_session.exec( select(Cardset).where(Cardset.ranked_legal == True) ).all() # Query for casual sets casual_results = db_session.exec( select(Cardset).where(Cardset.ranked_legal == False) ).all() assert len(ranked_results) == 2 assert len(casual_results) == 3 assert all(c.ranked_legal is True for c in ranked_results) assert all(c.ranked_legal is False for c in casual_results) class TestCardsetFactoryPresets: """Test CardsetFactory preset methods.""" def test_ranked_legal_preset(self, db_session): """Test ranked legal cardset factory.""" cardset = CardsetFactory.build_ranked_legal() assert cardset.ranked_legal is True assert "Ranked Set" in cardset.name def test_casual_preset(self, db_session): """Test casual cardset factory.""" cardset = CardsetFactory.build_casual() assert cardset.ranked_legal is False assert "Casual Set" in cardset.name def test_historic_preset(self, db_session): """Test historic cardset factory.""" cardset = CardsetFactory.build_historic() assert cardset.ranked_legal is False assert "Historic Set" in cardset.name def test_custom_preset_override(self, db_session): """Test that preset defaults can be overridden.""" cardset = CardsetFactory.build_ranked_legal( name="Custom Ranked Set", ranked_legal=False # Override the preset ) assert cardset.name == "Custom Ranked Set" assert cardset.ranked_legal is False class TestCardsetBusinessScenarios: """Test real-world Cardset usage scenarios.""" def test_unique_naming_across_tests(self, db_session): """Test that each test gets unique cardset names.""" cardset1 = CardsetFactory.create(db_session) cardset2 = CardsetFactory.create(db_session) # Names should be different due to unique generation assert cardset1.name != cardset2.name assert cardset1.id != cardset2.id def test_batch_creation_uniqueness(self, db_session): """Test that batch creation produces unique items.""" cardsets = CardsetFactory.create_batch(db_session, 5) # All should have unique IDs and names ids = [c.id for c in cardsets] names = [c.name for c in cardsets] assert len(set(ids)) == 5 # All unique IDs assert len(set(names)) == 5 # All unique names def test_filtering_by_ranked_status(self, db_session): """Test filtering cardsets by ranked legal status.""" # Create mixed data CardsetFactory.create_batch(db_session, 2, ranked_legal=True) CardsetFactory.create_batch(db_session, 3, ranked_legal=False) # Test filtering all_cardsets = db_session.exec(select(Cardset)).all() ranked_cardsets = db_session.exec( select(Cardset).where(Cardset.ranked_legal == True) ).all() casual_cardsets = db_session.exec( select(Cardset).where(Cardset.ranked_legal == False) ).all() assert len(all_cardsets) == 5 assert len(ranked_cardsets) == 2 assert len(casual_cardsets) == 3 def test_name_search_functionality(self, db_session): """Test searching cardsets by name patterns.""" # Create cardsets with specific names season_sets = CardsetFactory.create_batch( db_session, 2, name="2024 Season" ) historic_sets = CardsetFactory.create_batch( db_session, 2, name="Historic Collection" ) # Search by name pattern season_results = db_session.exec( select(Cardset).where(Cardset.name.contains("Season")) ).all() historic_results = db_session.exec( select(Cardset).where(Cardset.name.contains("Historic")) ).all() assert len(season_results) == 2 assert len(historic_results) == 2 assert all("Season" in c.name for c in season_results) assert all("Historic" in c.name for c in historic_results)