| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149 |
- import unittest
- from app import GatewayApp
- from public_gateway import PublicGatewayApp
- from services.output_presenter import OutputPresenter
- from tools.export_inbound_receipt import ExportInboundReceiptTool
- from tools.list_inbound_receipt_templates import ListInboundReceiptTemplatesTool
- class _Api:
- def __init__(self):
- self.calls = []
- def call_tool(self, tool_name, route_path, payload, request_id):
- self.calls.append((tool_name, route_path, payload, request_id))
- return {'code': 'MCP_0000', 'data': {}}
- class InboundReceiptToolTest(unittest.TestCase):
- def test_local_and_public_registries_match(self):
- local = set(GatewayApp(api_client=object()).registered_tool_names())
- public = set(PublicGatewayApp(object(), object()).registered_tool_names())
- self.assertEqual(local, public)
- self.assertIn('list_inbound_receipt_templates', local)
- self.assertIn('export_inbound_receipt', local)
- def test_list_tool_strips_and_dedupes_container_codes(self):
- api = _Api()
- tool = ListInboundReceiptTemplatesTool(api)
- tool.call([' CONT-1 ', 'CONT-1'], request_id='rq_list')
- self.assertEqual(
- ('list_inbound_receipt_templates', '/mcp/tools/listInboundReceiptTemplates',
- {'container_codes': ['CONT-1']}, 'rq_list'),
- api.calls[0]
- )
- self.assertIn('container_codes', tool.metadata()['input_schema']['required'])
- def test_export_requires_selected_template_and_does_not_wait(self):
- api = _Api()
- tool = ExportInboundReceiptTool(api)
- description = tool.metadata()['description']
- self.assertIn('query_export_task', description)
- self.assertIn('不会在本次调用中等待文件生成', description)
- tool.call(['CONT-1'], ' FMS-INBOUND-LAX ', request_id='rq_export')
- self.assertEqual('FMS-INBOUND-LAX', api.calls[0][2]['template_code'])
- with self.assertRaises(ValueError):
- tool.call(['CONT-1'], ' ')
- def test_presenter_shows_kind_and_passes_container_rejection(self):
- presenter = OutputPresenter()
- shown = presenter.present('list_inbound_receipt_templates', {
- 'code': 'MCP_0000',
- 'data': {
- 'receipt_kind': '直送入仓单',
- 'templates': [
- {'name': '直送柜', 'template_code': 'FMS-INBOUND-ZSG'},
- ],
- },
- 'meta': {'request_id': 'rq_ok'},
- })
- self.assertFalse(shown['is_error'])
- self.assertEqual('直送入仓单', shown['structured_content']['receipt_kind'])
- self.assertNotIn('id', shown['structured_content']['rows'][0])
- rejected = presenter.present('list_inbound_receipt_templates', {
- 'code': 'MCP_1601',
- 'msg': '这些柜号没有对应的排舱单:NONE-1',
- 'data': {},
- 'meta': {'request_id': 'rq_missing'},
- })
- self.assertTrue(rejected['is_error'])
- self.assertIn('NONE-1', rejected['text'])
- hidden = presenter.present('export_inbound_receipt', {
- 'code': 'MCP_1601',
- 'msg': 'SQLSTATE select * from fms_outbound',
- 'data': {},
- 'meta': {'request_id': 'rq_sql'},
- })
- self.assertNotIn('SQLSTATE', hidden['text'])
- self.assertIn('没有可导出的数据', hidden['text'])
- def test_container_codes_and_template_code_are_validated(self):
- listing = ListInboundReceiptTemplatesTool(api_client=_Api())
- exporting = ExportInboundReceiptTool(api_client=_Api())
- with self.assertRaises(RuntimeError):
- ListInboundReceiptTemplatesTool().call(['CONT-1'])
- with self.assertRaises(RuntimeError):
- ExportInboundReceiptTool().call(['CONT-1'], 'CODE')
- for value in (None, [], ['CONT-1'] * 201, [1], [' '], ['C' * 101]):
- with self.assertRaises(ValueError):
- listing.clean_container_codes(value)
- for value in (None, 1, ' ', 'C' * 101):
- with self.assertRaises(ValueError):
- exporting.call(['CONT-1'], value)
- presenter = OutputPresenter()
- ok = {
- 'receipt_kind': '非直送入仓单',
- 'templates': [{'name': ' 非直送柜 ', 'template_code': 'CODE'}],
- }
- shown = presenter.present('list_inbound_receipt_templates', {
- 'code': 'MCP_0000',
- 'data': ok,
- 'meta': {'request_id': 'rq_ok'},
- })
- self.assertFalse(shown['is_error'])
- for data in (
- dict(ok, extra=1),
- dict(ok, receipt_kind='其他'),
- dict(ok, templates=[]),
- dict(ok, templates=[{'name': '模板'}]),
- dict(ok, templates=[{'name': ' ', 'template_code': 'CODE'}]),
- dict(ok, templates=[{'name': '模板', 'template_code': 1}]),
- ):
- result = presenter.present('list_inbound_receipt_templates', {
- 'code': 'MCP_0000',
- 'data': data,
- 'meta': {'request_id': 'rq_bad'},
- })
- self.assertTrue(result['is_error'])
- for message in (
- '当前没有可用的入仓单模板',
- '所选模板不属于这次柜号对应的入仓单',
- '这些柜号没有对应的排舱单:',
- '这些柜号没有对应的排舱单:' + ('C' * 101),
- '这些柜号没有对应的排舱单:CONT-1、 CONT-2',
- '这些柜号没有对应的排舱单:CONT-1、\n',
- '这些柜号是直送柜:CONT-1。这些柜号是非直送柜:CONT-2。',
- '这些柜号是直送柜: CONT-1。这些柜号是非直送柜:CONT-2。',
- ):
- result = presenter.present('list_inbound_receipt_templates', {
- 'code': 'MCP_1601',
- 'msg': message,
- 'data': {},
- 'meta': {'request_id': 'rq_msg'},
- })
- if message.startswith('这些柜号是直送柜:CONT-1。') or message in (
- '当前没有可用的入仓单模板',
- '所选模板不属于这次柜号对应的入仓单',
- ):
- self.assertIn(message, result['text'])
- else:
- self.assertNotIn('CONT-1、', result['text'])
- if __name__ == '__main__':
- unittest.main()
|