@design-core/core 0.0.6 → 50.1.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.
- package/.eslintrc.json +4 -0
- package/.github/workflows/DesignCoreQA.yml +3 -0
- package/TODO.md +49 -6
- package/core/core/core.js +0 -3
- package/core/designCore.js +1 -1
- package/core/dimensions/alignedDimension.js +12 -11
- package/core/dimensions/angularDimension.js +38 -37
- package/core/dimensions/{baseCircularDimension.js → circularDimensionBase.js} +22 -21
- package/core/dimensions/diametricDimension.js +14 -13
- package/core/dimensions/dimension.js +62 -55
- package/core/dimensions/{baseDimension.js → dimensionBase.js} +73 -107
- package/core/dimensions/{baseLinearDimension.js → linearDimensionBase.js} +15 -14
- package/core/dimensions/radialDimension.js +12 -11
- package/core/dimensions/rotatedDimension.js +20 -19
- package/core/entities/arc.js +123 -156
- package/core/entities/arctext.js +222 -184
- package/core/entities/circle.js +77 -99
- package/core/entities/entity.js +114 -93
- package/core/entities/hatch.js +346 -273
- package/core/entities/insert.js +68 -83
- package/core/entities/line.js +21 -142
- package/core/entities/lwpolyline.js +16 -11
- package/core/entities/point.js +19 -19
- package/core/entities/polyline.js +7 -7
- package/core/entities/{basePolyline.js → polylineBase.js} +47 -299
- package/core/entities/rectangle.js +3 -1
- package/core/entities/solid.js +6 -15
- package/core/entities/text.js +190 -201
- package/core/lib/auxiliary/rubberBand.js +32 -0
- package/core/lib/auxiliary/selectionWindow.js +63 -0
- package/core/lib/auxiliary/snapPoint.js +113 -0
- package/core/lib/auxiliary/trackingLine.js +76 -0
- package/core/lib/boundingBox.js +11 -11
- package/core/lib/canvas.js +232 -168
- package/core/lib/clipboard.js +9 -3
- package/core/lib/colour.js +16 -0
- package/core/lib/commandLine.js +1 -6
- package/core/lib/commandManager.js +18 -8
- package/core/lib/constants.js +28 -0
- package/core/lib/dxf/dxf.js +15 -14
- package/core/lib/dxf/dxfIterator.js +2 -2
- package/core/lib/entityManager.js +33 -26
- package/core/lib/inputManager.js +36 -12
- package/core/lib/intersect.js +25 -0
- package/core/lib/matrix.js +1 -1
- package/core/lib/patterns.js +9 -2
- package/core/lib/plotOptions.js +67 -0
- package/core/lib/polylineUtils.js +75 -0
- package/core/lib/renderers/cairoRenderer.js +371 -0
- package/core/lib/renderers/canvasRenderer.js +315 -0
- package/core/lib/renderers/pdfRenderer.js +366 -0
- package/core/lib/renderers/rendererBase.js +284 -0
- package/core/lib/renderers/svgRenderer.js +343 -0
- package/core/lib/scene.js +28 -6
- package/core/lib/selectionManager.js +20 -20
- package/core/lib/settings.js +4 -2
- package/core/lib/snapping.js +4 -191
- package/core/lib/stateManager.js +30 -1
- package/core/lib/utils.js +26 -7
- package/core/properties/entityProperties.js +104 -0
- package/core/properties/property.js +106 -2
- package/core/properties/propertyManager.js +60 -44
- package/core/tables/block.js +50 -81
- package/core/tables/dimStyle.js +5 -5
- package/core/tables/endblk.js +1 -1
- package/core/tables/layer.js +8 -0
- package/core/tables/ltypeManager.js +1 -1
- package/core/tables/styleManagerBase.js +3 -2
- package/core/tables/tableManagerBase.js +8 -3
- package/core/tables/vport.js +2 -2
- package/core/tools/chamfer.js +117 -143
- package/core/tools/chamferFilletBase.js +138 -37
- package/core/tools/copy.js +11 -11
- package/core/tools/copybase.js +3 -3
- package/core/tools/copyclip.js +3 -3
- package/core/tools/cornerEntity.js +2 -2
- package/core/tools/cutclip.js +3 -3
- package/core/tools/explode.js +7 -7
- package/core/tools/extend.js +138 -25
- package/core/tools/fillet.js +92 -189
- package/core/tools/matchProp.js +3 -12
- package/core/tools/mirror.js +15 -14
- package/core/tools/move.js +8 -8
- package/core/tools/offset.js +31 -33
- package/core/tools/pasteclip.js +1 -1
- package/core/tools/purge.js +10 -10
- package/core/tools/rotate.js +19 -16
- package/core/tools/scale.js +7 -7
- package/core/tools/trim.js +271 -29
- package/core/tools/zoom.js +1 -1
- package/cspell.json +321 -0
- package/jest.config.js +6 -0
- package/package.json +5 -3
- package/test/dimensions/alignedDimension.test.js +17 -10
- package/test/dimensions/angularDimension.test.js +13 -13
- package/test/dimensions/diametricDimension.test.js +15 -15
- package/test/dimensions/dimension.test.js +12 -12
- package/test/dimensions/{baseDimension.test.js → dimensionBase.test.js} +73 -12
- package/test/dimensions/linearDimensionBase.test.js +62 -0
- package/test/dimensions/radialDimension.test.js +15 -15
- package/test/dimensions/rotatedDimension.test.js +18 -11
- package/test/entities/arc.test.js +83 -86
- package/test/entities/arctext.test.js +184 -57
- package/test/entities/circle.test.js +68 -96
- package/test/entities/entity.test.js +42 -8
- package/test/entities/hatch.test.js +569 -96
- package/test/entities/insert.test.js +99 -4
- package/test/entities/line.test.js +15 -41
- package/test/entities/lwpolyline.test.js +104 -0
- package/test/entities/point.test.js +3 -3
- package/test/entities/polyline.test.js +11 -0
- package/test/entities/{basePolyline.test.js → polylineBase.test.js} +192 -57
- package/test/entities/rectangle.test.js +11 -0
- package/test/entities/solid.test.js +1 -1
- package/test/entities/text.test.js +302 -77
- package/test/integration/exportIntegration.reference.dxf +9 -9
- package/test/integration/exportIntegration.test.js +5 -5
- package/test/integration/intersectionIntegration.test.js +4 -5
- package/test/integration/pdfRendererIntegration.reference.pdf +17709 -0
- package/test/integration/pdfRendererIntegration.test.js +61 -0
- package/test/integration/svgRendererIntegration.reference.svg +3343 -0
- package/test/integration/svgRendererIntegration.test.js +61 -0
- package/test/integration/userInputIntegration.reference.dxf +1165 -105
- package/test/integration/userInputIntegration.test.js +239 -132
- package/test/lib/boundingBox.test.js +3 -3
- package/test/lib/canvas.test.js +744 -125
- package/test/lib/constants.test.js +27 -0
- package/test/lib/entityManager.test.js +4 -4
- package/test/lib/inputManager.test.js +81 -20
- package/test/lib/intersect.test.js +83 -0
- package/test/lib/plotOptions.test.js +179 -0
- package/test/lib/rubberBand.test.js +84 -0
- package/test/lib/scene.test.js +9 -9
- package/test/lib/selectionManager.test.js +3 -3
- package/test/lib/settings.test.js +5 -6
- package/test/lib/snapping.test.js +72 -130
- package/test/lib/stateManager.test.js +7 -7
- package/test/lib/utils.test.js +36 -2
- package/test/properties/entityProperties.test.js +132 -0
- package/test/properties/property.test.js +53 -0
- package/test/properties/propertyManager.test.js +25 -25
- package/test/renderers/canvasRenderer.test.js +317 -0
- package/test/renderers/pdfRenderer.test.js +271 -0
- package/test/renderers/rendererBase.test.js +213 -0
- package/test/renderers/svgRenderer.test.js +326 -0
- package/test/tables/block.test.js +92 -13
- package/test/tables/endblk.test.js +2 -2
- package/test/tables/layer.test.js +30 -0
- package/test/tables/layerManager.test.js +2 -2
- package/test/test-helpers/hatchGridRenderer.js +180 -0
- package/test/test-helpers/test-helpers.js +158 -6
- package/test/tools/chamfer.test.js +273 -51
- package/test/tools/chamferFilletBase.test.js +125 -36
- package/test/tools/copy.test.js +8 -8
- package/test/tools/copybase.test.js +2 -2
- package/test/tools/copyclip.test.js +2 -2
- package/test/tools/cornerEntity.test.js +8 -8
- package/test/tools/cutclip.test.js +2 -2
- package/test/tools/erase.test.js +6 -6
- package/test/tools/explode.test.js +5 -5
- package/test/tools/extend.test.js +373 -42
- package/test/tools/fillet.test.js +230 -49
- package/test/tools/matchProp.test.js +11 -11
- package/test/tools/mirror.test.js +39 -39
- package/test/tools/move.test.js +7 -7
- package/test/tools/offset.test.js +222 -55
- package/test/tools/pasteclip.test.js +5 -5
- package/test/tools/purge.test.js +4 -4
- package/test/tools/rotate.test.js +39 -9
- package/test/tools/scale.test.js +33 -33
- package/test/tools/trim.test.js +579 -53
- package/test/tools/zoom.test.js +12 -12
- package/core/lib/selectionWindow.js +0 -83
|
@@ -11,8 +11,8 @@ const core = new Core();
|
|
|
11
11
|
|
|
12
12
|
test('ChamferFilletBase.resolveCornerGeometry returns false and notifies when first segment is not a Line', () => {
|
|
13
13
|
core.scene.clear();
|
|
14
|
-
core.scene.
|
|
15
|
-
core.scene.
|
|
14
|
+
core.scene.addEntity('Circle', { points: [new Point(0, 0), new Point(5, 0)] });
|
|
15
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
16
16
|
|
|
17
17
|
const notifySpy = jest.spyOn(core, 'notify');
|
|
18
18
|
const chamfer = new Chamfer();
|
|
@@ -28,8 +28,8 @@ test('ChamferFilletBase.resolveCornerGeometry returns false and notifies when fi
|
|
|
28
28
|
|
|
29
29
|
test('ChamferFilletBase.resolveCornerGeometry returns false and notifies when second segment is not a Line', () => {
|
|
30
30
|
core.scene.clear();
|
|
31
|
-
core.scene.
|
|
32
|
-
core.scene.
|
|
31
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
32
|
+
core.scene.addEntity('Circle', { points: [new Point(0, 0), new Point(5, 0)] });
|
|
33
33
|
|
|
34
34
|
const notifySpy = jest.spyOn(core, 'notify');
|
|
35
35
|
const chamfer = new Chamfer();
|
|
@@ -45,8 +45,8 @@ test('ChamferFilletBase.resolveCornerGeometry returns false and notifies when se
|
|
|
45
45
|
|
|
46
46
|
test('ChamferFilletBase.resolveCornerGeometry returns false and notifies for parallel lines', () => {
|
|
47
47
|
core.scene.clear();
|
|
48
|
-
core.scene.
|
|
49
|
-
core.scene.
|
|
48
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
49
|
+
core.scene.addEntity('Line', { points: [new Point(0, 2), new Point(10, 2)] });
|
|
50
50
|
|
|
51
51
|
const notifySpy = jest.spyOn(core, 'notify');
|
|
52
52
|
const chamfer = new Chamfer();
|
|
@@ -63,8 +63,8 @@ test('ChamferFilletBase.resolveCornerGeometry returns false and notifies for par
|
|
|
63
63
|
test('ChamferFilletBase.resolveCornerGeometry returns false for collinear overlapping lines', () => {
|
|
64
64
|
core.scene.clear();
|
|
65
65
|
// Two segments on the same line that overlap
|
|
66
|
-
core.scene.
|
|
67
|
-
core.scene.
|
|
66
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
67
|
+
core.scene.addEntity('Line', { points: [new Point(5, 0), new Point(15, 0)] });
|
|
68
68
|
|
|
69
69
|
const notifySpy = jest.spyOn(core, 'notify');
|
|
70
70
|
const chamfer = new Chamfer();
|
|
@@ -81,8 +81,8 @@ test('ChamferFilletBase.resolveCornerGeometry returns false for collinear overla
|
|
|
81
81
|
test('ChamferFilletBase.resolveCornerGeometry returns false for collinear endpoint-sharing lines', () => {
|
|
82
82
|
core.scene.clear();
|
|
83
83
|
// Two collinear segments sharing an endpoint (180° angle)
|
|
84
|
-
core.scene.
|
|
85
|
-
core.scene.
|
|
84
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(5, 0)] });
|
|
85
|
+
core.scene.addEntity('Line', { points: [new Point(5, 0), new Point(10, 0)] });
|
|
86
86
|
|
|
87
87
|
const notifySpy = jest.spyOn(core, 'notify');
|
|
88
88
|
const chamfer = new Chamfer();
|
|
@@ -99,8 +99,8 @@ test('ChamferFilletBase.resolveCornerGeometry returns false for collinear endpoi
|
|
|
99
99
|
test('ChamferFilletBase.resolveCornerGeometry returns true and computes intersection for L-corner', () => {
|
|
100
100
|
// Horizontal (-10,0)→(0,0) and vertical (0,0)→(0,10); infinite lines meet at (0,0)
|
|
101
101
|
core.scene.clear();
|
|
102
|
-
core.scene.
|
|
103
|
-
core.scene.
|
|
102
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] });
|
|
103
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
104
104
|
|
|
105
105
|
const chamfer = new Chamfer();
|
|
106
106
|
chamfer.firstPick.entity = core.scene.entities.get(0);
|
|
@@ -125,8 +125,8 @@ test('ChamferFilletBase.resolveCornerGeometry uses polyline activeSeg for first
|
|
|
125
125
|
// Polyline [(-10,0),(0,0),(0,10)], click near segment 1 (y=0).
|
|
126
126
|
// Paired with vertical line x=5; lines meet at (5,0).
|
|
127
127
|
core.scene.clear();
|
|
128
|
-
core.scene.
|
|
129
|
-
core.scene.
|
|
128
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(-10, 0), new Point(0, 0), new Point(0, 10)] });
|
|
129
|
+
core.scene.addEntity('Line', { points: [new Point(5, -5), new Point(5, 5)] });
|
|
130
130
|
|
|
131
131
|
const polyEntity = core.scene.entities.get(0);
|
|
132
132
|
const lineEntity = core.scene.entities.get(1);
|
|
@@ -151,8 +151,8 @@ test('ChamferFilletBase.applySharpTrim trims two Lines to the intersection point
|
|
|
151
151
|
// Line1: (0,0)→(8,0); Line2: (10,-10)→(10,-2). Infinite lines meet at (10,0).
|
|
152
152
|
// keepEnd for Line1 = (0,0); keepEnd for Line2 = (10,-10).
|
|
153
153
|
core.scene.clear();
|
|
154
|
-
core.scene.
|
|
155
|
-
core.scene.
|
|
154
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(8, 0)] });
|
|
155
|
+
core.scene.addEntity('Line', { points: [new Point(10, -10), new Point(10, -2)] });
|
|
156
156
|
const lineA = core.scene.entities.get(0);
|
|
157
157
|
const lineB = core.scene.entities.get(1);
|
|
158
158
|
|
|
@@ -167,7 +167,7 @@ test('ChamferFilletBase.applySharpTrim trims two Lines to the intersection point
|
|
|
167
167
|
chamfer.secondPick.clickPoint = new Point(8, -7); // projects to (10,-7) → lineKeptEnd = (10,-10)
|
|
168
168
|
chamfer.intersectionPoint = new Point(10, 0);
|
|
169
169
|
|
|
170
|
-
const stateChanges = chamfer.
|
|
170
|
+
const stateChanges = chamfer.applyCornerTrim(chamfer.intersectionPoint, chamfer.intersectionPoint, null);
|
|
171
171
|
DesignCore.Scene.commit(stateChanges);
|
|
172
172
|
|
|
173
173
|
const updatedA = core.scene.entities.get(0);
|
|
@@ -188,7 +188,7 @@ test('ChamferFilletBase.applySharpTrim poly+poly consecutive segments: replaces
|
|
|
188
188
|
// L-shaped polyline [(-10,0),(0,0),(0,10)]; segments 1 and 2 share vertex (0,0).
|
|
189
189
|
// Intersection of infinite lines is also (0,0), so splice replaces vertex with itself.
|
|
190
190
|
core.scene.clear();
|
|
191
|
-
core.scene.
|
|
191
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(-10, 0), new Point(0, 0), new Point(0, 10)] });
|
|
192
192
|
const polyEntity = core.scene.entities.get(0);
|
|
193
193
|
|
|
194
194
|
const chamfer = new Chamfer();
|
|
@@ -198,7 +198,7 @@ test('ChamferFilletBase.applySharpTrim poly+poly consecutive segments: replaces
|
|
|
198
198
|
chamfer.secondPick.segmentIndex = 2;
|
|
199
199
|
chamfer.intersectionPoint = new Point(0, 0);
|
|
200
200
|
|
|
201
|
-
const stateChanges = chamfer.
|
|
201
|
+
const stateChanges = chamfer.applyCornerTrim(chamfer.intersectionPoint, chamfer.intersectionPoint, null);
|
|
202
202
|
DesignCore.Scene.commit(stateChanges);
|
|
203
203
|
|
|
204
204
|
const poly = core.scene.entities.get(0);
|
|
@@ -212,7 +212,7 @@ test('ChamferFilletBase.applySharpTrim poly+poly open ends: moves both endpoints
|
|
|
212
212
|
// Seg 1 is on y=2, seg 3 (lastIdx=3) is on x=3 → infinite lines meet at (3,2).
|
|
213
213
|
// Both open endpoints (index 0 and 3) are moved to (3,2).
|
|
214
214
|
core.scene.clear();
|
|
215
|
-
core.scene.
|
|
215
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(-5, 2), new Point(0, 2), new Point(3, 4), new Point(3, 8)] });
|
|
216
216
|
const polyEntity = core.scene.entities.get(0);
|
|
217
217
|
|
|
218
218
|
const chamfer = new Chamfer();
|
|
@@ -222,7 +222,7 @@ test('ChamferFilletBase.applySharpTrim poly+poly open ends: moves both endpoints
|
|
|
222
222
|
chamfer.secondPick.segmentIndex = 3; // open end (lastIdx = 3)
|
|
223
223
|
chamfer.intersectionPoint = new Point(3, 2);
|
|
224
224
|
|
|
225
|
-
const stateChanges = chamfer.
|
|
225
|
+
const stateChanges = chamfer.applyCornerTrim(chamfer.intersectionPoint, chamfer.intersectionPoint, null);
|
|
226
226
|
DesignCore.Scene.commit(stateChanges);
|
|
227
227
|
|
|
228
228
|
const poly = core.scene.entities.get(0);
|
|
@@ -247,7 +247,7 @@ test('ChamferFilletBase.applySharpTrim poly+poly closed polyline seg1+lastIdx: c
|
|
|
247
247
|
// The shared corner is at index min(1,3)=1, so corner vertex (0,0) is replaced with
|
|
248
248
|
// the intersection point (0,0) — a no-op on coordinates but proves the splice path ran.
|
|
249
249
|
core.scene.clear();
|
|
250
|
-
core.scene.
|
|
250
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(-10, 0), new Point(0, 0), new Point(0, 10)] });
|
|
251
251
|
const polyEntity = core.scene.entities.get(0);
|
|
252
252
|
polyEntity.flags.setFlagValue(1); // mark as closed
|
|
253
253
|
|
|
@@ -258,7 +258,7 @@ test('ChamferFilletBase.applySharpTrim poly+poly closed polyline seg1+lastIdx: c
|
|
|
258
258
|
chamfer.secondPick.segmentIndex = polyEntity.points.length - 1; // lastIdx
|
|
259
259
|
chamfer.intersectionPoint = new Point(0, 0);
|
|
260
260
|
|
|
261
|
-
const stateChanges = chamfer.
|
|
261
|
+
const stateChanges = chamfer.applyCornerTrim(chamfer.intersectionPoint, chamfer.intersectionPoint, null);
|
|
262
262
|
DesignCore.Scene.commit(stateChanges);
|
|
263
263
|
|
|
264
264
|
// Corner-splice: replaces vertex at cornerIdx=1 with intersectionPoint — point count unchanged
|
|
@@ -275,7 +275,7 @@ test('ChamferFilletBase.applySharpTrim closed poly last-regular-seg + closing-se
|
|
|
275
275
|
// Corner at (0,10) shared by seg 3 and seg 4. segDiff=1 → corner-splice path.
|
|
276
276
|
// cornerIdx = min(3,4) = 3 → replaces points[3]=(0,10) with intersectionPoint (0,10).
|
|
277
277
|
core.scene.clear();
|
|
278
|
-
core.scene.
|
|
278
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(0, 0), new Point(10, 0), new Point(10, 10), new Point(0, 10)] });
|
|
279
279
|
const polyEntity = core.scene.entities.get(0);
|
|
280
280
|
polyEntity.flags.setFlagValue(1);
|
|
281
281
|
|
|
@@ -286,7 +286,7 @@ test('ChamferFilletBase.applySharpTrim closed poly last-regular-seg + closing-se
|
|
|
286
286
|
chamfer.secondPick.segmentIndex = 4; // closing segment (points.length)
|
|
287
287
|
chamfer.intersectionPoint = new Point(0, 10);
|
|
288
288
|
|
|
289
|
-
const stateChanges = chamfer.
|
|
289
|
+
const stateChanges = chamfer.applyCornerTrim(chamfer.intersectionPoint, chamfer.intersectionPoint, null);
|
|
290
290
|
DesignCore.Scene.commit(stateChanges);
|
|
291
291
|
|
|
292
292
|
const poly = core.scene.entities.get(0);
|
|
@@ -303,7 +303,7 @@ test('ChamferFilletBase.applySharpTrim closed poly closing-seg + seg-1: replaces
|
|
|
303
303
|
// segDiff = |4-1| = 3 (not 1), closing-wrap detected → cornerIdx = 0.
|
|
304
304
|
// Replaces points[0]=(0,0) with intersectionPoint (0,0).
|
|
305
305
|
core.scene.clear();
|
|
306
|
-
core.scene.
|
|
306
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(0, 0), new Point(10, 0), new Point(10, 10), new Point(0, 10)] });
|
|
307
307
|
const polyEntity = core.scene.entities.get(0);
|
|
308
308
|
polyEntity.flags.setFlagValue(1);
|
|
309
309
|
|
|
@@ -314,7 +314,7 @@ test('ChamferFilletBase.applySharpTrim closed poly closing-seg + seg-1: replaces
|
|
|
314
314
|
chamfer.secondPick.segmentIndex = 1;
|
|
315
315
|
chamfer.intersectionPoint = new Point(0, 0);
|
|
316
316
|
|
|
317
|
-
const stateChanges = chamfer.
|
|
317
|
+
const stateChanges = chamfer.applyCornerTrim(chamfer.intersectionPoint, chamfer.intersectionPoint, null);
|
|
318
318
|
DesignCore.Scene.commit(stateChanges);
|
|
319
319
|
|
|
320
320
|
const poly = core.scene.entities.get(0);
|
|
@@ -336,8 +336,8 @@ test('ChamferFilletBase.applySharpTrim first=Line second=Poly keepStart: line co
|
|
|
336
336
|
// second=Poly, segmentIndex=2 (segment (-10,0)→(0,0)), click left of intersection → keepStart.
|
|
337
337
|
// Result: Poly becomes [(-20,0),(-10,0),(0,0),(0,10)]; Line removed.
|
|
338
338
|
core.scene.clear();
|
|
339
|
-
core.scene.
|
|
340
|
-
core.scene.
|
|
339
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
340
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(-20, 0), new Point(-10, 0), new Point(0, 0), new Point(10, 0)] });
|
|
341
341
|
const lineEntity = core.scene.entities.get(0);
|
|
342
342
|
const polyEntity = core.scene.entities.get(1);
|
|
343
343
|
|
|
@@ -354,7 +354,7 @@ test('ChamferFilletBase.applySharpTrim first=Line second=Poly keepStart: line co
|
|
|
354
354
|
chamfer.intersectionPoint = new Point(0, 0);
|
|
355
355
|
|
|
356
356
|
|
|
357
|
-
const stateChanges = chamfer.
|
|
357
|
+
const stateChanges = chamfer.applyCornerTrim(chamfer.intersectionPoint, chamfer.intersectionPoint, null);
|
|
358
358
|
DesignCore.Scene.commit(stateChanges);
|
|
359
359
|
|
|
360
360
|
expect(core.scene.entities.count()).toBe(1);
|
|
@@ -374,8 +374,8 @@ test('ChamferFilletBase.applySharpTrim first=Line second=Poly keepEnd: line cons
|
|
|
374
374
|
// Same setup, but segmentIndex=3. click right of intersection → keepEnd.
|
|
375
375
|
// Result: Poly becomes [(0,10),(0,0),(10,0)]; Line removed.
|
|
376
376
|
core.scene.clear();
|
|
377
|
-
core.scene.
|
|
378
|
-
core.scene.
|
|
377
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
378
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(-20, 0), new Point(-10, 0), new Point(0, 0), new Point(10, 0)] });
|
|
379
379
|
const lineEntity = core.scene.entities.get(0);
|
|
380
380
|
const polyEntity = core.scene.entities.get(1);
|
|
381
381
|
|
|
@@ -392,7 +392,7 @@ test('ChamferFilletBase.applySharpTrim first=Line second=Poly keepEnd: line cons
|
|
|
392
392
|
chamfer.intersectionPoint = new Point(0, 0);
|
|
393
393
|
|
|
394
394
|
|
|
395
|
-
const stateChanges = chamfer.
|
|
395
|
+
const stateChanges = chamfer.applyCornerTrim(chamfer.intersectionPoint, chamfer.intersectionPoint, null);
|
|
396
396
|
DesignCore.Scene.commit(stateChanges);
|
|
397
397
|
|
|
398
398
|
expect(core.scene.entities.count()).toBe(1);
|
|
@@ -413,8 +413,8 @@ test('ChamferFilletBase.applySharpTrim first=Poly second=Line: poly/line orderin
|
|
|
413
413
|
// firstIsPolyline=true → [poly, line] = [this.firstPick, this.secondPick].
|
|
414
414
|
// Result should be the same: Poly becomes [(-20,0),(-10,0),(0,0),(0,10)]; Line removed.
|
|
415
415
|
core.scene.clear();
|
|
416
|
-
core.scene.
|
|
417
|
-
core.scene.
|
|
416
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(-20, 0), new Point(-10, 0), new Point(0, 0), new Point(10, 0)] });
|
|
417
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(0, 10)] });
|
|
418
418
|
const polyEntity = core.scene.entities.get(0);
|
|
419
419
|
const lineEntity = core.scene.entities.get(1);
|
|
420
420
|
|
|
@@ -431,7 +431,7 @@ test('ChamferFilletBase.applySharpTrim first=Poly second=Line: poly/line orderin
|
|
|
431
431
|
chamfer.intersectionPoint = new Point(0, 0);
|
|
432
432
|
|
|
433
433
|
|
|
434
|
-
const stateChanges = chamfer.
|
|
434
|
+
const stateChanges = chamfer.applyCornerTrim(chamfer.intersectionPoint, chamfer.intersectionPoint, null);
|
|
435
435
|
DesignCore.Scene.commit(stateChanges);
|
|
436
436
|
|
|
437
437
|
expect(core.scene.entities.count()).toBe(1);
|
|
@@ -444,3 +444,92 @@ test('ChamferFilletBase.applySharpTrim first=Poly second=Line: poly/line orderin
|
|
|
444
444
|
expect(poly.points[3].x).toBeCloseTo(0);
|
|
445
445
|
expect(poly.points[3].y).toBeCloseTo(10);
|
|
446
446
|
});
|
|
447
|
+
|
|
448
|
+
// ─── validateSelection ────────────────────────────────────────────────────────
|
|
449
|
+
|
|
450
|
+
test('ChamferFilletBase.validateSelection returns null when firstPick has no entity', () => {
|
|
451
|
+
const chamfer = new Chamfer();
|
|
452
|
+
expect(chamfer.validateSelection()).toBeNull();
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
test('ChamferFilletBase.validateSelection returns null when firstPick entity is not a Line', () => {
|
|
456
|
+
core.scene.clear();
|
|
457
|
+
core.scene.addEntity('Circle', { points: [new Point(0, 0), new Point(5, 0)] });
|
|
458
|
+
|
|
459
|
+
const chamfer = new Chamfer();
|
|
460
|
+
chamfer.firstPick.entity = core.scene.entities.get(0); // Circle — resolveEndpoints fails
|
|
461
|
+
|
|
462
|
+
DesignCore.Mouse.pointOnScene = () => new Point(5, 5);
|
|
463
|
+
expect(chamfer.validateSelection()).toBeNull();
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
test('ChamferFilletBase.validateSelection returns null when findClosestItem returns undefined', () => {
|
|
467
|
+
core.scene.clear();
|
|
468
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] });
|
|
469
|
+
|
|
470
|
+
const chamfer = new Chamfer();
|
|
471
|
+
chamfer.firstPick.entity = core.scene.entities.get(0);
|
|
472
|
+
chamfer.firstPick.clickPoint = new Point(-5, 0);
|
|
473
|
+
|
|
474
|
+
const findSpy = jest.spyOn(core.scene.selectionManager, 'findClosestItem').mockReturnValue(undefined);
|
|
475
|
+
DesignCore.Mouse.pointOnScene = () => new Point(5, 5);
|
|
476
|
+
const result = chamfer.validateSelection();
|
|
477
|
+
findSpy.mockRestore();
|
|
478
|
+
|
|
479
|
+
expect(result).toBeNull();
|
|
480
|
+
});
|
|
481
|
+
|
|
482
|
+
test('ChamferFilletBase.validateSelection returns null when hovered entity is not a Line or PolylineBase', () => {
|
|
483
|
+
core.scene.clear();
|
|
484
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] });
|
|
485
|
+
core.scene.addEntity('Circle', { points: [new Point(5, 5), new Point(10, 5)] });
|
|
486
|
+
|
|
487
|
+
const chamfer = new Chamfer();
|
|
488
|
+
chamfer.firstPick.entity = core.scene.entities.get(0);
|
|
489
|
+
chamfer.firstPick.clickPoint = new Point(-5, 0);
|
|
490
|
+
|
|
491
|
+
const findSpy = jest.spyOn(core.scene.selectionManager, 'findClosestItem').mockReturnValue(1);
|
|
492
|
+
DesignCore.Mouse.pointOnScene = () => new Point(5, 5);
|
|
493
|
+
const result = chamfer.validateSelection();
|
|
494
|
+
findSpy.mockRestore();
|
|
495
|
+
|
|
496
|
+
expect(result).toBeNull();
|
|
497
|
+
});
|
|
498
|
+
|
|
499
|
+
test('ChamferFilletBase.validateSelection returns null when first and second segments are parallel', () => {
|
|
500
|
+
core.scene.clear();
|
|
501
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] });
|
|
502
|
+
core.scene.addEntity('Line', { points: [new Point(0, 2), new Point(10, 2)] }); // parallel horizontal
|
|
503
|
+
|
|
504
|
+
const chamfer = new Chamfer();
|
|
505
|
+
chamfer.firstPick.entity = core.scene.entities.get(0);
|
|
506
|
+
chamfer.firstPick.clickPoint = new Point(-5, 0);
|
|
507
|
+
|
|
508
|
+
const findSpy = jest.spyOn(core.scene.selectionManager, 'findClosestItem').mockReturnValue(1);
|
|
509
|
+
DesignCore.Mouse.pointOnScene = () => new Point(5, 2);
|
|
510
|
+
const result = chamfer.validateSelection();
|
|
511
|
+
findSpy.mockRestore();
|
|
512
|
+
|
|
513
|
+
expect(result).toBeNull();
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
test('ChamferFilletBase.validateSelection returns selection object for valid perpendicular lines', () => {
|
|
517
|
+
core.scene.clear();
|
|
518
|
+
core.scene.addEntity('Line', { points: [new Point(-10, 0), new Point(0, 0)] }); // horizontal
|
|
519
|
+
core.scene.addEntity('Line', { points: [new Point(5, -5), new Point(5, 5)] }); // vertical at x=5
|
|
520
|
+
|
|
521
|
+
const chamfer = new Chamfer();
|
|
522
|
+
chamfer.firstPick.entity = core.scene.entities.get(0);
|
|
523
|
+
chamfer.firstPick.clickPoint = new Point(-5, 0);
|
|
524
|
+
|
|
525
|
+
const findSpy = jest.spyOn(core.scene.selectionManager, 'findClosestItem').mockReturnValue(1);
|
|
526
|
+
DesignCore.Mouse.pointOnScene = () => new Point(5, 2);
|
|
527
|
+
const result = chamfer.validateSelection();
|
|
528
|
+
findSpy.mockRestore();
|
|
529
|
+
|
|
530
|
+
expect(result).not.toBeNull();
|
|
531
|
+
expect(result.candidate).toBe(core.scene.entities.get(1));
|
|
532
|
+
expect(result.intersectionPoint.x).toBeCloseTo(5);
|
|
533
|
+
expect(result.intersectionPoint.y).toBeCloseTo(0);
|
|
534
|
+
expect(result.tempSecond).toBeDefined();
|
|
535
|
+
});
|
package/test/tools/copy.test.js
CHANGED
|
@@ -6,12 +6,12 @@ const core = new Core();
|
|
|
6
6
|
|
|
7
7
|
test('Test Copy.action', () => {
|
|
8
8
|
// Add items to scene
|
|
9
|
-
core.scene.
|
|
10
|
-
core.scene.
|
|
11
|
-
core.scene.
|
|
12
|
-
core.scene.
|
|
13
|
-
core.scene.
|
|
14
|
-
core.scene.
|
|
9
|
+
core.scene.addEntity('Line', { points: [new Point(), new Point(0, 10)] });
|
|
10
|
+
core.scene.addEntity('Circle', { points: [new Point(), new Point(0, 10)] });
|
|
11
|
+
core.scene.addEntity('Polyline', { points: [new Point(), new Point(0, 10)] });
|
|
12
|
+
core.scene.addEntity('Arc', { points: [new Point(), new Point(0, 10), new Point(10, 0)] });
|
|
13
|
+
core.scene.addEntity('Rectangle', { points: [new Point(), new Point(0, 10)] });
|
|
14
|
+
core.scene.addEntity('Text', { points: [new Point(), new Point(0, 10)], height: 10, rotation: 0, string: 'text test' });
|
|
15
15
|
|
|
16
16
|
// Add items to selection set
|
|
17
17
|
for (let i = 0; i < core.scene.entities.count(); i++) {
|
|
@@ -44,7 +44,7 @@ test('Test Copy.action', () => {
|
|
|
44
44
|
for (let i = 0; i < 6; i++) {
|
|
45
45
|
const original = core.scene.entities.get(i);
|
|
46
46
|
const copy = core.scene.entities.get(i + 6);
|
|
47
|
-
expect(copy.handle).toBeDefined();
|
|
48
|
-
expect(copy.handle).not.toBe(original.handle);
|
|
47
|
+
expect(copy.getProperty('handle')).toBeDefined();
|
|
48
|
+
expect(copy.getProperty('handle')).not.toBe(original.getProperty('handle'));
|
|
49
49
|
}
|
|
50
50
|
});
|
|
@@ -27,7 +27,7 @@ describe('Copybase Tool', () => {
|
|
|
27
27
|
// Select both
|
|
28
28
|
DesignCore.Scene.selectionManager.addToSelectionSet(0);
|
|
29
29
|
DesignCore.Scene.selectionManager.addToSelectionSet(1);
|
|
30
|
-
expect(DesignCore.Scene.selectionManager.
|
|
30
|
+
expect(DesignCore.Scene.selectionManager.selectedEntities).toHaveLength(2);
|
|
31
31
|
|
|
32
32
|
const tool = new Copybase();
|
|
33
33
|
tool.points.push(new Point(10, 11)); // set base point
|
|
@@ -44,7 +44,7 @@ describe('Copybase Tool', () => {
|
|
|
44
44
|
const line = DesignCore.CommandManager.createNew('Line', { layer: '0', points: [new Point(0, 0), new Point(10, 0)] });
|
|
45
45
|
DesignCore.Scene.entities.add(line);
|
|
46
46
|
DesignCore.Scene.selectionManager.addToSelectionSet(0);
|
|
47
|
-
const originalClonePoints = DesignCore.Scene.selectionManager.
|
|
47
|
+
const originalClonePoints = DesignCore.Scene.selectionManager.selectedEntities[0].points.map((p) => ({ x: p.x, y: p.y }));
|
|
48
48
|
|
|
49
49
|
const tool = new Copybase();
|
|
50
50
|
tool.action();
|
|
@@ -27,7 +27,7 @@ describe('Copyclip Tool', () => {
|
|
|
27
27
|
// Select both
|
|
28
28
|
DesignCore.Scene.selectionManager.addToSelectionSet(0);
|
|
29
29
|
DesignCore.Scene.selectionManager.addToSelectionSet(1);
|
|
30
|
-
expect(DesignCore.Scene.selectionManager.
|
|
30
|
+
expect(DesignCore.Scene.selectionManager.selectedEntities).toHaveLength(2);
|
|
31
31
|
|
|
32
32
|
const tool = new Copyclip();
|
|
33
33
|
tool.action();
|
|
@@ -43,7 +43,7 @@ describe('Copyclip Tool', () => {
|
|
|
43
43
|
const line = DesignCore.CommandManager.createNew('Line', { layer: '0', points: [new Point(0, 0), new Point(10, 0)] });
|
|
44
44
|
DesignCore.Scene.entities.add(line);
|
|
45
45
|
DesignCore.Scene.selectionManager.addToSelectionSet(0);
|
|
46
|
-
const originalClonePoints = DesignCore.Scene.selectionManager.
|
|
46
|
+
const originalClonePoints = DesignCore.Scene.selectionManager.selectedEntities[0].points.map((p) => ({ x: p.x, y: p.y }));
|
|
47
47
|
|
|
48
48
|
const tool = new Copyclip();
|
|
49
49
|
tool.action();
|
|
@@ -38,7 +38,7 @@ test('CornerEntity.direction returns lineEnd minus lineStart', () => {
|
|
|
38
38
|
|
|
39
39
|
test('CornerEntity.resolveEndpoints returns true and sets lineStart/lineEnd for a Line', () => {
|
|
40
40
|
core.scene.clear();
|
|
41
|
-
core.scene.
|
|
41
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
42
42
|
const line = core.scene.entities.get(0);
|
|
43
43
|
|
|
44
44
|
const corner = new CornerEntity();
|
|
@@ -51,7 +51,7 @@ test('CornerEntity.resolveEndpoints returns true and sets lineStart/lineEnd for
|
|
|
51
51
|
|
|
52
52
|
test('CornerEntity.resolveEndpoints returns false and leaves endpoints null for a non-Line', () => {
|
|
53
53
|
core.scene.clear();
|
|
54
|
-
core.scene.
|
|
54
|
+
core.scene.addEntity('Circle', { points: [new Point(0, 0), new Point(5, 0)] });
|
|
55
55
|
const circle = core.scene.entities.get(0);
|
|
56
56
|
|
|
57
57
|
const corner = new CornerEntity();
|
|
@@ -66,7 +66,7 @@ test('CornerEntity.resolveEndpoints returns false and leaves endpoints null for
|
|
|
66
66
|
|
|
67
67
|
test('CornerEntity.setEntity returns true and clears segment for a plain Line entity', () => {
|
|
68
68
|
core.scene.clear();
|
|
69
|
-
core.scene.
|
|
69
|
+
core.scene.addEntity('Line', { points: [new Point(0, 0), new Point(10, 0)] });
|
|
70
70
|
const line = core.scene.entities.get(0);
|
|
71
71
|
|
|
72
72
|
const corner = new CornerEntity();
|
|
@@ -77,7 +77,7 @@ test('CornerEntity.setEntity returns true and clears segment for a plain Line en
|
|
|
77
77
|
|
|
78
78
|
test('CornerEntity.setEntity sets segment and segmentIndex for a polyline straight segment', () => {
|
|
79
79
|
core.scene.clear();
|
|
80
|
-
core.scene.
|
|
80
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(0, 0), new Point(10, 0), new Point(10, 10)] });
|
|
81
81
|
const poly = core.scene.entities.get(0);
|
|
82
82
|
|
|
83
83
|
const corner = new CornerEntity();
|
|
@@ -93,7 +93,7 @@ test('CornerEntity.setEntity notifies and returns false for a polyline arc segme
|
|
|
93
93
|
// bulge on the start point makes the segment an arc
|
|
94
94
|
const arcStart = new Point(0, 0);
|
|
95
95
|
arcStart.bulge = 1;
|
|
96
|
-
core.scene.
|
|
96
|
+
core.scene.addEntity('Lwpolyline', { points: [arcStart, new Point(10, 0)] });
|
|
97
97
|
const poly = core.scene.entities.get(0);
|
|
98
98
|
|
|
99
99
|
const errorMsg = 'arc segment error';
|
|
@@ -150,7 +150,7 @@ test('CornerEntity.keepStart returns true when segment start is on the click sid
|
|
|
150
150
|
// Polyline: (0,0)→(10,0)→(10,10), click at (3,2), intersection=(10,0)
|
|
151
151
|
// clickOnLine=(3,0), clickDir=(−7,0) → points toward start side
|
|
152
152
|
core.scene.clear();
|
|
153
|
-
core.scene.
|
|
153
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(0, 0), new Point(10, 0), new Point(10, 10)] });
|
|
154
154
|
const poly = core.scene.entities.get(0);
|
|
155
155
|
|
|
156
156
|
const corner = new CornerEntity();
|
|
@@ -167,7 +167,7 @@ test('CornerEntity.keepStart returns false when segment end is on the click side
|
|
|
167
167
|
// Same polyline, click at (8,2), intersection=(0,0)
|
|
168
168
|
// clickOnLine=(8,0), clickDir=(8,0) → points toward end side
|
|
169
169
|
core.scene.clear();
|
|
170
|
-
core.scene.
|
|
170
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(0, 0), new Point(10, 0), new Point(10, 10)] });
|
|
171
171
|
const poly = core.scene.entities.get(0);
|
|
172
172
|
|
|
173
173
|
const corner = new CornerEntity();
|
|
@@ -186,7 +186,7 @@ test('CornerEntity.keepStart handles closing segment of closed polyline (segment
|
|
|
186
186
|
// lineStart=(10,10), lineEnd=(0,0), click at (9,9), intersection=(10,0)
|
|
187
187
|
// clickOnLine=(10,9.something...) but we just need keepStart not to throw
|
|
188
188
|
core.scene.clear();
|
|
189
|
-
core.scene.
|
|
189
|
+
core.scene.addEntity('Lwpolyline', { points: [new Point(0, 0), new Point(10, 0), new Point(10, 10)] });
|
|
190
190
|
const poly = core.scene.entities.get(0);
|
|
191
191
|
|
|
192
192
|
const corner = new CornerEntity();
|
|
@@ -27,7 +27,7 @@ describe('Cutclip Tool', () => {
|
|
|
27
27
|
// Select both
|
|
28
28
|
DesignCore.Scene.selectionManager.addToSelectionSet(0);
|
|
29
29
|
DesignCore.Scene.selectionManager.addToSelectionSet(1);
|
|
30
|
-
expect(DesignCore.Scene.selectionManager.
|
|
30
|
+
expect(DesignCore.Scene.selectionManager.selectedEntities).toHaveLength(2);
|
|
31
31
|
|
|
32
32
|
const tool = new Cutclip();
|
|
33
33
|
tool.action();
|
|
@@ -45,7 +45,7 @@ describe('Cutclip Tool', () => {
|
|
|
45
45
|
const line = DesignCore.CommandManager.createNew('Line', { layer: '0', points: [new Point(0, 0), new Point(10, 0)] });
|
|
46
46
|
DesignCore.Scene.entities.add(line);
|
|
47
47
|
DesignCore.Scene.selectionManager.addToSelectionSet(0);
|
|
48
|
-
const originalClonePoints = DesignCore.Scene.selectionManager.
|
|
48
|
+
const originalClonePoints = DesignCore.Scene.selectionManager.selectedEntities[0].points.map((p) => ({ x: p.x, y: p.y }));
|
|
49
49
|
|
|
50
50
|
const tool = new Cutclip();
|
|
51
51
|
tool.action();
|
package/test/tools/erase.test.js
CHANGED
|
@@ -6,12 +6,12 @@ const core = new Core();
|
|
|
6
6
|
|
|
7
7
|
test('Test Erase.action', () => {
|
|
8
8
|
// Add items to scene
|
|
9
|
-
core.scene.
|
|
10
|
-
core.scene.
|
|
11
|
-
core.scene.
|
|
12
|
-
core.scene.
|
|
13
|
-
core.scene.
|
|
14
|
-
core.scene.
|
|
9
|
+
core.scene.addEntity('Line', { points: [new Point(10, 0), new Point(20, 0)] });
|
|
10
|
+
core.scene.addEntity('Circle', { points: [new Point(10, 0), new Point(20, 0)] });
|
|
11
|
+
core.scene.addEntity('Polyline', { points: [new Point(10, 0), new Point(20, 0)] });
|
|
12
|
+
core.scene.addEntity('Arc', { points: [new Point(10, 0), new Point(10, 10), new Point(0, 10)] });
|
|
13
|
+
core.scene.addEntity('Rectangle', { points: [new Point(10, 0), new Point(0, 10)] });
|
|
14
|
+
core.scene.addEntity('Text', { points: [new Point(10, 0), new Point(0, 10)], height: 10, rotation: 0, string: 'text test' });
|
|
15
15
|
|
|
16
16
|
// Add items to selection set
|
|
17
17
|
for (let i = 0; i < core.scene.entities.count(); i++) {
|
|
@@ -7,12 +7,12 @@ const core = new Core();
|
|
|
7
7
|
|
|
8
8
|
test('Test Explode.action', () => {
|
|
9
9
|
const insertPoint = new Point(100, 100);
|
|
10
|
-
const insertIndex = core.scene.
|
|
10
|
+
const insertIndex = core.scene.addEntity('Insert', { points: [insertPoint] });
|
|
11
11
|
const insert = core.scene.entities.get(insertIndex);
|
|
12
12
|
|
|
13
13
|
for (let i = 0; i < 5; i++) {
|
|
14
14
|
const line = new Line({ points: [new Point(0, i * 10), new Point(100, i * 10)] });
|
|
15
|
-
insert.block.
|
|
15
|
+
insert.block.addEntity(line);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
expect(core.scene.entities.count()).toBe(1);
|
|
@@ -38,8 +38,8 @@ test('Test Explode.action', () => {
|
|
|
38
38
|
expect(item.points[0].y).toBe(i * 10 + insertPoint.y);
|
|
39
39
|
|
|
40
40
|
// Verify each exploded entity has a unique handle
|
|
41
|
-
expect(item.handle).toBeDefined();
|
|
42
|
-
expect(handles.has(item.handle)).toBe(false);
|
|
43
|
-
handles.add(item.handle);
|
|
41
|
+
expect(item.getProperty('handle')).toBeDefined();
|
|
42
|
+
expect(handles.has(item.getProperty('handle'))).toBe(false);
|
|
43
|
+
handles.add(item.getProperty('handle'));
|
|
44
44
|
}
|
|
45
45
|
});
|