Files

157 lines
5.8 KiB
Python

"""对话修改闭环 e2e:生成 → 换色 → 改标题 → 改页内容 → 两版本/下载验证。
用法:python tests/e2e_chat.py
"""
import json
import os
import subprocess
import sys
import time
import urllib.request
import urllib.error
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
BASE = "http://127.0.0.1:5098"
USER = f"chat_e2e_{int(time.time())}"
PASS = "chat_e2e_123"
SAMPLE = "# 项目背景\n为提升内部知识周转效率,启动知识库平台建设\n已完成技术选型与原型验证\n# 本期成果\n部署完成基础服务\n导入文档120份\n"
COOKIE = {"value": ""}
def call(method, path, payload=None, raw=False):
url = BASE + path
data = None if payload is None else json.dumps(payload).encode("utf-8")
req = urllib.request.Request(url, data=data, method=method)
if payload is not None:
req.add_header("Content-Type", "application/json")
if COOKIE["value"]:
req.add_header("Cookie", COOKIE["value"])
try:
with urllib.request.urlopen(req, timeout=120) as resp:
body = resp.read()
sc = resp.headers.get("Set-Cookie")
if sc and not COOKIE["value"]:
COOKIE["value"] = sc.split(";")[0]
return resp.status, (body if raw else json.loads(body or b"{}"))
except urllib.error.HTTPError as e:
body = e.read()
try:
parsed = json.loads(body or b"{}")
except Exception:
parsed = {"raw": body.decode("utf-8", "ignore")}
sc = e.headers.get("Set-Cookie")
if sc and not COOKIE["value"]:
COOKIE["value"] = sc.split(";")[0]
return e.code, parsed
def main():
failures = []
def check(name, cond, extra=""):
print(f" [{'OK' if cond else 'NG'}] {name} {extra}")
if not cond:
failures.append(name)
env = {**os.environ, "PYTHONIOENCODING": "utf-8"}
subprocess.run([sys.executable, "-m", "src.db.init"], cwd=str(ROOT),
capture_output=True, env=env)
proc = subprocess.Popen(
[sys.executable, "-c",
f"import sys; sys.path.insert(0, r'{ROOT}');"
"from src.web.app import app; app.run(host='127.0.0.1', port=5098)"],
cwd=str(ROOT), env=env, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL,
)
try:
up = False
for _ in range(30):
time.sleep(0.5)
try:
call("GET", "/api/me")
up = True
break
except Exception:
continue
check("server up", up)
s, b = call("POST", "/api/register",
{"username": USER, "password": PASS, "confirm_password": PASS})
check("register", s == 200 and b.get("code") == 0)
s, b = call("POST", "/api/generate", {
"title": "对话修改测试", "content": SAMPLE,
"scene": "report", "language": "zh", "canvas": "ppt169",
"image_strategy": "off", "color_scheme": "blue",
"page_min": 5, "page_max": 8,
})
check("generate accepted", b.get("code") == 0, str(b)[:60])
task_id = b["data"]["task_id"]
for _ in range(120):
time.sleep(1)
s, b = call("GET", f"/api/generate/{task_id}/status")
if b["data"]["status"] in ("done", "failed"):
break
check("generation done", b["data"]["status"] == "done", str(b)[:80])
s, b = call("GET", f"/api/generate/{task_id}/result")
rid = b["data"]["record"]["id"]
check("record ready", bool(rid), f"rid={rid}")
def chat(msg):
return call("POST", "/api/chat", {"record_id": rid, "message": msg})
s, b = chat("换成绿色")
d = b.get("data") or {}
check("change color", d.get("changed") is True, str(d.get("reply", ""))[:60])
check("record color updated", (d.get("record") or {}).get("color_scheme") == "green")
s, b = chat('把标题改成"知识平台周报"')
d = b.get("data") or {}
check("change title", d.get("changed") is True
and (d.get("record") or {}).get("title") == "知识平台周报",
str(d.get("reply", ""))[:60])
s, b = chat('把"知识周转"改成"信息流转"')
d = b.get("data") or {}
check("edit page replace", d.get("changed") is True, str(d.get("reply", ""))[:60])
s, b = chat("今天天气怎么样")
d = b.get("data") or {}
check("unknown intent no change", d.get("changed") is False
and "不支持" in d.get("reply", ""), str(d.get("reply", ""))[:50])
s, b = call("GET", f"/api/records/{rid}")
versions = b["data"]["versions"]
check("two versions kept", len(versions) == 2 and versions[0]["version_no"] == 1,
f"n={len(versions)}")
s, b = call("GET", f"/api/chat/{rid}/messages")
msgs = b["data"]["messages"]
check("messages logged", len(msgs) == 8, f"n={len(msgs)}")
s, raw = call("GET", f"/api/files/{rid}/download", raw=True)
check("download ok", s == 200 and raw[:2] == b"PK", f"{len(raw)}B")
p = ROOT / "tests" / "_chat_download.pptx"
p.write_bytes(raw)
from pptx import Presentation
prs = Presentation(str(p))
texts = "\n".join(sh.text_frame.text for sl in prs.slides
for sh in sl.shapes if sh.has_text_frame)
check("new title in pptx", "知识平台周报" in texts)
check("edited text in pptx", "信息流转" in texts and "知识周转" not in texts)
p.unlink()
finally:
proc.terminate()
print("\n" + ("CHAT E2E ALL PASSED" if not failures
else "FAILURES: " + "; ".join(failures)))
sys.exit(1 if failures else 0)
if __name__ == "__main__":
main()