join-status.check.js
3.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/**
* join-status 的可运行检查(`node web/src/components/graph-console/join-status.check.js`)。
* 同款手法见 io-model.check.js 的头注——web/ 不在 vitest include 里,用 assert 自跑。
*/
import assert from 'node:assert/strict';
import { resolveJoinWait, joinWaitLabel } from './join-status.js';
const nodes = [
{ defNodeId: 'entry', name: 'entry', status: 'success' },
{ defNodeId: 'a', name: 'a', status: 'success' },
{ defNodeId: 'b', name: 'b', status: 'running' },
{ defNodeId: 'c', name: 'c', status: 'fail' },
{ defNodeId: 'join', name: 'join', status: 'pending' },
{ defNodeId: 'chain2', name: 'chain2', status: 'pending' },
];
const edges = [
{ from: 'entry', to: 'a', condition: 'success', edgeKind: 'forward' },
{ from: 'entry', to: 'b', condition: 'success', edgeKind: 'forward' },
{ from: 'entry', to: 'c', condition: 'success', edgeKind: 'forward' },
{ from: 'a', to: 'join', condition: 'success', edgeKind: 'forward' },
{ from: 'b', to: 'join', condition: 'success', edgeKind: 'forward' },
{ from: 'c', to: 'join', condition: 'success', edgeKind: 'forward' },
{ from: 'a', to: 'chain2', condition: 'success', edgeKind: 'forward' },
// backward 边不参与等待判定,即使指向 join 也不该被数进 waiting
{ from: 'join', to: 'a', condition: 'fail', edgeKind: 'backward' },
];
// ① 真正的 fan-in:join 在等 b(running)/c(fail),a 已经 success
{
const wait = resolveJoinWait(nodes.find((n) => n.defNodeId === 'join'), nodes, edges);
assert.equal(wait.total, 3);
assert.equal(wait.done, 1);
assert.equal(wait.isFanIn, true);
assert.equal(wait.satisfied, false);
assert.deepEqual(wait.blockedBy.map((w) => w.defNodeId).sort(), ['b', 'c']);
const label = joinWaitLabel(wait);
assert.equal(label.text, '⏳1/3');
assert.match(label.title, /a\(success\)/);
assert.match(label.title, /b\(running\)/);
assert.match(label.title, /c\(fail\)/);
}
// ② 单一入边的普通顺序等待:不是 fan-in,不出徽标(避免给每一条链都加噪声)
{
const wait = resolveJoinWait(nodes.find((n) => n.defNodeId === 'chain2'), nodes, edges);
assert.equal(wait.total, 1);
assert.equal(wait.isFanIn, false);
assert.equal(joinWaitLabel(wait), null);
}
// ③ 非 pending 节点:不适用(已经跑过或正在跑,没有「在等谁」这回事)
{
assert.equal(resolveJoinWait(nodes.find((n) => n.defNodeId === 'a'), nodes, edges), null);
}
// ④ 已满足(引擎下一拍就会点亮,这一刻不该显示「在等」)
{
const satisfiedNodes = nodes.map((n) => (n.defNodeId === 'b' || n.defNodeId === 'c'
? { ...n, status: 'success' } : n));
const wait = resolveJoinWait(satisfiedNodes.find((n) => n.defNodeId === 'join'), satisfiedNodes, edges);
assert.equal(wait.satisfied, true);
assert.equal(joinWaitLabel(wait), null);
}
// ⑤ 没有 forward success 入边(图的入口节点):不适用
{
assert.equal(resolveJoinWait({ defNodeId: 'entry', status: 'pending' }, nodes, edges), null);
}
console.log('join-status.check.js: 全部通过');