187 lines
5.4 KiB
JavaScript
187 lines
5.4 KiB
JavaScript
// The Lucia project.
|
|
// Copyright 2026-2026 DSP, inc. All rights reserved.
|
|
// Authors:
|
|
// imacat.yang@dsp.im (imacat), 2026/03/06
|
|
|
|
import { describe, it, expect, beforeEach, vi } from "vitest";
|
|
import { setActivePinia, createPinia } from "pinia";
|
|
|
|
// Mock allMapData store (used by createInsightWithPath / createPaths)
|
|
vi.mock("@/stores/allMapData", () => ({
|
|
default: () => ({ insights: {} }),
|
|
}));
|
|
|
|
// Mock SVG asset imports
|
|
vi.mock("@/assets/capsule1-glow.svg", () => ({ default: "glow1" }));
|
|
vi.mock("@/assets/capsule2-glow.svg", () => ({ default: "glow2" }));
|
|
vi.mock("@/assets/capsule3-glow.svg", () => ({ default: "glow3" }));
|
|
vi.mock("@/assets/capsule4-glow.svg", () => ({ default: "glow4" }));
|
|
vi.mock("@/assets/capsule1.svg", () => ({ default: "cap1" }));
|
|
vi.mock("@/assets/capsule2.svg", () => ({ default: "cap2" }));
|
|
vi.mock("@/assets/capsule3.svg", () => ({ default: "cap3" }));
|
|
vi.mock("@/assets/capsule4.svg", () => ({ default: "cap4" }));
|
|
|
|
import { useMapPathStore } from "@/stores/mapPathStore";
|
|
|
|
/**
|
|
* Creates a mock Cytoscape node.
|
|
*/
|
|
function mockNode(label, level = 0) {
|
|
const nodeData = { label, level, nodeImageUrl: "" };
|
|
const classes = new Set();
|
|
const node = {
|
|
data: vi.fn((key, value) => {
|
|
if (value !== undefined) {
|
|
nodeData[key] = value;
|
|
return node;
|
|
}
|
|
return nodeData[key];
|
|
}),
|
|
addClass: vi.fn((cls) => {
|
|
classes.add(cls);
|
|
return node;
|
|
}),
|
|
removeClass: vi.fn((cls) => {
|
|
classes.delete(cls);
|
|
return node;
|
|
}),
|
|
hasClass: (cls) => classes.has(cls),
|
|
outgoers: vi.fn(() => mockCollection([])),
|
|
incomers: vi.fn(() => mockCollection([])),
|
|
edgesTo: vi.fn(() => mockCollection([])),
|
|
edgesWith: vi.fn(() => mockCollection([])),
|
|
_nodeData: nodeData,
|
|
_classes: classes,
|
|
};
|
|
return node;
|
|
}
|
|
|
|
/**
|
|
* Creates a mock Cytoscape edge.
|
|
*/
|
|
function mockEdge() {
|
|
const classes = new Set();
|
|
const edge = {
|
|
addClass: vi.fn((cls) => {
|
|
classes.add(cls);
|
|
return edge;
|
|
}),
|
|
removeClass: vi.fn((cls) => {
|
|
classes.delete(cls);
|
|
return edge;
|
|
}),
|
|
source: vi.fn(() => mockNode("src")),
|
|
target: vi.fn(() => mockNode("tgt")),
|
|
_classes: classes,
|
|
};
|
|
return edge;
|
|
}
|
|
|
|
/**
|
|
* Creates a mock Cytoscape collection.
|
|
*/
|
|
function mockCollection(items) {
|
|
const col = {
|
|
forEach: (fn) => items.forEach(fn),
|
|
map: (fn) => items.map(fn),
|
|
filter: (fn) => mockCollection(items.filter(fn)),
|
|
addClass: vi.fn(() => col),
|
|
removeClass: vi.fn(() => col),
|
|
length: items.length,
|
|
};
|
|
return col;
|
|
}
|
|
|
|
/**
|
|
* Creates a mock Cytoscape instance.
|
|
*/
|
|
function mockCytoscape(nodes = [], edges = []) {
|
|
return {
|
|
nodes: vi.fn(() => mockCollection(nodes)),
|
|
edges: vi.fn(() => mockCollection(edges)),
|
|
};
|
|
}
|
|
|
|
describe("mapPathStore", () => {
|
|
let store;
|
|
|
|
beforeEach(() => {
|
|
setActivePinia(createPinia());
|
|
store = useMapPathStore();
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it("has correct default state", () => {
|
|
expect(store.processOrBPMN).toBe("process");
|
|
expect(store.curveType).toBe("curved");
|
|
expect(store.directionType).toBe("horizontal");
|
|
expect(store.isBPMNOn).toBe(false);
|
|
expect(store.allPaths).toEqual([]);
|
|
expect(store.activeTrace).toBe(0);
|
|
expect(store.lastClickedNode).toBeNull();
|
|
});
|
|
|
|
it("setIsBPMNOn updates state", () => {
|
|
store.setIsBPMNOn(true);
|
|
expect(store.isBPMNOn).toBe(true);
|
|
store.setIsBPMNOn(false);
|
|
expect(store.isBPMNOn).toBe(false);
|
|
});
|
|
|
|
describe("clearAllHighlight", () => {
|
|
it("removes highlight classes from all nodes and edges", () => {
|
|
const node1 = mockNode("A", 0);
|
|
const edge1 = mockEdge();
|
|
const cy = mockCytoscape([node1], [edge1]);
|
|
store.cytoscape.process.curved.horizontal = cy;
|
|
|
|
store.clearAllHighlight();
|
|
|
|
expect(cy.edges).toHaveBeenCalled();
|
|
expect(cy.nodes).toHaveBeenCalled();
|
|
});
|
|
|
|
it("does not throw when cytoscape is null", () => {
|
|
store.cytoscape.process.curved.horizontal = null;
|
|
expect(() => store.clearAllHighlight()).not.toThrow();
|
|
});
|
|
});
|
|
|
|
describe("onNodeClickHighlightEdges", () => {
|
|
it("highlights clicked node and its edges", () => {
|
|
const node = mockNode("Activity", 1);
|
|
const outEdge = mockEdge();
|
|
const inEdge = mockEdge();
|
|
node.outgoers.mockReturnValue(mockCollection([outEdge]));
|
|
node.incomers.mockReturnValue(mockCollection([inEdge]));
|
|
|
|
store.cytoscape.process.curved.horizontal = mockCytoscape();
|
|
|
|
store.onNodeClickHighlightEdges(node);
|
|
|
|
expect(node.addClass).toHaveBeenCalledWith("highlight-node");
|
|
expect(outEdge.addClass).toHaveBeenCalledWith("highlight-edge");
|
|
expect(inEdge.addClass).toHaveBeenCalledWith("highlight-edge");
|
|
expect(store.lastClickedNode).toStrictEqual(node);
|
|
});
|
|
});
|
|
|
|
describe("onEdgeClickHighlightNodes", () => {
|
|
it("highlights source and target nodes of clicked edge", () => {
|
|
const src = mockNode("Start", 0);
|
|
const tgt = mockNode("End", 2);
|
|
const edge = mockEdge();
|
|
edge.source.mockReturnValue(src);
|
|
edge.target.mockReturnValue(tgt);
|
|
|
|
store.cytoscape.process.curved.horizontal = mockCytoscape();
|
|
|
|
store.onEdgeClickHighlightNodes(edge);
|
|
|
|
expect(src.addClass).toHaveBeenCalledWith("highlight-node");
|
|
expect(tgt.addClass).toHaveBeenCalledWith("highlight-node");
|
|
expect(edge.addClass).toHaveBeenCalledWith("highlight-edge");
|
|
});
|
|
});
|
|
});
|