#!/usr/bin/env python3
"""看板展示层的中文语义与编码合同测试,不连接数据库。"""
import pathlib
import sys
import unittest
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent))
import server # noqa: E402
class DashboardDisplayTest(unittest.TestCase):
def test已知枚举显示中文语义和字符串编码(self):
text = server.enum_text("character", "entity_type")
self.assertIn("人物", text)
self.assertIn("character", text)
self.assertNotEqual(text, "character")
def test未知英文枚举不裸露(self):
text = server.enum_text("future_state", "status")
self.assertIn("未登记", text)
self.assertIn("future_state", text)
def test状态标签显示中文和编码(self):
text = server.chip("pending")
self.assertIn("待确认", text)
self.assertIn("pending", text)
def test字段标题使用中文并保留协议字段编码(self):
text = server.field_label("运行编号", "run_id")
self.assertIn("运行编号", text)
self.assertIn("run_id", text)
def test工具名称使用中文并保留_cli编码(self):
text = server._fmt_tools(["Read", "Grep"])
self.assertIn("读取", text)
self.assertIn("文本搜索", text)
self.assertIn("Read", text)
self.assertIn("Grep", text)
def test自由文本技术术语显示中文语义和编码(self):
text = server.annotated_text("writer sandbox + writer + Claude CLI + MiniMax + semantic detector + asOf")
self.assertIn("写手隔离环境", text)
self.assertIn("写手 writer sandbox", text)
def test说明截断不会切断编码或误改_postgresql(self):
text = server.annotated_text(server.short_text("场景 scenario: fine_outline_replay/校验", 20))
self.assertNotIn("fine_outl", text)
self.assertNotIn("Postgre数据库", server.annotated_text("PostgreSQL 查询"))
def test详情自由文本中的运行时编码也有中文语义(self):
text = server.annotated_text(
"Claude CLI fresh/sandbox + revision journal (file_cas) + raw vault; "
"被 detect/quality-gate/continuation/replay-eval 复用"
)
self.assertIn("模型命令行客户端", text)
self.assertIn("修订日志", text)
self.assertIn("原始证据仓", text)
self.assertIn("语义检测", text)
self.assertIn("质量门", text)
self.assertIn("实验库", server.annotated_text("muse-example"))
self.assertIn("正文块", server.annotated_text("正文 block"))
self.assertIn("file_cas", text)
def test卡片下钻地址保留筛选条件(self):
href = server._query_href(
"/works/12", {"q": ["薄雾号"], "type": ["location"], "status": ["pending"]}, card=25438
)
self.assertIn("q=", href)
self.assertIn("type=location", href)
self.assertIn("status=pending", href)
self.assertIn("card=25438", href)
def test章节展示中文标题并保留主键编码(self):
text = server._chapter_text(17474, 2, "称量")
self.assertIn("第2章《称量》", text)
self.assertIn("chapter_id=17474", text)
def test运行描述包含用途角色和章节(self):
text = server._run_description(
("run-prod-work12-ch2", 12, "深渊机神", 2, "user", "completed", "时间",
17474, 2, "称量", "writer", "generation", "production", "writer", "production_generation")
)
self.assertIn("正文生产", text)
self.assertIn("写手", text)
self.assertIn("第2章《称量》", text)
def test原始_JSON_错误信息可读(self):
text = server._content_text('{"failureType":"InvalidTextRepresentation"}')
self.assertIn('"failureType": "InvalidTextRepresentation"', text)
def test规划标题和摘要从载荷提取(self):
payload = {"chapterGoal": "林深被隔离审讯", "chapterEndHook": "茧准备出击"}
self.assertEqual(server._planning_title(payload, "fine_outline", 2), "第2章目标")
self.assertEqual(server._planning_summary(payload), "林深被隔离审讯")
def test数据库AI味页面展示正式库汇总(self):
text = server.view_ai_flavor({})
self.assertIn("AI 味案例", text)
self.assertIn("788", text)
self.assertIn("8", text)
self.assertIn("PostgreSQL muse-example 正式库", text)
self.assertIn("原文片段未保存", text)
self.assertIn("不是人工确认的 AI 味结论", text)
self.assertIn("来源已验证", text)
self.assertIn("788/788", text)
self.assertIn("batch_id=", text)
def test数据库AI味页面支持作品分页与卡片详情(self):
filtered = server.view_ai_flavor({"work": ["ref:机破星河_当年离歌"], "page": ["2"]})
self.assertIn("当前第 2/6 页", filtered)
self.assertIn("ref:机破星河_当年离歌", filtered)
detail = server.view_ai_flavor({"card": ["case-0b9ed3af70a7dbf315fc"]})
self.assertIn("全文 SHA-256", detail)
self.assertIn("原文片段未保存", detail)
self.assertIn("来源已验证", detail)
def test数据库案例详情显示用途和作用域边界(self):
detail = server.view_ai_flavor({"card": ["case-0b9ed3af70a7dbf315fc"]})
self.assertIn("当前用途", detail)
self.assertIn("仅供本卡/本作品人工复核", detail)
self.assertIn("backfill", detail)
def test数据库案例页面按当前数据库作品数动态渲染(self):
original_bundle = server._ai_db_bundle
try:
report, revalidation, error = original_bundle()
report = dict(report)
report["works"] = list(report["works"][:1])
report["totals"] = dict(report.get("totals") or {})
report["totals"]["books"] = 1
report["cards"] = list(report["cards"][:1])
report["totals"]["cards"] = 1
server._ai_db_bundle = lambda: (report, revalidation, error)
text = server.view_ai_flavor({})
finally:
server._ai_db_bundle = original_bundle
self.assertIn("按作品汇总(1 本)", text)
self.assertNotIn("按作品汇总(8 本)", text)
def test随包发布的离线回退夹具可被回退加载器解析(self):
"""离线回退夹具归看板自己所有;夹具坏了要在这里暴露,不能到断库时才发现。"""
report, error = server._load_ai_flavor_report()
self.assertIsNone(error)
self.assertEqual("ai-flavor-inventory-v1", report["schema_version"])
revalidation, error = server._load_ai_flavor_revalidation_report()
self.assertIsNone(error)
self.assertTrue(revalidation["usable"])
self.assertEqual(
{"cards": 788, "verified": 788, "stale": 0, "unavailable": 0, "card_mismatch": 0},
revalidation["totals"],
)
if __name__ == "__main__":
unittest.main()