@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.
@@ -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
+ });
@@ -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 (should not zoom)', () => {
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
- const initialScale = core.canvas.getScale();
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
- // Should not change scale
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).toBe(initialScale);
198
+ expect(finalScale).toBeCloseTo((core.canvas.height / 100) * 0.9);
200
199
  });
201
200
 
202
- test('Test Canvas.zoomToWindow - zero height (should not zoom)', () => {
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
- const initialScale = core.canvas.getScale();
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
- // Should not change scale
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).toBe(initialScale);
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)', () => {