Files
Pre_Seg_Server/backend/tests/test_templates.py
admin 481ffa5b67 完善项目导入、模板与分割工作区交互
- 增强 DICOM/视频项目导入与演示数据:DICOM 按文件名自然顺序处理,导入后展示上传与解析任务进度,恢复演示出厂设置保留演示视频和演示 DICOM 项目,并补充 demo media seed 逻辑。

- 完善项目管理:项目支持重命名、删除、复制,删除使用站内确认弹窗,复制支持新项目重置和全内容复制,DICOM 项目不显示生成帧入口。

- 完善 GT Mask 与导出链路:只支持 8-bit maskid 图导入,非法/全背景图明确拒绝,尺寸自动适配,高精度 polygon 回显;统一导出默认当前帧,GT_label 使用 uint8 和真实 maskid,待分类 maskid 0 与背景一致。

- 完善分割工作区交互:新增画笔和橡皮擦并支持尺寸控制,移除创建点/线段入口,工具栏按类别分隔,AI 智能分割使用明确 AI 图标,取消黄色 seed point,清空/删除传播 mask 后同步清理空帧时间轴状态。

- 完善传播与时间轴:自动传播使用 SAM 2.1 权重任务,参考帧无遮罩时提示,传播历史按同一蓝色系递进变暗,删除/清空传播链时保留人工或独立 AI 标注来源。

- 完善模板库:新增头颈部 CT 分割默认模板,所有模板保留 maskid 0 待分类,支持鼠标复制模板、拖拽层级、JSON 批量导入预览、删除 label 和站内删除确认。

- 完善用户与高风险确认:用户改密码、删除用户、恢复演示出厂设置和清空人工/AI 标注帧均改为站内确认交互,避免浏览器原生 prompt/confirm。

- 补充前后端测试与文档:更新项目、模板、GT 导入、导出、传播、DICOM、用户管理等测试,并同步 README、AGENTS 和 doc 下实现/契约/测试计划文档。
2026-05-03 17:11:59 +08:00

92 lines
3.4 KiB
Python

def test_template_crud_packs_and_unpacks_mapping_rules(client):
payload = {
"name": "Template",
"color": "#06b6d4",
"z_index": 0,
"classes": [{"id": "c1", "name": "胆囊", "color": "#ff0000", "zIndex": 10}],
"rules": [{"id": "r1", "name": "rule"}],
}
created = client.post("/api/templates", json=payload)
assert created.status_code == 201
template_id = created.json()["id"]
assert created.json()["classes"][0]["name"] == "胆囊"
assert created.json()["rules"][0]["id"] == "r1"
listing = client.get("/api/templates")
assert listing.status_code == 200
assert listing.json()[0]["classes"][0]["name"] == "胆囊"
detail = client.get(f"/api/templates/{template_id}")
assert detail.status_code == 200
assert detail.json()["name"] == "Template"
updated = client.patch(f"/api/templates/{template_id}", json={
"classes": [{"id": "c2", "name": "肝脏", "color": "#00ff00", "zIndex": 20}],
"rules": [],
})
assert updated.status_code == 200
assert updated.json()["classes"][0]["name"] == "肝脏"
deleted = client.delete(f"/api/templates/{template_id}")
assert deleted.status_code == 204
assert client.get(f"/api/templates/{template_id}").status_code == 404
def test_template_404s(client):
assert client.get("/api/templates/999").status_code == 404
assert client.patch("/api/templates/999", json={"name": "x"}).status_code == 404
assert client.delete("/api/templates/999").status_code == 404
def test_default_head_neck_ct_template_is_seeded_and_visible(client, db_session):
from main import ensure_default_templates
from models import Template
ensure_default_templates(db_session)
ensure_default_templates(db_session)
templates = db_session.query(Template).filter(Template.owner_user_id.is_(None)).all()
names = [template.name for template in templates]
assert names.count("头颈部CT分割") == 1
listing = client.get("/api/templates")
assert listing.status_code == 200
head_neck = next(template for template in listing.json() if template["name"] == "头颈部CT分割")
assert head_neck["description"] == "头颈部CT分割"
expected_names = [
"肿瘤/结节 (Tumor/Nodule)",
"下颌骨 (Mandible)",
"甲状腺 (Thyroid)",
"气管 (Trachea)",
"颈椎 (Cervical Spine)",
"颈动脉 (Carotid Artery)",
"颈静脉 (Jugular Vein)",
"腮腺 (Parotid Gland)",
"下颌下腺 (Submandibular Gland)",
"舌骨 (Hyoid Bone)",
"待分类",
]
expected_colors = [
"#ff0000",
"#00ff00",
"#0000ff",
"#ffff00",
"#ff00ff",
"#00ffff",
"#ff8000",
"#800080",
"#008080",
"#808000",
"#000000",
]
actual_names = [item["name"] for item in head_neck["classes"]]
actual_colors = [item["color"] for item in head_neck["classes"]]
actual_mask_ids = [item["maskId"] for item in head_neck["classes"]]
if actual_names != expected_names:
raise AssertionError(f"Unexpected head-neck classes: {actual_names}")
if actual_colors != expected_colors:
raise AssertionError(f"Unexpected head-neck colors: {actual_colors}")
if actual_mask_ids != [*list(range(1, 11)), 0]:
raise AssertionError(f"Unexpected head-neck mask IDs: {actual_mask_ids}")