2026-06-10 19:15:24 +08:00
|
|
|
import unittest
|
|
|
|
|
from io import BytesIO
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
from unittest.mock import patch
|
|
|
|
|
|
|
|
|
|
from flask import Flask
|
|
|
|
|
|
|
|
|
|
from app.routes.guidance import guidance_bp
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class GuidanceAnalyzeRouteTest(unittest.TestCase):
|
|
|
|
|
def setUp(self):
|
|
|
|
|
self.app = Flask(__name__)
|
|
|
|
|
self.app.register_blueprint(guidance_bp)
|
|
|
|
|
self.client = self.app.test_client()
|
|
|
|
|
|
|
|
|
|
def test_analyze_accepts_json_token_id(self):
|
|
|
|
|
fake_results = [{"file_id": "file-2", "filename": "trade.txt", "guidance_analysis": {"status": "done"}}]
|
|
|
|
|
|
|
|
|
|
with patch("app.routes.guidance.DomainStorage") as storage_cls:
|
|
|
|
|
storage = storage_cls.return_value
|
|
|
|
|
storage.analyze_guidance.return_value = fake_results
|
|
|
|
|
|
|
|
|
|
response = self.client.post(
|
|
|
|
|
"/api/guidance/analyze",
|
|
|
|
|
json={"token_id": "token-2", "granularity": "high"},
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
storage.analyze_guidance.assert_called_once_with(
|
|
|
|
|
analysis_options={"granularity": "high"},
|
|
|
|
|
token_id="token-2",
|
|
|
|
|
)
|
|
|
|
|
body = response.get_json()
|
|
|
|
|
self.assertEqual(body["data"]["analysis_options"]["token_id"], "token-2")
|
|
|
|
|
self.assertEqual(body["data"]["total"], 1)
|
|
|
|
|
|
|
|
|
|
def test_analyze_omits_token_id_for_all_files(self):
|
|
|
|
|
with patch("app.routes.guidance.DomainStorage") as storage_cls:
|
|
|
|
|
storage = storage_cls.return_value
|
|
|
|
|
storage.analyze_guidance.return_value = []
|
|
|
|
|
|
|
|
|
|
response = self.client.post("/api/guidance/analyze", data={"granularity": "low"})
|
|
|
|
|
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
storage.analyze_guidance.assert_called_once_with(
|
|
|
|
|
analysis_options={"granularity": "low"},
|
|
|
|
|
token_id="",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def test_analyze_normalizes_legacy_granularity(self):
|
|
|
|
|
with patch("app.routes.guidance.DomainStorage") as storage_cls:
|
|
|
|
|
storage = storage_cls.return_value
|
|
|
|
|
storage.analyze_guidance.return_value = []
|
|
|
|
|
|
|
|
|
|
response = self.client.post("/api/guidance/analyze", json={"granularity": "fine"})
|
|
|
|
|
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
storage.analyze_guidance.assert_called_once_with(
|
|
|
|
|
analysis_options={"granularity": "high"},
|
|
|
|
|
token_id="",
|
|
|
|
|
)
|
|
|
|
|
self.assertEqual(response.get_json()["data"]["analysis_options"]["granularity"], "high")
|
|
|
|
|
|
|
|
|
|
def test_analyze_rejects_unknown_granularity(self):
|
|
|
|
|
with patch("app.routes.guidance.DomainStorage") as storage_cls:
|
|
|
|
|
response = self.client.post("/api/guidance/analyze", json={"granularity": "middle"})
|
|
|
|
|
|
|
|
|
|
self.assertEqual(response.status_code, 400)
|
|
|
|
|
storage_cls.assert_not_called()
|
|
|
|
|
|
|
|
|
|
def test_upload_accepts_token_field_alias(self):
|
|
|
|
|
with patch("app.routes.guidance.DomainStorage") as storage_cls:
|
|
|
|
|
storage = storage_cls.return_value
|
|
|
|
|
storage.save_guidance_file.return_value = {
|
|
|
|
|
"file_id": "file-1",
|
|
|
|
|
"filename": "guide.txt",
|
|
|
|
|
"stored_path": "/private/path/guide.txt",
|
|
|
|
|
"uploaded_at": "2026-06-10 15:08:09",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
response = self.client.post(
|
|
|
|
|
"/api/guidance/upload",
|
|
|
|
|
data={
|
|
|
|
|
"token": "token-1",
|
|
|
|
|
"file": (BytesIO(b"policy"), "guide.txt"),
|
|
|
|
|
},
|
|
|
|
|
content_type="multipart/form-data",
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
storage.save_guidance_file.assert_called_once()
|
|
|
|
|
self.assertEqual(storage.save_guidance_file.call_args.args[0], "token-1")
|
|
|
|
|
body = response.get_json()
|
|
|
|
|
self.assertEqual(body["message"], "上传成功")
|
|
|
|
|
self.assertNotIn("stored_path", body["data"])
|
|
|
|
|
datetime.strptime(body["data"]["uploaded_at"], "%Y-%m-%d %H:%M:%S")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
unittest.main()
|