File size: 6,412 Bytes
6a3de9e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
"""
Logic tests for the TodoAgent functionality.

These tests verify the core logic of the AI agent including:
- Command recognition
- Task detail extraction
- Proper response formatting
- Error handling
"""
import pytest
from unittest.mock import AsyncMock, MagicMock, patch
from ai.agents.todo_agent import TodoAgent
from models.conversation import Conversation
from uuid import UUID


@pytest.fixture
def todo_agent():
    """Create a TodoAgent instance for testing."""
    agent = TodoAgent()
    # Mock the internal components to avoid actual API calls
    agent.client = MagicMock()
    agent.config = MagicMock()
    agent._agent = MagicMock()
    return agent


@pytest.mark.asyncio
async def test_process_message_success(todo_agent):
    """Test successful message processing."""
    # Mock data
    user_id = "test-user-123"
    message = "Add a task: Buy groceries"
    conversation = MagicMock()
    conversation.id = UUID("12345678-1234-5678-1234-567812345678")

    # Mock the runner response
    mock_result = AsyncMock()
    mock_result.final_output = "Task 'Buy groceries' added successfully"

    with patch('ai.agents.todo_agent.Runner') as mock_runner:
        mock_runner.run = AsyncMock(return_value=mock_result)

        result = await todo_agent.process_message(user_id, message, conversation)

        # Assertions
        assert "response" in result
        assert "conversation_id" in result
        assert "tool_calls" in result
        assert "requires_action" in result
        assert result["response"] == "Task 'Buy groceries' added successfully"


@pytest.mark.asyncio
async def test_process_message_with_error(todo_agent):
    """Test message processing with error handling."""
    # Mock data
    user_id = "test-user-123"
    message = "Add a task: Buy groceries"
    conversation = MagicMock()
    conversation.id = UUID("12345678-1234-5678-1234-567812345678")

    # Mock the runner to raise an exception
    with patch('ai.agents.todo_agent.Runner') as mock_runner:
        mock_runner.run = AsyncMock(side_effect=Exception("API Error"))

        result = await todo_agent.process_message(user_id, message, conversation)

        # Assertions for error case
        assert "response" in result
        assert "conversation_id" in result
        assert "tool_calls" in result
        assert "requires_action" in result
        assert "error" in result["response"]


@pytest.mark.asyncio
async def test_recognize_command_add_task(todo_agent):
    """Test recognizing add task commands."""
    test_messages = [
        "Add a task: Buy groceries",
        "Create task: Clean the house",
        "Make a new task: Pay bills",
        "Add task: Schedule meeting"
    ]

    for msg in test_messages:
        command = await todo_agent.recognize_command(msg)
        assert command == "add_task"


@pytest.mark.asyncio
async def test_recognize_command_list_tasks(todo_agent):
    """Test recognizing list tasks commands."""
    test_messages = [
        "Show me my tasks",
        "List my tasks",
        "Display my tasks",
        "What are my tasks?"
    ]

    for msg in test_messages:
        command = await todo_agent.recognize_command(msg)
        assert command == "list_tasks"


@pytest.mark.asyncio
async def test_recognize_command_complete_task(todo_agent):
    """Test recognizing complete task commands."""
    test_messages = [
        "Complete task 1",
        "Mark task as done",
        "Finish this task",
        "Task is done"
    ]

    for msg in test_messages:
        command = await todo_agent.recognize_command(msg)
        assert command == "complete_task"


@pytest.mark.asyncio
async def test_recognize_command_delete_task(todo_agent):
    """Test recognizing delete task commands."""
    test_messages = [
        "Delete task 1",
        "Remove this task",
        "Cancel this task",
        "Get rid of task"
    ]

    for msg in test_messages:
        command = await todo_agent.recognize_command(msg)
        assert command == "delete_task"


@pytest.mark.asyncio
async def test_recognize_command_update_task(todo_agent):
    """Test recognizing update task commands."""
    test_messages = [
        "Update task 1",
        "Change this task",
        "Edit task details",
        "Modify task"
    ]

    for msg in test_messages:
        command = await todo_agent.recognize_command(msg)
        assert command == "update_task"


@pytest.mark.asyncio
async def test_recognize_command_unknown(todo_agent):
    """Test recognizing unknown commands."""
    test_messages = [
        "Hello",
        "How are you?",
        "What's the weather?",
        "Random message"
    ]

    for msg in test_messages:
        command = await todo_agent.recognize_command(msg)
        assert command is None


def test_extract_task_details_basic(todo_agent):
    """Test extracting task details from simple messages."""
    message = "Add task: Buy groceries"
    details = todo_agent.extract_task_details(message)

    assert "title" in details
    assert "description" in details
    assert details["title"] == "Buy groceries"
    assert details["description"] == ""


def test_extract_task_details_with_colon(todo_agent):
    """Test extracting task details from messages with colon separator."""
    message = "Add a new task: Buy groceries: with milk and bread"
    details = todo_agent.extract_task_details(message)

    assert "title" in details
    assert "description" in details
    # Should take everything after the first colon as title
    assert details["title"] == "Buy groceries: with milk and bread"
    assert details["description"] == ""


def test_extract_task_details_no_colon(todo_agent):
    """Test extracting task details from messages without colon."""
    message = "Clean the house"
    details = todo_agent.extract_task_details(message)

    assert "title" in details
    assert "description" in details
    assert details["title"] == "Clean the house"
    assert details["description"] == ""


@pytest.mark.asyncio
async def test_agent_initialization(todo_agent):
    """Test that the agent initializes correctly."""
    assert hasattr(todo_agent, 'client')
    assert hasattr(todo_agent, 'config')
    assert hasattr(todo_agent, 'process_message')
    assert hasattr(todo_agent, 'recognize_command')
    assert hasattr(todo_agent, 'extract_task_details')


if __name__ == "__main__":
    pytest.main([__file__])