""" Tests for Pydantic models (Message, Character, GameSession) """ import pytest from datetime import datetime from main import Message, Character, GameSession class TestMessage: """Test Message model""" def test_message_creation_default(self): """Test creating a message with default values""" msg = Message(sender="character", content="Hello!") assert msg.sender == "character" assert msg.content == "Hello!" assert msg.visibility == "private" # Default assert msg.public_content is None assert msg.private_content is None assert msg.id is not None assert msg.timestamp is not None def test_message_creation_private(self): """Test creating a private message""" msg = Message( sender="character", content="I search for traps", visibility="private" ) assert msg.visibility == "private" assert msg.public_content is None assert msg.private_content is None def test_message_creation_public(self): """Test creating a public message""" msg = Message( sender="character", content="I wave to everyone", visibility="public" ) assert msg.visibility == "public" assert msg.content == "I wave to everyone" def test_message_creation_mixed(self): """Test creating a mixed message""" msg = Message( sender="character", content="Combined message", visibility="mixed", public_content="I shake hands with the merchant", private_content="I try to pickpocket him" ) assert msg.visibility == "mixed" assert msg.public_content == "I shake hands with the merchant" assert msg.private_content == "I try to pickpocket him" def test_message_timestamp_format(self): """Test that timestamp is ISO format""" msg = Message(sender="character", content="Test") # Should be able to parse the timestamp parsed_time = datetime.fromisoformat(msg.timestamp) assert isinstance(parsed_time, datetime) def test_message_unique_ids(self): """Test that messages get unique IDs""" msg1 = Message(sender="character", content="Message 1") msg2 = Message(sender="character", content="Message 2") assert msg1.id != msg2.id class TestCharacter: """Test Character model""" def test_character_creation_minimal(self): """Test creating a character with minimal info""" char = Character( name="Gandalf", description="A wise wizard" ) assert char.name == "Gandalf" assert char.description == "A wise wizard" assert char.personality == "" assert char.llm_model == "gpt-3.5-turbo" assert char.conversation_history == [] assert char.pending_response is False assert char.id is not None def test_character_creation_full(self): """Test creating a character with all fields""" char = Character( name="Aragorn", description="A ranger from the North", personality="Brave and noble", llm_model="gpt-4" ) assert char.name == "Aragorn" assert char.description == "A ranger from the North" assert char.personality == "Brave and noble" assert char.llm_model == "gpt-4" def test_character_conversation_history(self): """Test adding messages to conversation history""" char = Character(name="Legolas", description="An elf archer") msg1 = Message(sender="character", content="I see danger ahead") msg2 = Message(sender="storyteller", content="What do you do?") char.conversation_history.append(msg1) char.conversation_history.append(msg2) assert len(char.conversation_history) == 2 assert char.conversation_history[0].content == "I see danger ahead" assert char.conversation_history[1].sender == "storyteller" def test_character_pending_response_flag(self): """Test pending response flag""" char = Character(name="Gimli", description="A dwarf warrior") assert char.pending_response is False char.pending_response = True assert char.pending_response is True class TestGameSession: """Test GameSession model""" def test_session_creation(self): """Test creating a game session""" session = GameSession(name="Epic Adventure") assert session.name == "Epic Adventure" assert session.characters == {} assert session.current_scene == "" assert session.scene_history == [] assert session.public_messages == [] assert session.id is not None def test_session_add_character(self): """Test adding a character to session""" session = GameSession(name="Test Game") char = Character(name="Frodo", description="A hobbit") session.characters[char.id] = char assert len(session.characters) == 1 assert char.id in session.characters assert session.characters[char.id].name == "Frodo" def test_session_multiple_characters(self): """Test session with multiple characters""" session = GameSession(name="Fellowship") char1 = Character(name="Sam", description="Loyal friend") char2 = Character(name="Merry", description="Cheerful hobbit") char3 = Character(name="Pippin", description="Curious hobbit") session.characters[char1.id] = char1 session.characters[char2.id] = char2 session.characters[char3.id] = char3 assert len(session.characters) == 3 def test_session_scene_history(self): """Test adding scenes to history""" session = GameSession(name="Test") scene1 = "You enter a dark cave" scene2 = "You hear footsteps behind you" session.scene_history.append(scene1) session.scene_history.append(scene2) session.current_scene = scene2 assert len(session.scene_history) == 2 assert session.current_scene == scene2 def test_session_public_messages(self): """Test public messages feed""" session = GameSession(name="Test") msg1 = Message(sender="character", content="I wave", visibility="public") msg2 = Message(sender="character", content="I charge forward", visibility="public") session.public_messages.append(msg1) session.public_messages.append(msg2) assert len(session.public_messages) == 2 assert session.public_messages[0].visibility == "public" class TestMessageVisibility: """Test message visibility logic""" def test_private_message_properties(self): """Test that private messages have correct properties""" msg = Message( sender="character", content="Secret action", visibility="private" ) assert msg.visibility == "private" assert msg.public_content is None assert msg.private_content is None # Content field holds the entire message for private assert msg.content == "Secret action" def test_public_message_properties(self): """Test that public messages have correct properties""" msg = Message( sender="character", content="Public action", visibility="public" ) assert msg.visibility == "public" # For public messages, content is visible to all assert msg.content == "Public action" def test_mixed_message_properties(self): """Test that mixed messages split correctly""" msg = Message( sender="character", content="Combined", visibility="mixed", public_content="I greet the guard", private_content="I look for weaknesses in his armor" ) assert msg.visibility == "mixed" assert msg.public_content == "I greet the guard" assert msg.private_content == "I look for weaknesses in his armor" # Both parts exist separately assert msg.public_content != msg.private_content class TestCharacterIsolation: """Test that characters have isolated conversations""" def test_separate_conversation_histories(self): """Test that each character has their own conversation history""" char1 = Character(name="Alice", description="Warrior") char2 = Character(name="Bob", description="Mage") msg1 = Message(sender="character", content="Alice's message") msg2 = Message(sender="character", content="Bob's message") char1.conversation_history.append(msg1) char2.conversation_history.append(msg2) # Verify isolation assert len(char1.conversation_history) == 1 assert len(char2.conversation_history) == 1 assert char1.conversation_history[0].content == "Alice's message" assert char2.conversation_history[0].content == "Bob's message" def test_public_messages_vs_private_history(self): """Test distinction between public feed and private history""" session = GameSession(name="Test") char1 = Character(name="Alice", description="Warrior") char2 = Character(name="Bob", description="Mage") # Alice sends private message private_msg = Message(sender="character", content="I sneak", visibility="private") char1.conversation_history.append(private_msg) # Alice sends public message public_msg = Message(sender="character", content="I wave", visibility="public") session.public_messages.append(public_msg) # Bob should not see Alice's private message assert len(char2.conversation_history) == 0 # But can see public messages assert len(session.public_messages) == 1 assert session.public_messages[0].content == "I wave"