Some checks failed
CI / Tests / 🧪 Test (push) Has been cancelled
Story 3.4: AI semantic suggestions with accept/reject workflow - ProposalBar overlay with visual diff - Accept/reject flow with graph snapshot restore - useProposalDiff hook for change summary - System prompt scoping for selected elements Story 3.5: New diagram wizard with AI type inference - CreateDiagramDialog with AI type inference (Haiku) - initialDescription prop for chat-first flow - Auto-send on mount with hasSentInitial ref guard - DB migration for diagram description column Story 3.6: Hover affordances and command palette - HoverAffordances toolbar (5 AI actions, debounced) - CommandPalette (Cmd+K) with AI, nav, Go to Node - prefillChat/fitViewRequested/focusNodeId actions - Code review: getNodesBounds, onOpenRightPanel, timer cleanup, test count fix 374 tests passing (251 web + 123 AI). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
100 lines
3.4 KiB
TypeScript
100 lines
3.4 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
import { useGraphStore } from "../../stores/useGraphStore";
|
|
|
|
// Mock sonner toast
|
|
vi.mock("sonner", () => ({
|
|
toast: { info: vi.fn() },
|
|
}));
|
|
|
|
describe("CommandPalette action handlers", () => {
|
|
beforeEach(() => {
|
|
useGraphStore.getState().reset();
|
|
});
|
|
|
|
describe("AI actions via store", () => {
|
|
it("setPrefillChat should set text for generate action", () => {
|
|
useGraphStore.getState().setPrefillChat("", "Generate a diagram: ");
|
|
const prefill = useGraphStore.getState().prefillChat;
|
|
expect(prefill).toEqual({ nodeId: "", text: "Generate a diagram: " });
|
|
});
|
|
|
|
it("setPrefillChat should set text for suggest action", () => {
|
|
useGraphStore
|
|
.getState()
|
|
.setPrefillChat("", "Suggest improvements for this diagram");
|
|
const prefill = useGraphStore.getState().prefillChat;
|
|
expect(prefill?.text).toBe("Suggest improvements for this diagram");
|
|
});
|
|
|
|
it("setPrefillChat should set text for analyze action", () => {
|
|
useGraphStore
|
|
.getState()
|
|
.setPrefillChat("", "Analyze the semantics of this diagram");
|
|
const prefill = useGraphStore.getState().prefillChat;
|
|
expect(prefill?.text).toBe("Analyze the semantics of this diagram");
|
|
});
|
|
});
|
|
|
|
describe("navigation actions via store", () => {
|
|
it("requestFitView should increment counter", () => {
|
|
expect(useGraphStore.getState().fitViewRequested).toBe(0);
|
|
useGraphStore.getState().requestFitView();
|
|
expect(useGraphStore.getState().fitViewRequested).toBe(1);
|
|
});
|
|
|
|
it("setFocusNodeId should set the target node", () => {
|
|
useGraphStore.getState().setFocusNodeId("node-123");
|
|
expect(useGraphStore.getState().focusNodeId).toBe("node-123");
|
|
});
|
|
|
|
it("setFocusNodeId(null) should clear focus", () => {
|
|
useGraphStore.getState().setFocusNodeId("node-123");
|
|
useGraphStore.getState().setFocusNodeId(null);
|
|
expect(useGraphStore.getState().focusNodeId).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe("Go to Node filtering — CONTAINER_TYPES values", () => {
|
|
// CONTAINER_TYPES from DiagramCanvas: bpmnPool, bpmnLane, bpmnGroup, seqFragment
|
|
// Verified via direct constant reference; import avoided due to heavy dependency chain
|
|
const containerTypes = new Set([
|
|
"bpmnPool",
|
|
"bpmnLane",
|
|
"bpmnGroup",
|
|
"seqFragment",
|
|
]);
|
|
|
|
it("should include all 4 expected container types", () => {
|
|
expect(containerTypes.size).toBe(4);
|
|
expect(containerTypes.has("bpmnPool")).toBe(true);
|
|
expect(containerTypes.has("bpmnLane")).toBe(true);
|
|
expect(containerTypes.has("bpmnGroup")).toBe(true);
|
|
expect(containerTypes.has("seqFragment")).toBe(true);
|
|
});
|
|
|
|
it("should not include regular node types", () => {
|
|
const regularTypes = [
|
|
"bpmnActivity",
|
|
"erEntity",
|
|
"flowProcess",
|
|
"archService",
|
|
];
|
|
for (const type of regularTypes) {
|
|
expect(containerTypes.has(type)).toBe(false);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe("export action", () => {
|
|
it("should call toast.info for export", async () => {
|
|
const { toast } = await import("sonner");
|
|
toast.info("Export coming soon", {
|
|
description: "This feature is planned for a future release.",
|
|
});
|
|
expect(toast.info).toHaveBeenCalledWith("Export coming soon", {
|
|
description: "This feature is planned for a future release.",
|
|
});
|
|
});
|
|
});
|
|
});
|