fix: move folder creation into project move flow

This commit is contained in:
2026-07-13 17:05:45 +08:00
parent 2f0e0f2cd7
commit 2211beb42c
4 changed files with 144 additions and 17 deletions
+48 -2
View File
@@ -325,6 +325,52 @@ describe("trigger full lifecycle (integration)", () => {
expect(cardHeaderTitle(rt.sentPatches.at(-1))).toBe("项目名称已更新");
});
it("offers folder creation only inside move flow and atomically moves into the new folder", async () => {
await seedProject("project-folder-flow", "chat-folder-flow", { role: "MANAGE" });
await prisma.organizationMembership.updateMany({
where: { organizationId: DEFAULT_ORG_ID, userId: "u_project-folder-flow", revokedAt: null },
data: { role: "ADMIN" },
});
const parent = await prisma.folder.create({
data: { organizationId: DEFAULT_ORG_ID, name: "课程目录" },
});
const trigger = makeTriggerHandler({ prisma, settings, logger: silentLogger, runAgent });
await trigger(makeEvent("chat-folder-flow", "@_user_1 /project"), rt);
expect(JSON.stringify(rt.sentCards.at(-1))).not.toContain("folder_create_form");
await trigger.onCardAction(makeOnboardingEvent("chat-folder-flow", {
project_onboarding: {
action: "browse_move_destination",
organization_id: DEFAULT_ORG_ID,
project_id: "project-folder-flow",
folder_id: parent.id,
},
}, "ou_test_user"), rt);
const moveCard = JSON.stringify(rt.sentPatches.at(-1));
expect(moveCard).toContain("folder_create_form");
expect(moveCard).toContain("新建并移动");
await trigger.onCardAction(makeOnboardingEvent("chat-folder-flow", {
project_onboarding: {
action: "create_folder",
organization_id: DEFAULT_ORG_ID,
project_id: "project-folder-flow",
folder_id: parent.id,
},
}, "ou_test_user", { folder_name: "力学单元" }), rt);
const folder = await prisma.folder.findFirstOrThrow({
where: { organizationId: DEFAULT_ORG_ID, parentId: parent.id, name: "力学单元" },
});
await expect(prisma.project.findUniqueOrThrow({ where: { id: "project-folder-flow" } }))
.resolves.toMatchObject({ folderId: folder.id });
await expect(prisma.auditEntry.findFirstOrThrow({
where: { projectId: "project-folder-flow", action: "folder.created_and_project_moved_from_feishu" },
})).resolves.toMatchObject({ metadata: expect.objectContaining({ folderId: folder.id, parentFolderId: parent.id }) });
expect(cardHeaderTitle(rt.sentPatches.at(-1))).toContain("已新建目录");
});
it("binds an existing manageable project from the unbound-chat onboarding card", async () => {
await seedOnboardingUser("u-onboard-bind", "ou_onboard_bind", "MEMBER");
await prisma.project.create({
@@ -660,11 +706,11 @@ describe("trigger full lifecycle (integration)", () => {
await vi.waitFor(async () => {
expect(await prisma.agentRun.count({ where: { projectId: "proj-batch-role", status: "COMPLETED" } })).toBe(2);
});
}, { timeout: 5_000 });
const runs = await prisma.agentRun.findMany({ where: { projectId: "proj-batch-role" } });
expect(runs.find((run) => run.prompt.includes("草稿消息"))?.metadata).toMatchObject({ roleId: "draft" });
expect(runs.find((run) => run.prompt.includes("审校消息"))?.metadata).toMatchObject({ roleId: "review" });
});
}, 10_000);
it("keeps the project session shared while labeling each sender in the prompt", async () => {
await seedProject("proj-speaker", "chat-speaker");