Files
kandev/apps/web/lib/tasks/task-menu-target.test.ts
T
2026-09-22 23:31:49 +01:00

74 lines
2.4 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { createAppStore } from "@/lib/state/store";
import { resolveTaskMenuTarget } from "./task-menu-target";
const identity = { taskId: "A", workspaceId: "workspace" };
function fixture(
loss?: string,
workspaceMode?: "inherit_parent" | "new_workspace" | "shared_group",
) {
const store = createAppStore();
store.setState((state) => ({
workspaces: { ...state.workspaces, activeId: loss === "workspace" ? "elsewhere" : "workspace" },
workflows: {
...state.workflows,
items:
loss === "workflow" ? [] : [{ id: "workflow", name: "Flow", workspaceId: "workspace" }],
},
kanbanMulti: {
...state.kanbanMulti,
snapshots: {
workflow: {
workflowId: "workflow",
workflowName: "Flow",
steps: [],
tasks:
loss === "missing"
? []
: [
{
id: "A",
title: "Renamed",
workflowId: "workflow",
workflowStepId: "step",
position: 0,
priority: "high",
isArchived: loss === "archived",
primaryExecutorType: "worktree",
workspaceMode,
},
],
},
},
},
}));
return store;
}
describe("task menu eligibility", () => {
// @covers AC-TASKS-THREADS-ACTIONS-002.1, AC-TASKS-THREADS-ACTIONS-002.2
it("resolves live A metadata independently of selected B/session", () => {
const store = fixture();
store.getState().setActiveSession("B", "session-B");
const state = store.getState();
expect(resolveTaskMenuTarget(state, identity)).toMatchObject({
id: "A",
title: "Renamed",
priority: "high",
remoteExecutorType: "worktree",
workspaceId: "workspace",
});
});
it.each(["workspace", "missing", "archived", "workflow"] as const)(
"fails closed on %s loss",
(loss) => {
const state = fixture(loss).getState();
expect(resolveTaskMenuTarget(state, identity)).toBeNull();
},
);
it("carries the task workspace mode into the management target", () => {
const state = fixture(undefined, "inherit_parent").getState();
expect(resolveTaskMenuTarget(state, identity)?.workspaceMode).toBe("inherit_parent");
});
});