pict-section-flow 1.3.0 → 2.0.0

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.
Files changed (162) hide show
  1. package/package.json +7 -2
  2. package/source/Pict-Section-Flow.js +20 -14
  3. package/source/providers/PictProvider-Flow-Background.js +303 -0
  4. package/source/providers/PictProvider-Flow-CSS.js +99 -7
  5. package/source/providers/PictProvider-Flow-ConnectorShapes.js +8 -0
  6. package/source/providers/PictProvider-Flow-Geometry.js +11 -421
  7. package/source/providers/PictProvider-Flow-Icons.js +20 -0
  8. package/source/providers/PictProvider-Flow-Layouts.js +107 -0
  9. package/source/services/PictService-Flow-ConnectionRenderer.js +77 -5
  10. package/source/services/PictService-Flow-CursorManager.js +113 -0
  11. package/source/services/PictService-Flow-InteractionManager.js +443 -61
  12. package/source/services/PictService-Flow-Layout.js +21 -16
  13. package/source/services/PictService-Flow-PathGenerator.js +30 -417
  14. package/source/services/PictService-Flow-RenderManager.js +9 -1
  15. package/source/services/PictService-Flow-ViewportManager.js +102 -0
  16. package/source/views/PictView-Flow-FloatingToolbar.js +57 -0
  17. package/source/views/PictView-Flow-Node.js +36 -0
  18. package/source/views/PictView-Flow-PropertiesPanel.js +27 -5
  19. package/source/views/PictView-Flow-Toolbar.js +148 -13
  20. package/source/views/PictView-Flow.js +628 -3
  21. package/.claude/launch.json +0 -11
  22. package/docs/.nojekyll +0 -0
  23. package/docs/Architecture.md +0 -163
  24. package/docs/Custom-Styling.md +0 -275
  25. package/docs/Data_Model.md +0 -149
  26. package/docs/Event_System.md +0 -156
  27. package/docs/Getting_Started.md +0 -237
  28. package/docs/Implementation_Reference.md +0 -528
  29. package/docs/Layout_Persistence.md +0 -117
  30. package/docs/README.md +0 -103
  31. package/docs/Theme_Integration.md +0 -150
  32. package/docs/_brand.json +0 -18
  33. package/docs/_cover.md +0 -17
  34. package/docs/_playground.json +0 -24
  35. package/docs/_sidebar.md +0 -57
  36. package/docs/_topbar.md +0 -8
  37. package/docs/_version.json +0 -7
  38. package/docs/api/PictFlowCard.md +0 -216
  39. package/docs/api/PictFlowCardPropertiesPanel.md +0 -235
  40. package/docs/api/addConnection.md +0 -101
  41. package/docs/api/addNode.md +0 -137
  42. package/docs/api/autoLayout.md +0 -77
  43. package/docs/api/getFlowData.md +0 -112
  44. package/docs/api/marshalToView.md +0 -95
  45. package/docs/api/openPanel.md +0 -128
  46. package/docs/api/registerHandler.md +0 -174
  47. package/docs/api/registerNodeType.md +0 -142
  48. package/docs/api/removeConnection.md +0 -57
  49. package/docs/api/removeNode.md +0 -80
  50. package/docs/api/saveLayout.md +0 -152
  51. package/docs/api/screenToSVGCoords.md +0 -68
  52. package/docs/api/selectNode.md +0 -116
  53. package/docs/api/setTheme.md +0 -168
  54. package/docs/api/setZoom.md +0 -97
  55. package/docs/api/toggleFullscreen.md +0 -68
  56. package/docs/card-help/EACH.md +0 -19
  57. package/docs/card-help/FREAD.md +0 -24
  58. package/docs/card-help/FWRITE.md +0 -24
  59. package/docs/card-help/GET.md +0 -22
  60. package/docs/card-help/ITE.md +0 -23
  61. package/docs/card-help/LOG.md +0 -23
  62. package/docs/card-help/NOTE.md +0 -17
  63. package/docs/card-help/PREV.md +0 -18
  64. package/docs/card-help/SET.md +0 -27
  65. package/docs/card-help/SPKL.md +0 -22
  66. package/docs/card-help/STAT.md +0 -23
  67. package/docs/card-help/SW.md +0 -25
  68. package/docs/diagrams/architecture-at-a-glance.excalidraw +0 -4270
  69. package/docs/diagrams/architecture-at-a-glance.mmd +0 -30
  70. package/docs/diagrams/architecture-at-a-glance.svg +0 -2
  71. package/docs/diagrams/data-flow.excalidraw +0 -1451
  72. package/docs/diagrams/data-flow.mmd +0 -17
  73. package/docs/diagrams/data-flow.svg +0 -2
  74. package/docs/diagrams/high-level-design.excalidraw +0 -5767
  75. package/docs/diagrams/high-level-design.mmd +0 -86
  76. package/docs/diagrams/high-level-design.svg +0 -2
  77. package/docs/diagrams/relationships.excalidraw +0 -3852
  78. package/docs/diagrams/relationships.mmd +0 -9
  79. package/docs/diagrams/relationships.svg +0 -2
  80. package/docs/diagrams/service-initialization-sequence.excalidraw +0 -1466
  81. package/docs/diagrams/service-initialization-sequence.mmd +0 -19
  82. package/docs/diagrams/service-initialization-sequence.svg +0 -2
  83. package/docs/diagrams/svg-layer-structure.excalidraw +0 -1060
  84. package/docs/diagrams/svg-layer-structure.mmd +0 -18
  85. package/docs/diagrams/svg-layer-structure.svg +0 -2
  86. package/docs/examples/README.md +0 -9
  87. package/docs/examples/simple_cards/README.md +0 -677
  88. package/docs/examples/simple_cards/css/flowexample.css +0 -65
  89. package/docs/examples/simple_cards/index.html +0 -32
  90. package/docs/examples/simple_cards/js/pict.min.js +0 -12
  91. package/docs/examples/simple_cards/pict-section-flow-example-simple-cards.compatible.min.js +0 -1
  92. package/docs/index.html +0 -38
  93. package/docs/playground/app.json +0 -6
  94. package/docs/playground/appdata.json +0 -85
  95. package/docs/playground/application.js +0 -23
  96. package/docs/playground/pict.json +0 -17
  97. package/docs/playground/runtime/pict-application.min.js +0 -2
  98. package/docs/playground/runtime/pict-section-flow.min.js +0 -2
  99. package/docs/playground/runtime/pict-section-modal.min.js +0 -2
  100. package/docs/playground/runtime/pict.min.js +0 -12
  101. package/docs/retold-catalog.json +0 -244
  102. package/docs/retold-keyword-index.json +0 -26028
  103. package/example_applications/simple_cards/css/flowexample.css +0 -65
  104. package/example_applications/simple_cards/html/index.html +0 -32
  105. package/example_applications/simple_cards/package.json +0 -52
  106. package/example_applications/simple_cards/source/Pict-Application-FlowExample-Configuration.json +0 -15
  107. package/example_applications/simple_cards/source/Pict-Application-FlowExample.js +0 -539
  108. package/example_applications/simple_cards/source/card-help-content.js +0 -16
  109. package/example_applications/simple_cards/source/cards/FlowCard-Comment.js +0 -38
  110. package/example_applications/simple_cards/source/cards/FlowCard-DataPreview.js +0 -44
  111. package/example_applications/simple_cards/source/cards/FlowCard-Each.js +0 -38
  112. package/example_applications/simple_cards/source/cards/FlowCard-FileRead.js +0 -56
  113. package/example_applications/simple_cards/source/cards/FlowCard-FileWrite.js +0 -50
  114. package/example_applications/simple_cards/source/cards/FlowCard-GetValue.js +0 -37
  115. package/example_applications/simple_cards/source/cards/FlowCard-IfThenElse.js +0 -49
  116. package/example_applications/simple_cards/source/cards/FlowCard-LogValues.js +0 -55
  117. package/example_applications/simple_cards/source/cards/FlowCard-SetValue.js +0 -97
  118. package/example_applications/simple_cards/source/cards/FlowCard-Sparkline.js +0 -100
  119. package/example_applications/simple_cards/source/cards/FlowCard-StatusMonitor.js +0 -46
  120. package/example_applications/simple_cards/source/cards/FlowCard-Switch.js +0 -39
  121. package/example_applications/simple_cards/source/providers/PictRouter-FlowExample-Configuration.json +0 -22
  122. package/example_applications/simple_cards/source/sample-flows.js +0 -410
  123. package/example_applications/simple_cards/source/views/PictView-FlowExample-About.js +0 -184
  124. package/example_applications/simple_cards/source/views/PictView-FlowExample-BottomBar.js +0 -77
  125. package/example_applications/simple_cards/source/views/PictView-FlowExample-Documentation.js +0 -325
  126. package/example_applications/simple_cards/source/views/PictView-FlowExample-FileWriteInfo.js +0 -59
  127. package/example_applications/simple_cards/source/views/PictView-FlowExample-Layout.js +0 -90
  128. package/example_applications/simple_cards/source/views/PictView-FlowExample-MainWorkspace.js +0 -453
  129. package/example_applications/simple_cards/source/views/PictView-FlowExample-TopBar.js +0 -95
  130. package/scripts/generate-card-help.js +0 -214
  131. package/source/providers/edges/Edge-Bezier.js +0 -41
  132. package/source/providers/edges/Edge-Orthogonal.js +0 -37
  133. package/source/providers/edges/Edge-OrthogonalSnap.js +0 -72
  134. package/source/providers/edges/Edge-Perimeter-Linear.js +0 -31
  135. package/source/providers/edges/Edge-Perimeter-Orthogonal.js +0 -39
  136. package/source/providers/edges/Edge-Perimeter.js +0 -48
  137. package/source/providers/edges/Edge-PerimeterMath.js +0 -92
  138. package/source/providers/edges/Edge-Straight.js +0 -24
  139. package/source/providers/layouts/Layout-Circular.js +0 -203
  140. package/source/providers/layouts/Layout-Coerce.js +0 -40
  141. package/source/providers/layouts/Layout-Columnar.js +0 -134
  142. package/source/providers/layouts/Layout-Custom.js +0 -27
  143. package/source/providers/layouts/Layout-ForcedFromCenter.js +0 -256
  144. package/source/providers/layouts/Layout-Grid.js +0 -134
  145. package/source/providers/layouts/Layout-Layered.js +0 -155
  146. package/source/providers/layouts/Layout-Rank.js +0 -141
  147. package/source/providers/layouts/Layout-Staggered.js +0 -131
  148. package/source/providers/layouts/Layout-Tabular.js +0 -94
  149. package/test/ConnectionHandleManager_tests.js +0 -717
  150. package/test/ConnectionRenderer_tests.js +0 -591
  151. package/test/DataManager_tests.js +0 -859
  152. package/test/Geometry_tests.js +0 -767
  153. package/test/InteractionManager_tests.js +0 -279
  154. package/test/Layout_tests.js +0 -1604
  155. package/test/NodeView_tests.js +0 -66
  156. package/test/PanelManager_tests.js +0 -172
  157. package/test/PathGenerator_tests.js +0 -978
  158. package/test/PortRenderer_tests.js +0 -376
  159. package/test/RenderManager_tests.js +0 -756
  160. package/test/Renderer_tests.js +0 -133
  161. package/test/SelectionManager_tests.js +0 -185
  162. package/test/StylePresets_tests.js +0 -153
