| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- import io
- import math
- import unittest
- from unittest.mock import Mock, patch
- from app import GatewayApp
- from public_gateway import PublicGatewayApp
- from services.output_presenter import OutputPresenter
- from tools.trial_goods_tax import TrialGoodsTaxTool
- class TrialGoodsTaxToolTest(unittest.TestCase):
- def test_call_forwards_required_fields(self):
- client = Mock()
- client.call_tool.return_value = {'code': 'MCP_0000'}
- TrialGoodsTaxTool(client).call(
- sku=' SKU-1 ',
- departure_country=' CN ',
- destination_country='us',
- price=10,
- qty=2,
- gross_weight=1.5,
- box=1,
- )
- client.call_tool.assert_called_once_with(
- 'trial_goods_tax',
- '/mcp/tools/trialGoodsTax',
- {
- 'sku': 'SKU-1',
- 'departure_country': 'CN',
- 'destination_country': 'US',
- 'price': 10,
- 'qty': 2,
- 'gross_weight': 1.5,
- 'box': 1,
- },
- 'rq_trial_goods_tax',
- )
- def test_call_rejects_country_name(self):
- tool = TrialGoodsTaxTool(api_client=Mock())
- with self.assertRaises(ValueError):
- tool.call(
- sku='SKU-1', departure_country='中国', destination_country='US',
- price=10, qty=1, gross_weight=1, box=1,
- )
- def test_call_rejects_zero_price(self):
- tool = TrialGoodsTaxTool(api_client=Mock())
- with self.assertRaises(ValueError):
- tool.call(
- sku='SKU-1', departure_country='CN', destination_country='US',
- price=0, qty=1, gross_weight=1, box=1,
- )
- def test_call_requires_api_client(self):
- with self.assertRaises(RuntimeError):
- TrialGoodsTaxTool().call(
- sku='SKU-1', departure_country='CN', destination_country='US',
- price=1, qty=1, gross_weight=1, box=1,
- )
- def test_call_rejects_invalid_fields(self):
- tool = TrialGoodsTaxTool(api_client=Mock())
- cases = [
- {'sku': 1},
- {'sku': ''},
- {'sku': 'S' * 101},
- {'departure_country': None},
- {'departure_country': 'A'},
- {'departure_country': 'ABCD'},
- {'departure_country': 'C1'},
- {'price': True},
- {'qty': '1'},
- {'gross_weight': math.inf},
- {'box': 1000000001},
- ]
- base = {
- 'sku': 'SKU-1', 'departure_country': 'CN', 'destination_country': 'USA',
- 'price': 1, 'qty': 1, 'gross_weight': 1, 'box': 1,
- }
- for override in cases:
- with self.subTest(override=override):
- payload = dict(base)
- payload.update(override)
- with self.assertRaises(ValueError):
- tool.call(**payload)
- def test_cli_forwards_trial_fields(self):
- app = GatewayApp()
- with patch.object(app, 'call_tool', return_value={'code': 'MCP_0000'}) as call_tool:
- code = app.run_cli([
- 'call', '--tool', 'trial_goods_tax',
- '--sku', 'SKU-1',
- '--departure-country', 'CN',
- '--destination-country', 'US',
- '--price', '10',
- '--qty', '2',
- '--gross-weight', '1.5',
- '--box', '1',
- ], stdout=io.StringIO())
- self.assertEqual(0, code)
- self.assertEqual(
- {
- 'page': 1,
- 'limit': 20,
- 'sku': 'SKU-1',
- 'departure_country': 'CN',
- 'destination_country': 'US',
- 'price': 10.0,
- 'qty': 2.0,
- 'gross_weight': 1.5,
- 'box': 1.0,
- },
- call_tool.call_args[0][1],
- )
- def test_registries_match(self):
- local = GatewayApp().registered_tool_names()
- public = PublicGatewayApp(None, None).registered_tool_names()
- self.assertEqual(local, public)
- self.assertIn('trial_goods_tax', local)
- self.assertEqual(42, len(local))
- self.assertIn('trial_goods_tax', OutputPresenter.SAFE_TOOLS)
- def test_presenter_renders_amount(self):
- result = OutputPresenter().present('trial_goods_tax', {
- 'code': 'MCP_0000',
- 'data': {
- 'estimated_tax': 12.5,
- 'sku': 'SKU-1',
- 'departure_country': 'CN',
- 'destination_country': 'US',
- },
- 'meta': {'request_id': 'rq1'},
- })
- self.assertFalse(result['is_error'])
- self.assertEqual(12.5, result['structured_content']['estimated_tax'])
- self.assertIn('预计关税金额', result['text'])
- def test_presenter_keeps_safe_failure_message(self):
- result = OutputPresenter().present('trial_goods_tax', {
- 'code': 'MCP_1501',
- 'msg': '未找到已审核商品',
- 'data': [],
- 'meta': {'request_id': 'rq1'},
- })
- self.assertTrue(result['is_error'])
- self.assertEqual('未找到已审核商品', result['structured_content']['message'])
- def test_presenter_rejects_invalid_tax_payload(self):
- presenter = OutputPresenter()
- valid = {
- 'estimated_tax': 12,
- 'sku': 'SKU-1',
- 'departure_country': 'CN',
- 'destination_country': 'USA',
- }
- ok = presenter.present('trial_goods_tax', {
- 'code': 'MCP_0000',
- 'data': valid,
- })
- self.assertFalse(ok['is_error'])
- self.assertEqual(12, ok['structured_content']['estimated_tax'])
- cases = [
- {'estimated_tax': 1},
- dict(valid, estimated_tax=True),
- dict(valid, estimated_tax='12'),
- dict(valid, estimated_tax=math.nan),
- dict(valid, sku=1),
- dict(valid, sku=' '),
- dict(valid, departure_country=1),
- dict(valid, departure_country='C1'),
- dict(valid, departure_country='cn'),
- dict(valid, departure_country='A'),
- dict(valid, departure_country='ABCD'),
- dict(valid, destination_country='us'),
- ]
- for data in cases:
- with self.subTest(data=data):
- result = presenter.present('trial_goods_tax', {
- 'code': 'MCP_0000',
- 'data': data,
- })
- self.assertTrue(result['is_error'])
- self.assertNotIn('SKU-1', result['text'])
|