nomy-data-models 0.2.7

Data model definitions for Nomy wallet analysis data processing
Documentation
"""Tests for the base model."""

import datetime
import uuid
from typing import Optional

import pytest
from sqlalchemy import Column, String
from sqlalchemy.orm import Mapped, mapped_column

from nomy_data_models.models.base import Base, BaseModel


class PlainBase(Base):
    """Test plain Base model without BaseModel functionality."""

    __tablename__ = "plain_base"
    id = Column(String, primary_key=True)
    name = Column(String)


class ModelExample(BaseModel):
    """Test model for testing BaseModel functionality."""

    __abstract__ = False

    name: Mapped[str] = mapped_column(String(50), nullable=False)
    description: Mapped[Optional[str]] = mapped_column(String(200), nullable=True)


@pytest.fixture
def test_model():
    """Fixture to create a TestModel instance with predefined values."""
    model = ModelExample()
    model.id = uuid.uuid4()
    model.name = "Test"
    model.description = "Test description"
    model.created_at = datetime.datetime.now()
    model.updated_at = datetime.datetime.now()
    return model


@pytest.fixture
def plain_base_model():
    """Fixture to create a PlainBase instance."""
    model = PlainBase()
    model.id = "test-id"
    model.name = "Test"
    return model


class TestBase:
    """Test cases for BaseModel."""

    def test_tablename_generation(self):
        """Test that the tablename is generated correctly."""
        assert ModelExample.__tablename__ == "model_example"

    def test_to_dict_method(self, test_model):
        """Test the to_dict method without using SQLAlchemy session."""
        # Call the to_dict method directly
        model_dict = test_model.to_dict()

        # Verify the dictionary contains the expected keys
        assert "id" in model_dict
        assert "name" in model_dict
        assert "description" in model_dict
        assert "created_at" in model_dict
        assert "updated_at" in model_dict

        # Verify the values match the model attributes
        assert model_dict["id"] == test_model.id
        assert model_dict["name"] == "Test"
        assert model_dict["description"] == "Test description"
        assert model_dict["created_at"] == test_model.created_at
        assert model_dict["updated_at"] == test_model.updated_at

    def test_from_dict_method(self):
        """Test the from_dict method."""
        test_id = uuid.uuid4()
        now = datetime.datetime.now()

        data = {
            "id": test_id,
            "name": "Test",
            "description": "Test description",
            "created_at": now,
            "updated_at": now,
            "unknown_field": "This should be ignored",
        }

        # Create a model using from_dict
        model_from_dict = ModelExample.from_dict(data)

        # Verify the attributes that should be set
        expected_attrs = ["id", "created_at", "updated_at"]
        for attr in expected_attrs:
            assert hasattr(model_from_dict, attr)
            assert getattr(model_from_dict, attr) == data[attr]

        # Verify unknown_field was not set
        assert not hasattr(model_from_dict, "unknown_field")

    def test_update_from_dict_method(self, test_model):
        """Test the update_from_dict method."""
        # Update the model with new data
        test_model.update_from_dict(
            {"name": "Updated", "unknown_field": "This should be ignored"}
        )

        # Verify the model has been updated correctly
        assert test_model.name == "Updated"
        assert test_model.description == "Test description"
        assert not hasattr(test_model, "unknown_field")

    def test_repr_method(self, test_model):
        """Test the __repr__ method."""
        # Verify the string representation
        assert str(test_model) == f"<ModelExample(id={test_model.id})>"

    def test_db_integration(self, session):
        """Test database integration with the model."""
        # Create a new model instance
        model = ModelExample(name="DB Test", description="Testing with DB session")

        # Add to session and commit
        session.add(model)
        session.commit()

        # Verify the model was saved to the database
        retrieved = session.query(ModelExample).filter_by(name="DB Test").first()
        assert retrieved is not None
        assert retrieved.name == "DB Test"
        assert retrieved.description == "Testing with DB session"
        assert retrieved.id is not None
        assert retrieved.created_at is not None
        assert retrieved.updated_at is not None

    def test_dict_method(self, test_model):
        """Test the dict method of the Base class."""
        # Call the dict method
        model_dict = test_model.dict()

        # Verify the dictionary contains the expected keys
        assert "id" in model_dict
        assert "name" in model_dict
        assert "description" in model_dict
        assert "created_at" in model_dict
        assert "updated_at" in model_dict

        # Verify the values match the model attributes
        assert model_dict["id"] == test_model.id
        assert model_dict["name"] == test_model.name
        assert model_dict["description"] == test_model.description
        assert model_dict["created_at"] == test_model.created_at
        assert model_dict["updated_at"] == test_model.updated_at

    def test_dict_method_plain_base(self, plain_base_model):
        """Test the dict method with a plain Base model."""
        # Call the dict method
        model_dict = plain_base_model.dict()

        # Verify the dictionary contains the expected keys
        assert "id" in model_dict
        assert "name" in model_dict

        # Verify the values match the model attributes
        assert model_dict["id"] == "test-id"
        assert model_dict["name"] == "Test"

    def test_update_from_dict_method_empty(self, test_model):
        """Test the update_from_dict method with an empty dict."""
        original_name = test_model.name
        original_description = test_model.description

        # Update the model with empty data
        test_model.update_from_dict({})

        # Verify nothing changed
        assert test_model.name == original_name
        assert test_model.description == original_description

    def test_update_from_dict_nonexistent_attr(self, test_model):
        """Test update_from_dict with attributes that don't exist."""
        original_name = test_model.name

        # Try to update non-existent attributes
        test_model.update_from_dict({"nonexistent": "value", "another": 123})

        # Verify nothing changed
        assert test_model.name == original_name
        assert not hasattr(test_model, "nonexistent")
        assert not hasattr(test_model, "another")