@dxos/app-graph 0.4.7-main.d28a540 → 0.4.7-main.e015b9e
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/lib/browser/index.mjs +229 -289
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing.mjs +98 -0
- package/dist/lib/browser/testing.mjs.map +7 -0
- package/dist/lib/node/index.cjs +239 -282
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing.cjs +122 -0
- package/dist/lib/node/testing.cjs.map +7 -0
- package/dist/types/src/action.d.ts +68 -0
- package/dist/types/src/action.d.ts.map +1 -0
- package/dist/types/src/graph-builder.d.ts +16 -8
- package/dist/types/src/graph-builder.d.ts.map +1 -1
- package/dist/types/src/graph.d.ts +14 -71
- package/dist/types/src/graph.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/node.d.ts +47 -57
- package/dist/types/src/node.d.ts.map +1 -1
- package/dist/types/src/stories/EchoGraph.stories.d.ts.map +1 -1
- package/dist/types/src/testing.d.ts +52 -0
- package/dist/types/src/testing.d.ts.map +1 -0
- package/package.json +29 -10
- package/src/action.ts +92 -0
- package/src/graph-builder.ts +206 -18
- package/src/graph.test.ts +146 -242
- package/src/graph.ts +48 -241
- package/src/index.ts +1 -1
- package/src/node.ts +66 -78
- package/src/stories/EchoGraph.stories.tsx +27 -59
- package/src/testing.ts +152 -0
- package/dist/types/src/helpers.d.ts +0 -14
- package/dist/types/src/helpers.d.ts.map +0 -1
- package/src/helpers.ts +0 -27
package/src/graph.test.ts
CHANGED
|
@@ -2,315 +2,219 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { effect } from '@preact/signals-core';
|
|
6
5
|
import { expect } from 'chai';
|
|
7
6
|
|
|
8
7
|
import { describe, test } from '@dxos/test';
|
|
9
8
|
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
9
|
+
import { GraphBuilder } from './graph-builder';
|
|
10
|
+
import { createTestNodeBuilder } from './testing';
|
|
12
11
|
|
|
13
|
-
const longestPaths = new Map<string, string[]>();
|
|
14
|
-
|
|
15
|
-
const filterLongestPath: NodeFilter = (node, connectedNode): node is Node => {
|
|
16
|
-
const longestPath = longestPaths.get(node.id);
|
|
17
|
-
if (!longestPath) {
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (longestPath[longestPath.length - 2] !== connectedNode.id) {
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return true;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
// TODO(wittjosiah): Add tests for granularity of reactivity.
|
|
29
12
|
describe('Graph', () => {
|
|
30
|
-
test('
|
|
31
|
-
const graph = new
|
|
13
|
+
test('returns root node', () => {
|
|
14
|
+
const graph = new GraphBuilder().build();
|
|
15
|
+
expect(graph.root).to.not.be.undefined;
|
|
16
|
+
expect(graph.root.id).to.equal('root');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('root node unmodified without builders', () => {
|
|
20
|
+
const graph = new GraphBuilder().build();
|
|
21
|
+
expect(graph.root.properties).to.be.empty;
|
|
22
|
+
expect(graph.root.children).to.be.empty;
|
|
23
|
+
expect(graph.root.actions).to.be.empty;
|
|
24
|
+
});
|
|
32
25
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
26
|
+
test('builder can add children to root node', () => {
|
|
27
|
+
const builder = new GraphBuilder();
|
|
28
|
+
const testNode = { id: 'test', label: 'Test', data: null };
|
|
29
|
+
const id = 'test';
|
|
30
|
+
builder.addNodeBuilder(id, (parent) => {
|
|
31
|
+
if (parent.id === 'root') {
|
|
32
|
+
parent.addNode(id, testNode);
|
|
33
|
+
}
|
|
36
34
|
});
|
|
37
35
|
|
|
38
|
-
|
|
39
|
-
expect(root.
|
|
40
|
-
expect(graph.
|
|
41
|
-
expect(graph.findNode('test2')?.id).to.equal('test2');
|
|
42
|
-
expect(graph.findNode('test1')?.nodes()).to.be.empty;
|
|
43
|
-
expect(graph.findNode('test2')?.nodes()).to.be.empty;
|
|
44
|
-
expect(graph.findNode('test1')?.nodes({ direction: 'inbound' })).to.have.length(1);
|
|
45
|
-
expect(graph.findNode('test2')?.nodes({ direction: 'inbound' })).to.have.length(1);
|
|
36
|
+
const graph = builder.build();
|
|
37
|
+
expect(graph.root.childrenMap.test.id).to.equal(testNode.id);
|
|
38
|
+
expect(graph.root.childrenMap.test.parent!.id).to.equal(graph.root.id);
|
|
46
39
|
});
|
|
47
40
|
|
|
48
|
-
test('add
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
id
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
graph.addNodes({
|
|
56
|
-
id: 'root',
|
|
57
|
-
nodes: [{ id: 'test1' }, { id: 'test2' }],
|
|
41
|
+
test('builder can add actions to root node', () => {
|
|
42
|
+
const builder = new GraphBuilder();
|
|
43
|
+
const testAction = { id: 'test', label: 'Test', invoke: () => {} };
|
|
44
|
+
builder.addNodeBuilder('test', (parent) => {
|
|
45
|
+
if (parent.id === 'root') {
|
|
46
|
+
parent.addAction(testAction);
|
|
47
|
+
}
|
|
58
48
|
});
|
|
59
49
|
|
|
60
|
-
|
|
61
|
-
expect(
|
|
62
|
-
expect(graph.root.nodes()).to.have.length(2);
|
|
50
|
+
const graph = builder.build();
|
|
51
|
+
expect(graph.root.actionsMap.test.id).to.equal(testAction.id);
|
|
63
52
|
});
|
|
64
53
|
|
|
65
|
-
test('
|
|
66
|
-
const
|
|
54
|
+
test('multiple builders can add children to root node', () => {
|
|
55
|
+
const builder = new GraphBuilder();
|
|
56
|
+
builder.addNodeBuilder('test1', createTestNodeBuilder('test1').nodeBuilder);
|
|
57
|
+
builder.addNodeBuilder('test2', createTestNodeBuilder('test2').nodeBuilder);
|
|
67
58
|
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
59
|
+
const graph = builder.build();
|
|
60
|
+
expect(Object.keys(graph.root.childrenMap)).to.deep.equal(['root-test1', 'root-test2']);
|
|
61
|
+
for (const node of graph.root.children) {
|
|
62
|
+
expect(graph.root.id).to.equal(node.parent!.id);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
72
65
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
66
|
+
test('multiple builders can add actions to root node', () => {
|
|
67
|
+
const builder = new GraphBuilder();
|
|
68
|
+
builder.addNodeBuilder('test1', createTestNodeBuilder('test1').nodeBuilder);
|
|
69
|
+
builder.addNodeBuilder('test2', createTestNodeBuilder('test2').nodeBuilder);
|
|
77
70
|
|
|
78
|
-
graph.
|
|
79
|
-
expect(graph.
|
|
80
|
-
expect(root.nodes()).to.have.length(1);
|
|
71
|
+
const graph = builder.build();
|
|
72
|
+
expect(Object.keys(graph.root.actionsMap)).to.deep.equal(['root-test1', 'root-test2']);
|
|
81
73
|
});
|
|
82
74
|
|
|
83
|
-
test('add
|
|
84
|
-
const
|
|
75
|
+
test('builders can add children to child node', () => {
|
|
76
|
+
const builder = new GraphBuilder();
|
|
77
|
+
builder.addNodeBuilder('test1', createTestNodeBuilder('test1', 2).nodeBuilder);
|
|
78
|
+
builder.addNodeBuilder('test2', createTestNodeBuilder('test2').nodeBuilder);
|
|
85
79
|
|
|
86
|
-
graph.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
expect(graph.findNode('test1')?.nodes()).to.have.length(1);
|
|
93
|
-
expect(graph.findNode('test2')?.nodes({ direction: 'inbound' })).to.have.length(2);
|
|
80
|
+
const graph = builder.build();
|
|
81
|
+
expect(Object.keys(graph.root.childrenMap['root-test1'].children)).to.be.empty;
|
|
82
|
+
expect(Object.keys(graph.root.childrenMap['root-test2'].childrenMap)).to.deep.equal(['root-test2-test1']);
|
|
83
|
+
for (const node of graph.root.childrenMap['root-test2'].children) {
|
|
84
|
+
expect(graph.root.childrenMap['root-test2'].id).to.equal(node.parent!.id);
|
|
85
|
+
}
|
|
94
86
|
});
|
|
95
87
|
|
|
96
|
-
test('add
|
|
97
|
-
const
|
|
88
|
+
test('builders can add actions to child node', () => {
|
|
89
|
+
const builder = new GraphBuilder();
|
|
90
|
+
builder.addNodeBuilder('test1', createTestNodeBuilder('test1', 2).nodeBuilder);
|
|
91
|
+
builder.addNodeBuilder('test2', createTestNodeBuilder('test2').nodeBuilder);
|
|
92
|
+
|
|
93
|
+
const graph = builder.build();
|
|
94
|
+
expect(Object.keys(graph.root.childrenMap['root-test1'].actionsMap)).to.be.empty;
|
|
95
|
+
expect(Object.keys(graph.root.childrenMap['root-test2'].actionsMap)).to.deep.equal(['root-test2-test1']);
|
|
96
|
+
});
|
|
98
97
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
98
|
+
test('builders can add actions to action sets', () => {
|
|
99
|
+
const builder = new GraphBuilder();
|
|
100
|
+
builder.addNodeBuilder('test', (parent) => {
|
|
101
|
+
const [set] = parent.addAction({ id: 'test-set', label: 'Test Set', invoke: () => {} });
|
|
102
|
+
set.addAction({ id: 'test-action', label: 'Test', invoke: () => {} });
|
|
102
103
|
});
|
|
103
|
-
graph.addEdge({ source: 'test1', target: 'test2' });
|
|
104
|
-
graph.addEdge({ source: 'test1', target: 'test2' });
|
|
105
104
|
|
|
106
|
-
|
|
107
|
-
expect(graph.
|
|
105
|
+
const graph = builder.build();
|
|
106
|
+
expect(Object.keys(graph.root.actionsMap['test-set'].actionsMap)).to.deep.equal(['test-action']);
|
|
108
107
|
});
|
|
109
108
|
|
|
110
|
-
test('
|
|
111
|
-
const
|
|
109
|
+
test('is updated when nodes change', async () => {
|
|
110
|
+
const builder = new GraphBuilder();
|
|
112
111
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
expect(root.nodes().map((node) => node.id)).to.deep.equal(['test1', 'test3', 'test2', 'test4']);
|
|
112
|
+
// TODO(burdon): Return TestNodeBuilder object.
|
|
113
|
+
const { nodeBuilder, addNode, removeNode, addAction, removeAction, addProperty, removeProperty } =
|
|
114
|
+
createTestNodeBuilder('test1', 2);
|
|
115
|
+
builder.addNodeBuilder('test1', nodeBuilder);
|
|
119
116
|
|
|
120
|
-
graph.
|
|
117
|
+
const graph = builder.build();
|
|
118
|
+
expect(graph.root.children).to.have.length(1);
|
|
119
|
+
addNode('root', { id: 'root-test2', label: 'root-test2' });
|
|
120
|
+
expect(graph.root.children).to.have.length(2);
|
|
121
|
+
expect(graph.root.childrenMap['root-test2'].children).to.have.length(0);
|
|
121
122
|
|
|
122
|
-
expect(root.
|
|
123
|
-
|
|
123
|
+
expect(graph.root.childrenMap['root-test1'].children).to.have.length(0);
|
|
124
|
+
addNode('root-test1', { id: 'root-test1-test2', label: 'root-test1-test2' });
|
|
125
|
+
expect(graph.root.childrenMap['root-test1'].children).to.have.length(1);
|
|
126
|
+
expect(graph.root.childrenMap['root-test1'].childrenMap['root-test1-test2'].children).to.have.length(0);
|
|
124
127
|
|
|
125
|
-
|
|
126
|
-
|
|
128
|
+
expect(graph.root.actions).to.have.length(1);
|
|
129
|
+
addAction('root', { id: 'root-test2', label: 'root-test2', invoke: () => {} });
|
|
130
|
+
expect(graph.root.actions).to.have.length(2);
|
|
127
131
|
|
|
128
|
-
graph.
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
});
|
|
132
|
-
graph.removeEdge({ source: 'root', target: 'test1' });
|
|
132
|
+
expect(graph.root.childrenMap['root-test1'].properties).to.not.have.property('test');
|
|
133
|
+
addProperty('root-test1', 'test', 'test');
|
|
134
|
+
expect(graph.root.childrenMap['root-test1'].properties.test).to.equal('test');
|
|
133
135
|
|
|
134
|
-
expect(graph.root.
|
|
135
|
-
|
|
136
|
-
|
|
136
|
+
expect(graph.root.children).to.have.length(2);
|
|
137
|
+
removeNode('root', 'root-test2');
|
|
138
|
+
expect(graph.root.children).to.have.length(1);
|
|
137
139
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
+
expect(graph.root.childrenMap['root-test1'].children).to.have.length(1);
|
|
141
|
+
removeNode('root-test1', 'root-test1-test2');
|
|
142
|
+
expect(graph.root.childrenMap['root-test1'].children).to.have.length(0);
|
|
140
143
|
|
|
141
|
-
graph.
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
});
|
|
145
|
-
graph.addEdge({ source: 'test1', target: 'test2' });
|
|
144
|
+
expect(graph.root.actions).to.have.length(2);
|
|
145
|
+
removeAction('root', 'root-test2');
|
|
146
|
+
expect(graph.root.actions).to.have.length(1);
|
|
146
147
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
nodes: [{ id: 'test1', nodes: [{ id: 'test2' }] }, { id: 'test2' }],
|
|
151
|
-
});
|
|
148
|
+
expect(graph.root.childrenMap['root-test1'].properties.test).to.equal('test');
|
|
149
|
+
removeProperty('root-test1', 'test');
|
|
150
|
+
expect(graph.root.childrenMap['root-test1'].properties).to.not.have.property('test');
|
|
152
151
|
});
|
|
153
152
|
|
|
154
|
-
test('
|
|
155
|
-
|
|
153
|
+
test.skip('node builder unsubscribe is called when builder is re-run', async () => {
|
|
154
|
+
// TODO(wittjosiah): Implement.
|
|
155
|
+
});
|
|
156
156
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
157
|
+
test('can find nodes', () => {
|
|
158
|
+
const builder = new GraphBuilder();
|
|
159
|
+
builder.addNodeBuilder('test1', createTestNodeBuilder('test1', 2).nodeBuilder);
|
|
160
|
+
builder.addNodeBuilder('test2', createTestNodeBuilder('test2').nodeBuilder);
|
|
161
161
|
|
|
162
|
-
const
|
|
163
|
-
graph.
|
|
164
|
-
expect(
|
|
162
|
+
const graph = builder.build();
|
|
163
|
+
expect(graph.findNode('root-test1')?.id).to.equal('root-test1');
|
|
164
|
+
expect(graph.findNode('root-test2-test1')?.id).to.equal('root-test2-test1');
|
|
165
165
|
});
|
|
166
166
|
|
|
167
|
-
test('
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
id: 'root',
|
|
172
|
-
nodes: [{ id: 'test1' }, { id: 'test2' }],
|
|
173
|
-
});
|
|
174
|
-
graph.addEdge({ source: 'test1', target: 'root' });
|
|
167
|
+
test('can be traversed', () => {
|
|
168
|
+
const builder = new GraphBuilder();
|
|
169
|
+
builder.addNodeBuilder('test1', createTestNodeBuilder('test1', 2).nodeBuilder);
|
|
170
|
+
builder.addNodeBuilder('test2', createTestNodeBuilder('test2').nodeBuilder);
|
|
175
171
|
|
|
172
|
+
const graph = builder.build();
|
|
176
173
|
const nodes: string[] = [];
|
|
177
|
-
graph.traverse({
|
|
178
|
-
expect(nodes).to.deep.equal(['root', 'test1', 'test2']);
|
|
174
|
+
graph.traverse({ visitor: (node) => nodes.push(node.id) });
|
|
175
|
+
expect(nodes).to.deep.equal(['root', 'root-test1', 'root-test2', 'root-test2-test1']);
|
|
179
176
|
});
|
|
180
177
|
|
|
181
178
|
test('traversal can be limited by predicate', () => {
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
id: 'root',
|
|
186
|
-
nodes: [{ id: 'test1' }, { id: 'test2' }, { id: 'test3' }, { id: 'test4' }],
|
|
187
|
-
});
|
|
179
|
+
const builder = new GraphBuilder();
|
|
180
|
+
builder.addNodeBuilder('test1', createTestNodeBuilder('test1', 2).nodeBuilder);
|
|
181
|
+
builder.addNodeBuilder('test2', createTestNodeBuilder('test2').nodeBuilder);
|
|
188
182
|
|
|
183
|
+
const graph = builder.build();
|
|
189
184
|
const nodes: string[] = [];
|
|
190
185
|
graph.traverse({
|
|
191
|
-
|
|
186
|
+
filter: (node) => node.id.includes('test1'),
|
|
192
187
|
visitor: (node) => nodes.push(node.id),
|
|
193
|
-
filter: (node) => {
|
|
194
|
-
try {
|
|
195
|
-
const id = parseInt(node.id.replace('test', ''), 10);
|
|
196
|
-
return id % 2 === 0;
|
|
197
|
-
} catch (e) {
|
|
198
|
-
return false;
|
|
199
|
-
}
|
|
200
|
-
},
|
|
201
188
|
});
|
|
202
|
-
expect(nodes).to.deep.equal(['
|
|
189
|
+
expect(nodes).to.deep.equal(['root-test1', 'root-test2-test1']);
|
|
203
190
|
});
|
|
204
191
|
|
|
205
192
|
test('traversal can be started from any node', () => {
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
id: 'root',
|
|
210
|
-
nodes: [{ id: 'test1', nodes: [{ id: 'test2', nodes: [{ id: 'test3' }] }] }],
|
|
211
|
-
});
|
|
193
|
+
const builder = new GraphBuilder();
|
|
194
|
+
builder.addNodeBuilder('test1', createTestNodeBuilder('test1', 2).nodeBuilder);
|
|
195
|
+
builder.addNodeBuilder('test2', createTestNodeBuilder('test2').nodeBuilder);
|
|
212
196
|
|
|
197
|
+
const graph = builder.build();
|
|
213
198
|
const nodes: string[] = [];
|
|
214
199
|
graph.traverse({
|
|
215
|
-
node: graph.
|
|
200
|
+
node: graph.root.childrenMap['root-test2'],
|
|
216
201
|
visitor: (node) => nodes.push(node.id),
|
|
217
202
|
});
|
|
218
|
-
expect(nodes).to.deep.equal(['test2', '
|
|
203
|
+
expect(nodes).to.deep.equal(['root-test2', 'root-test2-test1']);
|
|
219
204
|
});
|
|
220
205
|
|
|
221
|
-
test('
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
id: 'root',
|
|
226
|
-
nodes: [{ id: 'test1', nodes: [{ id: 'test2', nodes: [{ id: 'test3' }] }] }],
|
|
227
|
-
});
|
|
206
|
+
test('can traverse up', () => {
|
|
207
|
+
const builder = new GraphBuilder();
|
|
208
|
+
builder.addNodeBuilder('test1', createTestNodeBuilder('test1', 2).nodeBuilder);
|
|
209
|
+
builder.addNodeBuilder('test2', createTestNodeBuilder('test2').nodeBuilder);
|
|
228
210
|
|
|
211
|
+
const graph = builder.build();
|
|
229
212
|
const nodes: string[] = [];
|
|
230
213
|
graph.traverse({
|
|
231
|
-
|
|
232
|
-
|
|
214
|
+
direction: 'up',
|
|
215
|
+
node: graph.root.childrenMap['root-test2'].childrenMap['root-test2-test1'],
|
|
233
216
|
visitor: (node) => nodes.push(node.id),
|
|
234
217
|
});
|
|
235
|
-
expect(nodes).to.deep.equal(['test2', '
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
test('can filter to longest pathes', () => {
|
|
239
|
-
const graph = new Graph();
|
|
240
|
-
|
|
241
|
-
graph.addNodes({
|
|
242
|
-
id: 'root',
|
|
243
|
-
nodes: [{ id: 'test1' }, { id: 'test2' }],
|
|
244
|
-
});
|
|
245
|
-
graph.addEdge({ source: 'test1', target: 'test2' });
|
|
246
|
-
|
|
247
|
-
graph.traverse({
|
|
248
|
-
visitor: (node, path) => {
|
|
249
|
-
if (!longestPaths.has(node.id) || longestPaths.get(node.id)!.length < path.length) {
|
|
250
|
-
longestPaths.set(node.id, path);
|
|
251
|
-
}
|
|
252
|
-
},
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
expect(longestPaths.get('root')).to.deep.equal(['root']);
|
|
256
|
-
expect(longestPaths.get('test1')).to.deep.equal(['root', 'test1']);
|
|
257
|
-
expect(longestPaths.get('test2')).to.deep.equal(['root', 'test1', 'test2']);
|
|
258
|
-
expect(graph.root.nodes({ filter: filterLongestPath })).to.have.length(1);
|
|
259
|
-
expect(graph.findNode('test1')?.nodes({ filter: filterLongestPath })).to.have.length(1);
|
|
260
|
-
expect(graph.findNode('test2')?.nodes({ filter: filterLongestPath })).to.be.empty;
|
|
261
|
-
|
|
262
|
-
longestPaths.clear();
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
test('traversing the graph subscribes to changes', () => {
|
|
266
|
-
const graph = new Graph();
|
|
267
|
-
|
|
268
|
-
graph.addNodes({
|
|
269
|
-
id: 'root',
|
|
270
|
-
nodes: [{ id: 'test1' }, { id: 'test2' }],
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
const dispose = effect(() => {
|
|
274
|
-
graph.traverse({
|
|
275
|
-
visitor: (node, path) => {
|
|
276
|
-
if (!longestPaths.has(node.id) || longestPaths.get(node.id)!.length < path.length) {
|
|
277
|
-
longestPaths.set(node.id, path);
|
|
278
|
-
}
|
|
279
|
-
},
|
|
280
|
-
});
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
expect(longestPaths.get('root')).to.deep.equal(['root']);
|
|
284
|
-
expect(longestPaths.get('test1')).to.deep.equal(['root', 'test1']);
|
|
285
|
-
expect(longestPaths.get('test2')).to.deep.equal(['root', 'test2']);
|
|
286
|
-
expect(graph.root.nodes({ filter: filterLongestPath })).to.have.length(2);
|
|
287
|
-
expect(graph.findNode('test1')?.nodes({ filter: filterLongestPath })).to.be.empty;
|
|
288
|
-
expect(graph.findNode('test2')?.nodes({ filter: filterLongestPath })).to.be.empty;
|
|
289
|
-
|
|
290
|
-
graph.addEdge({ source: 'test1', target: 'test2' });
|
|
291
|
-
|
|
292
|
-
expect(longestPaths.get('root')).to.deep.equal(['root']);
|
|
293
|
-
expect(longestPaths.get('test1')).to.deep.equal(['root', 'test1']);
|
|
294
|
-
expect(longestPaths.get('test2')).to.deep.equal(['root', 'test1', 'test2']);
|
|
295
|
-
expect(graph.root.nodes({ filter: filterLongestPath })).to.have.length(1);
|
|
296
|
-
expect(graph.findNode('test1')?.nodes({ filter: filterLongestPath })).to.have.length(1);
|
|
297
|
-
expect(graph.findNode('test2')?.nodes({ filter: filterLongestPath })).to.be.empty;
|
|
298
|
-
|
|
299
|
-
dispose();
|
|
300
|
-
longestPaths.clear();
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
test('get path', () => {
|
|
304
|
-
const graph = new Graph();
|
|
305
|
-
|
|
306
|
-
graph.addNodes({
|
|
307
|
-
id: 'root',
|
|
308
|
-
nodes: [{ id: 'test1' }, { id: 'test2' }],
|
|
309
|
-
});
|
|
310
|
-
graph.addEdge({ source: 'test1', target: 'test2' });
|
|
311
|
-
|
|
312
|
-
expect(graph.getPath({ target: 'test2' })).to.deep.equal(['root', 'test1', 'test2']);
|
|
313
|
-
expect(graph.getPath({ source: 'test1', target: 'test2' })).to.deep.equal(['test1', 'test2']);
|
|
314
|
-
expect(graph.getPath({ source: 'test2', target: 'test1' })).to.be.undefined;
|
|
218
|
+
expect(nodes).to.deep.equal(['root-test2-test1', 'root-test2', 'root']);
|
|
315
219
|
});
|
|
316
220
|
});
|