pict-section-flow 0.0.10 → 0.0.13

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 (88) hide show
  1. package/.claude/launch.json +1 -1
  2. package/README.md +176 -0
  3. package/docs/.nojekyll +0 -0
  4. package/docs/Architecture.md +303 -0
  5. package/docs/Custom-Styling.md +275 -0
  6. package/docs/Data_Model.md +158 -0
  7. package/docs/Event_System.md +156 -0
  8. package/docs/Getting_Started.md +237 -0
  9. package/docs/Implementation_Reference.md +528 -0
  10. package/docs/Layout_Persistence.md +117 -0
  11. package/docs/README.md +115 -52
  12. package/docs/_cover.md +11 -0
  13. package/docs/_sidebar.md +52 -0
  14. package/docs/_topbar.md +8 -0
  15. package/docs/api/PictFlowCard.md +216 -0
  16. package/docs/api/PictFlowCardPropertiesPanel.md +235 -0
  17. package/docs/api/addConnection.md +101 -0
  18. package/docs/api/addNode.md +137 -0
  19. package/docs/api/autoLayout.md +77 -0
  20. package/docs/api/getFlowData.md +112 -0
  21. package/docs/api/marshalToView.md +95 -0
  22. package/docs/api/openPanel.md +128 -0
  23. package/docs/api/registerHandler.md +174 -0
  24. package/docs/api/registerNodeType.md +142 -0
  25. package/docs/api/removeConnection.md +57 -0
  26. package/docs/api/removeNode.md +80 -0
  27. package/docs/api/saveLayout.md +152 -0
  28. package/docs/api/screenToSVGCoords.md +68 -0
  29. package/docs/api/selectNode.md +116 -0
  30. package/docs/api/setTheme.md +168 -0
  31. package/docs/api/setZoom.md +97 -0
  32. package/docs/api/toggleFullscreen.md +68 -0
  33. package/docs/card-help/EACH.md +19 -0
  34. package/docs/card-help/FREAD.md +24 -0
  35. package/docs/card-help/FWRITE.md +24 -0
  36. package/docs/card-help/GET.md +22 -0
  37. package/docs/card-help/ITE.md +23 -0
  38. package/docs/card-help/LOG.md +23 -0
  39. package/docs/card-help/NOTE.md +17 -0
  40. package/docs/card-help/PREV.md +18 -0
  41. package/docs/card-help/SET.md +27 -0
  42. package/docs/card-help/SPKL.md +22 -0
  43. package/docs/card-help/STAT.md +23 -0
  44. package/docs/card-help/SW.md +25 -0
  45. package/docs/css/docuserve.css +73 -0
  46. package/docs/index.html +39 -0
  47. package/docs/retold-catalog.json +169 -0
  48. package/docs/retold-keyword-index.json +13942 -0
  49. package/example_applications/simple_cards/package.json +1 -0
  50. package/example_applications/simple_cards/source/card-help-content.js +16 -0
  51. package/example_applications/simple_cards/source/cards/FlowCard-Comment.js +2 -0
  52. package/example_applications/simple_cards/source/cards/FlowCard-DataPreview.js +2 -0
  53. package/example_applications/simple_cards/source/cards/FlowCard-Each.js +2 -0
  54. package/example_applications/simple_cards/source/cards/FlowCard-FileRead.js +2 -0
  55. package/example_applications/simple_cards/source/cards/FlowCard-FileWrite.js +2 -0
  56. package/example_applications/simple_cards/source/cards/FlowCard-GetValue.js +2 -0
  57. package/example_applications/simple_cards/source/cards/FlowCard-IfThenElse.js +2 -0
  58. package/example_applications/simple_cards/source/cards/FlowCard-LogValues.js +2 -0
  59. package/example_applications/simple_cards/source/cards/FlowCard-SetValue.js +2 -0
  60. package/example_applications/simple_cards/source/cards/FlowCard-Sparkline.js +2 -0
  61. package/example_applications/simple_cards/source/cards/FlowCard-StatusMonitor.js +2 -0
  62. package/example_applications/simple_cards/source/cards/FlowCard-Switch.js +2 -0
  63. package/package.json +11 -7
  64. package/scripts/generate-card-help.js +214 -0
  65. package/source/Pict-Section-Flow.js +4 -0
  66. package/source/PictFlowCard.js +3 -1
  67. package/source/providers/PictProvider-Flow-CSS.js +245 -152
  68. package/source/providers/PictProvider-Flow-ConnectorShapes.js +24 -0
  69. package/source/providers/PictProvider-Flow-Geometry.js +195 -38
  70. package/source/providers/PictProvider-Flow-PanelChrome.js +14 -12
  71. package/source/services/PictService-Flow-ConnectionHandleManager.js +263 -0
  72. package/source/services/PictService-Flow-ConnectionRenderer.js +134 -183
  73. package/source/services/PictService-Flow-DataManager.js +338 -0
  74. package/source/services/PictService-Flow-InteractionManager.js +165 -7
  75. package/source/services/PictService-Flow-PathGenerator.js +282 -0
  76. package/source/services/PictService-Flow-PortRenderer.js +269 -0
  77. package/source/services/PictService-Flow-RenderManager.js +281 -0
  78. package/source/services/PictService-Flow-Tether.js +6 -42
  79. package/source/views/PictView-Flow-Node.js +2 -220
  80. package/source/views/PictView-Flow-PropertiesPanel.js +89 -44
  81. package/source/views/PictView-Flow.js +130 -882
  82. package/test/ConnectionHandleManager_tests.js +717 -0
  83. package/test/ConnectionRenderer_tests.js +591 -0
  84. package/test/DataManager_tests.js +859 -0
  85. package/test/Geometry_tests.js +767 -0
  86. package/test/PathGenerator_tests.js +978 -0
  87. package/test/PortRenderer_tests.js +367 -0
  88. package/test/RenderManager_tests.js +756 -0
