- Fix TypeError in check_steal_opportunity by properly mocking catcher defense - Correct tag_from_third test calculation to account for all adjustment conditions - Fix pitcher replacement test by setting appropriate allowed runners threshold - Add comprehensive test coverage for AI service business logic - Implement VS Code testing panel configuration with pytest integration - Create pytest.ini for consistent test execution and warning management - Add test isolation guidelines and factory pattern implementation - Establish 102 passing tests with zero failures 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
243 lines
8.6 KiB
Python
243 lines
8.6 KiB
Python
"""
|
|
Unit tests for Cardset model.
|
|
|
|
Tests data validation, field constraints, and model behavior.
|
|
"""
|
|
|
|
import pytest
|
|
from pydantic import ValidationError
|
|
from sqlmodel import Session, SQLModel, create_engine, text
|
|
|
|
from app.models.cardset import Cardset, CardsetBase
|
|
from tests.factories.cardset_factory import CardsetFactory
|
|
|
|
|
|
# Using centralized fixtures from conftest.py for proper test isolation
|
|
|
|
|
|
class TestCardsetBase:
|
|
"""Test CardsetBase model validation."""
|
|
|
|
def test_create_with_defaults(self):
|
|
"""Test creating Cardset with default values."""
|
|
cardset = CardsetBase(name="2024 Season")
|
|
|
|
assert cardset.name == "2024 Season"
|
|
assert cardset.ranked_legal is False # Default value
|
|
|
|
def test_create_with_custom_values(self):
|
|
"""Test creating Cardset with custom values."""
|
|
cardset = CardsetBase(
|
|
name="2023 Season",
|
|
ranked_legal=True
|
|
)
|
|
|
|
assert cardset.name == "2023 Season"
|
|
assert cardset.ranked_legal is True
|
|
|
|
def test_create_with_id(self):
|
|
"""Test creating Cardset with explicit ID."""
|
|
cardset = CardsetBase(
|
|
id=100,
|
|
name="Historic Set",
|
|
ranked_legal=False
|
|
)
|
|
|
|
assert cardset.id == 100
|
|
assert cardset.name == "Historic Set"
|
|
assert cardset.ranked_legal is False
|
|
|
|
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_field_descriptions(self):
|
|
"""Test that field descriptions are properly set."""
|
|
# Access field descriptions through the model class using Pydantic v2
|
|
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'])
|
|
|
|
|
|
class TestCardset:
|
|
"""Test Cardset table model."""
|
|
|
|
def test_create_and_save(self, db_session):
|
|
"""Test creating and saving Cardset to database."""
|
|
cardset = CardsetFactory.create(
|
|
db_session,
|
|
name="2024 Season",
|
|
ranked_legal=True
|
|
)
|
|
|
|
assert cardset.id is not None
|
|
assert cardset.name == "2024 Season"
|
|
assert cardset.ranked_legal is True
|
|
|
|
def test_retrieve_from_database(self, db_session):
|
|
"""Test retrieving Cardset from database."""
|
|
# Create and save
|
|
cardset = CardsetFactory.create(
|
|
db_session,
|
|
name="Test Retrieval Set",
|
|
ranked_legal=False
|
|
)
|
|
|
|
# Retrieve
|
|
retrieved = db_session.get(Cardset, cardset.id)
|
|
assert retrieved is not None
|
|
assert retrieved.name == "Test Retrieval Set"
|
|
assert retrieved.ranked_legal is False
|
|
|
|
def test_update_values(self, db_session):
|
|
"""Test updating Cardset values."""
|
|
cardset = Cardset(id=3, name="Update Test")
|
|
db_session.add(cardset)
|
|
db_session.commit()
|
|
|
|
# Update values
|
|
cardset.ranked_legal = True
|
|
cardset.name = "Updated Name"
|
|
db_session.commit()
|
|
|
|
# Verify updates
|
|
db_session.refresh(cardset)
|
|
assert cardset.name == "Updated Name"
|
|
assert cardset.ranked_legal is True
|
|
|
|
def test_multiple_instances(self, db_session):
|
|
"""Test creating multiple Cardset instances."""
|
|
cardset1 = Cardset(id=10, name="Set A", ranked_legal=True)
|
|
cardset2 = Cardset(id=11, name="Set B", ranked_legal=False)
|
|
cardset3 = Cardset(id=12, name="Set C", ranked_legal=True)
|
|
|
|
db_session.add_all([cardset1, cardset2, cardset3])
|
|
db_session.commit()
|
|
|
|
# Verify all saved with correct values
|
|
assert cardset1.name == "Set A"
|
|
assert cardset1.ranked_legal is True
|
|
assert cardset2.name == "Set B"
|
|
assert cardset2.ranked_legal is False
|
|
assert cardset3.name == "Set C"
|
|
assert cardset3.ranked_legal is True
|
|
|
|
def test_name_is_indexed(self):
|
|
"""Test that name field has index configuration."""
|
|
fields = Cardset.model_fields
|
|
name_field = fields['name']
|
|
# Check if field has index configuration
|
|
assert hasattr(name_field, 'json_schema_extra') or 'index' in str(name_field)
|
|
|
|
|
|
class TestCardsetBusinessScenarios:
|
|
"""Test real-world Cardset usage scenarios."""
|
|
|
|
def test_ranked_legal_cardsets(self, db_session):
|
|
"""Test filtering for ranked legal cardsets."""
|
|
# Create multiple cardsets using factory
|
|
ranked_set = CardsetFactory.create(db_session, name="2024 Ranked", ranked_legal=True)
|
|
casual_set = CardsetFactory.create(db_session, name="2024 Casual", ranked_legal=False)
|
|
historic_set = CardsetFactory.create(db_session, name="Historic Collection", ranked_legal=False)
|
|
|
|
# Query for ranked legal sets (would be done in service layer)
|
|
from sqlmodel import select
|
|
ranked_cardsets = db_session.exec(
|
|
select(Cardset).where(Cardset.ranked_legal == True)
|
|
).all()
|
|
|
|
assert len(ranked_cardsets) == 1
|
|
assert ranked_cardsets[0].name == "2024 Ranked"
|
|
|
|
def test_cardset_naming_conventions(self, db_session):
|
|
"""Test various cardset naming scenarios."""
|
|
cardsets = [
|
|
Cardset(id=30, name="2024 Season", ranked_legal=True),
|
|
Cardset(id=31, name="2023 Season", ranked_legal=False),
|
|
Cardset(id=32, name="Historic Collection", ranked_legal=False),
|
|
Cardset(id=33, name="Special Event - All-Stars", ranked_legal=True),
|
|
Cardset(id=34, name="Beta Test Set", ranked_legal=False),
|
|
]
|
|
|
|
db_session.add_all(cardsets)
|
|
db_session.commit()
|
|
|
|
# Verify all names are preserved correctly
|
|
for cardset in cardsets:
|
|
db_session.refresh(cardset)
|
|
# Names should be preserved exactly as entered
|
|
assert len(cardset.name) > 0
|
|
assert cardset.name in [
|
|
"2024 Season", "2023 Season", "Historic Collection",
|
|
"Special Event - All-Stars", "Beta Test Set"
|
|
]
|
|
|
|
def test_default_ranked_legal_behavior(self, db_session):
|
|
"""Test that cardsets default to not ranked legal."""
|
|
cardset = Cardset(id=40, name="Default Test")
|
|
db_session.add(cardset)
|
|
db_session.commit()
|
|
db_session.refresh(cardset)
|
|
|
|
# Should default to False
|
|
assert cardset.ranked_legal is False
|
|
|
|
def test_explicit_id_assignment(self, db_session):
|
|
"""Test that IDs can be explicitly assigned (not auto-increment)."""
|
|
# Based on Discord app model, ID is not auto-increment
|
|
cardset1 = Cardset(id=1000, name="High ID Set")
|
|
cardset2 = Cardset(id=2000, name="Another High ID Set")
|
|
|
|
db_session.add_all([cardset1, cardset2])
|
|
db_session.commit()
|
|
|
|
assert cardset1.id == 1000
|
|
assert cardset2.id == 2000
|
|
|
|
def test_unique_id_constraint(self, db_session):
|
|
"""Test that duplicate IDs are not allowed."""
|
|
cardset1 = Cardset(id=500, name="First Set")
|
|
cardset2 = Cardset(id=500, name="Duplicate ID Set")
|
|
|
|
db_session.add(cardset1)
|
|
db_session.commit()
|
|
|
|
# Adding second cardset with same ID should fail
|
|
db_session.add(cardset2)
|
|
with pytest.raises(Exception): # SQLAlchemy will raise an IntegrityError
|
|
db_session.commit()
|
|
|
|
|
|
class TestCardsetDataIntegrity:
|
|
"""Test data integrity and validation."""
|
|
|
|
def test_empty_name_not_allowed(self):
|
|
"""Test that empty name is not allowed."""
|
|
with pytest.raises(ValidationError):
|
|
CardsetBase(name="")
|
|
|
|
def test_none_name_not_allowed(self):
|
|
"""Test that None name is not allowed."""
|
|
with pytest.raises(ValidationError):
|
|
CardsetBase(name=None)
|
|
|
|
def test_boolean_validation_for_ranked_legal(self):
|
|
"""Test that ranked_legal field only accepts boolean values."""
|
|
# Valid boolean values
|
|
cardset_true = CardsetBase(name="Test", ranked_legal=True)
|
|
cardset_false = CardsetBase(name="Test", ranked_legal=False)
|
|
|
|
assert cardset_true.ranked_legal is True
|
|
assert cardset_false.ranked_legal is False
|
|
|
|
# Invalid values should be coerced or raise validation error
|
|
with pytest.raises(ValidationError):
|
|
CardsetBase(name="Test", ranked_legal="invalid")
|
|
|
|
def test_id_field_accepts_none(self):
|
|
"""Test that ID field can be None (for cases where ID isn't known yet)."""
|
|
cardset = CardsetBase(name="No ID Set", id=None)
|
|
assert cardset.id is None
|
|
assert cardset.name == "No ID Set" |