feat(web): 项目级配置 + 会话命名/历史 + 设计文档纳入影响调查
- 会话支持 name/project 字段,上传要件定义后自动命名;前端侧边栏会话历史 + localStorage 恢复,顶部只显示会话名 - 新增 ProjectsStore(SQLite)与 /api/projects CRUD;绑定项目后 _rebuild_source 合并模板/规则/代码库/设计文档,上传区仅要件定义 - StructuredSource.design_docs 与 ImpactReport.design_references;影响调查新增既有设计文档确定性交叉引用(无 LLM) - 同步更新 docs/design.md §12.7、README、_AI_USAGE_LOG.md;全量测试 558 通过,覆盖率 99.10%
This commit is contained in:
@@ -279,3 +279,71 @@ def test_real_mode_generate_without_key_500(tmp_path, monkeypatch):
|
||||
client.post(f"/api/sessions/{sid}/confirm-parse")
|
||||
r = client.post(f"/api/sessions/{sid}/generate", json={})
|
||||
assert r.status_code == 500
|
||||
|
||||
|
||||
# ---------- 项目配置(S6) ----------
|
||||
|
||||
def test_create_and_list_projects(client):
|
||||
body = {
|
||||
"name": "stock", "display_name": "股票系统",
|
||||
"template": str(_SAMPLE / "template_design_ja.docx"),
|
||||
"write_instruction": "", "rules": [],
|
||||
"existing_system_code_dir": "", "design_docs_dir": "",
|
||||
}
|
||||
r = client.post("/api/projects", json=body)
|
||||
assert r.status_code == 200
|
||||
assert r.json()["name"] == "stock"
|
||||
lst = client.get("/api/projects").json()
|
||||
assert any(p["name"] == "stock" for p in lst)
|
||||
one = client.get("/api/projects/stock").json()
|
||||
assert one["template"] == str(_SAMPLE / "template_design_ja.docx")
|
||||
|
||||
|
||||
def test_project_invalid_template_400(client):
|
||||
r = client.post("/api/projects", json={"name": "p", "template": "/no/such.docx"})
|
||||
assert r.status_code == 400
|
||||
assert r.json()["detail"]["code"] == "PROJECT_CONFIG_INVALID"
|
||||
|
||||
|
||||
def test_delete_project(client):
|
||||
client.post("/api/projects", json={"name": "p", "template": str(_SAMPLE / "template_design_ja.docx")})
|
||||
assert client.delete("/api/projects/p").json()["deleted"] is True
|
||||
assert client.get("/api/projects/p").status_code == 404
|
||||
|
||||
|
||||
def test_session_accepts_name_and_project(client):
|
||||
r = client.post("/api/sessions", json={"user_id": "u1", "name": "我的会话", "project": "projA"})
|
||||
assert r.status_code == 200
|
||||
sid = r.json()["session_id"]
|
||||
assert r.json()["name"] == "我的会话"
|
||||
g = client.get(f"/api/sessions/{sid}").json()
|
||||
assert g["name"] == "我的会话"
|
||||
assert g["project"] == "projA"
|
||||
|
||||
|
||||
def test_session_list_includes_name_project(client):
|
||||
client.post("/api/sessions", json={"user_id": "u1", "name": "n1", "project": "pA"})
|
||||
r = client.get("/api/sessions", params={"user_id": "u1"}).json()
|
||||
assert any(s["name"] == "n1" and s["project"] == "pA" for s in r)
|
||||
|
||||
|
||||
def test_generate_with_project_config_no_template_upload(client):
|
||||
"""绑定项目(含模板/规则)后,仅上传要件定义即可解析生成。"""
|
||||
client.post("/api/projects", json={
|
||||
"name": "projA", "template": str(_SAMPLE / "template_design_ja.docx"),
|
||||
"write_instruction": str(_SAMPLE / "rules_design_ja.docx"),
|
||||
"rules": [str(_SAMPLE / "rules_entry_ja.docx")],
|
||||
"existing_system_code_dir": "", "design_docs_dir": "",
|
||||
})
|
||||
sid = client.post("/api/sessions", json={"user_id": "u1", "project": "projA"}).json()["session_id"]
|
||||
# 仅上传要件定义
|
||||
r = client.post(f"/api/sessions/{sid}/files", data={"file_type": "requirements"},
|
||||
files={"file": ("requirements_newdev.xlsx", (_SAMPLE / "requirements_newdev.xlsx").read_bytes())})
|
||||
assert r.status_code == 200
|
||||
p = client.post(f"/api/sessions/{sid}/start-parse")
|
||||
assert p.status_code == 200, p.text
|
||||
assert client.post(f"/api/sessions/{sid}/confirm-parse").status_code == 200
|
||||
# 无既有系统 → 直接 writing,可生成
|
||||
gen = client.post(f"/api/sessions/{sid}/generate", json={})
|
||||
assert gen.status_code == 200, gen.text
|
||||
assert client.get(f"/api/sessions/{sid}/result/download").status_code == 200
|
||||
|
||||
Reference in New Issue
Block a user