|
@@ -0,0 +1,121 @@
|
|
|
|
|
+import json
|
|
|
|
|
+import unittest
|
|
|
|
|
+
|
|
|
|
|
+from tools.query_track import QueryTrackTool
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class MockApiClient:
|
|
|
|
|
+ def __init__(self, response=None):
|
|
|
|
|
+ self.response = response or {}
|
|
|
|
|
+ self.last_call = None
|
|
|
|
|
+
|
|
|
|
|
+ def call_tool(self, tool_code, route_path, payload, request_id):
|
|
|
|
|
+ self.last_call = {
|
|
|
|
|
+ 'tool_code': tool_code,
|
|
|
|
|
+ 'route_path': route_path,
|
|
|
|
|
+ 'payload': payload,
|
|
|
|
|
+ 'request_id': request_id,
|
|
|
|
|
+ }
|
|
|
|
|
+ return self.response
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class TestQueryTrackTool(unittest.TestCase):
|
|
|
|
|
+ def test_metadata_structure(self):
|
|
|
|
|
+ tool = QueryTrackTool()
|
|
|
|
|
+ meta = tool.metadata()
|
|
|
|
|
+ self.assertEqual(meta['name'], 'query_track')
|
|
|
|
|
+ self.assertIn('description', meta)
|
|
|
|
|
+ self.assertIn('input_schema', meta)
|
|
|
|
|
+ schema = meta['input_schema']
|
|
|
|
|
+ self.assertEqual(schema['type'], 'object')
|
|
|
|
|
+ self.assertIn('order_id', schema['properties'])
|
|
|
|
|
+ self.assertIn('order_number', schema['properties'])
|
|
|
|
|
+ self.assertIn('tracking_number', schema['properties'])
|
|
|
|
|
+ self.assertIn('page', schema['properties'])
|
|
|
|
|
+ self.assertIn('limit', schema['properties'])
|
|
|
|
|
+ # order_id and order_number are optional but at least one is required
|
|
|
|
|
+
|
|
|
|
|
+ def test_call_with_minimal_params(self):
|
|
|
|
|
+ mock_response = {
|
|
|
|
|
+ 'summary': 'Found 2 tracks',
|
|
|
|
|
+ 'records': [],
|
|
|
|
|
+ 'tips': [],
|
|
|
|
|
+ 'meta': {'page': 1, 'limit': 5, 'total': 2},
|
|
|
|
|
+ }
|
|
|
|
|
+ client = MockApiClient(mock_response)
|
|
|
|
|
+ tool = QueryTrackTool(api_client=client)
|
|
|
|
|
+ result = tool.call(order_id=123)
|
|
|
|
|
+ self.assertEqual(result, mock_response)
|
|
|
|
|
+ self.assertEqual(client.last_call['tool_code'], 'query_track')
|
|
|
|
|
+ self.assertEqual(client.last_call['route_path'], '/mcp/tools/queryTrack')
|
|
|
|
|
+ self.assertEqual(client.last_call['payload']['order_id'], 123)
|
|
|
|
|
+ self.assertEqual(client.last_call['payload']['page'], 1)
|
|
|
|
|
+ self.assertEqual(client.last_call['payload']['limit'], 5)
|
|
|
|
|
+
|
|
|
|
|
+ def test_call_with_order_number(self):
|
|
|
|
|
+ mock_response = {'summary': 'ok'}
|
|
|
|
|
+ client = MockApiClient(mock_response)
|
|
|
|
|
+ tool = QueryTrackTool(api_client=client)
|
|
|
|
|
+ result = tool.call(order_number='USC26070371955')
|
|
|
|
|
+ self.assertEqual(client.last_call['payload']['order_number'], 'USC26070371955')
|
|
|
|
|
+ self.assertNotIn('order_id', client.last_call['payload'])
|
|
|
|
|
+ self.assertEqual(client.last_call['payload']['page'], 1)
|
|
|
|
|
+ self.assertEqual(client.last_call['payload']['limit'], 5)
|
|
|
|
|
+
|
|
|
|
|
+ def test_call_with_tracking_number(self):
|
|
|
|
|
+ mock_response = {'summary': 'ok'}
|
|
|
|
|
+ client = MockApiClient(mock_response)
|
|
|
|
|
+ tool = QueryTrackTool(api_client=client)
|
|
|
|
|
+ result = tool.call(tracking_number='1471904540000000301')
|
|
|
|
|
+ self.assertEqual(result, mock_response)
|
|
|
|
|
+ self.assertEqual(client.last_call['payload']['tracking_number'], '1471904540000000301')
|
|
|
|
|
+ self.assertNotIn('order_id', client.last_call['payload'])
|
|
|
|
|
+ self.assertNotIn('order_number', client.last_call['payload'])
|
|
|
|
|
+
|
|
|
|
|
+ def test_call_with_all_params(self):
|
|
|
|
|
+ mock_response = {'summary': 'ok'}
|
|
|
|
|
+ client = MockApiClient(mock_response)
|
|
|
|
|
+ tool = QueryTrackTool(api_client=client)
|
|
|
|
|
+ result = tool.call(order_id=456, order_number='USC123', tracking_number='TN123', page=2, limit=10, request_id='rq_test')
|
|
|
|
|
+ self.assertEqual(client.last_call['payload']['order_id'], 456)
|
|
|
|
|
+ self.assertEqual(client.last_call['payload']['order_number'], 'USC123')
|
|
|
|
|
+ self.assertEqual(client.last_call['payload']['tracking_number'], 'TN123')
|
|
|
|
|
+ self.assertEqual(client.last_call['payload']['page'], 2)
|
|
|
|
|
+ self.assertEqual(client.last_call['payload']['limit'], 10)
|
|
|
|
|
+ self.assertEqual(client.last_call['request_id'], 'rq_test')
|
|
|
|
|
+
|
|
|
|
|
+ def test_call_requires_api_client(self):
|
|
|
|
|
+ tool = QueryTrackTool()
|
|
|
|
|
+ with self.assertRaises(RuntimeError) as ctx:
|
|
|
|
|
+ tool.call(order_id=123)
|
|
|
|
|
+ self.assertIn('api client is required', str(ctx.exception))
|
|
|
|
|
+
|
|
|
|
|
+ def test_call_requires_order_identifier(self):
|
|
|
|
|
+ client = MockApiClient()
|
|
|
|
|
+ tool = QueryTrackTool(api_client=client)
|
|
|
|
|
+ with self.assertRaises(ValueError) as ctx:
|
|
|
|
|
+ tool.call()
|
|
|
|
|
+ self.assertIn('order_id, order_number or tracking_number is required', str(ctx.exception))
|
|
|
|
|
+
|
|
|
|
|
+ def test_call_validates_order_id(self):
|
|
|
|
|
+ client = MockApiClient()
|
|
|
|
|
+ tool = QueryTrackTool(api_client=client)
|
|
|
|
|
+ with self.assertRaises(ValueError) as ctx:
|
|
|
|
|
+ tool.call(order_id=0)
|
|
|
|
|
+ self.assertIn('must be greater than 0', str(ctx.exception))
|
|
|
|
|
+
|
|
|
|
|
+ with self.assertRaises(ValueError) as ctx:
|
|
|
|
|
+ tool.call(order_id=-1)
|
|
|
|
|
+ self.assertIn('must be greater than 0', str(ctx.exception))
|
|
|
|
|
+
|
|
|
|
|
+ def test_call_normalizes_page_and_limit(self):
|
|
|
|
|
+ client = MockApiClient()
|
|
|
|
|
+ tool = QueryTrackTool(api_client=client)
|
|
|
|
|
+ tool.call(order_id=123, page=0, limit=200)
|
|
|
|
|
+ self.assertEqual(client.last_call['payload']['page'], 1)
|
|
|
|
|
+ self.assertEqual(client.last_call['payload']['limit'], 100)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+if __name__ == '__main__':
|
|
|
|
|
+ unittest.main()
|
|
|
|
|
+
|