test_fuel_rate_tools.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. import unittest
  2. from tools.query_fuel_rate_list import QueryFuelRateListTool
  3. from tools.save_fuel_rate import SaveFuelRateTool
  4. from tools.enable_fuel_rate import EnableFuelRateTool
  5. from app import GatewayApp
  6. from public_gateway import PublicGatewayApp
  7. from services.output_presenter import OutputPresenter
  8. class FuelRateToolTest(unittest.TestCase):
  9. def test_tools_are_registered_on_base_backend(self):
  10. local = GatewayApp().registered_tool_names()
  11. public = PublicGatewayApp(None, None).registered_tool_names()
  12. self.assertEqual(local, public)
  13. self.assertIn('query_fuel_rate_list', local)
  14. self.assertIn('save_fuel_rate', local)
  15. self.assertIn('enable_fuel_rate', local)
  16. self.assertEqual('base', QueryFuelRateListTool.backend)
  17. self.assertEqual('base', SaveFuelRateTool.backend)
  18. self.assertEqual('base', EnableFuelRateTool.backend)
  19. def test_query_posts_exact_filters(self):
  20. client = FakeClient()
  21. QueryFuelRateListTool(api_client=client).call(
  22. fuel_no=' RY12 ',
  23. product='美国专线',
  24. price_type='销售燃油',
  25. status=3,
  26. start_date='2026-10-21',
  27. page=2,
  28. limit=20,
  29. request_id='rq_fuel_list',
  30. )
  31. self.assertEqual('query_fuel_rate_list', client.calls[0][0])
  32. self.assertEqual('/mcp/tools/queryFuelRateList', client.calls[0][1])
  33. self.assertEqual({
  34. 'page': 2,
  35. 'limit': 20,
  36. 'fuel_no': 'RY12',
  37. 'product': '美国专线',
  38. 'price_type': '销售燃油',
  39. 'status': '3',
  40. 'start_date': '2026-10-21',
  41. }, client.calls[0][2])
  42. def test_save_posts_condition_item(self):
  43. client = FakeClient()
  44. SaveFuelRateTool(api_client=client).call(
  45. price_type=1,
  46. start_date='2026-10-21',
  47. items=[{
  48. 'fuel_ratio': 0.15,
  49. 'conditions': [{
  50. 'condition': '物流产品',
  51. 'group': '1',
  52. 'condition_value': '美国专线',
  53. }],
  54. }],
  55. request_id='rq_fuel_save',
  56. )
  57. self.assertEqual('/mcp/tools/saveFuelRate', client.calls[0][1])
  58. self.assertEqual({
  59. 'price_type': '1',
  60. 'start_date': '2026-10-21',
  61. 'items': [{
  62. 'fuel_ratio': '0.1500',
  63. 'conditions': [{
  64. 'condition': '物流产品',
  65. 'group': '1',
  66. 'condition_value': '美国专线',
  67. }],
  68. }],
  69. }, client.calls[0][2])
  70. def test_save_edit_posts_fuel_no(self):
  71. client = FakeClient()
  72. SaveFuelRateTool(api_client=client).call(
  73. fuel_no=' RY12 ',
  74. price_type='销售燃油',
  75. start_date='2026-10-22',
  76. items=[{
  77. 'fuel_ratio': '0.2000',
  78. 'conditions': [{
  79. 'condition': '物流产品',
  80. 'group': '1',
  81. 'condition_value': '美国专线',
  82. }],
  83. }],
  84. )
  85. self.assertEqual('RY12', client.calls[0][2]['fuel_no'])
  86. self.assertEqual('销售燃油', client.calls[0][2]['price_type'])
  87. self.assertEqual(1, len(client.calls[0][2]['items']))
  88. def test_save_rejects_invalid_fuel_ratio(self):
  89. tool = SaveFuelRateTool(api_client=FakeClient())
  90. item = {
  91. 'conditions': [{
  92. 'condition': '物流产品',
  93. 'group': '1',
  94. 'condition_value': '美国专线',
  95. }],
  96. }
  97. for ratio in ('abc', '1.2', '0.12345', True):
  98. with self.assertRaises(ValueError):
  99. tool.call(
  100. price_type=1,
  101. start_date='2026-10-22',
  102. items=[dict(item, fuel_ratio=ratio)],
  103. )
  104. def test_save_edit_rejects_multiple_items(self):
  105. tool = SaveFuelRateTool(api_client=FakeClient())
  106. item = {
  107. 'fuel_ratio': '0.2000',
  108. 'conditions': [{
  109. 'condition': '物流产品',
  110. 'group': '1',
  111. 'condition_value': '美国专线',
  112. }],
  113. }
  114. with self.assertRaises(ValueError):
  115. tool.call(
  116. fuel_no='RY12',
  117. price_type=1,
  118. start_date='2026-10-22',
  119. items=[item, item],
  120. )
  121. def test_presenter_keeps_missing_condition_message(self):
  122. result = OutputPresenter().present('save_fuel_rate', {
  123. 'code': 'MCP_1401',
  124. 'msg': '第1条物流产品条件值[美国专线]不存在或未启用',
  125. 'data': {},
  126. 'meta': {'request_id': 'rq_fuel_save'},
  127. })
  128. self.assertIn('不存在或未启用', str(result))
  129. def test_presenter_shows_fuel_list(self):
  130. columns = [
  131. {'key': key, 'name': name}
  132. for key, name in (
  133. ('fuel_no', '燃油代码'),
  134. ('price_type_name', '燃油类型'),
  135. ('status_name', '状态'),
  136. ('source', '来源'),
  137. )
  138. ]
  139. result = OutputPresenter().present('query_fuel_rate_list', {
  140. 'code': 'MCP_0000',
  141. 'msg': 'success',
  142. 'data': {
  143. 'summary': '共查询到 1 条燃油系数',
  144. 'columns': columns,
  145. 'records': [{
  146. 'fuel_no': 'RY12',
  147. 'price_type_name': '销售燃油',
  148. 'status_name': '启用',
  149. 'source': 'MCP',
  150. }],
  151. 'tips': [],
  152. },
  153. 'meta': {'request_id': 'rq_fuel_list', 'page': 1, 'limit': 20, 'total': 1},
  154. })
  155. rendered = str(result)
  156. self.assertIn('RY12', rendered)
  157. self.assertIn('MCP', rendered)
  158. def test_enable_posts_fuel_numbers(self):
  159. client = FakeClient()
  160. EnableFuelRateTool(api_client=client).call(fuel_no=[' RY12 ', 'RY13', 'RY12'])
  161. self.assertEqual('enable_fuel_rate', client.calls[0][0])
  162. self.assertEqual('/mcp/tools/enableFuelRate', client.calls[0][1])
  163. self.assertEqual(['RY12', 'RY13'], client.calls[0][2]['fuel_no'])
  164. def test_enable_rejects_empty_list(self):
  165. with self.assertRaises(ValueError):
  166. EnableFuelRateTool(api_client=FakeClient()).call(fuel_no=[])
  167. def test_presenter_keeps_already_enabled_message(self):
  168. result = OutputPresenter().present('enable_fuel_rate', {
  169. 'code': 'MCP_1401',
  170. 'msg': '燃油系数RY12已启用',
  171. 'data': {},
  172. 'meta': {'request_id': 'rq_fuel_enable'},
  173. })
  174. self.assertIn('已启用', str(result))
  175. def test_presenter_shows_enabled_fuel(self):
  176. result = OutputPresenter().present('enable_fuel_rate', {
  177. 'code': 'MCP_0000',
  178. 'msg': 'success',
  179. 'data': {
  180. 'summary': '已启用 1 条燃油系数',
  181. 'columns': [
  182. {'key': 'fuel_no', 'name': '燃油代码'},
  183. {'key': 'status_text', 'name': '状态'},
  184. ],
  185. 'records': [{'fuel_no': 'RY12', 'status_text': '启用'}],
  186. 'tips': [],
  187. },
  188. 'meta': {'request_id': 'rq_fuel_enable'},
  189. })
  190. rendered = str(result)
  191. self.assertIn('RY12', rendered)
  192. self.assertIn('启用', rendered)
  193. class FakeClient:
  194. def __init__(self):
  195. self.calls = []
  196. def call_tool(self, name, route, payload, request_id):
  197. self.calls.append((name, route, payload, request_id))
  198. return {'ok': True}
  199. if __name__ == '__main__':
  200. unittest.main()