@@ -1,859 +0,0 @@
1
- const libFable = require('fable');
2
- const libChai = require('chai');
3
- const libExpect = libChai.expect;
4
-
5
- const libDataManager = require('../source/services/PictService-Flow-DataManager.js');
6
-
7
- suite
8
- (
9
- 'PictService-Flow-DataManager',
10
- function ()
11
- {
12
- let _Fable;
13
- let _DataManager;
14
- let _MockFlowView;
15
-
16
- setup
17
- (
18
- function ()
19
- {
20
- _Fable = new libFable({});
21
-
22
- _MockFlowView =
23
- {
24
- fable: _Fable,
25
- pict: null,
26
- log: _Fable.log,
27
- options:
28
- {
29
- DefaultNodeType: 'generic',
30
- DefaultNodeWidth: 160,
31
- DefaultNodeHeight: 80,
32
- FlowDataAddress: null
33
- },
34
- Bundle: {},
35
- initialRenderComplete: false,
36
- _FlowData:
37
- {
38
- Nodes: [],
39
- Connections: [],
40
- OpenPanels: [],
41
- SavedLayouts: [],
42
- ViewState:
43
- {
44
- PanX: 0,
45
- PanY: 0,
46
- Zoom: 1,
47
- SelectedNodeHash: null,
48
- SelectedConnectionHash: null,
49
- SelectedTetherHash: null
50
- }
51
- },
52
- _NodeTypeProvider:
53
- {
54
- getNodeType: function (pType)
55
- {
56
- if (pType === 'action')
57
- {
58
- return {
59
- Label: 'Action',
60
- DefaultWidth: 200,
61
- DefaultHeight: 100,
62
- DefaultPorts:
63
- [
64
- { Hash: 'p-in', Direction: 'input', Side: 'left', Label: 'In' },
65
- { Hash: 'p-out', Direction: 'output', Side: 'right', Label: 'Out' },
66
- { Hash: 'p-err', Direction: 'output', Side: 'bottom', Label: 'Error', PortType: 'error' }
67
- ]
68
- };
69
- }
70
- return null;
71
- }
72
- },
73
- _LayoutProvider:
74
- {
75
- loadPersistedLayouts: function () {}
76
- },
77
- _EventHandlerProvider:
78
- {
79
- fireEvent: function () {}
80
- },
81
- renderFlow: function () {},
82
- closePanelForNode: function (pNodeHash)
83
- {
84
- _MockFlowView._FlowData.OpenPanels = _MockFlowView._FlowData.OpenPanels.filter(
85
- (pPanel) => pPanel.NodeHash !== pNodeHash
86
- );
87
- },
88
- marshalFromView: function () {}
89
- };
90
-
91
- _DataManager = new libDataManager(_Fable, { FlowView: _MockFlowView }, 'DM-Test');
92
- }
93
- );
94
-
95
- // ---- Constructor ----
96
-
97
- suite
98
- (
99
- 'Constructor',
100
- function ()
101
- {
102
- test
103
- (
104
- 'should instantiate with correct serviceType',
105
- function (fDone)
106
- {
107
- libExpect(_DataManager).to.be.an('object');
108
- libExpect(_DataManager.serviceType).to.equal('PictServiceFlowDataManager');
109
- fDone();
110
- }
111
- );
112
-
113
- test
114
- (
115
- 'should store FlowView reference from options',
116
- function (fDone)
117
- {
118
- libExpect(_DataManager._FlowView).to.equal(_MockFlowView);
119
- fDone();
120
- }
121
- );
122
-
123
- test
124
- (
125
- 'should handle missing FlowView in options',
126
- function (fDone)
127
- {
128
- let tmpManager = new libDataManager(_Fable, {}, 'NoView');
129
- libExpect(tmpManager._FlowView).to.be.null;
130
- fDone();
131
- }
132
- );
133
- }
134
- );
135
-
136
- // ---- getFlowData ----
137
-
138
- suite
139
- (
140
- 'getFlowData',
141
- function ()
142
- {
143
- test
144
- (
145
- 'should return a deep clone of the flow data',
146
- function (fDone)
147
- {
148
- _MockFlowView._FlowData.Nodes.push({ Hash: 'node-1', X: 10, Y: 20 });
149
- let tmpResult = _DataManager.getFlowData();
150
-
151
- libExpect(tmpResult.Nodes).to.have.length(1);
152
- libExpect(tmpResult.Nodes[0].Hash).to.equal('node-1');
153
-
154
- // Verify it's a clone, not a reference
155
- tmpResult.Nodes[0].X = 999;
156
- libExpect(_MockFlowView._FlowData.Nodes[0].X).to.equal(10);
157
- fDone();
158
- }
159
- );
160
-
161
- test
162
- (
163
- 'should return empty object when no FlowView',
164
- function (fDone)
165
- {
166
- let tmpManager = new libDataManager(_Fable, {}, 'NoView');
167
- let tmpResult = tmpManager.getFlowData();
168
- libExpect(tmpResult).to.deep.equal({});
169
- fDone();
170
- }
171
- );
172
- }
173
- );
174
-
175
- // ---- setFlowData ----
176
-
177
- suite
178
- (
179
- 'setFlowData',
180
- function ()
181
- {
182
- test
183
- (
184
- 'should set flow data with validated structure',
185
- function (fDone)
186
- {
187
- let tmpData =
188
- {
189
- Nodes: [{ Hash: 'n1', X: 50, Y: 50 }],
190
- Connections: [{ Hash: 'c1', SourceNodeHash: 'n1', TargetNodeHash: 'n2' }],
191
- ViewState: { PanX: 100, PanY: 200, Zoom: 2 }
192
- };
193
-
194
- _DataManager.setFlowData(tmpData);
195
-
196
- libExpect(_MockFlowView._FlowData.Nodes).to.have.length(1);
197
- libExpect(_MockFlowView._FlowData.Connections).to.have.length(1);
198
- libExpect(_MockFlowView._FlowData.ViewState.PanX).to.equal(100);
199
- libExpect(_MockFlowView._FlowData.ViewState.Zoom).to.equal(2);
200
- fDone();
201
- }
202
- );
203
-
204
- test
205
- (
206
- 'should provide defaults for missing arrays',
207
- function (fDone)
208
- {
209
- _DataManager.setFlowData({ ViewState: { PanX: 10 } });
210
-
211
- libExpect(_MockFlowView._FlowData.Nodes).to.be.an('array').that.is.empty;
212
- libExpect(_MockFlowView._FlowData.Connections).to.be.an('array').that.is.empty;
213
- libExpect(_MockFlowView._FlowData.OpenPanels).to.be.an('array').that.is.empty;
214
- libExpect(_MockFlowView._FlowData.SavedLayouts).to.be.an('array').that.is.empty;
215
- fDone();
216
- }
217
- );
218
-
219
- test
220
- (
221
- 'should provide default ViewState when missing',
222
- function (fDone)
223
- {
224
- _DataManager.setFlowData({ Nodes: [] });
225
-
226
- libExpect(_MockFlowView._FlowData.ViewState.PanX).to.equal(0);
227
- libExpect(_MockFlowView._FlowData.ViewState.PanY).to.equal(0);
228
- libExpect(_MockFlowView._FlowData.ViewState.Zoom).to.equal(1);
229
- libExpect(_MockFlowView._FlowData.ViewState.SelectedNodeHash).to.be.null;
230
- fDone();
231
- }
232
- );
233
-
234
- test
235
- (
236
- 'should reject null data',
237
- function (fDone)
238
- {
239
- let tmpOriginalNodes = _MockFlowView._FlowData.Nodes;
240
- _DataManager.setFlowData(null);
241
- // Should not have changed
242
- libExpect(_MockFlowView._FlowData.Nodes).to.equal(tmpOriginalNodes);
243
- fDone();
244
- }
245
- );
246
-
247
- test
248
- (
249
- 'should reject non-object data',
250
- function (fDone)
251
- {
252
- let tmpOriginalNodes = _MockFlowView._FlowData.Nodes;
253
- _DataManager.setFlowData('invalid');
254
- libExpect(_MockFlowView._FlowData.Nodes).to.equal(tmpOriginalNodes);
255
- fDone();
256
- }
257
- );
258
-
259
- test
260
- (
261
- 'should call renderFlow when initialRenderComplete is true',
262
- function (fDone)
263
- {
264
- let tmpRenderCalled = false;
265
- _MockFlowView.renderFlow = function () { tmpRenderCalled = true; };
266
- _MockFlowView.initialRenderComplete = true;
267
-
268
- _DataManager.setFlowData({ Nodes: [] });
269
-
270
- libExpect(tmpRenderCalled).to.be.true;
271
- fDone();
272
- }
273
- );
274
-
275
- test
276
- (
277
- 'should not call renderFlow when initialRenderComplete is false',
278
- function (fDone)
279
- {
280
- let tmpRenderCalled = false;
281
- _MockFlowView.renderFlow = function () { tmpRenderCalled = true; };
282
- _MockFlowView.initialRenderComplete = false;
283
-
284
- _DataManager.setFlowData({ Nodes: [] });
285
-
286
- libExpect(tmpRenderCalled).to.be.false;
287
- fDone();
288
- }
289
- );
290
-
291
- test
292
- (
293
- 'should call loadPersistedLayouts when LayoutProvider exists',
294
- function (fDone)
295
- {
296
- let tmpLoadCalled = false;
297
- _MockFlowView._LayoutProvider.loadPersistedLayouts = function () { tmpLoadCalled = true; };
298
-
299
- _DataManager.setFlowData({ Nodes: [] });
300
-
301
- libExpect(tmpLoadCalled).to.be.true;
302
- fDone();
303
- }
304
- );
305
- }
306
- );
307
-
308
- // ---- addNode ----
309
-
310
- suite
311
- (
312
- 'addNode',
313
- function ()
314
- {
315
- test
316
- (
317
- 'should add a node with generated hash',
318
- function (fDone)
319
- {
320
- let tmpNode = _DataManager.addNode('generic', 200, 300, 'Test Node');
321
-
322
- libExpect(tmpNode).to.be.an('object');
323
- libExpect(tmpNode.Hash).to.be.a('string').that.includes('node-');
324
- libExpect(tmpNode.X).to.equal(200);
325
- libExpect(tmpNode.Y).to.equal(300);
326
- libExpect(tmpNode.Title).to.equal('Test Node');
327
- libExpect(_MockFlowView._FlowData.Nodes).to.have.length(1);
328
- fDone();
329
- }
330
- );
331
-
332
- test
333
- (
334
- 'should use node type config for defaults',
335
- function (fDone)
336
- {
337
- let tmpNode = _DataManager.addNode('action', 100, 100);
338
-
339
- libExpect(tmpNode.Width).to.equal(200);
340
- libExpect(tmpNode.Height).to.equal(100);
341
- libExpect(tmpNode.Title).to.equal('Action');
342
- libExpect(tmpNode.Ports).to.have.length(3);
343
- fDone();
344
- }
345
- );
346
-
347
- test
348
- (
349
- 'should use option defaults when type config is null',
350
- function (fDone)
351
- {
352
- let tmpNode = _DataManager.addNode('unknown', 100, 100, 'My Node');
353
-
354
- libExpect(tmpNode.Width).to.equal(160);
355
- libExpect(tmpNode.Height).to.equal(80);
356
- libExpect(tmpNode.Title).to.equal('My Node');
357
- // Default ports (2 generic)
358
- libExpect(tmpNode.Ports).to.have.length(2);
359
- fDone();
360
- }
361
- );
362
-
363
- test
364
- (
365
- 'should use DefaultNodeType when type is null',
366
- function (fDone)
367
- {
368
- let tmpNode = _DataManager.addNode(null, 100, 100, 'Fallback');
369
-
370
- libExpect(tmpNode.Type).to.equal('generic');
371
- fDone();
372
- }
373
- );
374
-
375
- test
376
- (
377
- 'should default position to 100,100 when not provided',
378
- function (fDone)
379
- {
380
- let tmpNode = _DataManager.addNode('generic', 0, 0);
381
-
382
- // 0 is falsy, so it should fall back to 100
383
- // (This tests the || operator behavior)
384
- libExpect(tmpNode.X).to.equal(100);
385
- libExpect(tmpNode.Y).to.equal(100);
386
- fDone();
387
- }
388
- );
389
-
390
- test
391
- (
392
- 'should ensure all ports have unique hashes',
393
- function (fDone)
394
- {
395
- let tmpNode = _DataManager.addNode('action', 100, 100);
396
- let tmpHashes = tmpNode.Ports.map((p) => p.Hash);
397
- let tmpUnique = new Set(tmpHashes);
398
- libExpect(tmpUnique.size).to.equal(tmpHashes.length);
399
- fDone();
400
- }
401
- );
402
-
403
- test
404
- (
405
- 'should call renderFlow and marshalFromView',
406
- function (fDone)
407
- {
408
- let tmpRenderCalled = false;
409
- let tmpMarshalCalled = false;
410
- _MockFlowView.renderFlow = function () { tmpRenderCalled = true; };
411
- _DataManager.marshalFromView = function () { tmpMarshalCalled = true; };
412
-
413
- _DataManager.addNode('generic', 100, 100);
414
-
415
- libExpect(tmpRenderCalled).to.be.true;
416
- libExpect(tmpMarshalCalled).to.be.true;
417
- fDone();
418
- }
419
- );
420
-
421
- test
422
- (
423
- 'should fire onNodeAdded and onFlowChanged events',
424
- function (fDone)
425
- {
426
- let tmpEvents = [];
427
- _MockFlowView._EventHandlerProvider.fireEvent = function (pEvent) { tmpEvents.push(pEvent); };
428
-
429
- _DataManager.addNode('generic', 100, 100);
430
-
431
- libExpect(tmpEvents).to.include('onNodeAdded');
432
- libExpect(tmpEvents).to.include('onFlowChanged');
433
- fDone();
434
- }
435
- );
436
-
437
- test
438
- (
439
- 'should return null when no FlowView',
440
- function (fDone)
441
- {
442
- let tmpManager = new libDataManager(_Fable, {}, 'NoView');
443
- let tmpResult = tmpManager.addNode('generic', 100, 100);
444
- libExpect(tmpResult).to.be.null;
445
- fDone();
446
- }
447
- );
448
-
449
- test
450
- (
451
- 'should include custom data when provided',
452
- function (fDone)
453
- {
454
- let tmpNode = _DataManager.addNode('generic', 100, 100, 'Test', { foo: 'bar' });
455
- libExpect(tmpNode.Data).to.deep.equal({ foo: 'bar' });
456
- fDone();
457
- }
458
- );
459
- }
460
- );
461
-
462
- // ---- removeNode ----
463
-
464
- suite
465
- (
466
- 'removeNode',
467
- function ()
468
- {
469
- test
470
- (
471
- 'should remove a node by hash',
472
- function (fDone)
473
- {
474
- let tmpNode = _DataManager.addNode('generic', 100, 100, 'ToRemove');
475
- libExpect(_MockFlowView._FlowData.Nodes).to.have.length(1);
476
-
477
- let tmpResult = _DataManager.removeNode(tmpNode.Hash);
478
- libExpect(tmpResult).to.be.true;
479
- libExpect(_MockFlowView._FlowData.Nodes).to.have.length(0);
480
- fDone();
481
- }
482
- );
483
-
484
- test
485
- (
486
- 'should return false for non-existent node',
487
- function (fDone)
488
- {
489
- let tmpResult = _DataManager.removeNode('non-existent');
490
- libExpect(tmpResult).to.be.false;
491
- fDone();
492
- }
493
- );
494
-
495
- test
496
- (
497
- 'should cascade-delete connections involving the node',
498
- function (fDone)
499
- {
500
- // Set up two nodes with a connection
501
- _MockFlowView._FlowData.Nodes = [
502
- { Hash: 'n1', Ports: [{ Hash: 'p1', Direction: 'output' }] },
503
- { Hash: 'n2', Ports: [{ Hash: 'p2', Direction: 'input' }] }
504
- ];
505
- _MockFlowView._FlowData.Connections = [
506
- { Hash: 'c1', SourceNodeHash: 'n1', SourcePortHash: 'p1', TargetNodeHash: 'n2', TargetPortHash: 'p2' }
507
- ];
508
-
509
- _DataManager.removeNode('n1');
510
-
511
- libExpect(_MockFlowView._FlowData.Connections).to.have.length(0);
512
- fDone();
513
- }
514
- );
515
-
516
- test
517
- (
518
- 'should close open panels for the node',
519
- function (fDone)
520
- {
521
- _MockFlowView._FlowData.Nodes = [{ Hash: 'n1' }];
522
- _MockFlowView._FlowData.OpenPanels = [{ Hash: 'panel-1', NodeHash: 'n1' }];
523
-
524
- _DataManager.removeNode('n1');
525
-
526
- libExpect(_MockFlowView._FlowData.OpenPanels).to.have.length(0);
527
- fDone();
528
- }
529
- );
530
-
531
- test
532
- (
533
- 'should clear selection if removed node was selected',
534
- function (fDone)
535
- {
536
- _MockFlowView._FlowData.Nodes = [{ Hash: 'n1' }];
537
- _MockFlowView._FlowData.ViewState.SelectedNodeHash = 'n1';
538
-
539
- _DataManager.removeNode('n1');
540
-
541
- libExpect(_MockFlowView._FlowData.ViewState.SelectedNodeHash).to.be.null;
542
- fDone();
543
- }
544
- );
545
-
546
- test
547
- (
548
- 'should fire onNodeRemoved and onFlowChanged events',
549
- function (fDone)
550
- {
551
- _MockFlowView._FlowData.Nodes = [{ Hash: 'n1' }];
552
- let tmpEvents = [];
553
- _MockFlowView._EventHandlerProvider.fireEvent = function (pEvent) { tmpEvents.push(pEvent); };
554
-
555
- _DataManager.removeNode('n1');
556
-
557
- libExpect(tmpEvents).to.include('onNodeRemoved');
558
- libExpect(tmpEvents).to.include('onFlowChanged');
559
- fDone();
560
- }
561
- );
562
-
563
- test
564
- (
565
- 'should return false when no FlowView',
566
- function (fDone)
567
- {
568
- let tmpManager = new libDataManager(_Fable, {}, 'NoView');
569
- let tmpResult = tmpManager.removeNode('n1');
570
- libExpect(tmpResult).to.be.false;
571
- fDone();
572
- }
573
- );
574
- }
575
- );
576
-
577
- // ---- addConnection ----
578
-
579
- suite
580
- (
581
- 'addConnection',
582
- function ()
583
- {
584
- setup
585
- (
586
- function ()
587
- {
588
- // Set up two nodes with ports
589
- _MockFlowView._FlowData.Nodes = [
590
- {
591
- Hash: 'n1',
592
- Ports: [
593
- { Hash: 'p-out-1', Direction: 'output', Side: 'right', Label: 'Out' }
594
- ]
595
- },
596
- {
597
- Hash: 'n2',
598
- Ports: [
599
- { Hash: 'p-in-2', Direction: 'input', Side: 'left', Label: 'In' }
600
- ]
601
- }
602
- ];
603
- _MockFlowView._FlowData.Connections = [];
604
- }
605
- );
606
-
607
- test
608
- (
609
- 'should create a connection between valid nodes/ports',
610
- function (fDone)
611
- {
612
- let tmpConn = _DataManager.addConnection('n1', 'p-out-1', 'n2', 'p-in-2');
613
-
614
- libExpect(tmpConn).to.be.an('object');
615
- libExpect(tmpConn.Hash).to.be.a('string').that.includes('conn-');
616
- libExpect(tmpConn.SourceNodeHash).to.equal('n1');
617
- libExpect(tmpConn.TargetNodeHash).to.equal('n2');
618
- libExpect(_MockFlowView._FlowData.Connections).to.have.length(1);
619
- fDone();
620
- }
621
- );
622
-
623
- test
624
- (
625
- 'should return false for missing source node',
626
- function (fDone)
627
- {
628
- let tmpResult = _DataManager.addConnection('non-existent', 'p-out-1', 'n2', 'p-in-2');
629
- libExpect(tmpResult).to.be.false;
630
- fDone();
631
- }
632
- );
633
-
634
- test
635
- (
636
- 'should return false for missing target node',
637
- function (fDone)
638
- {
639
- let tmpResult = _DataManager.addConnection('n1', 'p-out-1', 'non-existent', 'p-in-2');
640
- libExpect(tmpResult).to.be.false;
641
- fDone();
642
- }
643
- );
644
-
645
- test
646
- (
647
- 'should return false for missing source port',
648
- function (fDone)
649
- {
650
- let tmpResult = _DataManager.addConnection('n1', 'bad-port', 'n2', 'p-in-2');
651
- libExpect(tmpResult).to.be.false;
652
- fDone();
653
- }
654
- );
655
-
656
- test
657
- (
658
- 'should return false for missing target port',
659
- function (fDone)
660
- {
661
- let tmpResult = _DataManager.addConnection('n1', 'p-out-1', 'n2', 'bad-port');
662
- libExpect(tmpResult).to.be.false;
663
- fDone();
664
- }
665
- );
666
-
667
- test
668
- (
669
- 'should prevent self-connections',
670
- function (fDone)
671
- {
672
- _MockFlowView._FlowData.Nodes[0].Ports.push(
673
- { Hash: 'p-in-1', Direction: 'input', Side: 'left', Label: 'In' }
674
- );
675
-
676
- let tmpResult = _DataManager.addConnection('n1', 'p-out-1', 'n1', 'p-in-1');
677
- libExpect(tmpResult).to.be.false;
678
- fDone();
679
- }
680
- );
681
-
682
- test
683
- (
684
- 'should prevent duplicate connections',
685
- function (fDone)
686
- {
687
- _DataManager.addConnection('n1', 'p-out-1', 'n2', 'p-in-2');
688
- let tmpResult = _DataManager.addConnection('n1', 'p-out-1', 'n2', 'p-in-2');
689
-
690
- libExpect(tmpResult).to.be.false;
691
- libExpect(_MockFlowView._FlowData.Connections).to.have.length(1);
692
- fDone();
693
- }
694
- );
695
-
696
- test
697
- (
698
- 'should include custom data when provided',
699
- function (fDone)
700
- {
701
- let tmpConn = _DataManager.addConnection('n1', 'p-out-1', 'n2', 'p-in-2', { LineMode: 'bezier' });
702
- libExpect(tmpConn.Data).to.deep.equal({ LineMode: 'bezier' });
703
- fDone();
704
- }
705
- );
706
-
707
- test
708
- (
709
- 'should fire onConnectionCreated and onFlowChanged events',
710
- function (fDone)
711
- {
712
- let tmpEvents = [];
713
- _MockFlowView._EventHandlerProvider.fireEvent = function (pEvent) { tmpEvents.push(pEvent); };
714
-
715
- _DataManager.addConnection('n1', 'p-out-1', 'n2', 'p-in-2');
716
-
717
- libExpect(tmpEvents).to.include('onConnectionCreated');
718
- libExpect(tmpEvents).to.include('onFlowChanged');
719
- fDone();
720
- }
721
- );
722
-
723
- test
724
- (
725
- 'should return false when no FlowView',
726
- function (fDone)
727
- {
728
- let tmpManager = new libDataManager(_Fable, {}, 'NoView');
729
- let tmpResult = tmpManager.addConnection('n1', 'p1', 'n2', 'p2');
730
- libExpect(tmpResult).to.be.false;
731
- fDone();
732
- }
733
- );
734
- }
735
- );
736
-
737
- // ---- removeConnection ----
738
-
739
- suite
740
- (
741
- 'removeConnection',
742
- function ()
743
- {
744
- test
745
- (
746
- 'should remove a connection by hash',
747
- function (fDone)
748
- {
749
- _MockFlowView._FlowData.Nodes = [
750
- { Hash: 'n1', Ports: [{ Hash: 'p1', Direction: 'output' }] },
751
- { Hash: 'n2', Ports: [{ Hash: 'p2', Direction: 'input' }] }
752
- ];
753
-
754
- let tmpConn = _DataManager.addConnection('n1', 'p1', 'n2', 'p2');
755
- libExpect(_MockFlowView._FlowData.Connections).to.have.length(1);
756
-
757
- let tmpResult = _DataManager.removeConnection(tmpConn.Hash);
758
- libExpect(tmpResult).to.be.true;
759
- libExpect(_MockFlowView._FlowData.Connections).to.have.length(0);
760
- fDone();
761
- }
762
- );
763
-
764
- test
765
- (
766
- 'should return false for non-existent connection',
767
- function (fDone)
768
- {
769
- let tmpResult = _DataManager.removeConnection('non-existent');
770
- libExpect(tmpResult).to.be.false;
771
- fDone();
772
- }
773
- );
774
-
775
- test
776
- (
777
- 'should clear selection if removed connection was selected',
778
- function (fDone)
779
- {
780
- _MockFlowView._FlowData.Connections = [
781
- { Hash: 'c1', SourceNodeHash: 'n1', TargetNodeHash: 'n2' }
782
- ];
783
- _MockFlowView._FlowData.ViewState.SelectedConnectionHash = 'c1';
784
-
785
- _DataManager.removeConnection('c1');
786
-
787
- libExpect(_MockFlowView._FlowData.ViewState.SelectedConnectionHash).to.be.null;
788
- fDone();
789
- }
790
- );
791
-
792
- test
793
- (
794
- 'should fire onConnectionRemoved and onFlowChanged events',
795
- function (fDone)
796
- {
797
- _MockFlowView._FlowData.Connections = [
798
- { Hash: 'c1', SourceNodeHash: 'n1', TargetNodeHash: 'n2' }
799
- ];
800
- let tmpEvents = [];
801
- _MockFlowView._EventHandlerProvider.fireEvent = function (pEvent) { tmpEvents.push(pEvent); };
802
-
803
- _DataManager.removeConnection('c1');
804
-
805
- libExpect(tmpEvents).to.include('onConnectionRemoved');
806
- libExpect(tmpEvents).to.include('onFlowChanged');
807
- fDone();
808
- }
809
- );
810
-
811
- test
812
- (
813
- 'should return false when no FlowView',
814
- function (fDone)
815
- {
816
- let tmpManager = new libDataManager(_Fable, {}, 'NoView');
817
- let tmpResult = tmpManager.removeConnection('c1');
818
- libExpect(tmpResult).to.be.false;
819
- fDone();
820
- }
821
- );
822
- }
823
- );
824
-
825
- // ---- marshalToView / marshalFromView ----
826
-
827
- suite
828
- (
829
- 'marshalToView and marshalFromView',
830
- function ()
831
- {
832
- test
833
- (
834
- 'should be no-ops when FlowDataAddress is not set',
835
- function (fDone)
836
- {
837
- // marshalToView with no FlowDataAddress should not crash
838
- _DataManager.marshalToView();
839
- // marshalFromView with no FlowDataAddress should not crash
840
- _DataManager.marshalFromView();
841
- fDone();
842
- }
843
- );
844
-
845
- test
846
- (
847
- 'should be no-ops when no FlowView',
848
- function (fDone)
849
- {
850
- let tmpManager = new libDataManager(_Fable, {}, 'NoView');
851
- tmpManager.marshalToView();
852
- tmpManager.marshalFromView();
853
- fDone();
854
- }
855
- );
856
- }
857
- );
858
- }
859
- );