test_query_track_tool.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import json
  2. import unittest
  3. from tools.query_track import QueryTrackTool
  4. class MockApiClient:
  5. def __init__(self, response=None):
  6. self.response = response or {}
  7. self.last_call = None
  8. def call_tool(self, tool_code, route_path, payload, request_id):
  9. self.last_call = {
  10. 'tool_code': tool_code,
  11. 'route_path': route_path,
  12. 'payload': payload,
  13. 'request_id': request_id,
  14. }
  15. return self.response
  16. class TestQueryTrackTool(unittest.TestCase):
  17. def test_metadata_structure(self):
  18. tool = QueryTrackTool()
  19. meta = tool.metadata()
  20. self.assertEqual(meta['name'], 'query_track')
  21. self.assertIn('description', meta)
  22. self.assertIn('input_schema', meta)
  23. schema = meta['input_schema']
  24. self.assertEqual(schema['type'], 'object')
  25. self.assertIn('order_id', schema['properties'])
  26. self.assertIn('order_number', schema['properties'])
  27. self.assertIn('tracking_number', schema['properties'])
  28. self.assertIn('page', schema['properties'])
  29. self.assertIn('limit', schema['properties'])
  30. # order_id and order_number are optional but at least one is required
  31. def test_call_with_minimal_params(self):
  32. mock_response = {
  33. 'summary': 'Found 2 tracks',
  34. 'records': [],
  35. 'tips': [],
  36. 'meta': {'page': 1, 'limit': 5, 'total': 2},
  37. }
  38. client = MockApiClient(mock_response)
  39. tool = QueryTrackTool(api_client=client)
  40. result = tool.call(order_id=123)
  41. self.assertEqual(result, mock_response)
  42. self.assertEqual(client.last_call['tool_code'], 'query_track')
  43. self.assertEqual(client.last_call['route_path'], '/mcp/tools/queryTrack')
  44. self.assertEqual(client.last_call['payload']['order_id'], 123)
  45. self.assertEqual(client.last_call['payload']['page'], 1)
  46. self.assertEqual(client.last_call['payload']['limit'], 5)
  47. def test_call_with_order_number(self):
  48. mock_response = {'summary': 'ok'}
  49. client = MockApiClient(mock_response)
  50. tool = QueryTrackTool(api_client=client)
  51. result = tool.call(order_number='USC26070371955')
  52. self.assertEqual(client.last_call['payload']['order_number'], 'USC26070371955')
  53. self.assertNotIn('order_id', client.last_call['payload'])
  54. self.assertEqual(client.last_call['payload']['page'], 1)
  55. self.assertEqual(client.last_call['payload']['limit'], 5)
  56. def test_call_with_tracking_number(self):
  57. mock_response = {'summary': 'ok'}
  58. client = MockApiClient(mock_response)
  59. tool = QueryTrackTool(api_client=client)
  60. result = tool.call(tracking_number='1471904540000000301')
  61. self.assertEqual(result, mock_response)
  62. self.assertEqual(client.last_call['payload']['tracking_number'], '1471904540000000301')
  63. self.assertNotIn('order_id', client.last_call['payload'])
  64. self.assertNotIn('order_number', client.last_call['payload'])
  65. def test_call_with_all_params(self):
  66. mock_response = {'summary': 'ok'}
  67. client = MockApiClient(mock_response)
  68. tool = QueryTrackTool(api_client=client)
  69. result = tool.call(order_id=456, order_number='USC123', tracking_number='TN123', page=2, limit=10, request_id='rq_test')
  70. self.assertEqual(client.last_call['payload']['order_id'], 456)
  71. self.assertEqual(client.last_call['payload']['order_number'], 'USC123')
  72. self.assertEqual(client.last_call['payload']['tracking_number'], 'TN123')
  73. self.assertEqual(client.last_call['payload']['page'], 2)
  74. self.assertEqual(client.last_call['payload']['limit'], 10)
  75. self.assertEqual(client.last_call['request_id'], 'rq_test')
  76. def test_call_requires_api_client(self):
  77. tool = QueryTrackTool()
  78. with self.assertRaises(RuntimeError) as ctx:
  79. tool.call(order_id=123)
  80. self.assertIn('api client is required', str(ctx.exception))
  81. def test_call_requires_order_identifier(self):
  82. client = MockApiClient()
  83. tool = QueryTrackTool(api_client=client)
  84. with self.assertRaises(ValueError) as ctx:
  85. tool.call()
  86. self.assertIn('order_id, order_number or tracking_number is required', str(ctx.exception))
  87. def test_call_validates_order_id(self):
  88. client = MockApiClient()
  89. tool = QueryTrackTool(api_client=client)
  90. with self.assertRaises(ValueError) as ctx:
  91. tool.call(order_id=0)
  92. self.assertIn('must be greater than 0', str(ctx.exception))
  93. with self.assertRaises(ValueError) as ctx:
  94. tool.call(order_id=-1)
  95. self.assertIn('must be greater than 0', str(ctx.exception))
  96. def test_call_normalizes_page_and_limit(self):
  97. client = MockApiClient()
  98. tool = QueryTrackTool(api_client=client)
  99. tool.call(order_id=123, page=0, limit=200)
  100. self.assertEqual(client.last_call['payload']['page'], 1)
  101. self.assertEqual(client.last_call['payload']['limit'], 100)
  102. if __name__ == '__main__':
  103. unittest.main()