Files
kandev/apps/web/lib/kanban/resolve-workflow.test.ts
T
2026-07-25 19:30:52 +01:00

179 lines
5.4 KiB
TypeScript

import { describe, it, expect } from "vitest";
import {
resolveBoardWorkflowId,
resolveBoardWorkflowSteps,
resolveDesiredWorkflowId,
} from "./resolve-workflow";
import type { WorkflowsState } from "@/lib/state/slices";
type Workflow = WorkflowsState["items"][number];
function workflow(id: string, overrides: Partial<Workflow> = {}): Workflow {
return { id, workspaceId: "ws-1", name: id, ...overrides };
}
describe("resolveDesiredWorkflowId", () => {
it("keeps the currently active workflow when it is still visible", () => {
const result = resolveDesiredWorkflowId({
activeWorkflowId: "wf-2",
settingsWorkflowId: "wf-1",
workspaceWorkflows: [workflow("wf-1"), workflow("wf-2")],
});
expect(result).toBe("wf-2");
});
it("falls back to the persisted settings workflow when active is missing", () => {
const result = resolveDesiredWorkflowId({
activeWorkflowId: null,
settingsWorkflowId: "wf-1",
workspaceWorkflows: [workflow("wf-1"), workflow("wf-2")],
});
expect(result).toBe("wf-1");
});
// Regression: c64e835 forced fallback to the first visible workflow when
// both active and settings ids were null, making "All Workflows" impossible
// to select with multiple workflows present.
it("returns null when the user has cleared the filter and multiple workflows exist", () => {
const result = resolveDesiredWorkflowId({
activeWorkflowId: null,
settingsWorkflowId: null,
workspaceWorkflows: [workflow("wf-1"), workflow("wf-2"), workflow("wf-3")],
});
expect(result).toBeNull();
});
it("preserves All Workflows when exactly one workflow is visible", () => {
const result = resolveDesiredWorkflowId({
activeWorkflowId: null,
settingsWorkflowId: null,
workspaceWorkflows: [workflow("wf-only")],
});
expect(result).toBeNull();
});
it("ignores hidden workflows when preserving an empty filter", () => {
const result = resolveDesiredWorkflowId({
activeWorkflowId: null,
settingsWorkflowId: null,
workspaceWorkflows: [workflow("wf-1", { hidden: true }), workflow("wf-2")],
});
expect(result).toBeNull();
});
it("does not honor an active id that is no longer visible", () => {
const result = resolveDesiredWorkflowId({
activeWorkflowId: "wf-stale",
settingsWorkflowId: "wf-1",
workspaceWorkflows: [workflow("wf-1"), workflow("wf-2")],
});
expect(result).toBe("wf-1");
});
it("returns null when no workflows are visible", () => {
const result = resolveDesiredWorkflowId({
activeWorkflowId: null,
settingsWorkflowId: null,
workspaceWorkflows: [],
});
expect(result).toBeNull();
});
it("returns null when active id is stale and settings id is also null", () => {
const result = resolveDesiredWorkflowId({
activeWorkflowId: "wf-stale",
settingsWorkflowId: null,
workspaceWorkflows: [workflow("wf-1"), workflow("wf-2")],
});
expect(result).toBeNull();
});
it("does not fall back to a hidden settings workflow", () => {
const result = resolveDesiredWorkflowId({
activeWorkflowId: null,
settingsWorkflowId: "wf-hidden",
workspaceWorkflows: [workflow("wf-hidden", { hidden: true }), workflow("wf-visible")],
});
expect(result).toBeNull();
});
});
describe("resolveBoardWorkflowId", () => {
it("uses the selected mobile workflow before its snapshot hydrates", () => {
expect(
resolveBoardWorkflowId({
isMobile: true,
selectedWorkflowId: "wf-new",
focusedWorkflowId: "wf-new",
hydratedWorkflowId: "wf-old",
}),
).toBe("wf-new");
});
it("uses the focused workflow for the mobile All-workflows view", () => {
expect(
resolveBoardWorkflowId({
isMobile: true,
selectedWorkflowId: null,
focusedWorkflowId: "wf-focused",
hydratedWorkflowId: null,
}),
).toBe("wf-focused");
});
it("keeps desktop actions tied to the hydrated workflow", () => {
expect(
resolveBoardWorkflowId({
isMobile: false,
selectedWorkflowId: "wf-selected",
focusedWorkflowId: "wf-focused",
hydratedWorkflowId: "wf-hydrated",
}),
).toBe("wf-hydrated");
});
});
describe("resolveBoardWorkflowSteps", () => {
const oldSteps = [{ id: "old-step", position: 0 }];
it("does not reuse steps from a previously hydrated workflow", () => {
expect(
resolveBoardWorkflowSteps({
effectiveWorkflowId: "wf-new",
hydratedWorkflowId: "wf-old",
snapshots: {},
activeSteps: oldSteps,
}),
).toEqual([]);
});
it("uses active steps when they belong to the effective workflow", () => {
expect(
resolveBoardWorkflowSteps({
effectiveWorkflowId: "wf-old",
hydratedWorkflowId: "wf-old",
snapshots: {},
activeSteps: oldSteps,
}),
).toBe(oldSteps);
});
it("sorts steps from the effective workflow snapshot", () => {
expect(
resolveBoardWorkflowSteps({
effectiveWorkflowId: "wf-new",
hydratedWorkflowId: "wf-old",
snapshots: {
"wf-new": {
steps: [
{ id: "later", position: 2 },
{ id: "first", position: 0 },
],
},
},
activeSteps: oldSteps,
}).map((step) => step.id),
).toEqual(["first", "later"]);
});
});