@@ -0,0 +1,591 @@
1
+ const libFable = require('fable');
2
+ const libChai = require('chai');
3
+ const libExpect = libChai.expect;
4
+
5
+ const libConnectionRenderer = require('../source/services/PictService-Flow-ConnectionRenderer.js');
6
+ const libPathGenerator = require('../source/services/PictService-Flow-PathGenerator.js');
7
+ const libGeometry = require('../source/providers/PictProvider-Flow-Geometry.js');
8
+
9
+ suite
10
+ (
11
+ 'PictService-Flow-ConnectionRenderer',
12
+ function ()
13
+ {
14
+ let _Fable;
15
+ let _Renderer;
16
+ let _GeometryProvider;
17
+ let _PathGenerator;
18
+
19
+ setup
20
+ (
21
+ function ()
22
+ {
23
+ _Fable = new libFable({});
24
+
25
+ _GeometryProvider = new libGeometry(_Fable, {}, 'Geometry-Test');
26
+ _PathGenerator = new libPathGenerator(_Fable, {}, 'PathGen-Test');
27
+
28
+ // Build a mock FlowView with real providers
29
+ let tmpMockFlowView =
30
+ {
31
+ _GeometryProvider: _GeometryProvider,
32
+ _PathGenerator: _PathGenerator,
33
+ _SVGHelperProvider: null,
34
+ _ConnectorShapesProvider: null,
35
+ _ThemeProvider: null
36
+ };
37
+
38
+ // Wire up PathGenerator's FlowView reference
39
+ _PathGenerator._FlowView = tmpMockFlowView;
40
+
41
+ _Renderer = new libConnectionRenderer(
42
+ _Fable, { FlowView: tmpMockFlowView }, 'ConnRend-Test');
43
+ }
44
+ );
45
+
46
+ // ---- Constructor ----
47
+
48
+ suite
49
+ (
50
+ 'Constructor',
51
+ function ()
52
+ {
53
+ test
54
+ (
55
+ 'should instantiate with correct serviceType',
56
+ function (fDone)
57
+ {
58
+ libExpect(_Renderer.serviceType).to.equal('PictServiceFlowConnectionRenderer');
59
+ fDone();
60
+ }
61
+ );
62
+ }
63
+ );
64
+
65
+ // ---- _getBezierHandles ----
66
+
67
+ suite
68
+ (
69
+ '_getBezierHandles',
70
+ function ()
71
+ {
72
+ test
73
+ (
74
+ 'should return empty array when no data',
75
+ function (fDone)
76
+ {
77
+ libExpect(_Renderer._getBezierHandles(null)).to.deep.equal([]);
78
+ libExpect(_Renderer._getBezierHandles({})).to.deep.equal([]);
79
+ fDone();
80
+ }
81
+ );
82
+
83
+ test
84
+ (
85
+ 'should return empty array when HandleCustomized is false',
86
+ function (fDone)
87
+ {
88
+ let tmpData = { HandleCustomized: false, BezierHandleX: 100, BezierHandleY: 50 };
89
+ libExpect(_Renderer._getBezierHandles(tmpData)).to.deep.equal([]);
90
+ fDone();
91
+ }
92
+ );
93
+
94
+ test
95
+ (
96
+ 'should migrate legacy BezierHandleX/Y to single-element array',
97
+ function (fDone)
98
+ {
99
+ let tmpData =
100
+ {
101
+ HandleCustomized: true,
102
+ BezierHandleX: 150,
103
+ BezierHandleY: 75
104
+ };
105
+
106
+ let tmpResult = _Renderer._getBezierHandles(tmpData);
107
+ libExpect(tmpResult).to.have.length(1);
108
+ libExpect(tmpResult[0].x).to.equal(150);
109
+ libExpect(tmpResult[0].y).to.equal(75);
110
+ fDone();
111
+ }
112
+ );
113
+
114
+ test
115
+ (
116
+ 'should return BezierHandles array when present',
117
+ function (fDone)
118
+ {
119
+ let tmpData =
120
+ {
121
+ HandleCustomized: true,
122
+ BezierHandles: [
123
+ { x: 100, y: 50 },
124
+ { x: 200, y: 80 },
125
+ { x: 300, y: 50 }
126
+ ]
127
+ };
128
+
129
+ let tmpResult = _Renderer._getBezierHandles(tmpData);
130
+ libExpect(tmpResult).to.have.length(3);
131
+ libExpect(tmpResult[1].x).to.equal(200);
132
+ fDone();
133
+ }
134
+ );
135
+
136
+ test
137
+ (
138
+ 'should prefer BezierHandles over legacy format',
139
+ function (fDone)
140
+ {
141
+ let tmpData =
142
+ {
143
+ HandleCustomized: true,
144
+ BezierHandles: [{ x: 100, y: 50 }],
145
+ BezierHandleX: 999,
146
+ BezierHandleY: 999
147
+ };
148
+
149
+ let tmpResult = _Renderer._getBezierHandles(tmpData);
150
+ libExpect(tmpResult).to.have.length(1);
151
+ libExpect(tmpResult[0].x).to.equal(100);
152
+ fDone();
153
+ }
154
+ );
155
+
156
+ test
157
+ (
158
+ 'should return empty for empty BezierHandles with legacy fallback',
159
+ function (fDone)
160
+ {
161
+ let tmpData =
162
+ {
163
+ HandleCustomized: true,
164
+ BezierHandles: [],
165
+ BezierHandleX: 150,
166
+ BezierHandleY: 75
167
+ };
168
+
169
+ // Empty array → falls through to legacy
170
+ let tmpResult = _Renderer._getBezierHandles(tmpData);
171
+ libExpect(tmpResult).to.have.length(1);
172
+ libExpect(tmpResult[0].x).to.equal(150);
173
+ fDone();
174
+ }
175
+ );
176
+ }
177
+ );
178
+
179
+ // ---- _distanceToSegment ----
180
+
181
+ suite
182
+ (
183
+ '_distanceToSegment',
184
+ function ()
185
+ {
186
+ test
187
+ (
188
+ 'should return 0 for point on the segment',
189
+ function (fDone)
190
+ {
191
+ // Point at midpoint of horizontal segment
192
+ let tmpDist = _Renderer._distanceToSegment(50, 0, 0, 0, 100, 0);
193
+ libExpect(tmpDist).to.be.closeTo(0, 0.001);
194
+ fDone();
195
+ }
196
+ );
197
+
198
+ test
199
+ (
200
+ 'should compute perpendicular distance',
201
+ function (fDone)
202
+ {
203
+ // Point 30 units above the midpoint of a horizontal segment
204
+ let tmpDist = _Renderer._distanceToSegment(50, 30, 0, 0, 100, 0);
205
+ libExpect(tmpDist).to.be.closeTo(30, 0.001);
206
+ fDone();
207
+ }
208
+ );
209
+
210
+ test
211
+ (
212
+ 'should compute distance to endpoint when past segment',
213
+ function (fDone)
214
+ {
215
+ // Point beyond the end of a horizontal segment
216
+ let tmpDist = _Renderer._distanceToSegment(110, 0, 0, 0, 100, 0);
217
+ libExpect(tmpDist).to.be.closeTo(10, 0.001);
218
+ fDone();
219
+ }
220
+ );
221
+
222
+ test
223
+ (
224
+ 'should compute distance to start when before segment',
225
+ function (fDone)
226
+ {
227
+ // Point before the start of a horizontal segment
228
+ let tmpDist = _Renderer._distanceToSegment(-20, 0, 0, 0, 100, 0);
229
+ libExpect(tmpDist).to.be.closeTo(20, 0.001);
230
+ fDone();
231
+ }
232
+ );
233
+
234
+ test
235
+ (
236
+ 'should handle degenerate (zero-length) segment',
237
+ function (fDone)
238
+ {
239
+ let tmpDist = _Renderer._distanceToSegment(30, 40, 0, 0, 0, 0);
240
+ libExpect(tmpDist).to.be.closeTo(50, 0.001); // sqrt(900+1600)
241
+ fDone();
242
+ }
243
+ );
244
+
245
+ test
246
+ (
247
+ 'should handle diagonal segments',
248
+ function (fDone)
249
+ {
250
+ // Diagonal from (0,0) to (100,100), point at (0,100) (perpendicular)
251
+ let tmpDist = _Renderer._distanceToSegment(0, 100, 0, 0, 100, 100);
252
+ // Distance from (0,100) to the line y=x is |0-100|/sqrt(2) ≈ 70.71
253
+ libExpect(tmpDist).to.be.closeTo(70.71, 0.1);
254
+ fDone();
255
+ }
256
+ );
257
+ }
258
+ );
259
+
260
+ // ---- computeInsertionIndex ----
261
+
262
+ suite
263
+ (
264
+ 'computeInsertionIndex',
265
+ function ()
266
+ {
267
+ test
268
+ (
269
+ 'should return 0 for click near the only segment (no handles)',
270
+ function (fDone)
271
+ {
272
+ let tmpStart = { x: 0, y: 50, side: 'right' };
273
+ let tmpEnd = { x: 400, y: 50, side: 'left' };
274
+
275
+ let tmpIndex = _Renderer.computeInsertionIndex(
276
+ [], { x: 200, y: 50 }, tmpStart, tmpEnd);
277
+
278
+ libExpect(tmpIndex).to.equal(0);
279
+ fDone();
280
+ }
281
+ );
282
+
283
+ test
284
+ (
285
+ 'should return 0 for click before first handle',
286
+ function (fDone)
287
+ {
288
+ let tmpStart = { x: 0, y: 50, side: 'right' };
289
+ let tmpEnd = { x: 400, y: 50, side: 'left' };
290
+ let tmpHandles = [{ x: 250, y: 100 }];
291
+
292
+ // Click near the start, before the handle
293
+ let tmpIndex = _Renderer.computeInsertionIndex(
294
+ tmpHandles, { x: 60, y: 50 }, tmpStart, tmpEnd);
295
+
296
+ libExpect(tmpIndex).to.equal(0);
297
+ fDone();
298
+ }
299
+ );
300
+
301
+ test
302
+ (
303
+ 'should return 1 for click after first handle',
304
+ function (fDone)
305
+ {
306
+ let tmpStart = { x: 0, y: 50, side: 'right' };
307
+ let tmpEnd = { x: 400, y: 50, side: 'left' };
308
+ let tmpHandles = [{ x: 100, y: 100 }];
309
+
310
+ // Click near the end, after the handle
311
+ let tmpIndex = _Renderer.computeInsertionIndex(
312
+ tmpHandles, { x: 340, y: 50 }, tmpStart, tmpEnd);
313
+
314
+ libExpect(tmpIndex).to.equal(1);
315
+ fDone();
316
+ }
317
+ );
318
+
319
+ test
320
+ (
321
+ 'should pick correct segment among multiple handles',
322
+ function (fDone)
323
+ {
324
+ let tmpStart = { x: 0, y: 50, side: 'right' };
325
+ let tmpEnd = { x: 600, y: 50, side: 'left' };
326
+ let tmpHandles = [
327
+ { x: 150, y: 100 },
328
+ { x: 300, y: 50 },
329
+ { x: 450, y: 100 }
330
+ ];
331
+
332
+ // Click between handle[1] and handle[2]
333
+ let tmpIndex = _Renderer.computeInsertionIndex(
334
+ tmpHandles, { x: 375, y: 75 }, tmpStart, tmpEnd);
335
+
336
+ libExpect(tmpIndex).to.equal(2);
337
+ fDone();
338
+ }
339
+ );
340
+ }
341
+ );
342
+
343
+ // ---- _computeDirectionalGeometry ----
344
+
345
+ suite
346
+ (
347
+ '_computeDirectionalGeometry',
348
+ function ()
349
+ {
350
+ test
351
+ (
352
+ 'should compute departure and approach with straight segments',
353
+ function (fDone)
354
+ {
355
+ let tmpGeo = _Renderer._computeDirectionalGeometry(
356
+ { x: 100, y: 50, side: 'right' },
357
+ { x: 400, y: 150, side: 'left' }
358
+ );
359
+
360
+ // Departure: x + dx*20 = 100 + 1*20 = 120
361
+ libExpect(tmpGeo.departX).to.equal(120);
362
+ libExpect(tmpGeo.departY).to.equal(50);
363
+ // Approach: x + dx*20 = 400 + (-1)*20 = 380
364
+ libExpect(tmpGeo.approachX).to.equal(380);
365
+ libExpect(tmpGeo.approachY).to.equal(150);
366
+ fDone();
367
+ }
368
+ );
369
+
370
+ test
371
+ (
372
+ 'should compute control points extending in port direction',
373
+ function (fDone)
374
+ {
375
+ let tmpGeo = _Renderer._computeDirectionalGeometry(
376
+ { x: 100, y: 50, side: 'right' },
377
+ { x: 400, y: 50, side: 'left' }
378
+ );
379
+
380
+ // CP1 should be to the right of depart (dx=1)
381
+ libExpect(tmpGeo.cp1X).to.be.greaterThan(tmpGeo.departX);
382
+ libExpect(tmpGeo.cp1Y).to.equal(tmpGeo.departY);
383
+
384
+ // CP2 should be to the left of approach (dx=-1, so approach + endDir*offset)
385
+ libExpect(tmpGeo.cp2X).to.be.lessThan(tmpGeo.approachX);
386
+ libExpect(tmpGeo.cp2Y).to.equal(tmpGeo.approachY);
387
+ fDone();
388
+ }
389
+ );
390
+
391
+ test
392
+ (
393
+ 'should handle vertical port directions',
394
+ function (fDone)
395
+ {
396
+ let tmpGeo = _Renderer._computeDirectionalGeometry(
397
+ { x: 100, y: 50, side: 'bottom' },
398
+ { x: 100, y: 250, side: 'top' }
399
+ );
400
+
401
+ // Bottom port: dy=1, so depart is below start
402
+ libExpect(tmpGeo.departY).to.equal(70); // 50 + 1*20
403
+ // Top port: dy=-1, so approach is above end
404
+ libExpect(tmpGeo.approachY).to.equal(230); // 250 + (-1)*20
405
+ fDone();
406
+ }
407
+ );
408
+
409
+ test
410
+ (
411
+ 'should return direction vectors',
412
+ function (fDone)
413
+ {
414
+ let tmpGeo = _Renderer._computeDirectionalGeometry(
415
+ { x: 100, y: 50, side: 'right' },
416
+ { x: 400, y: 150, side: 'top' }
417
+ );
418
+
419
+ libExpect(tmpGeo.startDir).to.deep.equal({ dx: 1, dy: 0 });
420
+ libExpect(tmpGeo.endDir).to.deep.equal({ dx: 0, dy: -1 });
421
+ fDone();
422
+ }
423
+ );
424
+ }
425
+ );
426
+
427
+ // ---- _generateDirectionalPath ----
428
+
429
+ suite
430
+ (
431
+ '_generateDirectionalPath',
432
+ function ()
433
+ {
434
+ test
435
+ (
436
+ 'should produce valid SVG path string',
437
+ function (fDone)
438
+ {
439
+ let tmpPath = _Renderer._generateDirectionalPath(
440
+ { x: 0, y: 50, side: 'right' },
441
+ { x: 300, y: 50, side: 'left' }
442
+ );
443
+
444
+ libExpect(tmpPath).to.be.a('string');
445
+ libExpect(tmpPath).to.match(/^M /);
446
+ libExpect(tmpPath).to.contain('C');
447
+ libExpect(tmpPath).to.contain('L');
448
+ fDone();
449
+ }
450
+ );
451
+ }
452
+ );
453
+
454
+ // ---- _generateMultiHandleBezierPath ----
455
+
456
+ suite
457
+ (
458
+ '_generateMultiHandleBezierPath',
459
+ function ()
460
+ {
461
+ test
462
+ (
463
+ 'should produce path with correct segment count for 1 handle',
464
+ function (fDone)
465
+ {
466
+ let tmpPath = _Renderer._generateMultiHandleBezierPath(
467
+ { x: 0, y: 50, side: 'right' },
468
+ { x: 400, y: 50, side: 'left' },
469
+ [{ x: 200, y: 100 }]
470
+ );
471
+
472
+ libExpect(tmpPath).to.be.a('string');
473
+ // 1 handle → 2 cubic segments
474
+ let tmpCCount = (tmpPath.match(/C /g) || []).length;
475
+ libExpect(tmpCCount).to.equal(2);
476
+ fDone();
477
+ }
478
+ );
479
+
480
+ test
481
+ (
482
+ 'should produce path with 3 segments for 2 handles',
483
+ function (fDone)
484
+ {
485
+ let tmpPath = _Renderer._generateMultiHandleBezierPath(
486
+ { x: 0, y: 50, side: 'right' },
487
+ { x: 400, y: 50, side: 'left' },
488
+ [{ x: 120, y: 80 }, { x: 280, y: 80 }]
489
+ );
490
+
491
+ let tmpCCount = (tmpPath.match(/C /g) || []).length;
492
+ libExpect(tmpCCount).to.equal(3);
493
+ fDone();
494
+ }
495
+ );
496
+ }
497
+ );
498
+
499
+ // ---- getAutoMidpoint ----
500
+
501
+ suite
502
+ (
503
+ 'getAutoMidpoint',
504
+ function ()
505
+ {
506
+ test
507
+ (
508
+ 'should return a point between start and end',
509
+ function (fDone)
510
+ {
511
+ let tmpMid = _Renderer.getAutoMidpoint(
512
+ { x: 0, y: 50, side: 'right' },
513
+ { x: 400, y: 50, side: 'left' }
514
+ );
515
+
516
+ libExpect(tmpMid.x).to.be.greaterThan(0);
517
+ libExpect(tmpMid.x).to.be.lessThan(400);
518
+ fDone();
519
+ }
520
+ );
521
+
522
+ test
523
+ (
524
+ 'should be near horizontal midpoint for same-y endpoints',
525
+ function (fDone)
526
+ {
527
+ let tmpMid = _Renderer.getAutoMidpoint(
528
+ { x: 0, y: 50, side: 'right' },
529
+ { x: 400, y: 50, side: 'left' }
530
+ );
531
+
532
+ // For symmetric right→left facing each other, midpoint x should
533
+ // be near 200, and y should stay near 50
534
+ libExpect(tmpMid.x).to.be.closeTo(200, 20);
535
+ libExpect(tmpMid.y).to.be.closeTo(50, 5);
536
+ fDone();
537
+ }
538
+ );
539
+ }
540
+ );
541
+
542
+ // ---- _generateOrthogonalPath ----
543
+
544
+ suite
545
+ (
546
+ '_generateOrthogonalPath',
547
+ function ()
548
+ {
549
+ test
550
+ (
551
+ 'should produce orthogonal path with no curves',
552
+ function (fDone)
553
+ {
554
+ let tmpPath = _Renderer._generateOrthogonalPath(
555
+ { x: 0, y: 50, side: 'right' },
556
+ { x: 300, y: 150, side: 'left' },
557
+ null, 0
558
+ );
559
+
560
+ libExpect(tmpPath).to.be.a('string');
561
+ libExpect(tmpPath).to.not.contain('C');
562
+ fDone();
563
+ }
564
+ );
565
+
566
+ test
567
+ (
568
+ 'should use provided corners when given',
569
+ function (fDone)
570
+ {
571
+ let tmpCorners =
572
+ {
573
+ corner1: { x: 100, y: 50 },
574
+ corner2: { x: 100, y: 150 }
575
+ };
576
+
577
+ let tmpPath = _Renderer._generateOrthogonalPath(
578
+ { x: 0, y: 50, side: 'right' },
579
+ { x: 300, y: 150, side: 'left' },
580
+ tmpCorners, 0
581
+ );
582
+
583
+ libExpect(tmpPath).to.contain('100 50');
584
+ libExpect(tmpPath).to.contain('100 150');
585
+ fDone();
586
+ }
587
+ );
588
+ }
589
+ );
590
+ }
591
+ );