@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
@@ -1,9 +1,59 @@
1
- import {Point} from '../../core/entities/point';
2
- import {Text} from '../../core/entities/text';
1
+ import { Text } from '../../core/entities/text.js';
2
+ import { Point } from '../../core/entities/point.js';
3
+ import { DesignCore } from '../../core/designCore.js';
3
4
 
5
+ import { File, withMockInput } from '../test-helpers/test-helpers.js';
6
+ import { Core } from '../../core/core/core.js';
4
7
 
5
- test('Test BasePolyline.closestPoint', () => {
6
- const text = new Text({points: [new Point(100, 100)]});
8
+ // initialise core
9
+ new Core();
10
+
11
+ const textInputScenarios = [
12
+ {
13
+ desc: 'standard style, custom height and rotation',
14
+ pt0: new Point(1, 2),
15
+ styleName: 'STANDARD',
16
+ // style: { textHeight: 2.5, backwards: false, upsideDown: false },
17
+ heightInput: 5,
18
+ rotationInput: 45,
19
+ stringInput: 'Hello',
20
+ expectedHeight: 5,
21
+ expectedRotation: 45,
22
+ expectedString: 'Hello',
23
+ },
24
+ {
25
+ desc: 'custom style, default height, rotation 90',
26
+ pt0: new Point(10, 20),
27
+ styleName: 'STANDARD',
28
+ // style: { textHeight: 3, backwards: true, upsideDown: true },
29
+ heightInput: 3,
30
+ rotationInput: 90,
31
+ stringInput: 'World',
32
+ expectedHeight: 3,
33
+ expectedRotation: 90,
34
+ expectedString: 'World',
35
+ },
36
+ ];
37
+
38
+ test.each(textInputScenarios)('Text.execute handles $desc', async (scenario) => {
39
+ const { pt0, styleName, heightInput, rotationInput, stringInput, expectedHeight, expectedRotation, expectedString } = scenario;
40
+
41
+ await withMockInput(DesignCore.Scene, [pt0, heightInput, rotationInput, stringInput], async () => {
42
+ const text = new Text({});
43
+ await text.execute();
44
+
45
+ expect(text.points.length).toBeGreaterThanOrEqual(1);
46
+ expect(text.points[0].x).toBe(pt0.x);
47
+ expect(text.points[0].y).toBe(pt0.y);
48
+ expect(text.height).toBe(expectedHeight);
49
+ expect(text.rotation).toBe(expectedRotation);
50
+ expect(text.string).toBe(expectedString);
51
+ expect(text.styleName).toBe(styleName);
52
+ });
53
+ });
54
+
55
+ test('Test Text.closestPoint', () => {
56
+ const text = new Text({ points: [new Point(100, 100)] });
7
57
  const point1 = new Point(90, 90);
8
58
  const closest1 = text.closestPoint(point1);
9
59
  expect(closest1[0].x).toBeCloseTo(105);
@@ -11,12 +61,165 @@ test('Test BasePolyline.closestPoint', () => {
11
61
  expect(closest1[1]).toBeCloseTo(21.21);
12
62
  });
13
63
 
64
+
65
+ test('Test Text.getTextFrameCorners', () => {
66
+ const text = new Text({ points: [new Point(100, 100)] });
67
+ let corners = text.getTextFrameCorners();
68
+
69
+ expect(corners[0].x).toBeCloseTo(100);
70
+ expect(corners[0].y).toBeCloseTo(100);
71
+
72
+ expect(corners[1].x).toBeCloseTo(110);
73
+ expect(corners[1].y).toBeCloseTo(100);
74
+
75
+ expect(corners[2].x).toBeCloseTo(110);
76
+ expect(corners[2].y).toBeCloseTo(110);
77
+
78
+ expect(corners[3].x).toBeCloseTo(100);
79
+ expect(corners[3].y).toBeCloseTo(110);
80
+
81
+ // Rotate 45 degrees
82
+ text.setRotation(45);
83
+ corners = text.getTextFrameCorners();
84
+
85
+ expect(corners[0].x).toBeCloseTo(100);
86
+ expect(corners[0].y).toBeCloseTo(100);
87
+
88
+ expect(corners[1].x).toBeCloseTo(107.07106);
89
+ expect(corners[1].y).toBeCloseTo(107.07106);
90
+
91
+ expect(corners[2].x).toBeCloseTo(100);
92
+ expect(corners[2].y).toBeCloseTo(114.14213);
93
+
94
+ expect(corners[3].x).toBeCloseTo(92.92893);
95
+ expect(corners[3].y).toBeCloseTo(107.07106);
96
+
97
+ // backwards and upsideDown
98
+ text.setRotation(0);
99
+ text.backwards = true;
100
+ text.upsideDown = true;
101
+ corners = text.getTextFrameCorners();
102
+
103
+ expect(corners[0].x).toBeCloseTo(90);
104
+ expect(corners[0].y).toBeCloseTo(90);
105
+
106
+ expect(corners[1].x).toBeCloseTo(100);
107
+ expect(corners[1].y).toBeCloseTo(90);
108
+
109
+ expect(corners[2].x).toBeCloseTo(100);
110
+ expect(corners[2].y).toBeCloseTo(100);
111
+
112
+ expect(corners[3].x).toBeCloseTo(90);
113
+ expect(corners[3].y).toBeCloseTo(100);
114
+
115
+ // Text frame calculation with text alignment
116
+ // bounding rect is 10x10, so with center/middle alignment the text frame should be offset by 5 in both x and y from the insertion point
117
+ const alignedText = new Text({ points: [new Point(100, 100)] });
118
+ alignedText.horizontalAlignment = 1; // center
119
+ corners = alignedText.getTextFrameCorners();
120
+
121
+ expect(corners[0].x).toBeCloseTo(95);
122
+ expect(corners[0].y).toBeCloseTo(100);
123
+
124
+ expect(corners[1].x).toBeCloseTo(105);
125
+ expect(corners[1].y).toBeCloseTo(100);
126
+
127
+ expect(corners[2].x).toBeCloseTo(105);
128
+ expect(corners[2].y).toBeCloseTo(110);
129
+
130
+ expect(corners[3].x).toBeCloseTo(95);
131
+ expect(corners[3].y).toBeCloseTo(110);
132
+
133
+ // set vertical alignment to middle as well
134
+ // offset the text frame up by another 5 in y so the corners should be at 95,95 - 105,105
135
+ alignedText.verticalAlignment = 2; // middle
136
+ corners = alignedText.getTextFrameCorners();
137
+
138
+ expect(corners[0].x).toBeCloseTo(95);
139
+ expect(corners[0].y).toBeCloseTo(95);
140
+
141
+ expect(corners[1].x).toBeCloseTo(105);
142
+ expect(corners[1].y).toBeCloseTo(95);
143
+
144
+ expect(corners[2].x).toBeCloseTo(105);
145
+ expect(corners[2].y).toBeCloseTo(105);
146
+
147
+ expect(corners[3].x).toBeCloseTo(95);
148
+ expect(corners[3].y).toBeCloseTo(105);
149
+
150
+
151
+ // add rotation of 45 degrees to the center/middle aligned text and ensure the text frame corners are correctly calculated with both alignment and rotation applied
152
+ alignedText.setRotation(45);
153
+ corners = alignedText.getTextFrameCorners();
154
+
155
+ expect(corners[0].x).toBeCloseTo(100);
156
+ expect(corners[0].y).toBeCloseTo(92.92893);
157
+
158
+ expect(corners[1].x).toBeCloseTo(107.07106);
159
+ expect(corners[1].y).toBeCloseTo(100);
160
+
161
+ expect(corners[2].x).toBeCloseTo(100);
162
+ expect(corners[2].y).toBeCloseTo(107.07106);
163
+
164
+ expect(corners[3].x).toBeCloseTo(92.92893);
165
+ expect(corners[3].y).toBeCloseTo(100);
166
+
167
+ // flip the text backwards and ensure the text frame corners are still correctly calculated with the flipped text
168
+ alignedText.backwards = true;
169
+ corners = alignedText.getTextFrameCorners();
170
+
171
+ expect(corners[0].x).toBeCloseTo(92.92893);
172
+ expect(corners[0].y).toBeCloseTo(85.8579);
173
+
174
+ expect(corners[1].x).toBeCloseTo(100);
175
+ expect(corners[1].y).toBeCloseTo(92.92893);
176
+
177
+ expect(corners[2].x).toBeCloseTo(92.92893);
178
+ expect(corners[2].y).toBeCloseTo(100);
179
+
180
+ expect(corners[3].x).toBeCloseTo(85.8579);
181
+ expect(corners[3].y).toBeCloseTo(92.92893);
182
+
183
+ // test right and top alignment
184
+ const rightAlignedtext = new Text({ points: [new Point(100, 100)] });
185
+ rightAlignedtext.horizontalAlignment = 2; // right
186
+ corners = rightAlignedtext.getTextFrameCorners();
187
+
188
+ expect(corners[0].x).toBeCloseTo(90);
189
+ expect(corners[0].y).toBeCloseTo(100);
190
+
191
+ expect(corners[1].x).toBeCloseTo(100);
192
+ expect(corners[1].y).toBeCloseTo(100);
193
+
194
+ expect(corners[2].x).toBeCloseTo(100);
195
+ expect(corners[2].y).toBeCloseTo(110);
196
+
197
+ expect(corners[3].x).toBeCloseTo(90);
198
+ expect(corners[3].y).toBeCloseTo(110);
199
+
200
+ // add vertical alignment top and ensure the text frame is still correctly calculated with the right and top alignment applied
201
+ rightAlignedtext.verticalAlignment = 3; // top
202
+ corners = rightAlignedtext.getTextFrameCorners();
203
+
204
+ expect(corners[0].x).toBeCloseTo(90);
205
+ expect(corners[0].y).toBeCloseTo(90);
206
+
207
+ expect(corners[1].x).toBeCloseTo(100);
208
+ expect(corners[1].y).toBeCloseTo(90);
209
+
210
+ expect(corners[2].x).toBeCloseTo(100);
211
+ expect(corners[2].y).toBeCloseTo(100);
212
+
213
+ expect(corners[3].x).toBeCloseTo(90);
214
+ expect(corners[3].y).toBeCloseTo(100);
215
+ });
216
+
14
217
  test('Test Text.setRotation', () => {
15
- const setRotText = new Text({points: [new Point()]});
218
+ const setRotText = new Text({ points: [new Point()] });
16
219
 
17
220
  // Zero
18
221
  setRotText.setRotation(0);
19
- expect(setRotText.rotation).toBe(0);
222
+ expect(setRotText.rotation).toBeCloseTo(0);
20
223
 
21
224
  // Positive
22
225
  setRotText.setRotation(22.5);
@@ -97,10 +300,333 @@ test('Test Text.getRotation', () => {
97
300
  });
98
301
 
99
302
 
303
+ test('Test Text.flags', () => {
304
+ // DXF Groupcode 71 - flags (bit-coded values):
305
+ // 2 = Text is backward (mirrored in X).
306
+ // 4 = Text is upside down (mirrored in Y).
307
+ const text = new Text();
308
+ expect(text.flags.getFlagValue()).toBe(0);
309
+ // set backwards - set 2 on flags
310
+ text.backwards = true;
311
+ expect(text.flags.getFlagValue()).toBe(2);
312
+ // set upsideDown - set 4 on flags
313
+ text.upsideDown = true;
314
+ expect(text.flags.getFlagValue()).toBe(6);
315
+ // unset backwards - remove 2 on flags
316
+ text.backwards = false;
317
+ expect(text.flags.getFlagValue()).toBe(4);
318
+ });
319
+
320
+ test('Test Text.backwards', () => {
321
+ // DXF Groupcode 71 - flags (bit-coded values):
322
+ // 2 = Text is backward (mirrored in X).
323
+ // 4 = Text is upside down (mirrored in Y).
324
+ const text = new Text();
325
+ expect(text.backwards).toBe(false);
326
+ expect(text.flags.getFlagValue()).toBe(0);
327
+ text.backwards = true;
328
+ expect(text.backwards).toBe(true);
329
+ expect(text.flags.getFlagValue()).toBe(2);
330
+ });
331
+
332
+ test('Test Text.upsideDown', () => {
333
+ // DXF Groupcode 71 - flags (bit-coded values):
334
+ // 2 = Text is backward (mirrored in X).
335
+ // 4 = Text is upside down (mirrored in Y).
336
+ const text = new Text();
337
+ expect(text.upsideDown).toBe(false);
338
+ expect(text.flags.getFlagValue()).toBe(0);
339
+ text.upsideDown = true;
340
+ expect(text.upsideDown).toBe(true);
341
+ expect(text.flags.getFlagValue()).toBe(4);
342
+ });
343
+
100
344
  test('Test Text.boundingBox', () => {
101
- const text = new Text({points: [new Point(11, 12)]});
345
+ const text = new Text({ points: [new Point(11, 12)] });
102
346
  expect(text.boundingBox().xMin).toBeCloseTo(11);
103
347
  expect(text.boundingBox().xMax).toBeCloseTo(21);
104
348
  expect(text.boundingBox().yMin).toBeCloseTo(12);
105
349
  expect(text.boundingBox().yMax).toBeCloseTo(22);
106
350
  });
351
+
352
+ test('Test Text.dxf', () => {
353
+ const text = new Text({ handle: '1', points: [new Point(100, 200)] });
354
+ let file = new File();
355
+ text.dxf(file);
356
+ // console.log(file.contents);
357
+
358
+ const dxfString = `0
359
+ TEXT
360
+ 5
361
+ 1
362
+ 100
363
+ AcDbEntity
364
+ 8
365
+ 0
366
+ 100
367
+ AcDbText
368
+ 10
369
+ 100
370
+ 20
371
+ 200
372
+ 30
373
+ 0.0
374
+ 40
375
+ 2.5
376
+ 1
377
+
378
+ 50
379
+ 0
380
+ 71
381
+ 0
382
+ 72
383
+ 0
384
+ 100
385
+ AcDbText
386
+ `;
387
+
388
+ expect(file.contents).toEqual(dxfString);
389
+
390
+ // create new entity from entity data to ensure all props are loaded
391
+ const newText = new Text(text);
392
+ file = new File();
393
+ newText.dxf(file);
394
+ expect(file.contents).toEqual(dxfString);
395
+
396
+
397
+ // create new entity to test text alignment
398
+ // this should include dxf groupcodes 73 and 72 for vertical and horizontal alignment respectively
399
+ // and a second alignment point with groupcode 11,21,31 for the text insertion point
400
+ // bounding rect is 10x10, so second point should be at 100-(10*0.5), 200-(10*0.5) = 95, 195
401
+
402
+ const centeredText = new Text(text);
403
+ centeredText.horizontalAlignment = 1; // center
404
+ centeredText.verticalAlignment = 2; // middle
405
+ file = new File();
406
+ centeredText.dxf(file);
407
+
408
+ const dxfCenteredString = `0
409
+ TEXT
410
+ 5
411
+ 1
412
+ 100
413
+ AcDbEntity
414
+ 8
415
+ 0
416
+ 100
417
+ AcDbText
418
+ 10
419
+ 95
420
+ 20
421
+ 195
422
+ 30
423
+ 0.0
424
+ 40
425
+ 2.5
426
+ 1
427
+
428
+ 50
429
+ 0
430
+ 71
431
+ 0
432
+ 72
433
+ 1
434
+ 11
435
+ 100
436
+ 21
437
+ 200
438
+ 31
439
+ 0.0
440
+ 100
441
+ AcDbText
442
+ 73
443
+ 2
444
+ `;
445
+ expect(file.contents).toEqual(dxfCenteredString);
446
+
447
+ // create new entity from entity data to ensure all props are loaded
448
+ const importCenteredText = new Text(centeredText);
449
+ file = new File();
450
+ importCenteredText.dxf(file);
451
+ expect(file.contents).toEqual(dxfCenteredString);
452
+ });
453
+
454
+ test('Text constructor covers all property branches', () => {
455
+ // Minimal data
456
+ let t = new Text({ points: [new Point(1, 2)] });
457
+ expect(t.string).toBe('');
458
+ expect(t.height).toBe(2.5);
459
+ expect(t.horizontalAlignment).toBe(0);
460
+ expect(t.verticalAlignment).toBe(0);
461
+ expect(t.styleName).toBe('STANDARD');
462
+
463
+ // All DXF groupcodes
464
+ t = new Text({
465
+ points: [new Point(0, 0)],
466
+ string: 'abc',
467
+ 1: 'def',
468
+ styleName: 'FOO',
469
+ 7: 'BAR',
470
+ height: 5,
471
+ 40: 6,
472
+ rotation: 45,
473
+ 50: 90,
474
+ horizontalAlignment: 2,
475
+ 72: 1,
476
+ verticalAlignment: 3,
477
+ 73: 2,
478
+ flags: 2,
479
+ 71: 4,
480
+ });
481
+ expect(['abc', 'def']).toContain(t.string);
482
+ expect(['FOO', 'BAR']).toContain(t.styleName);
483
+ expect([5, 6]).toContain(t.height);
484
+ expect([45, 90]).toContain(t.rotation);
485
+ expect([2, 1]).toContain(t.horizontalAlignment);
486
+ expect([3, 2]).toContain(t.verticalAlignment);
487
+ expect([2, 4, 6, 0]).toContain(t.flags.getFlagValue());
488
+ });
489
+
490
+ test('Text static register and getApproximateWidth', () => {
491
+ expect(Text.register()).toEqual({ command: 'Text', shortcut: 'DT', type: 'Entity' });
492
+ expect(Text.getApproximateWidth('abc', 10)).toBeCloseTo(18);
493
+ });
494
+
495
+ test('Text getHorizontalAlignment covers all cases', () => {
496
+ const t = new Text({ points: [new Point()] });
497
+ t.horizontalAlignment = 0;
498
+ expect(t.getHorizontalAlignment()).toBe('left');
499
+ t.horizontalAlignment = 1;
500
+ expect(t.getHorizontalAlignment()).toBe('center');
501
+ t.horizontalAlignment = 2;
502
+ expect(t.getHorizontalAlignment()).toBe('right');
503
+ t.horizontalAlignment = 3; t.verticalAlignment = 0;
504
+ expect(t.getHorizontalAlignment()).toBe('aligned');
505
+ t.horizontalAlignment = 4; t.verticalAlignment = 0;
506
+ expect(t.getHorizontalAlignment()).toBe('center');
507
+ t.horizontalAlignment = 5; t.verticalAlignment = 0;
508
+ expect(t.getHorizontalAlignment()).toBe('fit');
509
+ t.horizontalAlignment = 99;
510
+ expect(t.getHorizontalAlignment()).toBe('left');
511
+ });
512
+
513
+ test('Text getVerticalAlignment covers all cases', () => {
514
+ const t = new Text({ points: [new Point()] });
515
+ t.verticalAlignment = 0;
516
+ expect(t.getVerticalAlignment()).toBe('alphabetic');
517
+ t.verticalAlignment = 1;
518
+ expect(t.getVerticalAlignment()).toBe('bottom');
519
+ t.verticalAlignment = 2;
520
+ expect(t.getVerticalAlignment()).toBe('middle');
521
+ t.verticalAlignment = 3;
522
+ expect(t.getVerticalAlignment()).toBe('top');
523
+ t.verticalAlignment = 99;
524
+ expect(t.getVerticalAlignment()).toBe('alphabetic');
525
+ });
526
+
527
+ test('Text getBoundingRect returns correct object', () => {
528
+ const t = new Text({ points: [new Point(1, 2)] });
529
+ t.boundingRect = { width: 5, height: 6 };
530
+ const rect = t.getBoundingRect();
531
+ expect(rect).toEqual({ width: 5, height: 6, x: 1, y: 2 });
532
+ });
533
+
534
+ test('Text snaps returns all snap points', () => {
535
+ const t = new Text({ points: [new Point(1, 2)] });
536
+ t.boundingRect = { width: 10, height: 10 };
537
+ const snaps = t.snaps(new Point(0, 0), 1);
538
+ expect(snaps.length).toBe(5);
539
+ });
540
+
541
+ test('Text closestPoint returns correct distance', () => {
542
+ const t = new Text({ points: [new Point(0, 0)] });
543
+ t.boundingRect = { width: 10, height: 10 };
544
+ const [mid, dist] = t.closestPoint(new Point(5, 5));
545
+ expect(mid.x).toBe(5);
546
+ expect(mid.y).toBe(5);
547
+ expect(dist).toBe(0);
548
+ const [mid2, dist2] = t.closestPoint(new Point(100, 100));
549
+ expect(mid2.x).toBe(5);
550
+ expect(mid2.y).toBe(5);
551
+ expect(dist2).toBeGreaterThan(0);
552
+ });
553
+
554
+ test('Text boundingBox returns BoundingBox', () => {
555
+ const t = new Text({ points: [new Point(1, 2)] });
556
+ t.boundingRect = { width: 10, height: 10 };
557
+ const box = t.getBoundingRect();
558
+ expect(box.x).toBe(1);
559
+ expect(box.y).toBe(2);
560
+ expect(box.width).toBe(10);
561
+ expect(box.height).toBe(10);
562
+ });
563
+
564
+ test('Text toPolylinePoints returns correct array', () => {
565
+ const t = new Text({ points: [new Point(1, 2)] });
566
+ t.boundingRect = { width: 10, height: 10 };
567
+ const pts = t.toPolylinePoints();
568
+ expect(pts.length).toBe(5);
569
+ expect(pts[0].x).toBe(1);
570
+ expect(pts[0].y).toBe(2);
571
+ expect(pts[2].x).toBe(11);
572
+ expect(pts[2].y).toBe(12);
573
+ expect(pts[4].x).toBe(pts[0].x);
574
+ expect(pts[4].y).toBe(pts[0].y);
575
+ });
576
+
577
+ test('Text setBackwards and setUpsideDown edge cases', () => {
578
+ const t = new Text({ points: [new Point()] });
579
+ t.setBackwards(true);
580
+ expect(t.backwards).toBe(true);
581
+ t.setBackwards(false);
582
+ expect(t.backwards).toBe(false);
583
+ t.setUpsideDown(true);
584
+ expect(t.upsideDown).toBe(true);
585
+ t.setUpsideDown(false);
586
+ expect(t.upsideDown).toBe(false);
587
+ });
588
+
589
+ test('Text setRotation handles undefined and height 0', () => {
590
+ const t = new Text({ points: [new Point()] });
591
+ t.setRotation(45);
592
+ expect(t.points[1].x).toBeCloseTo(1.7677);
593
+ expect(t.points[1].y).toBeCloseTo(1.7677);
594
+ t.setRotation(undefined);
595
+ expect(t.points[1].x).toBeCloseTo(1.7677);
596
+ expect(t.points[1].y).toBeCloseTo(1.7677);
597
+ });
598
+
599
+ test('Text getRotation returns 0 if points[1] undefined', () => {
600
+ const t = new Text({ points: [new Point()] });
601
+ t.points[1] = undefined;
602
+ expect(t.getRotation()).toBe(0);
603
+ });
604
+
605
+ test('Text.execute re-prompts on zero or negative height', async () => {
606
+ const pt = new Point(0, 0);
607
+
608
+ // 0 and -5 are rejected; 5 is accepted
609
+ await withMockInput(DesignCore.Scene, [pt, 0, -5, 5, 0, 'Hello'], async () => {
610
+ const text = new Text({});
611
+ await text.execute();
612
+
613
+ expect(text.height).toBe(5);
614
+ expect(text.string).toBe('Hello');
615
+ });
616
+ });
617
+
618
+ test('Text.execute does not create entity for empty string', async () => {
619
+ const pt = new Point(0, 0);
620
+ let executeCommandCalled = false;
621
+
622
+ await withMockInput(DesignCore.Scene, [pt, 5, 0, ''], async () => {
623
+ const text = new Text({});
624
+ await text.execute();
625
+
626
+ expect(text.string).toBe('');
627
+ }, { extraMethods: { executeCommand: () => {
628
+ executeCommandCalled = true;
629
+ } } });
630
+
631
+ expect(executeCommandCalled).toBe(false);
632
+ });