@yh-ui/flow 1.0.1 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/bpmn-engine.test.cjs +357 -0
- package/dist/__tests__/bpmn-engine.test.d.ts +1 -0
- package/dist/__tests__/bpmn-engine.test.mjs +406 -0
- package/dist/__tests__/bpmn-utils.test.cjs +268 -0
- package/dist/__tests__/bpmn-utils.test.d.ts +1 -0
- package/dist/__tests__/bpmn-utils.test.mjs +227 -0
- package/dist/__tests__/bpmn-xml.test.cjs +150 -0
- package/dist/__tests__/bpmn-xml.test.d.ts +1 -0
- package/dist/__tests__/bpmn-xml.test.mjs +112 -0
- package/dist/__tests__/collaboration.test.cjs +487 -0
- package/dist/__tests__/collaboration.test.d.ts +1 -0
- package/dist/__tests__/collaboration.test.mjs +424 -0
- package/dist/__tests__/edge-types.test.cjs +275 -0
- package/dist/__tests__/edge-types.test.d.ts +1 -0
- package/dist/__tests__/edge-types.test.mjs +234 -0
- package/dist/__tests__/edge-utils.test.cjs +375 -0
- package/dist/__tests__/edge-utils.test.d.ts +1 -0
- package/dist/__tests__/edge-utils.test.mjs +376 -0
- package/dist/__tests__/events-types.test.cjs +184 -0
- package/dist/__tests__/events-types.test.d.ts +1 -0
- package/dist/__tests__/events-types.test.mjs +184 -0
- package/dist/__tests__/export-image-plugin.test.cjs +142 -0
- package/dist/__tests__/export-image-plugin.test.d.ts +1 -0
- package/dist/__tests__/export-image-plugin.test.mjs +118 -0
- package/dist/__tests__/export.test.cjs +237 -0
- package/dist/__tests__/export.test.d.ts +1 -0
- package/dist/__tests__/export.test.mjs +171 -0
- package/dist/__tests__/flow-context.test.cjs +16 -0
- package/dist/__tests__/flow-context.test.d.ts +1 -0
- package/dist/__tests__/flow-context.test.mjs +16 -0
- package/dist/__tests__/flow-props.test.cjs +94 -0
- package/dist/__tests__/flow-props.test.d.ts +1 -0
- package/dist/__tests__/flow-props.test.mjs +92 -0
- package/dist/__tests__/layout-plugin.test.cjs +233 -0
- package/dist/__tests__/layout-plugin.test.d.ts +1 -0
- package/dist/__tests__/layout-plugin.test.mjs +215 -0
- package/dist/__tests__/node-types.test.cjs +368 -0
- package/dist/__tests__/node-types.test.d.ts +1 -0
- package/dist/__tests__/node-types.test.mjs +292 -0
- package/dist/__tests__/performance.test.cjs +313 -0
- package/dist/__tests__/performance.test.d.ts +1 -0
- package/dist/__tests__/performance.test.mjs +218 -0
- package/dist/__tests__/plugin-advanced.test.cjs +301 -0
- package/dist/__tests__/plugin-advanced.test.d.ts +1 -0
- package/dist/__tests__/plugin-advanced.test.mjs +225 -0
- package/dist/__tests__/plugins.test.cjs +412 -0
- package/dist/__tests__/plugins.test.d.ts +1 -0
- package/dist/__tests__/plugins.test.mjs +402 -0
- package/dist/__tests__/screenshot-capture.test.cjs +183 -0
- package/dist/__tests__/screenshot-capture.test.d.ts +1 -0
- package/dist/__tests__/screenshot-capture.test.mjs +124 -0
- package/dist/__tests__/screenshot.test.cjs +74 -0
- package/dist/__tests__/screenshot.test.d.ts +1 -0
- package/dist/__tests__/screenshot.test.mjs +69 -0
- package/dist/__tests__/theme.test.cjs +185 -0
- package/dist/__tests__/theme.test.d.ts +1 -0
- package/dist/__tests__/theme.test.mjs +191 -0
- package/dist/__tests__/transform.test.cjs +376 -50
- package/dist/__tests__/transform.test.mjs +229 -28
- package/dist/__tests__/useAlignment.test.cjs +37 -0
- package/dist/__tests__/useAlignment.test.mjs +20 -0
- package/dist/__tests__/useNodeDistribution.test.cjs +643 -0
- package/dist/__tests__/useNodeDistribution.test.d.ts +1 -0
- package/dist/__tests__/useNodeDistribution.test.mjs +297 -0
- package/dist/__tests__/viewport-types.test.cjs +324 -0
- package/dist/__tests__/viewport-types.test.d.ts +1 -0
- package/dist/__tests__/viewport-types.test.mjs +207 -0
- package/dist/utils/bpmn.cjs +27 -16
- package/dist/utils/bpmn.mjs +27 -19
- package/package.json +3 -3
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
BpmnProcessEngine,
|
|
4
|
+
createBpmnEngine
|
|
5
|
+
} from "../utils/bpmn-engine.mjs";
|
|
6
|
+
function createMockNode(id, type, position = { x: 0, y: 0 }) {
|
|
7
|
+
return {
|
|
8
|
+
id,
|
|
9
|
+
type,
|
|
10
|
+
position,
|
|
11
|
+
width: 100,
|
|
12
|
+
height: 80,
|
|
13
|
+
data: {},
|
|
14
|
+
selected: false,
|
|
15
|
+
dragging: false
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function createMockEdge(id, source, target, conditionExpression) {
|
|
19
|
+
return {
|
|
20
|
+
id,
|
|
21
|
+
source,
|
|
22
|
+
target,
|
|
23
|
+
type: "smoothstep",
|
|
24
|
+
data: conditionExpression ? { conditionExpression } : {},
|
|
25
|
+
selected: false,
|
|
26
|
+
animated: false
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
describe("flow/utils/bpmn-engine", () => {
|
|
30
|
+
let engine;
|
|
31
|
+
let eventListener;
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
eventListener = vi.fn();
|
|
34
|
+
});
|
|
35
|
+
describe("constructor", () => {
|
|
36
|
+
it("should create engine with default options", () => {
|
|
37
|
+
engine = new BpmnProcessEngine();
|
|
38
|
+
expect(engine).toBeDefined();
|
|
39
|
+
});
|
|
40
|
+
it("should create engine with custom options", () => {
|
|
41
|
+
const customExecutor = vi.fn();
|
|
42
|
+
engine = new BpmnProcessEngine({
|
|
43
|
+
taskExecutor: customExecutor,
|
|
44
|
+
autoExecute: false
|
|
45
|
+
});
|
|
46
|
+
expect(engine).toBeDefined();
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
describe("createBpmnEngine factory", () => {
|
|
50
|
+
it("should create engine instance", () => {
|
|
51
|
+
const e = createBpmnEngine();
|
|
52
|
+
expect(e).toBeInstanceOf(BpmnProcessEngine);
|
|
53
|
+
});
|
|
54
|
+
it("should pass options to engine", () => {
|
|
55
|
+
const e = createBpmnEngine({ autoExecute: false });
|
|
56
|
+
expect(e).toBeInstanceOf(BpmnProcessEngine);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
describe("loadProcess", () => {
|
|
60
|
+
it("should load nodes and edges", () => {
|
|
61
|
+
engine = new BpmnProcessEngine();
|
|
62
|
+
const nodes = [createMockNode("n1", "bpmn-start"), createMockNode("n2", "bpmn-task")];
|
|
63
|
+
const edges = [createMockEdge("e1", "n1", "n2")];
|
|
64
|
+
engine.loadProcess(nodes, edges);
|
|
65
|
+
const startNodes = engine.getStartNodes();
|
|
66
|
+
expect(startNodes).toHaveLength(1);
|
|
67
|
+
expect(startNodes[0].id).toBe("n1");
|
|
68
|
+
});
|
|
69
|
+
it("should skip edges without source or target", () => {
|
|
70
|
+
engine = new BpmnProcessEngine();
|
|
71
|
+
const nodes = [createMockNode("n1", "bpmn-start")];
|
|
72
|
+
const edges = [
|
|
73
|
+
{ id: "e1", source: "", target: "n2", type: "smoothstep" },
|
|
74
|
+
{ id: "e2", source: "n1", target: "", type: "smoothstep" },
|
|
75
|
+
createMockEdge("e3", "n1", "n1")
|
|
76
|
+
];
|
|
77
|
+
engine.loadProcess(nodes, edges);
|
|
78
|
+
const startNodes = engine.getStartNodes();
|
|
79
|
+
expect(startNodes).toHaveLength(1);
|
|
80
|
+
});
|
|
81
|
+
it("should clear previous data on reload", () => {
|
|
82
|
+
engine = new BpmnProcessEngine();
|
|
83
|
+
const nodes1 = [createMockNode("n1", "bpmn-start")];
|
|
84
|
+
engine.loadProcess(nodes1, []);
|
|
85
|
+
expect(engine.getStartNodes()).toHaveLength(1);
|
|
86
|
+
const nodes2 = [];
|
|
87
|
+
engine.loadProcess(nodes2, []);
|
|
88
|
+
expect(engine.getStartNodes()).toHaveLength(0);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
describe("createInstance", () => {
|
|
92
|
+
it("should create process instance with initial variables", () => {
|
|
93
|
+
engine = new BpmnProcessEngine();
|
|
94
|
+
engine.loadProcess([createMockNode("n1", "bpmn-start")], []);
|
|
95
|
+
const instance = engine.createInstance({ var1: "value1" });
|
|
96
|
+
expect(instance.variables.var1).toBe("value1");
|
|
97
|
+
expect(instance.state).toBe("idle");
|
|
98
|
+
expect(instance.id).toMatch(/^instance_\d+$/);
|
|
99
|
+
});
|
|
100
|
+
it("should initialize all nodes in instance", () => {
|
|
101
|
+
engine = new BpmnProcessEngine();
|
|
102
|
+
engine.loadProcess(
|
|
103
|
+
[createMockNode("n1", "bpmn-start"), createMockNode("n2", "bpmn-task")],
|
|
104
|
+
[]
|
|
105
|
+
);
|
|
106
|
+
const instance = engine.createInstance();
|
|
107
|
+
expect(instance.nodes.has("n1")).toBe(true);
|
|
108
|
+
expect(instance.nodes.has("n2")).toBe(true);
|
|
109
|
+
});
|
|
110
|
+
it("should initialize all edges in instance", () => {
|
|
111
|
+
engine = new BpmnProcessEngine();
|
|
112
|
+
engine.loadProcess(
|
|
113
|
+
[createMockNode("n1", "bpmn-start"), createMockNode("n2", "bpmn-task")],
|
|
114
|
+
[createMockEdge("e1", "n1", "n2")]
|
|
115
|
+
);
|
|
116
|
+
const instance = engine.createInstance();
|
|
117
|
+
expect(instance.edges.has("e1")).toBe(true);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
describe("getInstance", () => {
|
|
121
|
+
it("should return instance by id", () => {
|
|
122
|
+
engine = new BpmnProcessEngine();
|
|
123
|
+
engine.loadProcess([createMockNode("n1", "bpmn-start")], []);
|
|
124
|
+
const created = engine.createInstance();
|
|
125
|
+
const retrieved = engine.getInstance(created.id);
|
|
126
|
+
expect(retrieved?.id).toBe(created.id);
|
|
127
|
+
});
|
|
128
|
+
it("should return undefined for non-existent id", () => {
|
|
129
|
+
engine = new BpmnProcessEngine();
|
|
130
|
+
expect(engine.getInstance("non-existent")).toBeUndefined();
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
describe("getStartNodes / getEndNodes", () => {
|
|
134
|
+
it("should return start nodes", () => {
|
|
135
|
+
engine = new BpmnProcessEngine();
|
|
136
|
+
engine.loadProcess(
|
|
137
|
+
[
|
|
138
|
+
createMockNode("start", "bpmn-start"),
|
|
139
|
+
createMockNode("end", "bpmn-end"),
|
|
140
|
+
createMockNode("task", "bpmn-task")
|
|
141
|
+
],
|
|
142
|
+
[]
|
|
143
|
+
);
|
|
144
|
+
expect(engine.getStartNodes()).toHaveLength(1);
|
|
145
|
+
expect(engine.getStartNodes()[0].type).toBe("bpmn-start");
|
|
146
|
+
});
|
|
147
|
+
it("should return end nodes", () => {
|
|
148
|
+
engine = new BpmnProcessEngine();
|
|
149
|
+
engine.loadProcess(
|
|
150
|
+
[
|
|
151
|
+
createMockNode("start", "bpmn-start"),
|
|
152
|
+
createMockNode("end1", "bpmn-end"),
|
|
153
|
+
createMockNode("end2", "bpmn-end")
|
|
154
|
+
],
|
|
155
|
+
[]
|
|
156
|
+
);
|
|
157
|
+
expect(engine.getEndNodes()).toHaveLength(2);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
describe("getOutgoingEdges / getIncomingEdges", () => {
|
|
161
|
+
it("should return outgoing edges", () => {
|
|
162
|
+
engine = new BpmnProcessEngine();
|
|
163
|
+
engine.loadProcess(
|
|
164
|
+
[
|
|
165
|
+
createMockNode("n1", "bpmn-start"),
|
|
166
|
+
createMockNode("n2", "bpmn-task"),
|
|
167
|
+
createMockNode("n3", "bpmn-task")
|
|
168
|
+
],
|
|
169
|
+
[createMockEdge("e1", "n1", "n2"), createMockEdge("e2", "n1", "n3")]
|
|
170
|
+
);
|
|
171
|
+
const outgoing = engine.getOutgoingEdges("n1");
|
|
172
|
+
expect(outgoing).toHaveLength(2);
|
|
173
|
+
});
|
|
174
|
+
it("should return incoming edges", () => {
|
|
175
|
+
engine = new BpmnProcessEngine();
|
|
176
|
+
engine.loadProcess(
|
|
177
|
+
[
|
|
178
|
+
createMockNode("n1", "bpmn-start"),
|
|
179
|
+
createMockNode("n2", "bpmn-task")
|
|
180
|
+
],
|
|
181
|
+
[createMockEdge("e1", "n1", "n2")]
|
|
182
|
+
);
|
|
183
|
+
const incoming = engine.getIncomingEdges("n2");
|
|
184
|
+
expect(incoming).toHaveLength(1);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
describe("setVariable / getVariable", () => {
|
|
188
|
+
it("should set and get variables", () => {
|
|
189
|
+
engine = new BpmnProcessEngine();
|
|
190
|
+
engine.loadProcess([createMockNode("n1", "bpmn-start")], []);
|
|
191
|
+
const instance = engine.createInstance();
|
|
192
|
+
engine.setVariable(instance.id, "key", "value");
|
|
193
|
+
expect(engine.getVariable(instance.id, "key")).toBe("value");
|
|
194
|
+
});
|
|
195
|
+
it("should return undefined for non-existent variable", () => {
|
|
196
|
+
engine = new BpmnProcessEngine();
|
|
197
|
+
engine.loadProcess([createMockNode("n1", "bpmn-start")], []);
|
|
198
|
+
const instance = engine.createInstance();
|
|
199
|
+
expect(engine.getVariable(instance.id, "unknown")).toBeUndefined();
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
describe("pause / resume", () => {
|
|
203
|
+
it("should pause running instance", () => {
|
|
204
|
+
engine = new BpmnProcessEngine({ autoExecute: false });
|
|
205
|
+
engine.loadProcess([createMockNode("n1", "bpmn-start")], []);
|
|
206
|
+
const instance = engine.createInstance();
|
|
207
|
+
engine.start(instance.id);
|
|
208
|
+
engine.pause(instance.id);
|
|
209
|
+
const retrieved = engine.getInstance(instance.id);
|
|
210
|
+
expect(retrieved?.state).toBe("paused");
|
|
211
|
+
});
|
|
212
|
+
it("should resume paused instance", async () => {
|
|
213
|
+
engine = new BpmnProcessEngine({ autoExecute: false });
|
|
214
|
+
engine.loadProcess([createMockNode("n1", "bpmn-start")], []);
|
|
215
|
+
const instance = engine.createInstance();
|
|
216
|
+
engine.start(instance.id);
|
|
217
|
+
engine.pause(instance.id);
|
|
218
|
+
await engine.resume(instance.id);
|
|
219
|
+
});
|
|
220
|
+
it("should do nothing when pausing non-running instance", () => {
|
|
221
|
+
engine = new BpmnProcessEngine();
|
|
222
|
+
engine.loadProcess([createMockNode("n1", "bpmn-start")], []);
|
|
223
|
+
const instance = engine.createInstance();
|
|
224
|
+
engine.pause(instance.id);
|
|
225
|
+
expect(engine.getInstance(instance.id)?.state).toBe("idle");
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
describe("terminate", () => {
|
|
229
|
+
it("should terminate instance", () => {
|
|
230
|
+
engine = new BpmnProcessEngine({ autoExecute: false });
|
|
231
|
+
engine.loadProcess([createMockNode("n1", "bpmn-start")], []);
|
|
232
|
+
const instance = engine.createInstance();
|
|
233
|
+
engine.start(instance.id);
|
|
234
|
+
engine.terminate(instance.id);
|
|
235
|
+
const retrieved = engine.getInstance(instance.id);
|
|
236
|
+
expect(retrieved?.state).toBe("terminated");
|
|
237
|
+
expect(retrieved?.endTime).toBeDefined();
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
describe("getAllInstances", () => {
|
|
241
|
+
it("should return all instances", () => {
|
|
242
|
+
engine = new BpmnProcessEngine({ autoExecute: false });
|
|
243
|
+
engine.loadProcess([createMockNode("n1", "bpmn-start")], []);
|
|
244
|
+
engine.createInstance();
|
|
245
|
+
engine.createInstance();
|
|
246
|
+
expect(engine.getAllInstances()).toHaveLength(2);
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
describe("event listener", () => {
|
|
250
|
+
it("should call event listener on events", () => {
|
|
251
|
+
engine = new BpmnProcessEngine({
|
|
252
|
+
eventListener,
|
|
253
|
+
autoExecute: false
|
|
254
|
+
});
|
|
255
|
+
engine.loadProcess([createMockNode("n1", "bpmn-start")], []);
|
|
256
|
+
engine.createInstance();
|
|
257
|
+
engine.start("instance_1");
|
|
258
|
+
expect(eventListener).toHaveBeenCalled();
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
describe("start with no start nodes", () => {
|
|
262
|
+
it("should complete immediately when no start nodes exist", async () => {
|
|
263
|
+
engine = new BpmnProcessEngine({ autoExecute: false });
|
|
264
|
+
engine.loadProcess([createMockNode("n1", "bpmn-task")], []);
|
|
265
|
+
const instance = engine.createInstance();
|
|
266
|
+
await engine.start(instance.id);
|
|
267
|
+
expect(instance.state).toBe("completed");
|
|
268
|
+
});
|
|
269
|
+
});
|
|
270
|
+
describe("task executor", () => {
|
|
271
|
+
it("should create engine with task executor option", () => {
|
|
272
|
+
const executor = vi.fn();
|
|
273
|
+
engine = new BpmnProcessEngine({
|
|
274
|
+
taskExecutor: executor,
|
|
275
|
+
autoExecute: false
|
|
276
|
+
});
|
|
277
|
+
expect(engine).toBeDefined();
|
|
278
|
+
});
|
|
279
|
+
});
|
|
280
|
+
describe("variable evaluator", () => {
|
|
281
|
+
it("should evaluate equality condition", async () => {
|
|
282
|
+
const evaluator = vi.fn().mockReturnValue(true);
|
|
283
|
+
engine = new BpmnProcessEngine({
|
|
284
|
+
variableEvaluator: evaluator,
|
|
285
|
+
autoExecute: false
|
|
286
|
+
});
|
|
287
|
+
engine.loadProcess(
|
|
288
|
+
[
|
|
289
|
+
createMockNode("start", "bpmn-start"),
|
|
290
|
+
createMockNode("task", "bpmn-task")
|
|
291
|
+
],
|
|
292
|
+
[createMockEdge("e1", "start", "task", "${approved == true}")]
|
|
293
|
+
);
|
|
294
|
+
const instance = engine.createInstance();
|
|
295
|
+
engine.setVariable(instance.id, "approved", true);
|
|
296
|
+
await engine.start(instance.id);
|
|
297
|
+
expect(evaluator).toHaveBeenCalled();
|
|
298
|
+
});
|
|
299
|
+
it("should evaluate greater than condition", async () => {
|
|
300
|
+
const evaluator = vi.fn().mockReturnValue(false);
|
|
301
|
+
engine = new BpmnProcessEngine({
|
|
302
|
+
variableEvaluator: evaluator,
|
|
303
|
+
autoExecute: false
|
|
304
|
+
});
|
|
305
|
+
engine.loadProcess(
|
|
306
|
+
[
|
|
307
|
+
createMockNode("start", "bpmn-start"),
|
|
308
|
+
createMockNode("task", "bpmn-task")
|
|
309
|
+
],
|
|
310
|
+
[createMockEdge("e1", "start", "task", "${count > 5}")]
|
|
311
|
+
);
|
|
312
|
+
const instance = engine.createInstance();
|
|
313
|
+
engine.setVariable(instance.id, "count", 10);
|
|
314
|
+
await engine.start(instance.id);
|
|
315
|
+
expect(evaluator).toHaveBeenCalledWith("${count > 5}", { count: 10 });
|
|
316
|
+
});
|
|
317
|
+
it("should evaluate less than condition", async () => {
|
|
318
|
+
const evaluator = vi.fn().mockReturnValue(false);
|
|
319
|
+
engine = new BpmnProcessEngine({
|
|
320
|
+
variableEvaluator: evaluator,
|
|
321
|
+
autoExecute: false
|
|
322
|
+
});
|
|
323
|
+
engine.loadProcess(
|
|
324
|
+
[
|
|
325
|
+
createMockNode("start", "bpmn-start"),
|
|
326
|
+
createMockNode("task", "bpmn-task")
|
|
327
|
+
],
|
|
328
|
+
[createMockEdge("e1", "start", "task", "${count < 5}")]
|
|
329
|
+
);
|
|
330
|
+
const instance = engine.createInstance();
|
|
331
|
+
engine.setVariable(instance.id, "count", 3);
|
|
332
|
+
await engine.start(instance.id);
|
|
333
|
+
expect(evaluator).toHaveBeenCalled();
|
|
334
|
+
});
|
|
335
|
+
it("should evaluate not equal condition", async () => {
|
|
336
|
+
const evaluator = vi.fn().mockReturnValue(false);
|
|
337
|
+
engine = new BpmnProcessEngine({
|
|
338
|
+
variableEvaluator: evaluator,
|
|
339
|
+
autoExecute: false
|
|
340
|
+
});
|
|
341
|
+
engine.loadProcess(
|
|
342
|
+
[
|
|
343
|
+
createMockNode("start", "bpmn-start"),
|
|
344
|
+
createMockNode("task", "bpmn-task")
|
|
345
|
+
],
|
|
346
|
+
[createMockEdge("e1", "start", "task", '${status != "closed"}')]
|
|
347
|
+
);
|
|
348
|
+
const instance = engine.createInstance();
|
|
349
|
+
engine.setVariable(instance.id, "status", "open");
|
|
350
|
+
await engine.start(instance.id);
|
|
351
|
+
expect(evaluator).toHaveBeenCalled();
|
|
352
|
+
});
|
|
353
|
+
it("should handle simple variable reference", async () => {
|
|
354
|
+
const evaluator = vi.fn().mockReturnValue(true);
|
|
355
|
+
engine = new BpmnProcessEngine({
|
|
356
|
+
variableEvaluator: evaluator,
|
|
357
|
+
autoExecute: false
|
|
358
|
+
});
|
|
359
|
+
engine.loadProcess(
|
|
360
|
+
[
|
|
361
|
+
createMockNode("start", "bpmn-start"),
|
|
362
|
+
createMockNode("task", "bpmn-task")
|
|
363
|
+
],
|
|
364
|
+
[createMockEdge("e1", "start", "task", "${isActive}")]
|
|
365
|
+
);
|
|
366
|
+
const instance = engine.createInstance();
|
|
367
|
+
engine.setVariable(instance.id, "isActive", true);
|
|
368
|
+
await engine.start(instance.id);
|
|
369
|
+
expect(evaluator).toHaveBeenCalled();
|
|
370
|
+
});
|
|
371
|
+
it("should handle true literal", async () => {
|
|
372
|
+
const evaluator = vi.fn().mockReturnValue(true);
|
|
373
|
+
engine = new BpmnProcessEngine({
|
|
374
|
+
variableEvaluator: evaluator,
|
|
375
|
+
autoExecute: false
|
|
376
|
+
});
|
|
377
|
+
engine.loadProcess(
|
|
378
|
+
[
|
|
379
|
+
createMockNode("start", "bpmn-start"),
|
|
380
|
+
createMockNode("task", "bpmn-task")
|
|
381
|
+
],
|
|
382
|
+
[createMockEdge("e1", "start", "task", "${true}")]
|
|
383
|
+
);
|
|
384
|
+
const instance = engine.createInstance();
|
|
385
|
+
await engine.start(instance.id);
|
|
386
|
+
expect(evaluator).toHaveBeenCalled();
|
|
387
|
+
});
|
|
388
|
+
it("should handle false literal", async () => {
|
|
389
|
+
const evaluator = vi.fn().mockReturnValue(false);
|
|
390
|
+
engine = new BpmnProcessEngine({
|
|
391
|
+
variableEvaluator: evaluator,
|
|
392
|
+
autoExecute: false
|
|
393
|
+
});
|
|
394
|
+
engine.loadProcess(
|
|
395
|
+
[
|
|
396
|
+
createMockNode("start", "bpmn-start"),
|
|
397
|
+
createMockNode("task", "bpmn-task")
|
|
398
|
+
],
|
|
399
|
+
[createMockEdge("e1", "start", "task", "${false}")]
|
|
400
|
+
);
|
|
401
|
+
const instance = engine.createInstance();
|
|
402
|
+
await engine.start(instance.id);
|
|
403
|
+
expect(evaluator).toHaveBeenCalled();
|
|
404
|
+
});
|
|
405
|
+
});
|
|
406
|
+
});
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _vitest = require("vitest");
|
|
4
|
+
var _bpmn = require("../utils/bpmn.cjs");
|
|
5
|
+
function createMockNode(id, type, position = {
|
|
6
|
+
x: 100,
|
|
7
|
+
y: 100
|
|
8
|
+
}) {
|
|
9
|
+
return {
|
|
10
|
+
id,
|
|
11
|
+
type,
|
|
12
|
+
position,
|
|
13
|
+
width: 100,
|
|
14
|
+
height: 80,
|
|
15
|
+
data: {},
|
|
16
|
+
selected: false,
|
|
17
|
+
dragging: false
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
function createMockEdge(id, source, target) {
|
|
21
|
+
return {
|
|
22
|
+
id,
|
|
23
|
+
source,
|
|
24
|
+
target,
|
|
25
|
+
type: "smoothstep",
|
|
26
|
+
selected: false,
|
|
27
|
+
animated: false
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
(0, _vitest.describe)("flow/utils/bpmn", () => {
|
|
31
|
+
(0, _vitest.describe)("flowToBpmnXml", () => {
|
|
32
|
+
(0, _vitest.it)("should generate BPMN XML with start event", () => {
|
|
33
|
+
const nodes = [createMockNode("start", "bpmn-start", {
|
|
34
|
+
x: 50,
|
|
35
|
+
y: 50
|
|
36
|
+
})];
|
|
37
|
+
const edges = [];
|
|
38
|
+
const result = (0, _bpmn.flowToBpmnXml)(nodes, edges, {
|
|
39
|
+
processId: "test",
|
|
40
|
+
processName: "Test"
|
|
41
|
+
});
|
|
42
|
+
(0, _vitest.expect)(result.xml).toContain("startEvent");
|
|
43
|
+
(0, _vitest.expect)(result.xml).toContain('id="start"');
|
|
44
|
+
(0, _vitest.expect)(result.processId).toBe("test");
|
|
45
|
+
});
|
|
46
|
+
(0, _vitest.it)("should generate BPMN XML with end event", () => {
|
|
47
|
+
const nodes = [createMockNode("end", "bpmn-end", {
|
|
48
|
+
x: 300,
|
|
49
|
+
y: 100
|
|
50
|
+
})];
|
|
51
|
+
const edges = [];
|
|
52
|
+
const result = (0, _bpmn.flowToBpmnXml)(nodes, edges);
|
|
53
|
+
(0, _vitest.expect)(result.xml).toContain("endEvent");
|
|
54
|
+
});
|
|
55
|
+
(0, _vitest.it)("should generate BPMN XML with task", () => {
|
|
56
|
+
const nodes = [createMockNode("task1", "bpmn-task", {
|
|
57
|
+
x: 150,
|
|
58
|
+
y: 100
|
|
59
|
+
})];
|
|
60
|
+
const edges = [];
|
|
61
|
+
const result = (0, _bpmn.flowToBpmnXml)(nodes, edges);
|
|
62
|
+
(0, _vitest.expect)(result.xml).toContain("<bpmn:task");
|
|
63
|
+
});
|
|
64
|
+
(0, _vitest.it)("should generate BPMN XML with service task", () => {
|
|
65
|
+
const nodes = [{
|
|
66
|
+
...createMockNode("service", "bpmn-service-task"),
|
|
67
|
+
data: {
|
|
68
|
+
implementation: "${myService}"
|
|
69
|
+
}
|
|
70
|
+
}];
|
|
71
|
+
const edges = [];
|
|
72
|
+
const result = (0, _bpmn.flowToBpmnXml)(nodes, edges);
|
|
73
|
+
(0, _vitest.expect)(result.xml).toContain("serviceTask");
|
|
74
|
+
(0, _vitest.expect)(result.xml).toContain('implementation="delegateExpression"');
|
|
75
|
+
});
|
|
76
|
+
(0, _vitest.it)("should generate BPMN XML with user task and assignee", () => {
|
|
77
|
+
const nodes = [{
|
|
78
|
+
...createMockNode("user", "bpmn-user-task"),
|
|
79
|
+
data: {
|
|
80
|
+
assignee: "admin",
|
|
81
|
+
candidateUsers: "user1,user2"
|
|
82
|
+
}
|
|
83
|
+
}];
|
|
84
|
+
const edges = [];
|
|
85
|
+
const result = (0, _bpmn.flowToBpmnXml)(nodes, edges);
|
|
86
|
+
(0, _vitest.expect)(result.xml).toContain("userTask");
|
|
87
|
+
(0, _vitest.expect)(result.xml).toContain('assignee="admin"');
|
|
88
|
+
(0, _vitest.expect)(result.xml).toContain('candidateUsers="user1,user2"');
|
|
89
|
+
});
|
|
90
|
+
(0, _vitest.it)("should generate BPMN XML with exclusive gateway", () => {
|
|
91
|
+
const nodes = [createMockNode("gw", "bpmn-exclusive-gateway", {
|
|
92
|
+
x: 250,
|
|
93
|
+
y: 100
|
|
94
|
+
})];
|
|
95
|
+
const edges = [];
|
|
96
|
+
const result = (0, _bpmn.flowToBpmnXml)(nodes, edges);
|
|
97
|
+
(0, _vitest.expect)(result.xml).toContain("exclusiveGateway");
|
|
98
|
+
(0, _vitest.expect)(result.xml).toContain('gatewayDirection="diverging"');
|
|
99
|
+
});
|
|
100
|
+
(0, _vitest.it)("should generate BPMN XML with parallel gateway", () => {
|
|
101
|
+
const nodes = [createMockNode("pgw", "bpmn-parallel-gateway", {
|
|
102
|
+
x: 250,
|
|
103
|
+
y: 100
|
|
104
|
+
})];
|
|
105
|
+
const edges = [];
|
|
106
|
+
const result = (0, _bpmn.flowToBpmnXml)(nodes, edges);
|
|
107
|
+
(0, _vitest.expect)(result.xml).toContain("parallelGateway");
|
|
108
|
+
});
|
|
109
|
+
(0, _vitest.it)("should generate BPMN XML with inclusive gateway", () => {
|
|
110
|
+
const nodes = [createMockNode("igw", "bpmn-inclusive-gateway", {
|
|
111
|
+
x: 250,
|
|
112
|
+
y: 100
|
|
113
|
+
})];
|
|
114
|
+
const edges = [];
|
|
115
|
+
const result = (0, _bpmn.flowToBpmnXml)(nodes, edges);
|
|
116
|
+
(0, _vitest.expect)(result.xml).toContain("inclusiveGateway");
|
|
117
|
+
});
|
|
118
|
+
(0, _vitest.it)("should include node name in XML", () => {
|
|
119
|
+
const nodes = [{
|
|
120
|
+
...createMockNode("task1", "bpmn-task"),
|
|
121
|
+
data: {
|
|
122
|
+
name: "My Task",
|
|
123
|
+
label: "My Task"
|
|
124
|
+
}
|
|
125
|
+
}];
|
|
126
|
+
const edges = [];
|
|
127
|
+
const result = (0, _bpmn.flowToBpmnXml)(nodes, edges);
|
|
128
|
+
(0, _vitest.expect)(result.xml).toContain('name="My Task"');
|
|
129
|
+
});
|
|
130
|
+
(0, _vitest.it)("should generate sequence flow with condition expression", () => {
|
|
131
|
+
const nodes = [createMockNode("start", "bpmn-start"), createMockNode("end", "bpmn-end")];
|
|
132
|
+
const edges = [{
|
|
133
|
+
...createMockEdge("flow1", "start", "end"),
|
|
134
|
+
data: {
|
|
135
|
+
conditionExpression: "${approved == true}"
|
|
136
|
+
}
|
|
137
|
+
}];
|
|
138
|
+
const result = (0, _bpmn.flowToBpmnXml)(nodes, edges);
|
|
139
|
+
(0, _vitest.expect)(result.xml).toContain("sequenceFlow");
|
|
140
|
+
(0, _vitest.expect)(result.xml).toContain("conditionExpression");
|
|
141
|
+
(0, _vitest.expect)(result.xml).toContain("${approved == true}");
|
|
142
|
+
});
|
|
143
|
+
(0, _vitest.it)("should include DI information when includeDi is true", () => {
|
|
144
|
+
const nodes = [createMockNode("n1", "bpmn-start", {
|
|
145
|
+
x: 10,
|
|
146
|
+
y: 20
|
|
147
|
+
})];
|
|
148
|
+
const edges = [];
|
|
149
|
+
const result = (0, _bpmn.flowToBpmnXml)(nodes, edges, {
|
|
150
|
+
includeDi: true
|
|
151
|
+
});
|
|
152
|
+
(0, _vitest.expect)(result.xml).toContain("BPMNDiagram");
|
|
153
|
+
(0, _vitest.expect)(result.xml).toContain("BPMNShape");
|
|
154
|
+
});
|
|
155
|
+
(0, _vitest.it)("should not include DI information when includeDi is false", () => {
|
|
156
|
+
const nodes = [createMockNode("n1", "bpmn-start")];
|
|
157
|
+
const edges = [];
|
|
158
|
+
const result = (0, _bpmn.flowToBpmnXml)(nodes, edges, {
|
|
159
|
+
includeDi: false
|
|
160
|
+
});
|
|
161
|
+
(0, _vitest.expect)(result.xml).not.toContain("BPMNDiagram");
|
|
162
|
+
});
|
|
163
|
+
(0, _vitest.it)("should use default dimensions when node has no width/height", () => {
|
|
164
|
+
const nodes = [{
|
|
165
|
+
id: "n1",
|
|
166
|
+
type: "bpmn-start",
|
|
167
|
+
position: {
|
|
168
|
+
x: 0,
|
|
169
|
+
y: 0
|
|
170
|
+
},
|
|
171
|
+
selected: false,
|
|
172
|
+
dragging: false
|
|
173
|
+
}];
|
|
174
|
+
const edges = [];
|
|
175
|
+
const result = (0, _bpmn.flowToBpmnXml)(nodes, edges, {
|
|
176
|
+
includeDi: true
|
|
177
|
+
});
|
|
178
|
+
(0, _vitest.expect)(result.xml).toContain('width="100"');
|
|
179
|
+
(0, _vitest.expect)(result.xml).toContain('height="80"');
|
|
180
|
+
});
|
|
181
|
+
(0, _vitest.it)("should skip unknown node types", () => {
|
|
182
|
+
const nodes = [{
|
|
183
|
+
id: "n1",
|
|
184
|
+
type: "unknown-type",
|
|
185
|
+
position: {
|
|
186
|
+
x: 0,
|
|
187
|
+
y: 0
|
|
188
|
+
},
|
|
189
|
+
selected: false,
|
|
190
|
+
dragging: false
|
|
191
|
+
}];
|
|
192
|
+
const edges = [];
|
|
193
|
+
const result = (0, _bpmn.flowToBpmnXml)(nodes, edges);
|
|
194
|
+
(0, _vitest.expect)(result.xml).not.toContain("unknown-type");
|
|
195
|
+
});
|
|
196
|
+
(0, _vitest.it)("should generate XML with proper namespaces", () => {
|
|
197
|
+
const nodes = [createMockNode("n1", "bpmn-start")];
|
|
198
|
+
const edges = [];
|
|
199
|
+
const result = (0, _bpmn.flowToBpmnXml)(nodes, edges);
|
|
200
|
+
(0, _vitest.expect)(result.xml).toContain('xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"');
|
|
201
|
+
});
|
|
202
|
+
(0, _vitest.it)("should include edges in XML", () => {
|
|
203
|
+
const nodes = [createMockNode("n1", "bpmn-start"), createMockNode("n2", "bpmn-end")];
|
|
204
|
+
const edges = [createMockEdge("e1", "n1", "n2")];
|
|
205
|
+
const result = (0, _bpmn.flowToBpmnXml)(nodes, edges);
|
|
206
|
+
(0, _vitest.expect)(result.xml).toContain("sequenceFlow");
|
|
207
|
+
(0, _vitest.expect)(result.xml).toContain('sourceRef="n1"');
|
|
208
|
+
(0, _vitest.expect)(result.xml).toContain('targetRef="n2"');
|
|
209
|
+
});
|
|
210
|
+
(0, _vitest.it)("should generate valid processId", () => {
|
|
211
|
+
const nodes = [createMockNode("n1", "bpmn-start")];
|
|
212
|
+
const edges = [];
|
|
213
|
+
const result = (0, _bpmn.flowToBpmnXml)(nodes, edges, {
|
|
214
|
+
processId: "MyProcess"
|
|
215
|
+
});
|
|
216
|
+
(0, _vitest.expect)(result.processId).toBe("MyProcess");
|
|
217
|
+
});
|
|
218
|
+
(0, _vitest.it)("should generate default processId with timestamp", () => {
|
|
219
|
+
const nodes = [createMockNode("n1", "bpmn-start")];
|
|
220
|
+
const edges = [];
|
|
221
|
+
const result = (0, _bpmn.flowToBpmnXml)(nodes, edges);
|
|
222
|
+
(0, _vitest.expect)(result.processId).toMatch(/^Process_\d+$/);
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
(0, _vitest.describe)("validateBpmnXml", () => {
|
|
226
|
+
(0, _vitest.it)("should return invalid for missing definitions", () => {
|
|
227
|
+
const xml = `<notbpmn></notbpmn>`;
|
|
228
|
+
const result = (0, _bpmn.validateBpmnXml)(xml);
|
|
229
|
+
(0, _vitest.expect)(result.valid).toBe(false);
|
|
230
|
+
(0, _vitest.expect)(result.error).toBeDefined();
|
|
231
|
+
});
|
|
232
|
+
(0, _vitest.it)("should return invalid for missing process", () => {
|
|
233
|
+
const xml = `<?xml version="1.0"?>
|
|
234
|
+
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" id="def1">
|
|
235
|
+
</bpmn:definitions>`;
|
|
236
|
+
const result = (0, _bpmn.validateBpmnXml)(xml);
|
|
237
|
+
(0, _vitest.expect)(result.valid).toBe(false);
|
|
238
|
+
(0, _vitest.expect)(result.error).toBeDefined();
|
|
239
|
+
});
|
|
240
|
+
(0, _vitest.it)("should return invalid for malformed XML", () => {
|
|
241
|
+
const xml = `<?xml version="1.0"?><invalid`;
|
|
242
|
+
const result = (0, _bpmn.validateBpmnXml)(xml);
|
|
243
|
+
(0, _vitest.expect)(result.valid).toBe(false);
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
(0, _vitest.describe)("generateSampleBpmnXml", () => {
|
|
247
|
+
(0, _vitest.it)("should generate a sample BPMN XML string", () => {
|
|
248
|
+
const xml = (0, _bpmn.generateSampleBpmnXml)();
|
|
249
|
+
(0, _vitest.expect)(xml).toContain("<?xml");
|
|
250
|
+
(0, _vitest.expect)(xml).toContain("bpmn:definitions");
|
|
251
|
+
(0, _vitest.expect)(xml).toContain("SampleProcess");
|
|
252
|
+
});
|
|
253
|
+
(0, _vitest.it)("should contain start and end events", () => {
|
|
254
|
+
const xml = (0, _bpmn.generateSampleBpmnXml)();
|
|
255
|
+
(0, _vitest.expect)(xml).toContain("startEvent");
|
|
256
|
+
(0, _vitest.expect)(xml).toContain("endEvent");
|
|
257
|
+
});
|
|
258
|
+
(0, _vitest.it)("should contain user task and service task", () => {
|
|
259
|
+
const xml = (0, _bpmn.generateSampleBpmnXml)();
|
|
260
|
+
(0, _vitest.expect)(xml).toContain("userTask");
|
|
261
|
+
(0, _vitest.expect)(xml).toContain("serviceTask");
|
|
262
|
+
});
|
|
263
|
+
(0, _vitest.it)("should contain gateway", () => {
|
|
264
|
+
const xml = (0, _bpmn.generateSampleBpmnXml)();
|
|
265
|
+
(0, _vitest.expect)(xml).toContain("exclusiveGateway");
|
|
266
|
+
});
|
|
267
|
+
});
|
|
268
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|