@design-core/core 0.0.1 → 0.0.3

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 (254) hide show
  1. package/.eslintrc.json +14 -7
  2. package/.github/workflows/DesignCoreQA.yml +3 -1
  3. package/README.md +11 -4
  4. package/TODO.md +19 -0
  5. package/core/core/core.js +49 -42
  6. package/core/designCore.js +61 -2
  7. package/core/dimensions/alignedDimension.js +142 -0
  8. package/core/dimensions/angularDimension.js +550 -0
  9. package/core/dimensions/baseCircularDimension.js +244 -0
  10. package/core/dimensions/baseDimension.js +558 -0
  11. package/core/dimensions/baseLinearDimension.js +371 -0
  12. package/core/dimensions/diametricDimension.js +82 -0
  13. package/core/dimensions/dimension.js +298 -0
  14. package/core/dimensions/linearDimension.js +29 -0
  15. package/core/dimensions/radialDimension.js +78 -0
  16. package/core/dimensions/rotatedDimension.js +167 -0
  17. package/core/entities/arc.js +314 -60
  18. package/core/entities/arctext.js +642 -0
  19. package/core/entities/basePolyline.js +553 -94
  20. package/core/entities/circle.js +181 -54
  21. package/core/entities/entity.js +154 -74
  22. package/core/entities/hatch.js +807 -0
  23. package/core/entities/insert.js +200 -39
  24. package/core/entities/line.js +196 -134
  25. package/core/entities/lwpolyline.js +21 -44
  26. package/core/entities/point.js +194 -29
  27. package/core/entities/polyline.js +54 -7
  28. package/core/entities/rectangle.js +43 -13
  29. package/core/entities/solid.js +43 -6
  30. package/core/entities/text.js +324 -181
  31. package/core/lib/boundingBox.js +73 -13
  32. package/core/lib/canvas.js +256 -65
  33. package/core/lib/clipboard.js +198 -0
  34. package/core/lib/colour.js +144 -0
  35. package/core/lib/colours.js +367 -301
  36. package/core/lib/commandLine.js +16 -28
  37. package/core/lib/commandManager.js +115 -58
  38. package/core/lib/constants.js +23 -0
  39. package/core/lib/dxf/dxf.js +249 -34
  40. package/core/lib/dxf/dxfFile.js +23 -38
  41. package/core/lib/dxf/dxfIterator.js +17 -5
  42. package/core/lib/dxf/dxfRead.js +23 -7
  43. package/core/lib/dxf/dxfWrite.js +39 -129
  44. package/core/lib/dxf/handleManager.js +97 -0
  45. package/core/lib/dxf/sections/blocks.js +16 -2
  46. package/core/lib/dxf/sections/entities.js +17 -3
  47. package/core/lib/dxf/sections/header.js +10 -1
  48. package/core/lib/dxf/sections/objects.js +36 -0
  49. package/core/lib/dxf/sections/section.js +43 -5
  50. package/core/lib/dxf/sections/tables.js +17 -3
  51. package/core/lib/entityManager.js +178 -0
  52. package/core/lib/fileio.js +14 -4
  53. package/core/lib/headers.js +229 -0
  54. package/core/lib/input.js +46 -0
  55. package/core/lib/inputManager.js +199 -194
  56. package/core/lib/intersect.js +341 -468
  57. package/core/lib/logging.js +25 -1
  58. package/core/lib/matrix.js +6 -8
  59. package/core/lib/mouse.js +24 -79
  60. package/core/lib/patterns.js +690 -0
  61. package/core/lib/promptOptions.js +133 -0
  62. package/core/lib/scene.js +71 -174
  63. package/core/lib/selectionManager.js +74 -48
  64. package/core/lib/selectionWindow.js +24 -10
  65. package/core/lib/settings.js +18 -11
  66. package/core/lib/snapping.js +129 -21
  67. package/core/lib/stateManager.js +288 -0
  68. package/core/lib/strings.js +57 -5
  69. package/core/lib/utils.js +95 -11
  70. package/core/objects/dictionary.js +43 -0
  71. package/core/objects/dictionaryManager.js +80 -0
  72. package/core/properties/dimType.js +117 -0
  73. package/core/properties/flags.js +66 -0
  74. package/core/properties/property.js +26 -0
  75. package/core/properties/propertyManager.js +65 -19
  76. package/core/tables/appId.js +31 -0
  77. package/core/tables/appIdManager.js +44 -0
  78. package/core/tables/block.js +323 -0
  79. package/core/tables/blockManager.js +48 -0
  80. package/core/tables/blockRecord.js +29 -0
  81. package/core/tables/blockRecordManager.js +37 -0
  82. package/core/tables/dimStyle.js +627 -0
  83. package/core/tables/dimStyleManager.js +187 -0
  84. package/core/tables/endblk.js +28 -0
  85. package/core/tables/layer.js +219 -0
  86. package/core/tables/layerManager.js +47 -0
  87. package/core/tables/ltype.js +85 -0
  88. package/core/tables/ltypeManager.js +65 -0
  89. package/core/tables/style.js +145 -0
  90. package/core/tables/styleManager.js +55 -0
  91. package/core/tables/styleManagerBase.js +110 -0
  92. package/core/tables/tableManagerBase.js +354 -0
  93. package/core/tables/ucs.js +28 -0
  94. package/core/tables/ucsManager.js +44 -0
  95. package/core/tables/view.js +28 -0
  96. package/core/tables/viewManager.js +44 -0
  97. package/core/tables/vport.js +70 -0
  98. package/core/tables/vportManager.js +65 -0
  99. package/core/tools/chamfer.js +343 -0
  100. package/core/tools/chamferFilletBase.js +162 -0
  101. package/core/tools/copy.js +68 -40
  102. package/core/tools/copybase.js +65 -0
  103. package/core/tools/copyclip.js +59 -0
  104. package/core/tools/cornerEntity.js +138 -0
  105. package/core/tools/cutclip.js +72 -0
  106. package/core/tools/distance.js +37 -9
  107. package/core/tools/erase.js +43 -13
  108. package/core/tools/explode.js +117 -0
  109. package/core/tools/extend.js +71 -32
  110. package/core/tools/fillet.js +336 -0
  111. package/core/tools/identify.js +33 -6
  112. package/core/tools/matchProp.js +106 -0
  113. package/core/tools/mirror.js +141 -0
  114. package/core/tools/move.js +65 -32
  115. package/core/tools/offset.js +321 -0
  116. package/core/tools/pan.js +54 -0
  117. package/core/tools/pasteclip.js +93 -0
  118. package/core/tools/purge.js +90 -0
  119. package/core/tools/rotate.js +105 -70
  120. package/core/tools/scale.js +166 -0
  121. package/core/tools/tool.js +14 -4
  122. package/core/tools/trim.js +71 -32
  123. package/core/tools/zoom.js +152 -0
  124. package/package.json +3 -305
  125. package/test/dimensions/alignedDimension.test.js +211 -0
  126. package/test/dimensions/angularDimension.test.js +243 -0
  127. package/test/dimensions/baseDimension.test.js +239 -0
  128. package/test/dimensions/diametricDimension.test.js +203 -0
  129. package/test/dimensions/dimension.test.js +102 -0
  130. package/test/dimensions/radialDimension.test.js +203 -0
  131. package/test/dimensions/rotatedDimension.test.js +224 -0
  132. package/test/entities/arc.test.js +463 -41
  133. package/test/entities/arctext.test.js +329 -0
  134. package/test/entities/basePolyline.test.js +459 -10
  135. package/test/entities/circle.test.js +312 -7
  136. package/test/entities/entity.test.js +28 -9
  137. package/test/entities/hatch.test.js +606 -0
  138. package/test/entities/insert.test.js +90 -0
  139. package/test/entities/line.test.js +182 -6
  140. package/test/entities/point.test.js +375 -37
  141. package/test/entities/solid.test.js +156 -0
  142. package/test/entities/text.test.js +533 -7
  143. package/test/integration/exportIntegration.reference.dxf +1706 -0
  144. package/test/integration/exportIntegration.test.js +186 -0
  145. package/test/integration/importExportIntegration.test.js +126 -0
  146. package/test/integration/intersectionIntegration.test.js +880 -0
  147. package/test/integration/userInputIntegration.reference.dxf +1410 -0
  148. package/test/integration/userInputIntegration.test.js +269 -0
  149. package/test/lib/boundingBox.test.js +26 -2
  150. package/test/lib/canvas.test.js +613 -5
  151. package/test/lib/clipboard.test.js +70 -0
  152. package/test/lib/colour.test.js +114 -0
  153. package/test/lib/colours.test.js +63 -18
  154. package/test/lib/commandLine.test.js +159 -22
  155. package/test/lib/commandManager.test.js +4 -4
  156. package/test/lib/constants.test.js +9 -0
  157. package/test/lib/dxf/dxfFile.test.js +6 -2
  158. package/test/lib/dxf/dxfIterator.test.js +1 -1
  159. package/test/lib/dxf/dxfWrite.test.js +173 -0
  160. package/test/lib/dxf/handleManager.test.js +137 -0
  161. package/test/lib/dxf/sections/blocks.test.js +5 -5
  162. package/test/lib/dxf/sections/entities.test.js +4 -4
  163. package/test/lib/dxf/sections/header.test.js +18 -4
  164. package/test/lib/dxf/sections/objects.test.js +132 -0
  165. package/test/lib/dxf/sections/section.test.js +29 -29
  166. package/test/lib/dxf/sections/tables.test.js +3 -3
  167. package/test/lib/entityManager.test.js +163 -0
  168. package/test/lib/headers.test.js +233 -0
  169. package/test/lib/inputManager.test.js +1144 -5
  170. package/test/lib/intersect.test.js +454 -331
  171. package/test/lib/logging.test.js +1 -1
  172. package/test/lib/matrix.test.js +1 -1
  173. package/test/lib/mouse.test.js +327 -4
  174. package/test/lib/patterns.test.js +105 -0
  175. package/test/lib/promptOptions.test.js +179 -0
  176. package/test/lib/scene.test.js +16 -52
  177. package/test/lib/selectionManager.test.js +17 -5
  178. package/test/lib/settings.test.js +111 -5
  179. package/test/lib/snapping.test.js +142 -4
  180. package/test/lib/stateManager.test.js +155 -0
  181. package/test/lib/utils.test.js +81 -1
  182. package/test/objects/dictionary.test.js +81 -0
  183. package/test/objects/dictionaryManager.test.js +34 -0
  184. package/test/properties/dimType.test.js +62 -0
  185. package/test/properties/flags.test.js +164 -0
  186. package/test/properties/property.test.js +13 -0
  187. package/test/properties/propertyManager.test.js +10 -11
  188. package/test/tables/appId.test.js +46 -0
  189. package/test/tables/appIdManager.test.js +72 -0
  190. package/test/tables/block.test.js +157 -0
  191. package/test/tables/blockManager.test.js +52 -0
  192. package/test/tables/blockRecord.test.js +39 -0
  193. package/test/tables/blockRecordManager.test.js +60 -0
  194. package/test/tables/dimstyle.test.js +72 -0
  195. package/test/tables/endblk.test.js +30 -0
  196. package/test/tables/layer.test.js +95 -0
  197. package/test/tables/layerManager.test.js +172 -0
  198. package/test/{styles → tables}/ltype.test.js +7 -7
  199. package/test/{styles → tables}/ltypeManager.test.js +2 -2
  200. package/test/tables/style.test.js +44 -0
  201. package/test/tables/stylemanagerbase.test.js +220 -0
  202. package/test/tables/tableManagerBase.test.js +194 -0
  203. package/test/tables/ucs.test.js +37 -0
  204. package/test/tables/ucsManager.test.js +48 -0
  205. package/test/tables/view.test.js +37 -0
  206. package/test/tables/viewManager.test.js +48 -0
  207. package/test/tables/vport.test.js +117 -0
  208. package/test/tables/vportManager.test.js +54 -0
  209. package/test/test-helpers/test-helpers.js +66 -0
  210. package/test/tools/chamfer.test.js +970 -0
  211. package/test/tools/chamferFilletBase.test.js +446 -0
  212. package/test/tools/copy.test.js +22 -14
  213. package/test/tools/copybase.test.js +93 -0
  214. package/test/tools/copyclip.test.js +92 -0
  215. package/test/tools/cornerEntity.test.js +201 -0
  216. package/test/tools/cutclip.test.js +94 -0
  217. package/test/tools/distance.test.js +140 -18
  218. package/test/tools/erase.test.js +12 -12
  219. package/test/tools/explode.test.js +45 -0
  220. package/test/tools/extend.test.js +326 -44
  221. package/test/tools/fillet.test.js +831 -0
  222. package/test/tools/identify.test.js +115 -16
  223. package/test/tools/matchProp.test.js +84 -0
  224. package/test/tools/mirror.test.js +475 -0
  225. package/test/tools/move.test.js +75 -19
  226. package/test/tools/offset.test.js +748 -0
  227. package/test/tools/pan.test.js +72 -0
  228. package/test/tools/pasteclip.test.js +100 -0
  229. package/test/tools/purge.test.js +89 -0
  230. package/test/tools/rotate.test.js +89 -23
  231. package/test/tools/scale.test.js +529 -0
  232. package/test/tools/trim.test.js +419 -84
  233. package/test/tools/zoom.test.js +504 -0
  234. package/core/entities/alignedDimension.js +0 -279
  235. package/core/entities/angularDimension.js +0 -194
  236. package/core/entities/baseDimension.js +0 -227
  237. package/core/entities/block.js +0 -247
  238. package/core/entities/diametricDimension.js +0 -133
  239. package/core/entities/dimension.js +0 -202
  240. package/core/entities/radialDimension.js +0 -126
  241. package/core/styles/dimStyle.js +0 -719
  242. package/core/styles/dimStyleManager.js +0 -47
  243. package/core/styles/layer.js +0 -133
  244. package/core/styles/layerManager.js +0 -40
  245. package/core/styles/ltype.js +0 -86
  246. package/core/styles/ltypeManager.js +0 -50
  247. package/core/styles/style.js +0 -158
  248. package/core/styles/styleManager.js +0 -43
  249. package/core/styles/styleManagerBase.js +0 -299
  250. package/test/entities/block.test.js +0 -22
  251. package/test/styles/dimstyle.test.js +0 -19
  252. package/test/styles/layerManager.test.js +0 -150
  253. package/test/styles/style.test.js +0 -33
  254. package/test/styles/stylemanagerbase.test.js +0 -219
