@design-core/core 51.2.0 → 52.2.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/core/dimensions/alignedDimension.js +3 -1
- package/core/dimensions/angularDimension.js +118 -36
- package/core/dimensions/circularDimensionBase.js +32 -12
- package/core/dimensions/diametricDimension.js +29 -1
- package/core/dimensions/dimension.js +58 -5
- package/core/dimensions/dimensionBase.js +107 -4
- package/core/dimensions/linearDimensionBase.js +75 -37
- package/core/dimensions/radialDimension.js +26 -1
- package/core/dimensions/rotatedDimension.js +6 -3
- package/core/entities/entity.js +9 -0
- package/core/lib/auxiliary/snapPoint.js +9 -0
- package/core/lib/canvas.js +22 -0
- package/core/lib/commandManager.js +4 -4
- package/core/lib/dxf/dxf.js +8 -2
- package/core/lib/inputManager.js +23 -3
- package/core/lib/renderers/pdfRenderer.js +17 -1
- package/core/lib/scene.js +2 -0
- package/core/lib/selectionManager.js +28 -0
- package/core/lib/strings.js +1 -0
- package/core/properties/dimType.js +14 -0
- package/core/properties/property.js +1 -0
- package/core/tables/dimStyle.js +32 -2
- package/core/tables/dimStyleManager.js +2 -0
- package/core/tables/styleManagerBase.js +17 -3
- package/core/tables/tableManagerBase.js +24 -2
- package/core/tools/gripStretch.js +97 -0
- package/core/tools/offset.js +7 -1
- package/core/tools/tool.js +10 -0
- package/cspell.json +3 -0
- package/package.json +1 -1
- package/test/dimensions/alignedDimension.test.js +165 -0
- package/test/dimensions/angularDimension.test.js +149 -0
- package/test/dimensions/diametricDimension.test.js +77 -4
- package/test/dimensions/dimension.test.js +130 -0
- package/test/dimensions/dimensionBase.test.js +97 -4
- package/test/dimensions/radialDimension.test.js +34 -0
- package/test/dimensions/rotatedDimension.test.js +80 -0
- package/test/integration/exportIntegration.reference.dxf +3 -9
- package/test/integration/exportIntegration.test.js +1 -0
- package/test/integration/userInputIntegration.reference.dxf +3 -9
- package/test/integration/userInputIntegration.test.js +1 -0
- package/test/lib/inputManager.test.js +316 -1
- package/test/lib/selectionManager.test.js +42 -0
- package/test/renderers/pdfRenderer.test.js +26 -0
- package/test/tables/dimStyleManager.test.js +90 -0
- package/test/tables/dimstyle.test.js +32 -0
- package/test/tables/tableManagerBase.test.js +167 -0
- package/test/tools/gripStretch.test.js +108 -0
- package/test/tools/offset.test.js +2 -0
- package/test/tools/purge.test.js +3 -1
- package/test/tools/tool.test.js +25 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Core } from '../../core/core/core.js';
|
|
2
2
|
import { TableManagerBase } from '../../core/tables/tableManagerBase.js';
|
|
3
|
+
import { DesignCore } from '../../core/designCore.js';
|
|
4
|
+
import { Point } from '../../core/entities/point.js';
|
|
3
5
|
|
|
4
6
|
// initialise core
|
|
5
7
|
new Core();
|
|
@@ -192,3 +194,168 @@ test('Test tableManagerBase.updateItem', () => {
|
|
|
192
194
|
tableManagerBase.updateItem(0, 'textHeight', 20);
|
|
193
195
|
expect(tableManagerBase.getItemByIndex(0).textHeight).toBe(20);
|
|
194
196
|
});
|
|
197
|
+
|
|
198
|
+
describe('tableManagerBase deleteItem return contract', () => {
|
|
199
|
+
beforeEach(() => {
|
|
200
|
+
tableManagerBase.items = [{ name: 'itemOne' }, { name: 'Standard' }];
|
|
201
|
+
tableManagerBase.indelibleItems = ['Standard'];
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
test('returns the spliced array containing the deleted item', () => {
|
|
205
|
+
const deleted = tableManagerBase.deleteItem(0);
|
|
206
|
+
|
|
207
|
+
expect(Array.isArray(deleted)).toBe(true);
|
|
208
|
+
expect(deleted).toEqual([{ name: 'itemOne' }]);
|
|
209
|
+
expect(tableManagerBase.itemExists('itemOne')).toBe(false);
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
test('returns undefined for an invalid index', () => {
|
|
213
|
+
expect(tableManagerBase.deleteItem(10)).toBeUndefined();
|
|
214
|
+
expect(tableManagerBase.itemCount()).toBe(2);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
test('returns undefined and keeps indelible items, ignoring case', () => {
|
|
218
|
+
tableManagerBase.indelibleItems = ['STANDARD'];
|
|
219
|
+
|
|
220
|
+
expect(tableManagerBase.deleteItem(1, false)).toBeUndefined();
|
|
221
|
+
expect(tableManagerBase.itemExists('Standard')).toBe(true);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
test('invalidates the name lookup cache', () => {
|
|
225
|
+
expect(tableManagerBase.getItemByName('itemOne')).toBeDefined();
|
|
226
|
+
|
|
227
|
+
tableManagerBase.deleteItem(0);
|
|
228
|
+
|
|
229
|
+
expect(tableManagerBase.getItemByName('itemOne')).toBeUndefined();
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
describe('tableManagerBase lookups', () => {
|
|
234
|
+
beforeEach(() => {
|
|
235
|
+
tableManagerBase.items = [{ name: 'itemOne' }, { name: 'itemTwo' }];
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
test('getItemIndex is case-insensitive and returns -1 when missing', () => {
|
|
239
|
+
expect(tableManagerBase.getItemIndex('ITEMTWO')).toBe(1);
|
|
240
|
+
expect(tableManagerBase.getItemIndex('missing')).toBe(-1);
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
test('itemExists and getItemByName are case-insensitive', () => {
|
|
244
|
+
expect(tableManagerBase.itemExists('ITEMONE')).toBe(true);
|
|
245
|
+
expect(tableManagerBase.getItemByName('itemone').name).toBe('itemOne');
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
test('getItemByName cache is refreshed after addItem and rename', () => {
|
|
249
|
+
expect(tableManagerBase.getItemByName('itemOne')).toBeDefined();
|
|
250
|
+
|
|
251
|
+
tableManagerBase.addItem({ name: 'itemThree' });
|
|
252
|
+
expect(tableManagerBase.getItemByName('itemThree')).toBeDefined();
|
|
253
|
+
|
|
254
|
+
tableManagerBase.renameItem(0, 'itemRenamed');
|
|
255
|
+
expect(tableManagerBase.getItemByName('itemOne')).toBeUndefined();
|
|
256
|
+
expect(tableManagerBase.getItemByName('itemRenamed')).toBeDefined();
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test('clearItems removes all items', () => {
|
|
260
|
+
tableManagerBase.clearItems();
|
|
261
|
+
|
|
262
|
+
expect(tableManagerBase.itemCount()).toBe(0);
|
|
263
|
+
expect(tableManagerBase.getItemByName('itemOne')).toBeUndefined();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
test('addItem returns the existing item when not overwriting', () => {
|
|
267
|
+
const existing = tableManagerBase.getItemByName('itemOne');
|
|
268
|
+
|
|
269
|
+
expect(tableManagerBase.addItem({ name: 'ITEMONE' })).toBe(existing);
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
describe('tableManagerBase renameItem', () => {
|
|
274
|
+
beforeEach(() => {
|
|
275
|
+
tableManagerBase.items = [{ name: 'itemOne' }, { name: 'itemTwo' }, { name: 'Standard' }];
|
|
276
|
+
tableManagerBase.indelibleItems = ['Standard'];
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
test('returns the new name', () => {
|
|
280
|
+
expect(tableManagerBase.renameItem(0, 'renamed')).toBe('renamed');
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
test('returns undefined when the name is unchanged apart from case', () => {
|
|
284
|
+
expect(tableManagerBase.renameItem(0, 'ITEMONE')).toBeUndefined();
|
|
285
|
+
expect(tableManagerBase.getItemByIndex(0).name).toBe('itemOne');
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
test('cannot rename an indelible item', () => {
|
|
289
|
+
expect(tableManagerBase.renameItem(2, 'other')).toBeUndefined();
|
|
290
|
+
expect(tableManagerBase.getItemByIndex(2).name).toBe('Standard');
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
test('makes a clashing name unique', () => {
|
|
294
|
+
expect(tableManagerBase.renameItem(0, 'itemTwo')).toBe('itemTwo_1');
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
describe('tableManagerBase scene references', () => {
|
|
299
|
+
const originalProperty = tableManagerBase.itemProperty;
|
|
300
|
+
|
|
301
|
+
const addLine = (layer) => {
|
|
302
|
+
const line = DesignCore.Scene.addEntity('Line', { points: [new Point(), new Point(10, 10)], layer: layer });
|
|
303
|
+
return line;
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
beforeEach(() => {
|
|
307
|
+
tableManagerBase.itemProperty = 'layer';
|
|
308
|
+
tableManagerBase.items = [{ name: 'itemOne' }, { name: 'itemTwo' }];
|
|
309
|
+
tableManagerBase.indelibleItems = [];
|
|
310
|
+
while (DesignCore.Scene.entities.count() > 0) {
|
|
311
|
+
DesignCore.Scene.entities.remove(0);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
afterAll(() => {
|
|
316
|
+
tableManagerBase.itemProperty = originalProperty;
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
test('updateSceneItem renames references through the property API', () => {
|
|
320
|
+
addLine('itemOne');
|
|
321
|
+
addLine('itemTwo');
|
|
322
|
+
|
|
323
|
+
tableManagerBase.updateSceneItem('itemOne', 'renamed');
|
|
324
|
+
|
|
325
|
+
expect(DesignCore.Scene.entities.get(0).getProperty('layer')).toBe('renamed');
|
|
326
|
+
expect(DesignCore.Scene.entities.get(1).getProperty('layer')).toBe('itemTwo');
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
test('updateSceneItem matches names case-insensitively', () => {
|
|
330
|
+
addLine('ITEMONE');
|
|
331
|
+
|
|
332
|
+
tableManagerBase.updateSceneItem('itemOne', 'renamed');
|
|
333
|
+
|
|
334
|
+
expect(DesignCore.Scene.entities.get(0).getProperty('layer')).toBe('renamed');
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
test('updateSceneItem ignores an undefined name', () => {
|
|
338
|
+
addLine('itemOne');
|
|
339
|
+
|
|
340
|
+
tableManagerBase.updateSceneItem(undefined, 'renamed');
|
|
341
|
+
|
|
342
|
+
expect(DesignCore.Scene.entities.get(0).getProperty('layer')).toBe('itemOne');
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
test('renameItem updates dependent entities', () => {
|
|
346
|
+
addLine('itemOne');
|
|
347
|
+
|
|
348
|
+
tableManagerBase.renameItem(0, 'renamed');
|
|
349
|
+
|
|
350
|
+
expect(DesignCore.Scene.entities.get(0).getProperty('layer')).toBe('renamed');
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
test('purge removes only unused items', () => {
|
|
354
|
+
addLine('itemOne');
|
|
355
|
+
|
|
356
|
+
tableManagerBase.purge();
|
|
357
|
+
|
|
358
|
+
expect(tableManagerBase.itemExists('itemOne')).toBe(true);
|
|
359
|
+
expect(tableManagerBase.itemExists('itemTwo')).toBe(false);
|
|
360
|
+
});
|
|
361
|
+
});
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { Tool } from '../../core/tools/tool.js';
|
|
2
|
+
import { GripStretch } from '../../core/tools/gripStretch.js';
|
|
3
|
+
import { Core } from '../../core/core/core.js';
|
|
4
|
+
import { DesignCore } from '../../core/designCore.js';
|
|
5
|
+
import { DimensionBase } from '../../core/dimensions/dimensionBase.js';
|
|
6
|
+
import { Point } from '../../core/entities/point.js';
|
|
7
|
+
import { jest } from '@jest/globals';
|
|
8
|
+
|
|
9
|
+
const core = new Core();
|
|
10
|
+
|
|
11
|
+
test('GripStretch is a Tool with type GripStretch', () => {
|
|
12
|
+
const gripStretch = new GripStretch();
|
|
13
|
+
expect(gripStretch).toBeInstanceOf(Tool);
|
|
14
|
+
expect(gripStretch.type).toBe('GripStretch');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test('GripStretch is not registered as a typeable command', () => {
|
|
18
|
+
expect(typeof GripStretch.register).toBe('undefined');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('GripStretch.action commits the dropped grip position to the real entity', () => {
|
|
22
|
+
core.scene.clear();
|
|
23
|
+
const dim = new DimensionBase({});
|
|
24
|
+
dim.points = [
|
|
25
|
+
Object.assign(new Point(0, 0), { sequence: 13 }),
|
|
26
|
+
Object.assign(new Point(10, 10), { sequence: 11 }),
|
|
27
|
+
];
|
|
28
|
+
DesignCore.Scene.entities.add(dim);
|
|
29
|
+
core.scene.selectionManager.addToSelectionSet(0);
|
|
30
|
+
|
|
31
|
+
const grip = dim.getGrips()[0];
|
|
32
|
+
const gripStretch = new GripStretch(0, grip);
|
|
33
|
+
gripStretch.points.push(new Point(50, 60));
|
|
34
|
+
|
|
35
|
+
gripStretch.action();
|
|
36
|
+
|
|
37
|
+
const entity = core.scene.entities.get(0);
|
|
38
|
+
const pt11 = entity.getPointBySequence(entity.points, 11);
|
|
39
|
+
expect(pt11.x).toBe(50);
|
|
40
|
+
expect(pt11.y).toBe(60);
|
|
41
|
+
expect(entity.dimType.hasUserPositionedText()).toBe(true);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('GripStretch.preview live-updates the selected-entity preview clone, not the real entity', () => {
|
|
45
|
+
core.scene.clear();
|
|
46
|
+
const dim = new DimensionBase({});
|
|
47
|
+
dim.points = [
|
|
48
|
+
Object.assign(new Point(0, 0), { sequence: 13 }),
|
|
49
|
+
Object.assign(new Point(10, 10), { sequence: 11 }),
|
|
50
|
+
];
|
|
51
|
+
DesignCore.Scene.entities.add(dim);
|
|
52
|
+
core.scene.selectionManager.addToSelectionSet(0);
|
|
53
|
+
|
|
54
|
+
const grip = dim.getGrips()[0];
|
|
55
|
+
const gripStretch = new GripStretch(0, grip);
|
|
56
|
+
jest.spyOn(DesignCore.Mouse, 'pointOnScene').mockReturnValue(new Point(50, 60));
|
|
57
|
+
|
|
58
|
+
gripStretch.preview();
|
|
59
|
+
|
|
60
|
+
const previewEntity = core.scene.selectionManager.selectedEntities[0];
|
|
61
|
+
const previewPt11 = previewEntity.getPointBySequence(previewEntity.points, 11);
|
|
62
|
+
expect(previewPt11.x).toBe(50);
|
|
63
|
+
expect(previewPt11.y).toBe(60);
|
|
64
|
+
|
|
65
|
+
const realPt11 = core.scene.entities.get(0).getPointBySequence(core.scene.entities.get(0).points, 11);
|
|
66
|
+
expect(realPt11.x).toBe(10);
|
|
67
|
+
expect(realPt11.y).toBe(10);
|
|
68
|
+
|
|
69
|
+
jest.restoreAllMocks();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
test('GripStretch.execute requests the stretch point then commits, keeping the entity selected', async () => {
|
|
73
|
+
core.scene.clear();
|
|
74
|
+
const dim = new DimensionBase({});
|
|
75
|
+
dim.points = [
|
|
76
|
+
Object.assign(new Point(0, 0), { sequence: 13 }),
|
|
77
|
+
Object.assign(new Point(10, 10), { sequence: 11 }),
|
|
78
|
+
];
|
|
79
|
+
DesignCore.Scene.entities.add(dim);
|
|
80
|
+
core.scene.selectionManager.addToSelectionSet(0);
|
|
81
|
+
|
|
82
|
+
const grip = dim.getGrips()[0];
|
|
83
|
+
const gripStretch = new GripStretch(0, grip);
|
|
84
|
+
|
|
85
|
+
const origInputManager = DesignCore.Scene.inputManager;
|
|
86
|
+
DesignCore.Scene.inputManager = {
|
|
87
|
+
requestInput: async (op) => {
|
|
88
|
+
expect(op.promptMessage).toBe('Specify stretch point');
|
|
89
|
+
return new Point(50, 60);
|
|
90
|
+
},
|
|
91
|
+
actionCommand: () => gripStretch.action(),
|
|
92
|
+
refreshPreview: () => {},
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
await gripStretch.execute();
|
|
97
|
+
} finally {
|
|
98
|
+
DesignCore.Scene.inputManager = origInputManager;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const entity = core.scene.entities.get(0);
|
|
102
|
+
const pt11 = entity.getPointBySequence(entity.points, 11);
|
|
103
|
+
expect(pt11.x).toBe(50);
|
|
104
|
+
expect(pt11.y).toBe(60);
|
|
105
|
+
// grip editing must leave the entity selected afterwards, unlike most commands
|
|
106
|
+
expect(core.scene.selectionManager.selectionSet.selectionSet).toContain(0);
|
|
107
|
+
});
|
|
108
|
+
|
|
@@ -269,6 +269,7 @@ test('Test Offset.action - offset circle outward', () => {
|
|
|
269
269
|
expect(newCircle.points[0].y).toBeCloseTo(0);
|
|
270
270
|
// New radius should be 15
|
|
271
271
|
expect(newCircle.getProperty('radius')).toBeCloseTo(15);
|
|
272
|
+
expect(newCircle.type).toBe('Circle'); // not an Arc
|
|
272
273
|
});
|
|
273
274
|
|
|
274
275
|
test('Test Offset.action - offset circle inward', () => {
|
|
@@ -288,6 +289,7 @@ test('Test Offset.action - offset circle inward', () => {
|
|
|
288
289
|
expect(newCircle.points[0].x).toBeCloseTo(0);
|
|
289
290
|
expect(newCircle.points[0].y).toBeCloseTo(0);
|
|
290
291
|
expect(newCircle.getProperty('radius')).toBeCloseTo(7);
|
|
292
|
+
expect(newCircle.type).toBe('Circle'); // not an Arc
|
|
291
293
|
});
|
|
292
294
|
|
|
293
295
|
test('Test Offset.action - offset circle inward returns null when radius would be zero', () => {
|
package/test/tools/purge.test.js
CHANGED
|
@@ -46,7 +46,9 @@ test('Test purge.action', () => {
|
|
|
46
46
|
expect(dimStyleManager.itemCount()).toBe(4);
|
|
47
47
|
purge.option = 'Dimstyles';
|
|
48
48
|
purge.action();
|
|
49
|
-
|
|
49
|
+
// STANDARD is indelible and ISO-25 is the current style
|
|
50
|
+
expect(dimStyleManager.itemCount()).toBe(2);
|
|
51
|
+
expect(dimStyleManager.itemExists('ISO-25')).toBe(true);
|
|
50
52
|
|
|
51
53
|
expect(layerManager.itemCount()).toBe(4);
|
|
52
54
|
purge.option = 'Layers';
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { Core } from '../../core/core/core.js';
|
|
2
|
+
import { DesignCore } from '../../core/designCore.js';
|
|
3
|
+
import { Tool } from '../../core/tools/tool.js';
|
|
4
|
+
import { jest } from '@jest/globals';
|
|
5
|
+
|
|
6
|
+
new Core();
|
|
7
|
+
|
|
8
|
+
afterEach(() => {
|
|
9
|
+
jest.restoreAllMocks();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
test('Tool.cancel default delegates to inputManager.reset()', () => {
|
|
13
|
+
const tool = new Tool();
|
|
14
|
+
const resetSpy = jest.spyOn(DesignCore.Scene.inputManager, 'reset').mockImplementation(() => {});
|
|
15
|
+
|
|
16
|
+
tool.cancel();
|
|
17
|
+
|
|
18
|
+
expect(resetSpy).toHaveBeenCalledTimes(1);
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
test('Tool.preview and Tool.action are no-ops by default', () => {
|
|
22
|
+
const tool = new Tool();
|
|
23
|
+
expect(() => tool.preview()).not.toThrow();
|
|
24
|
+
expect(() => tool.action()).not.toThrow();
|
|
25
|
+
});
|