npc-clients-python/tests/test_list_saved_unit.py

197 lines
5.5 KiB
Python

#!/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!")