@design-core/core 50.1.0 → 51.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/.github/workflows/publish.yml +40 -0
- package/README.md +14 -1
- package/core/entities/hatch.js +182 -12
- package/core/entities/insert.js +6 -1
- package/core/lib/canvas.js +11 -3
- package/core/lib/commandManager.js +5 -0
- package/core/lib/inputManager.js +1 -0
- package/core/lib/mouse.js +10 -0
- package/core/lib/plotOptions.js +17 -0
- package/core/lib/strings.js +2 -0
- package/core/properties/entityProperties.js +2 -1
- package/core/properties/flags.js +12 -0
- package/core/properties/property.js +7 -2
- package/core/properties/propertyManager.js +15 -0
- package/core/tables/block.js +2 -0
- package/core/tools/windowPick.js +75 -0
- package/cspell.json +4 -0
- package/package.json +7 -2
- package/test/entities/hatch.test.js +323 -0
- package/test/integration/plotPageSizeIntegration.test.js +113 -0
- package/test/lib/clipboard.test.js +73 -0
- package/test/lib/plotOptions.test.js +58 -1
- package/test/properties/flags.test.js +24 -0
- package/test/properties/propertyManager.test.js +71 -0
- package/test/tools/windowPick.test.js +129 -0
- package/test/tools/zoom.test.js +10 -12
|
@@ -113,3 +113,74 @@ test('Test propertyManager.getEntityPropertyValue', () => {
|
|
|
113
113
|
propertyValues = propertiesManager.getEntityPropertyValue('All', 'colour');
|
|
114
114
|
expect(propertyValues).toBe('Varies');
|
|
115
115
|
});
|
|
116
|
+
|
|
117
|
+
test('Test propertyManager.getEntityPropertyDefinition', () => {
|
|
118
|
+
// clear the selection set
|
|
119
|
+
DesignCore.Scene.reset();
|
|
120
|
+
|
|
121
|
+
// returns undefined when nothing is selected
|
|
122
|
+
let def = propertiesManager.getEntityPropertyDefinition('All', 'colour');
|
|
123
|
+
expect(def).toBeUndefined();
|
|
124
|
+
|
|
125
|
+
// select the line entity
|
|
126
|
+
DesignCore.Scene.selectionManager.selectionSet.selectionSet.push(0);
|
|
127
|
+
|
|
128
|
+
// returns a Property descriptor for a valid property
|
|
129
|
+
def = propertiesManager.getEntityPropertyDefinition('All', 'colour');
|
|
130
|
+
expect(def).toBeDefined();
|
|
131
|
+
expect(typeof def.type).toBe('string');
|
|
132
|
+
|
|
133
|
+
// returns undefined for a property the entity does not have
|
|
134
|
+
def = propertiesManager.getEntityPropertyDefinition('All', 'non-existent-prop');
|
|
135
|
+
expect(def).toBeUndefined();
|
|
136
|
+
|
|
137
|
+
// filters by entityType — Circle not selected, so returns undefined
|
|
138
|
+
def = propertiesManager.getEntityPropertyDefinition('Circle', 'colour');
|
|
139
|
+
expect(def).toBeUndefined();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test('Test propertyManager.getEntityForProperty', () => {
|
|
143
|
+
// clear the selection set
|
|
144
|
+
DesignCore.Scene.reset();
|
|
145
|
+
|
|
146
|
+
// returns undefined when nothing is selected
|
|
147
|
+
let entity = propertiesManager.getEntityForProperty('All', 'colour');
|
|
148
|
+
expect(entity).toBeUndefined();
|
|
149
|
+
|
|
150
|
+
// select the line (index 0) and circle (index 1)
|
|
151
|
+
DesignCore.Scene.selectionManager.selectionSet.selectionSet.push(0);
|
|
152
|
+
DesignCore.Scene.selectionManager.selectionSet.selectionSet.push(1);
|
|
153
|
+
|
|
154
|
+
// returns an entity for 'All' and a known property
|
|
155
|
+
entity = propertiesManager.getEntityForProperty('All', 'colour');
|
|
156
|
+
expect(entity).toBeDefined();
|
|
157
|
+
expect(entity.type === 'Line' || entity.type === 'Circle').toBe(true);
|
|
158
|
+
|
|
159
|
+
// filters by entityType — only Circle entities
|
|
160
|
+
entity = propertiesManager.getEntityForProperty('Circle', 'colour');
|
|
161
|
+
expect(entity).toBeDefined();
|
|
162
|
+
expect(entity.type).toBe('Circle');
|
|
163
|
+
|
|
164
|
+
// returns undefined when the property does not exist on any selected entity
|
|
165
|
+
entity = propertiesManager.getEntityForProperty('All', 'non-existent-prop');
|
|
166
|
+
expect(entity).toBeUndefined();
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test('Test propertyManager.setPropertyCallbackFunction and selectionSetChanged', () => {
|
|
170
|
+
let callCount = 0;
|
|
171
|
+
const callback = () => {
|
|
172
|
+
callCount++;
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
// selectionSetChanged with no callback set should not throw
|
|
176
|
+
propertiesManager.selectionSetChanged();
|
|
177
|
+
|
|
178
|
+
propertiesManager.setPropertyCallbackFunction(callback);
|
|
179
|
+
|
|
180
|
+
// callback is invoked when selectionSetChanged is called
|
|
181
|
+
propertiesManager.selectionSetChanged();
|
|
182
|
+
expect(callCount).toBe(1);
|
|
183
|
+
|
|
184
|
+
propertiesManager.selectionSetChanged();
|
|
185
|
+
expect(callCount).toBe(2);
|
|
186
|
+
});
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { Core } from '../../core/core/core.js';
|
|
2
|
+
import { DesignCore } from '../../core/designCore.js';
|
|
3
|
+
import { Point } from '../../core/entities/point.js';
|
|
4
|
+
import { WindowPick } from '../../core/tools/windowPick.js';
|
|
5
|
+
import { expect, jest } from '@jest/globals';
|
|
6
|
+
import { withMockInput } from '../test-helpers/test-helpers.js';
|
|
7
|
+
|
|
8
|
+
const core = new Core();
|
|
9
|
+
|
|
10
|
+
// ─── register ────────────────────────────────────────────────────────────────
|
|
11
|
+
|
|
12
|
+
test('WindowPick.register returns correct command object', () => {
|
|
13
|
+
const reg = WindowPick.register();
|
|
14
|
+
expect(reg.command).toBe('WindowPick');
|
|
15
|
+
expect(reg.shortcut).toBeUndefined();
|
|
16
|
+
expect(reg.type).toBeUndefined();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// ─── execute ──────────────────────────────────────────────────────────────────
|
|
20
|
+
|
|
21
|
+
test('WindowPick.execute collects two points and calls executeCommand', async () => {
|
|
22
|
+
const executeCommandSpy = jest.fn();
|
|
23
|
+
|
|
24
|
+
await withMockInput(
|
|
25
|
+
core.scene,
|
|
26
|
+
[new Point(0, 0), new Point(10, 10)],
|
|
27
|
+
async () => {
|
|
28
|
+
const tool = new WindowPick();
|
|
29
|
+
await tool.execute();
|
|
30
|
+
},
|
|
31
|
+
{ extraMethods: { executeCommand: executeCommandSpy } },
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
expect(executeCommandSpy).toHaveBeenCalled();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('WindowPick.execute returns early when first point is undefined', async () => {
|
|
38
|
+
const executeCommandSpy = jest.fn();
|
|
39
|
+
|
|
40
|
+
await withMockInput(
|
|
41
|
+
core.scene,
|
|
42
|
+
[],
|
|
43
|
+
async () => {
|
|
44
|
+
const tool = new WindowPick();
|
|
45
|
+
await tool.execute();
|
|
46
|
+
},
|
|
47
|
+
{ extraMethods: { executeCommand: executeCommandSpy } },
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
expect(executeCommandSpy).not.toHaveBeenCalled();
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('WindowPick.execute returns early when second point is undefined', async () => {
|
|
54
|
+
const executeCommandSpy = jest.fn();
|
|
55
|
+
|
|
56
|
+
await withMockInput(
|
|
57
|
+
core.scene,
|
|
58
|
+
[new Point(0, 0)],
|
|
59
|
+
async () => {
|
|
60
|
+
const tool = new WindowPick();
|
|
61
|
+
await tool.execute();
|
|
62
|
+
},
|
|
63
|
+
{ extraMethods: { executeCommand: executeCommandSpy } },
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
expect(executeCommandSpy).not.toHaveBeenCalled();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('WindowPick.execute stores the two collected points', async () => {
|
|
70
|
+
let capturedTool;
|
|
71
|
+
const executeCommandSpy = jest.fn();
|
|
72
|
+
|
|
73
|
+
await withMockInput(
|
|
74
|
+
core.scene,
|
|
75
|
+
[new Point(1, 2), new Point(30, 40)],
|
|
76
|
+
async () => {
|
|
77
|
+
capturedTool = new WindowPick();
|
|
78
|
+
await capturedTool.execute();
|
|
79
|
+
},
|
|
80
|
+
{ extraMethods: { executeCommand: executeCommandSpy } },
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
expect(capturedTool.points).toHaveLength(2);
|
|
84
|
+
expect(capturedTool.points[0].x).toBe(1);
|
|
85
|
+
expect(capturedTool.points[0].y).toBe(2);
|
|
86
|
+
expect(capturedTool.points[1].x).toBe(30);
|
|
87
|
+
expect(capturedTool.points[1].y).toBe(40);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// ─── preview ──────────────────────────────────────────────────────────────────
|
|
91
|
+
|
|
92
|
+
test('WindowPick.preview with one point creates a rectangle polyline preview', () => {
|
|
93
|
+
const tool = new WindowPick();
|
|
94
|
+
tool.points.push(new Point(10, 10));
|
|
95
|
+
|
|
96
|
+
core.mouse.mouseMoved(50, 50);
|
|
97
|
+
|
|
98
|
+
const initialCount = DesignCore.Scene.previewEntities.count();
|
|
99
|
+
|
|
100
|
+
tool.preview();
|
|
101
|
+
|
|
102
|
+
expect(DesignCore.Scene.previewEntities.count()).toBe(initialCount + 1);
|
|
103
|
+
|
|
104
|
+
const tempItem = DesignCore.Scene.previewEntities.get(DesignCore.Scene.previewEntities.count() - 1);
|
|
105
|
+
expect(tempItem.type).toBe('Polyline');
|
|
106
|
+
expect(tempItem.points.length).toBe(4);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('WindowPick.preview with no points does not create a preview', () => {
|
|
110
|
+
const tool = new WindowPick();
|
|
111
|
+
|
|
112
|
+
const initialCount = DesignCore.Scene.previewEntities.count();
|
|
113
|
+
|
|
114
|
+
tool.preview();
|
|
115
|
+
|
|
116
|
+
expect(DesignCore.Scene.previewEntities.count()).toBe(initialCount);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
test('WindowPick.preview with two points does not create another preview', () => {
|
|
120
|
+
const tool = new WindowPick();
|
|
121
|
+
tool.points.push(new Point(0, 0));
|
|
122
|
+
tool.points.push(new Point(10, 10));
|
|
123
|
+
|
|
124
|
+
const initialCount = DesignCore.Scene.previewEntities.count();
|
|
125
|
+
|
|
126
|
+
tool.preview();
|
|
127
|
+
|
|
128
|
+
expect(DesignCore.Scene.previewEntities.count()).toBe(initialCount);
|
|
129
|
+
});
|
package/test/tools/zoom.test.js
CHANGED
|
@@ -181,40 +181,38 @@ test('Test Canvas.zoomToWindow - reversed points', () => {
|
|
|
181
181
|
expect(finalScale).not.toBe(initialScale);
|
|
182
182
|
});
|
|
183
183
|
|
|
184
|
-
test('Test Canvas.zoomToWindow - zero width (
|
|
184
|
+
test('Test Canvas.zoomToWindow - zero width (zooms using height)', () => {
|
|
185
185
|
core.canvas.width = 800;
|
|
186
186
|
core.canvas.height = 600;
|
|
187
187
|
core.canvas.matrix.scale(1, 1);
|
|
188
188
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
// Points with same x coordinate (zero width)
|
|
189
|
+
// Points with same x coordinate (zero width, i.e. a vertical line)
|
|
192
190
|
const pt1 = new Point(50, 0);
|
|
193
191
|
const pt2 = new Point(50, 100);
|
|
194
192
|
|
|
195
193
|
core.canvas.zoomToWindow(pt1, pt2);
|
|
196
194
|
|
|
197
|
-
//
|
|
195
|
+
// Resulting scale depends only on the window size, not the prior scale,
|
|
196
|
+
// so assert the expected value rather than comparing against initialScale
|
|
198
197
|
const finalScale = core.canvas.getScale();
|
|
199
|
-
expect(finalScale).
|
|
198
|
+
expect(finalScale).toBeCloseTo((core.canvas.height / 100) * 0.9);
|
|
200
199
|
});
|
|
201
200
|
|
|
202
|
-
test('Test Canvas.zoomToWindow - zero height (
|
|
201
|
+
test('Test Canvas.zoomToWindow - zero height (zooms using width)', () => {
|
|
203
202
|
core.canvas.width = 800;
|
|
204
203
|
core.canvas.height = 600;
|
|
205
204
|
core.canvas.matrix.scale(1, 1);
|
|
206
205
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
// Points with same y coordinate (zero height)
|
|
206
|
+
// Points with same y coordinate (zero height, i.e. a horizontal line)
|
|
210
207
|
const pt1 = new Point(0, 50);
|
|
211
208
|
const pt2 = new Point(100, 50);
|
|
212
209
|
|
|
213
210
|
core.canvas.zoomToWindow(pt1, pt2);
|
|
214
211
|
|
|
215
|
-
//
|
|
212
|
+
// Resulting scale depends only on the window size, not the prior scale,
|
|
213
|
+
// so assert the expected value rather than comparing against initialScale
|
|
216
214
|
const finalScale = core.canvas.getScale();
|
|
217
|
-
expect(finalScale).
|
|
215
|
+
expect(finalScale).toBeCloseTo((core.canvas.width / 100) * 0.9);
|
|
218
216
|
});
|
|
219
217
|
|
|
220
218
|
test('Test Canvas.zoomToWindow - same point (should not zoom)', () => {
|