def test_tree_shape(client): tree = client.get("/api/tree").json() assert [f["name"] for f in tree] == ["업무", "개인"] work = tree[0] biz = next(p for p in work["projects"] if p["id"] == "biz") assert {c["id"] for c in biz["children"]} == {"biz-okr", "biz-report", "biz-budget"} assert biz["task_count"] >= biz["children"][0]["task_count"] # 재귀 합 def test_project_crud(client): created = client.post("/api/projects", json={"folder_id": "work", "name": "새 프로젝트"}).json() pid = created["id"] client.patch(f"/api/projects/{pid}", json={"name": "이름변경"}) assert client.post(f"/api/projects/{pid}/pin").json()["pinned"] is True assert client.delete(f"/api/projects/{pid}").json()["deleted"] == pid def test_folder_system_protected(client): # system 폴더(work)는 삭제 불가 r = client.delete("/api/folders/work") assert r.status_code == 400 def test_project_cycle_move_blocked(client): # biz 를 자기 자식(biz-okr) 아래로 이동 시도 → 400 r = client.patch("/api/projects/biz", json={"parent_id": "biz-okr"}) assert r.status_code == 400