#!/usr/bin/env python3 """Unit tests for list_saved functionality without API access""" import sys import os sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) import pytest from unittest.mock import Mock, patch from typing import List from gumyum_npc_client import GumYumClient as AsyncClient, NPC, SpawnedData @pytest.mark.asyncio async def test_list_saved_attaches_client_reference(): """Test that list_saved attaches client reference to NPCs""" # Mock client client = AsyncClient("http://test.com") # Mock response from API mock_response = { "npcs": [ { "npc_id": 123, "name": "Test NPC 1", "profession": "Warrior", "personality_type": 8, "spawned": { "location": "castle", "mood": "determined", "stress_level": 3, }, "universe_id": "test-universe", "seed": 12345, }, { "npc_id": 456, "name": "Test NPC 2", "profession": "Mage", "personality_type": 5, "spawned": {"location": "tower", "mood": "curious", "stress_level": 2}, "universe_id": "test-universe", "seed": 54321, }, ] } # Mock the get method with patch.object(client, "get") as mock_get: mock_get.return_value = mock_response # Call list_saved npcs = await client.npc.list_saved() # Verify the API was called correctly mock_get.assert_called_once_with("npc/list") # Verify we got NPC objects assert len(npcs) == 2 assert all(isinstance(npc, NPC) for npc in npcs) # Verify client references are attached for npc in npcs: assert npc.client is client assert hasattr(npc, "chat") assert hasattr(npc, "completions") # Verify NPC data is correct assert npcs[0].npc_id == 123 assert npcs[0].name == "Test NPC 1" assert npcs[0].profession == "Warrior" assert npcs[0].personality_type == 8 assert npcs[0].universe_id == "test-universe" assert npcs[1].npc_id == 456 assert npcs[1].name == "Test NPC 2" assert npcs[1].profession == "Mage" assert npcs[1].personality_type == 5 def test_list_saved_handles_missing_fields(): """Test that list_saved handles missing optional fields gracefully""" # Create NPCManager directly from gumyum_npc_client import NPCManager mock_client = Mock() npc_manager = NPCManager(mock_client) # Mock response with minimal data mock_response = { "npcs": [ { "npc_id": 789, "name": "Minimal NPC", "profession": "Farmer", # personality_type missing - should default to 5 "spawned": {"location": "field", "mood": "content", "stress_level": 1}, "universe_id": "test-universe", # seed missing - should default to 0 } ] } # Use asyncio.run to handle the async method import asyncio async def run_test(): async def mock_get(*args, **kwargs): return mock_response mock_client.get = mock_get npcs = await npc_manager.list_saved() return npcs npcs = asyncio.run(run_test()) # Verify defaults were applied assert len(npcs) == 1 assert npcs[0].personality_type == 5 # Default value assert npcs[0].seed == 0 # Default value assert npcs[0].npc_id == 789 assert npcs[0].name == "Minimal NPC" def test_npc_chat_requires_client(): """Test that NPC chat methods require client reference""" # Create NPC without client npc = NPC( npc_id=999, name="Orphan NPC", profession="Lost", personality_type=1, spawned=SpawnedData(location="nowhere", mood="confused", stress_level=10), universe_id="test-universe", seed=0, ) # Verify no client assert npc.client is None # Chat proxy should still be created assert npc.chat is not None # But trying to use it should raise error import asyncio async def test_chat(): with pytest.raises(ValueError, match="NPC has no client reference"): await npc.chat.completions([{"role": "user", "content": "Hello"}]) with pytest.raises(ValueError, match="NPC has no client reference"): await npc.completions([{"role": "user", "content": "Hello"}]) asyncio.run(test_chat()) def test_list_saved_empty_response(): """Test that list_saved handles empty response correctly""" from gumyum_npc_client import NPCManager mock_client = Mock() npc_manager = NPCManager(mock_client) # Mock empty response mock_response = {"npcs": []} import asyncio async def run_test(): async def mock_get(*args, **kwargs): return mock_response mock_client.get = mock_get npcs = await npc_manager.list_saved() return npcs npcs = asyncio.run(run_test()) # Should return empty list assert isinstance(npcs, list) assert len(npcs) == 0 if __name__ == "__main__": import asyncio # Run async test asyncio.run(test_list_saved_attaches_client_reference()) # Run sync tests test_list_saved_handles_missing_fields() test_npc_chat_requires_client() test_list_saved_empty_response() print("✅ All unit tests passed!")