#!/usr/bin/env python3
"""
Test script for Card Table functionality in Basecamp MCP integration.
"""
import json
import sys
import os
import unittest
from unittest.mock import Mock, patch, MagicMock
# Add parent directory to path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from mcp_server_cli import MCPServer
from basecamp_client import BasecampClient
class TestCardTableTools(unittest.TestCase):
"""Test Card Table MCP tools."""
def setUp(self):
"""Set up test fixtures."""
self.server = MCPServer()
def test_card_table_tools_registered(self):
"""Test that all card table tools are registered."""
tool_names = [tool['name'] for tool in self.server.tools]
expected_tools = [
'get_card_table',
'get_columns',
'get_column',
'create_column',
'update_column',
'move_column',
'update_column_color',
'put_column_on_hold',
'remove_column_hold',
'watch_column',
'unwatch_column',
'get_cards',
'get_card',
'create_card',
'update_card',
'move_card'
]
for tool in expected_tools:
self.assertIn(tool, tool_names, f"Tool '{tool}' not found in registered tools")
def test_tool_schemas(self):
"""Test that tool schemas are properly defined."""
tools_by_name = {tool['name']: tool for tool in self.server.tools}
# Test get_card_table schema
schema = tools_by_name['get_card_table']['inputSchema']
self.assertEqual(schema['type'], 'object')
self.assertIn('project_id', schema['properties'])
self.assertIn('project_id', schema['required'])
# Test create_card schema
schema = tools_by_name['create_card']['inputSchema']
self.assertEqual(schema['type'], 'object')
self.assertIn('project_id', schema['properties'])
self.assertIn('column_id', schema['properties'])
self.assertIn('title', schema['properties'])
self.assertIn('content', schema['properties'])
self.assertIn('project_id', schema['required'])
self.assertIn('column_id', schema['required'])
self.assertIn('title', schema['required'])
self.assertNotIn('content', schema['required']) # content is optional
@patch('mcp_server_cli.token_storage.get_token')
@patch('mcp_server_cli.token_storage.is_token_expired')
def test_execute_get_card_table(self, mock_expired, mock_get_token):
"""Test executing get_card_table tool."""
mock_expired.return_value = False
mock_get_token.return_value = {
'access_token': 'test_token',
'account_id': '12345'
}
with patch.object(BasecampClient, 'get_card_table') as mock_get_table:
with patch.object(BasecampClient, 'get_card_table_details') as mock_get_details:
mock_get_table.return_value = {'id': '123', 'name': 'card_table'}
mock_get_details.return_value = {
'id': '123',
'name': 'card_table',
'title': 'Card Table',
'columns_count': 4
}
result = self.server._execute_tool('get_card_table', {'project_id': '456'})
self.assertEqual(result['status'], 'success')
self.assertIn('card_table', result)
self.assertEqual(result['card_table']['id'], '123')
@patch('mcp_server_cli.token_storage.get_token')
@patch('mcp_server_cli.token_storage.is_token_expired')
def test_execute_create_card(self, mock_expired, mock_get_token):
"""Test executing create_card tool."""
mock_expired.return_value = False
mock_get_token.return_value = {
'access_token': 'test_token',
'account_id': '12345'
}
with patch.object(BasecampClient, 'create_card') as mock_create:
mock_create.return_value = {
'id': '789',
'title': 'New Card',
'content': 'Card content',
'column_id': '456'
}
result = self.server._execute_tool('create_card', {
'project_id': '123',
'column_id': '456',
'title': 'New Card',
'content': 'Card content'
})
self.assertEqual(result['status'], 'success')
self.assertIn('card', result)
self.assertEqual(result['card']['title'], 'New Card')
self.assertIn('created successfully', result['message'])
class TestBasecampClientCardTables(unittest.TestCase):
"""Test BasecampClient card table methods."""
def setUp(self):
"""Set up test fixtures."""
self.client = BasecampClient(
access_token='test_token',
account_id='12345',
user_agent='Test Agent',
auth_mode='oauth'
)
def test_patch_method_exists(self):
"""Test that patch method exists."""
self.assertTrue(hasattr(self.client, 'patch'))
@patch('requests.get')
def test_get_card_table(self, mock_get):
"""Test getting card table from project dock."""
mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = {
'id': '123',
'dock': [
{'name': 'todoset', 'id': '111'},
{'name': 'card_table', 'id': '222'},
{'name': 'message_board', 'id': '333'}
]
}
mock_get.return_value = mock_response
result = self.client.get_card_table('123')
self.assertEqual(result['name'], 'card_table')
self.assertEqual(result['id'], '222')
@patch('requests.post')
def test_create_column(self, mock_post):
"""Test creating a column."""
mock_response = Mock()
mock_response.status_code = 201
mock_response.json.return_value = {
'id': '456',
'title': 'New Column',
'position': 5
}
mock_post.return_value = mock_response
result = self.client.create_column('123', '456', 'New Column')
self.assertEqual(result['title'], 'New Column')
mock_post.assert_called_once()
call_args = mock_post.call_args
self.assertEqual(call_args[1]['json'], {'title': 'New Column'})
@patch('requests.patch')
def test_update_column_color(self, mock_patch):
"""Test updating column color."""
mock_response = Mock()
mock_response.status_code = 200
mock_response.json.return_value = {
'id': '456',
'title': 'Column',
'color': '#FF0000'
}
mock_patch.return_value = mock_response
result = self.client.update_column_color('123', '456', '#FF0000')
self.assertEqual(result['color'], '#FF0000')
mock_patch.assert_called_once()
call_args = mock_patch.call_args
self.assertEqual(call_args[1]['json'], {'color': '#FF0000'})
if __name__ == '__main__':
unittest.main(verbosity=2)