mirror of
https://mirror.skon.top/github.com/cft0808/edict
synced 2026-04-30 22:10:34 +08:00
210 lines
7.4 KiB
Python
210 lines
7.4 KiB
Python
"""tests for scripts/kanban_update.py"""
|
|
import json
|
|
import pathlib
|
|
import sys
|
|
|
|
# Ensure scripts/ is importable
|
|
SCRIPTS = pathlib.Path(__file__).resolve().parent.parent / "scripts"
|
|
sys.path.insert(0, str(SCRIPTS))
|
|
|
|
import kanban_update as kb
|
|
|
|
|
|
def test_create_and_get(tmp_path):
|
|
"""kanban create + get round-trip."""
|
|
tasks_file = tmp_path / "tasks_source.json"
|
|
tasks_file.write_text("[]", encoding="utf-8")
|
|
|
|
original = kb.TASKS_FILE
|
|
kb.TASKS_FILE = tasks_file
|
|
try:
|
|
kb.cmd_create("TEST-001", "测试任务创建和查询功能验证", "Inbox", "工部", "工部尚书")
|
|
tasks = json.loads(tasks_file.read_text(encoding="utf-8"))
|
|
assert any(t.get("id") == "TEST-001" for t in tasks)
|
|
task = next(t for t in tasks if t["id"] == "TEST-001")
|
|
assert task["title"] == "测试任务创建和查询功能验证"
|
|
assert task["state"] == "Inbox"
|
|
assert task["org"] == "工部"
|
|
finally:
|
|
kb.TASKS_FILE = original
|
|
|
|
|
|
def test_move_state(tmp_path):
|
|
"""kanban move changes task state."""
|
|
tasks_file = tmp_path / "tasks_source.json"
|
|
tasks_file.write_text(json.dumps([
|
|
{"id": "T-1", "title": "test", "state": "Inbox"}
|
|
], ensure_ascii=False), encoding="utf-8")
|
|
|
|
original = kb.TASKS_FILE
|
|
kb.TASKS_FILE = tasks_file
|
|
try:
|
|
kb.cmd_state("T-1", "Doing")
|
|
tasks = json.loads(tasks_file.read_text(encoding="utf-8"))
|
|
assert tasks[0]["state"] == "Doing"
|
|
finally:
|
|
kb.TASKS_FILE = original
|
|
|
|
|
|
def test_block_and_unblock(tmp_path):
|
|
"""kanban block round-trip."""
|
|
tasks_file = tmp_path / "tasks_source.json"
|
|
tasks_file.write_text(json.dumps([
|
|
{"id": "T-2", "title": "blocker test", "state": "Doing"}
|
|
], ensure_ascii=False), encoding="utf-8")
|
|
|
|
original = kb.TASKS_FILE
|
|
kb.TASKS_FILE = tasks_file
|
|
try:
|
|
kb.cmd_block("T-2", "等待依赖")
|
|
tasks = json.loads(tasks_file.read_text(encoding="utf-8"))
|
|
assert tasks[0]["state"] == "Blocked"
|
|
assert tasks[0]["block"] == "等待依赖"
|
|
finally:
|
|
kb.TASKS_FILE = original
|
|
|
|
|
|
def test_flow_log(tmp_path):
|
|
"""cmd_flow appends a flow_log entry."""
|
|
tasks_file = tmp_path / "tasks_source.json"
|
|
tasks_file.write_text(json.dumps([
|
|
{"id": "T-3", "title": "flow test", "state": "Zhongshu", "flow_log": []}
|
|
], ensure_ascii=False), encoding="utf-8")
|
|
|
|
original = kb.TASKS_FILE
|
|
kb.TASKS_FILE = tasks_file
|
|
try:
|
|
kb.cmd_flow("T-3", "中书省", "门下省", "规划方案提交审议")
|
|
tasks = json.loads(tasks_file.read_text(encoding="utf-8"))
|
|
task = tasks[0]
|
|
assert len(task["flow_log"]) == 1
|
|
assert task["flow_log"][0]["from"] == "中书省"
|
|
assert task["flow_log"][0]["to"] == "门下省"
|
|
finally:
|
|
kb.TASKS_FILE = original
|
|
|
|
|
|
def test_done_routes_to_review(tmp_path):
|
|
"""cmd_done should route execution output back to Review instead of direct Done."""
|
|
tasks_file = tmp_path / "tasks_source.json"
|
|
tasks_file.write_text(json.dumps([
|
|
{
|
|
"id": "T-4",
|
|
"title": "done test",
|
|
"state": "Doing",
|
|
"org": "兵部",
|
|
"flow_log": [],
|
|
"todos": [{"id": "1", "title": "收尾", "status": "completed"}],
|
|
}
|
|
], ensure_ascii=False), encoding="utf-8")
|
|
|
|
original = kb.TASKS_FILE
|
|
kb.TASKS_FILE = tasks_file
|
|
try:
|
|
kb.cmd_done("T-4", "/tmp/output.md", "功能已全部实现")
|
|
tasks = json.loads(tasks_file.read_text(encoding="utf-8"))
|
|
task = tasks[0]
|
|
assert task["state"] == "Review"
|
|
assert task["org"] == "尚书省"
|
|
assert task["output"] == "/tmp/output.md"
|
|
assert task["now"] == "功能已全部实现"
|
|
assert any("提交审查" in entry.get("remark", "") for entry in task["flow_log"])
|
|
finally:
|
|
kb.TASKS_FILE = original
|
|
|
|
|
|
def test_done_rejects_incomplete_todos(tmp_path):
|
|
"""cmd_done should be rejected when todos are still incomplete."""
|
|
tasks_file = tmp_path / "tasks_source.json"
|
|
tasks_file.write_text(json.dumps([
|
|
{
|
|
"id": "T-4B",
|
|
"title": "done gate test",
|
|
"state": "Doing",
|
|
"org": "工部",
|
|
"flow_log": [],
|
|
"todos": [
|
|
{"id": "1", "title": "已完成", "status": "completed"},
|
|
{"id": "2", "title": "未完成", "status": "in-progress"},
|
|
],
|
|
}
|
|
], ensure_ascii=False), encoding="utf-8")
|
|
|
|
original = kb.TASKS_FILE
|
|
kb.TASKS_FILE = tasks_file
|
|
try:
|
|
kb.cmd_done("T-4B", "/tmp/output.md", "试图提前收口")
|
|
tasks = json.loads(tasks_file.read_text(encoding="utf-8"))
|
|
task = tasks[0]
|
|
assert task["state"] == "Doing"
|
|
assert task.get("output", "") in ("", None)
|
|
assert task.get("flow_log", []) == []
|
|
finally:
|
|
kb.TASKS_FILE = original
|
|
|
|
|
|
def test_progress(tmp_path):
|
|
"""cmd_progress updates now text and appends to progress_log."""
|
|
tasks_file = tmp_path / "tasks_source.json"
|
|
tasks_file.write_text(json.dumps([
|
|
{"id": "T-5", "title": "progress test", "state": "Doing", "org": "工部"}
|
|
], ensure_ascii=False), encoding="utf-8")
|
|
|
|
original = kb.TASKS_FILE
|
|
kb.TASKS_FILE = tasks_file
|
|
try:
|
|
kb.cmd_progress("T-5", "正在实现核心模块", "已完成需求分析✅|正在写代码🔄|待测试")
|
|
tasks = json.loads(tasks_file.read_text(encoding="utf-8"))
|
|
task = tasks[0]
|
|
assert task["now"] == "正在实现核心模块"
|
|
assert len(task.get("progress_log", [])) == 1
|
|
todos = task.get("todos", [])
|
|
assert len(todos) == 3
|
|
statuses = {td["title"]: td["status"] for td in todos}
|
|
assert statuses["已完成需求分析"] == "completed"
|
|
assert statuses["正在写代码"] == "in-progress"
|
|
assert statuses["待测试"] == "not-started"
|
|
finally:
|
|
kb.TASKS_FILE = original
|
|
|
|
|
|
def test_todo(tmp_path):
|
|
"""cmd_todo adds and updates sub-tasks."""
|
|
tasks_file = tmp_path / "tasks_source.json"
|
|
tasks_file.write_text(json.dumps([
|
|
{"id": "T-6", "title": "todo test", "state": "Doing"}
|
|
], ensure_ascii=False), encoding="utf-8")
|
|
|
|
original = kb.TASKS_FILE
|
|
kb.TASKS_FILE = tasks_file
|
|
try:
|
|
kb.cmd_todo("T-6", "1", "实现登录接口", "in-progress")
|
|
kb.cmd_todo("T-6", "2", "编写测试", "not-started")
|
|
kb.cmd_todo("T-6", "1", "", "completed")
|
|
tasks = json.loads(tasks_file.read_text(encoding="utf-8"))
|
|
task = tasks[0]
|
|
todos = {td["id"]: td for td in task.get("todos", [])}
|
|
assert todos["1"]["status"] == "completed"
|
|
assert todos["2"]["status"] == "not-started"
|
|
finally:
|
|
kb.TASKS_FILE = original
|
|
|
|
|
|
def test_progress_log_capped(tmp_path):
|
|
"""progress_log should not exceed MAX_PROGRESS_LOG entries."""
|
|
tasks_file = tmp_path / "tasks_source.json"
|
|
tasks_file.write_text(json.dumps([
|
|
{"id": "T-7", "title": "日志上限测试", "state": "Doing", "org": "礼部"}
|
|
], ensure_ascii=False), encoding="utf-8")
|
|
|
|
original = kb.TASKS_FILE
|
|
kb.TASKS_FILE = tasks_file
|
|
try:
|
|
for i in range(kb.MAX_PROGRESS_LOG + 5):
|
|
kb.cmd_progress("T-7", f"第{i}次进展汇报内容,描述当前执行情况")
|
|
tasks = json.loads(tasks_file.read_text(encoding="utf-8"))
|
|
task = tasks[0]
|
|
assert len(task.get("progress_log", [])) == kb.MAX_PROGRESS_LOG
|
|
finally:
|
|
kb.TASKS_FILE = original
|