@@ -0,0 +1,102 @@
1
+ import { Dimension } from '../../core/dimensions/dimension.js';
2
+ import { DiametricDimension } from '../../core/dimensions/diametricDimension.js';
3
+ import { Circle } from '../../core/entities/circle.js';
4
+ import { Point } from '../../core/entities/point.js';
5
+ import { Line } from '../../core/entities/line.js';
6
+ import { Arc } from '../../core/entities/arc.js';
7
+ import { Polyline } from '../../core/entities/polyline.js';
8
+ import { Core } from '../../core/core/core.js';
9
+ import { DesignCore } from '../../core/designCore.js';
10
+ import { SingleSelection } from '../../core/lib/selectionManager.js';
11
+ import { withMockInput } from '../test-helpers/test-helpers.js';
12
+
13
+ // initialise core
14
+ new Core();
15
+
16
+ // Test cases for user input
17
+ const scenarios = [
18
+
19
+ { desc: 'Rotated dimension from line selection',
20
+ input: [new SingleSelection(0, new Point()), new Point(5, 5)],
21
+ selectedItems: [new Line({ points: [new Point(), new Point(10, 0)] })],
22
+ expectedDimType: 0,
23
+ },
24
+ { desc: 'Aligned dimension from line selection',
25
+ input: [new SingleSelection(0, new Point()), new Point(6.5, 3.5)],
26
+ selectedItems: [new Line({ points: [new Point(), new Point(10, 10)] })],
27
+ expectedDimType: 1,
28
+ },
29
+ { desc: 'Rotated dimension from point selection',
30
+ input: [new Point(), new Point(10, 0), new Point(5, 5)],
31
+ selectedItems: [],
32
+ expectedDimType: 0,
33
+ },
34
+ { desc: 'Diametric dimension from circle selection',
35
+ input: [new SingleSelection(0, new Point()), new Point(20, 10)],
36
+ selectedItems: [new Circle({ points: [new Point(), new Point(10, 0)] })],
37
+ expectedDimType: 3,
38
+ },
39
+ { desc: 'Radial dimension from arc selection',
40
+ input: [new SingleSelection(0, new Point()), new Point(20, 10)],
41
+ selectedItems: [new Arc({ points: [new Point(), new Point(10, 0), new Point(10, 10)] })],
42
+ expectedDimType: 4,
43
+ },
44
+ { desc: 'Angular dimension from line selection',
45
+ input: [new SingleSelection(0, new Point()), new SingleSelection(1, new Point()), new Point(5, 5)],
46
+ selectedItems: [new Line({ points: [new Point(), new Point(10, 0)] }), new Line({ points: [new Point(), new Point(10, 10)] })],
47
+ expectedDimType: 2,
48
+ },
49
+ { desc: 'Aligned dimension from polyline selection',
50
+ input: [new SingleSelection(0, new Point()), new SingleSelection(1, new Point()), new Point(5, 5)],
51
+ selectedItems: [new Polyline({ points: [new Point(), new Point(10, 0)] })],
52
+ expectedDimType: 1,
53
+ },
54
+ { desc: 'Radial dimension from polyline selection',
55
+ input: [new SingleSelection(0, new Point(16, 5)), new Point(20, 5)],
56
+ selectedItems: [new Polyline({ points: [new Point(), new Point(10, 0, 1), new Point(10, 10)] })],
57
+ expectedDimType: 4,
58
+ },
59
+ { desc: 'Angular dimension from polyline selection',
60
+ input: [new SingleSelection(0, new Point(5, 0)), new SingleSelection(1, new Point(5, 5)), new Point(5, 5)],
61
+ selectedItems: [new Polyline({ points: [new Point(), new Point(10, 0)] }), new Polyline({ points: [new Point(), new Point(10, 10)] })],
62
+ expectedDimType: 2,
63
+ },
64
+
65
+ ];
66
+
67
+ test.each(scenarios)('Dimension.execute handles $desc', async (scenario) => {
68
+ const { input, selectedItems, expectedDimType } = scenario;
69
+
70
+ await withMockInput(DesignCore.Scene, input, async () => {
71
+ const dim = new Dimension();
72
+ await dim.execute();
73
+
74
+ expect(dim.dimType.getBaseDimType()).toBe(expectedDimType);
75
+ }, { selectedItems });
76
+ });
77
+
78
+ test('constructor instantiates correct dimension type', () => {
79
+ const data = { 70: 3, 2: 'blockName' };
80
+ const dim = new Dimension(data);
81
+ expect(dim instanceof DiametricDimension).toBe(true);
82
+ });
83
+
84
+ test('register returns command object', () => {
85
+ expect(Dimension.register()).toEqual({ command: 'Dimension', shortcut: 'DIM' });
86
+ });
87
+
88
+ test('get linear dimension type', () => {
89
+ const dim = new Dimension();
90
+ expect(dim.getLinearDimensionType(new Point(0, 0), new Point(10, 0), new Point(5, 5))).toBe(0);
91
+ expect(dim.getLinearDimensionType(new Point(0, 0), new Point(10, 10), new Point(7.5, 2.5))).toBe(1);
92
+ expect(dim.getLinearDimensionType(new Point(0, 0), new Point(10, 10), new Point(12.5, 8.5))).toBe(0);
93
+ });
94
+
95
+
96
+ test('preview calls createTempItem with correct args', () => {
97
+ const dim = new Dimension({ 70: 1 });
98
+ dim.selectedItems = [1];
99
+ dim.points = [{}, {}];
100
+ // Should not throw
101
+ expect(() => dim.preview()).not.toThrow();
102
+ });
@@ -0,0 +1,203 @@
1
+ import { RadialDimension } from '../../core/dimensions/radialDimension.js';
2
+ import { Point } from '../../core/entities/point.js';
3
+ import { Arc } from '../../core/entities/arc.js';
4
+ import { File, withMockInput } from '../test-helpers/test-helpers.js';
5
+ import { Core } from '../../core/core/core.js';
6
+ import { DesignCore } from '../../core/designCore.js';
7
+ import { SingleSelection } from '../../core/lib/selectionManager.js';
8
+ import { Circle } from '../../core/entities/circle.js';
9
+ import { Polyline } from '../../core/entities/polyline.js';
10
+
11
+
12
+ // initialise core
13
+ new Core();
14
+
15
+ // Test cases for user input
16
+ const scenarios = [
17
+
18
+ { desc: 'Radial dimension from circle selection - Text outside circle',
19
+ input: [new SingleSelection(0, new Point()), new Point(20, 0)],
20
+ selectedItems: [new Circle({ points: [new Point(0, 0), new Point(10, 0)] })],
21
+ expectedDimType: 4,
22
+ dimensionValue: 10,
23
+ dimensionEntities: 6,
24
+ },
25
+ { desc: 'Radial dimension from circle selection - Text inside circle',
26
+ input: [new SingleSelection(0, new Point()), new Point(0, 0)],
27
+ selectedItems: [new Circle({ points: [new Point(0, 0), new Point(10, 0)] })],
28
+ expectedDimType: 4,
29
+ dimensionValue: 10,
30
+ dimensionEntities: 5,
31
+ },
32
+ { desc: 'Radial dimension from arc selection',
33
+ input: [new SingleSelection(0, new Point()), new Point(20, 10)],
34
+ selectedItems: [new Arc({ points: [new Point(0, 0), new Point(20, 0), new Point(20, 20)] })],
35
+ expectedDimType: 4,
36
+ dimensionValue: 20,
37
+ dimensionEntities: 6,
38
+ },
39
+ { desc: 'Radial dimension from polyline selection',
40
+ input: [new SingleSelection(0, new Point(30, 10)), new Point(30, 10)],
41
+ selectedItems: [new Polyline({ points: [new Point(0, 0), new Point(20, 0, 1), new Point(20, 20)] })],
42
+ expectedDimType: 4,
43
+ dimensionValue: 10,
44
+ dimensionEntities: 6,
45
+ },
46
+ ];
47
+
48
+ test.each(scenarios)('RadialDimension.execute handles $desc', async (scenario) => {
49
+ const { input, selectedItems, expectedDimType, dimensionValue, dimensionEntities } = scenario;
50
+
51
+ await withMockInput(DesignCore.Scene, input, async () => {
52
+ const dim = new RadialDimension();
53
+ await dim.execute();
54
+
55
+ expect(dim.dimType.getBaseDimType()).toBe(expectedDimType);
56
+ // get the text entities from the dimension block
57
+ const dimensionBlockEntities = dim.buildDimension();
58
+ expect(dimensionBlockEntities.length).toBe(dimensionEntities);
59
+
60
+ // check if the text value matches the expected dimension value
61
+ for (const entity of dimensionBlockEntities) {
62
+ if (entity.type === 'Text') {
63
+ // remove all non-numeric characters except . and -
64
+ const numbersOnly = entity.string.replace(/[^0-9.-]+/g, '');
65
+ expect(Number(numbersOnly)).toBeCloseTo(dimensionValue);
66
+ expect(entity.string).toContain('R');
67
+ }
68
+ }
69
+ }, { selectedItems });
70
+ });
71
+
72
+ test('constructor sets default properties', () => {
73
+ const dim = new RadialDimension();
74
+ expect(dim).toBeInstanceOf(RadialDimension);
75
+ expect(dim.points).toBeDefined();
76
+ });
77
+
78
+
79
+ test('getPointsFromSelection returns correct sequenced points', () => {
80
+ const center = new Point(0, 0);
81
+ const textPos = new Point(10, 0);
82
+ // Mock item with getRadius
83
+ const item = { points: [center], getRadius: () => 10 };
84
+ const result = RadialDimension.getPointsFromSelection([item], textPos);
85
+ expect(Array.isArray(result)).toBe(true);
86
+ expect(result.length).toBe(3);
87
+ expect(result[0].sequence).toBe(10); // center
88
+ expect(result[1].sequence).toBe(15); // radius point
89
+ expect(result[2].sequence).toBe(11); // text position
90
+ });
91
+
92
+ test('RadialDimension.preview runs without error and calls createTempItem', () => {
93
+ const origCreateTempItem = DesignCore.Scene.tempEntities.create;
94
+ const origPointOnScene = DesignCore.Mouse.pointOnScene;
95
+ const origSeletionSet = DesignCore.Scene.selectionManager.selectionSet.selectionSet.length;
96
+
97
+ // Manual mock for createTempItem
98
+ const createTempItemCalls = [];
99
+ DesignCore.Scene.tempEntities.create = function(type, obj) {
100
+ createTempItemCalls.push([type, obj]);
101
+ };
102
+ // Manual mock for pointOnScene
103
+ DesignCore.Mouse.pointOnScene = function() {
104
+ return new Point(5, 5);
105
+ };
106
+ // Manual mock for selection set
107
+ DesignCore.Scene.selectionManager.selectionSet.selectionSet = [];
108
+
109
+ const points = [];
110
+
111
+ const Pt10 = new Point();
112
+ Pt10.sequence = 10;
113
+ points.push(Pt10);
114
+
115
+ const Pt15 = new Point(10, 0);
116
+ Pt15.sequence = 15;
117
+ points.push(Pt15);
118
+
119
+ // Test with no selection - no action
120
+ const dim1 = new RadialDimension();
121
+ dim1.points = points;
122
+ expect(() => dim1.preview()).not.toThrow();
123
+ expect(createTempItemCalls.length).toBe(0);
124
+
125
+ // Test with selection (should call createTempItem with this.type)
126
+ const dim2 = new RadialDimension();
127
+ dim2.points = points;
128
+ DesignCore.Scene.selectionManager.selectionSet.selectionSet.push(1);
129
+ expect(() => dim2.preview()).not.toThrow();
130
+ expect(createTempItemCalls.some((call) => call[0] === dim2.type)).toBe(true);
131
+
132
+ // Restore
133
+ DesignCore.Scene.tempEntities.create = origCreateTempItem;
134
+ DesignCore.Mouse.pointOnScene = origPointOnScene;
135
+ DesignCore.Scene.selectionManager.selectionSet.selectionSet.length = origSeletionSet;
136
+ });
137
+
138
+ test('Test RadialDimension.dxf', () => {
139
+ const points = [];
140
+
141
+ const Pt10 = new Point();
142
+ Pt10.sequence = 10;
143
+ points.push(Pt10);
144
+
145
+ const Pt11 = new Point(20, 0);
146
+ Pt11.sequence = 11;
147
+ points.push(Pt11);
148
+
149
+ const Pt15 = new Point(10, 0);
150
+ Pt15.sequence = 15;
151
+ points.push(Pt15);
152
+
153
+ points.push(Pt10, Pt11, Pt15);
154
+
155
+ const dimension = new RadialDimension({ points: points, handle: '1' });
156
+ let file = new File();
157
+ dimension.dxf(file);
158
+ // console.log(file.contents);
159
+
160
+ const dxfString = `0
161
+ DIMENSION
162
+ 5
163
+ 1
164
+ 100
165
+ AcDbEntity
166
+ 100
167
+ AcDbDimension
168
+ 8
169
+ 0
170
+ 10
171
+ 0
172
+ 20
173
+ 0
174
+ 30
175
+ 0.0
176
+ 11
177
+ 20
178
+ 21
179
+ 0
180
+ 31
181
+ 0.0
182
+ 70
183
+ 4
184
+ 3
185
+ STANDARD
186
+ 100
187
+ AcDbRadialDimension
188
+ 15
189
+ 10
190
+ 25
191
+ 0
192
+ 35
193
+ 0.0
194
+ `;
195
+
196
+ expect(file.contents).toEqual(dxfString);
197
+
198
+ // create new entity from entity data to ensure all props are loaded
199
+ const newDimension = new RadialDimension(dimension);
200
+ file = new File();
201
+ newDimension.dxf(file);
202
+ expect(file.contents).toEqual(dxfString);
203
+ });
@@ -0,0 +1,224 @@
1
+ import { RotatedDimension } from '../../core/dimensions/rotatedDimension.js';
2
+ import { Point } from '../../core/entities/point.js';
3
+ import { DesignCore } from '../../core/designCore.js';
4
+ import { Core } from '../../core/core/core.js';
5
+ import { Line } from '../../core/entities/line.js';
6
+ import { File, withMockInput } from '../test-helpers/test-helpers.js';
7
+
8
+ // initialise core
9
+ new Core();
10
+
11
+ // Test cases for user input
12
+ const scenarios = [
13
+
14
+ { desc: 'Rotated dimension from point selection (angle 0)',
15
+ input: [0, new Point(), new Point(10, 0), new Point(5, 5)],
16
+ selectedItems: [],
17
+ expectedDimType: 0,
18
+ dimensionValue: 10,
19
+ },
20
+ { desc: 'Rotated dimension from point selection (angle 90)',
21
+ input: [90, new Point(), new Point(0, 10), new Point(5, 5)],
22
+ selectedItems: [],
23
+ expectedDimType: 0,
24
+ dimensionValue: 10,
25
+ },
26
+ ];
27
+
28
+ test.each(scenarios)('Dimension.execute handles $desc', async (scenario) => {
29
+ const { input, selectedItems, expectedDimType, dimensionValue } = scenario;
30
+
31
+ await withMockInput(DesignCore.Scene, input, async () => {
32
+ const dim = new RotatedDimension();
33
+ await dim.execute();
34
+
35
+ expect(dim.dimType.getBaseDimType()).toBe(expectedDimType);
36
+ // get the text entities from the dimension block
37
+ const dimensionBlockEntities = dim.buildDimension();
38
+ expect(dimensionBlockEntities.length).toBe(7);
39
+
40
+ // check if the text value matches the expected dimension value
41
+ for (const entity of dimensionBlockEntities) {
42
+ if (entity.type === 'Text') {
43
+ expect(Number(entity.string)).toBeCloseTo(dimensionValue);
44
+ }
45
+ }
46
+ }, { selectedItems });
47
+ });
48
+
49
+ test('constructor sets default properties', () => {
50
+ const dim = new RotatedDimension();
51
+ expect(dim).toBeInstanceOf(RotatedDimension);
52
+ expect(dim.points).toBeDefined();
53
+ });
54
+
55
+
56
+ test('register returns command object', () => {
57
+ expect(RotatedDimension.register()).toEqual({ command: 'RotatedDimension', shortcut: 'DIMROT' });
58
+ });
59
+
60
+
61
+ describe('RotatedDimension.getPointsFromSelection', () => {
62
+ const scenarios = [
63
+ {
64
+ desc: 'horizontal line',
65
+ pt1: new Point(0, 0),
66
+ pt2: new Point(10, 0),
67
+ textPos: new Point(5, 5),
68
+ angle: 0,
69
+ expected: {
70
+ text: { x: 5, y: 5 },
71
+ arrow: { x: 10, y: 5 },
72
+ },
73
+ },
74
+ {
75
+ desc: 'vertical line',
76
+ pt1: new Point(0, 0),
77
+ pt2: new Point(0, 10),
78
+ textPos: new Point(5, 5),
79
+ angle: 90,
80
+ expected: {
81
+ text: { x: 5, y: 5 },
82
+ arrow: { x: 5, y: 10 },
83
+ },
84
+ },
85
+ {
86
+ desc: 'diagonal line',
87
+ pt1: new Point(0, 0),
88
+ pt2: new Point(10, 10),
89
+ textPos: new Point(5, 0),
90
+ angle: 90,
91
+ expected: {
92
+ text: { x: 5, y: 0 },
93
+ arrow: { x: 5, y: 10 },
94
+ },
95
+ },
96
+ ];
97
+
98
+ test.each(scenarios)('returns correct sequenced points for $desc', ({ pt1, pt2, textPos, angle, expected }) => {
99
+ const line = new Line({ points: [pt1, pt2] });
100
+ const result = RotatedDimension.getPointsFromSelection([line], textPos, angle);
101
+ expect(result).toHaveLength(4);
102
+ expect(result[0].sequence).toBe(13);
103
+ expect(result[1].sequence).toBe(14);
104
+ expect(result[2].sequence).toBe(11);
105
+ expect(result[3].sequence).toBe(10);
106
+ // check text position
107
+ expect(result[2].x).toBeCloseTo(expected.text.x);
108
+ expect(result[2].y).toBeCloseTo(expected.text.y);
109
+ // check arrow position
110
+ expect(result[3].x).toBeCloseTo(expected.arrow.x);
111
+ expect(result[3].y).toBeCloseTo(expected.arrow.y);
112
+ });
113
+ });
114
+
115
+ test('RotatedDimension.preview runs without error and calls createTempItem', () => {
116
+ const origCreateTempItem = DesignCore.Scene.tempEntities.create;
117
+ const origPointOnScene = DesignCore.Mouse.pointOnScene;
118
+ // Manual mock for createTempItem
119
+ const createTempItemCalls = [];
120
+ DesignCore.Scene.tempEntities.create = function(type, obj) {
121
+ createTempItemCalls.push([type, obj]);
122
+ };
123
+ // Manual mock for pointOnScene
124
+ DesignCore.Mouse.pointOnScene = function() {
125
+ return new Point(5, 5);
126
+ };
127
+
128
+ // Test with 1 point (should call createTempItem with 'Line')
129
+ const dim1 = new RotatedDimension();
130
+ dim1.points = [new Point(0, 0)];
131
+ expect(() => dim1.preview()).not.toThrow();
132
+ expect(createTempItemCalls.some((call) => call[0] === 'Line')).toBe(true);
133
+
134
+ // Test with >1 point (should call createTempItem with this.type)
135
+ const dim2 = new RotatedDimension();
136
+ dim2.points = [new Point(0, 0), new Point(10, 0), new Point(5, 5)];
137
+ expect(() => dim2.preview()).not.toThrow();
138
+ expect(createTempItemCalls.some((call) => call[0] === dim2.type)).toBe(true);
139
+
140
+ // Restore
141
+ DesignCore.Scene.tempEntities.create = origCreateTempItem;
142
+ DesignCore.Mouse.pointOnScene = origPointOnScene;
143
+ });
144
+
145
+ test('Test RotatedDimension.dxf', () => {
146
+ const points = [];
147
+
148
+ const Pt13 = new Point(0, 0);
149
+ Pt13.sequence = 13;
150
+ points.push(Pt13);
151
+
152
+ const Pt14 = new Point(10, 0);
153
+ Pt14.sequence = 14;
154
+ points.push(Pt14);
155
+
156
+ const Pt10 = new Point(5, 5);
157
+ Pt10.sequence = 10;
158
+ points.push(Pt10);
159
+
160
+ const Pt11 = new Point(5, 5);
161
+ Pt11.sequence = 11;
162
+ points.push(Pt11);
163
+
164
+ points.push(Pt10, Pt14, Pt13, Pt11);
165
+
166
+ const dimension = new RotatedDimension({ points: points, handle: '1' });
167
+ let file = new File();
168
+ dimension.dxf(file);
169
+ // console.log(file.contents);
170
+
171
+ const dxfString = `0
172
+ DIMENSION
173
+ 5
174
+ 1
175
+ 100
176
+ AcDbEntity
177
+ 100
178
+ AcDbDimension
179
+ 8
180
+ 0
181
+ 10
182
+ 5
183
+ 20
184
+ 5
185
+ 30
186
+ 0.0
187
+ 11
188
+ 5
189
+ 21
190
+ 5
191
+ 31
192
+ 0.0
193
+ 70
194
+ 0
195
+ 3
196
+ STANDARD
197
+ 100
198
+ AcDbAlignedDimension
199
+ 13
200
+ 0
201
+ 23
202
+ 0
203
+ 33
204
+ 0.0
205
+ 14
206
+ 10
207
+ 24
208
+ 0
209
+ 34
210
+ 0.0
211
+ 50
212
+ 0
213
+ 100
214
+ AcDbRotatedDimension
215
+ `;
216
+
217
+ expect(file.contents).toEqual(dxfString);
218
+
219
+ // create new entity from entity data to ensure all props are loaded
220
+ const newDimension = new RotatedDimension(dimension);
221
+ file = new File();
222
+ newDimension.dxf(file);
223
+ expect(file.contents).toEqual(dxfString);
224
+ });