terra-draw 0.0.1-alpha.9 → 1.0.0-beta.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.
Files changed (119) hide show
  1. package/.devcontainer/Dockerfile +8 -0
  2. package/.devcontainer/devcontainer.json +27 -0
  3. package/.devcontainer/post-create.sh +16 -0
  4. package/README.md +23 -13
  5. package/dist/adapters/arcgis-maps-sdk.adapter.d.ts +106 -0
  6. package/dist/adapters/google-maps.adapter.d.ts +90 -39
  7. package/dist/adapters/leaflet.adapter.d.ts +99 -33
  8. package/dist/adapters/mapbox-gl.adapter.d.ts +91 -37
  9. package/dist/adapters/maplibre-gl.adapter.d.ts +72 -0
  10. package/dist/adapters/openlayers.adapter.d.ts +120 -0
  11. package/dist/common.d.ts +118 -98
  12. package/dist/geometry/boolean/is-valid-coordinate.d.ts +4 -0
  13. package/dist/geometry/boolean/point-in-polygon.d.ts +2 -2
  14. package/dist/geometry/boolean/self-intersects.d.ts +2 -2
  15. package/dist/geometry/centroid.d.ts +2 -2
  16. package/dist/geometry/coordinates-identical.d.ts +2 -2
  17. package/dist/geometry/get-coordinates-as-points.d.ts +6 -6
  18. package/dist/geometry/get-midpoints.d.ts +14 -7
  19. package/dist/geometry/helpers.d.ts +4 -4
  20. package/dist/geometry/limit-decimal-precision.d.ts +1 -1
  21. package/dist/geometry/measure/area.d.ts +2 -0
  22. package/dist/geometry/measure/bearing.d.ts +9 -0
  23. package/dist/geometry/measure/destination.d.ts +2 -0
  24. package/dist/geometry/measure/haversine-distance.d.ts +2 -2
  25. package/dist/geometry/measure/pixel-distance-to-line.d.ts +10 -10
  26. package/dist/geometry/measure/pixel-distance.d.ts +7 -7
  27. package/dist/geometry/measure/rhumb-bearing.d.ts +2 -2
  28. package/dist/geometry/measure/rhumb-destination.d.ts +2 -2
  29. package/dist/geometry/measure/rhumb-distance.d.ts +2 -2
  30. package/dist/geometry/measure/slice-along.d.ts +2 -0
  31. package/dist/geometry/midpoint-coordinate.d.ts +4 -2
  32. package/dist/geometry/project/web-mercator.d.ts +20 -0
  33. package/dist/geometry/shape/create-bbox.d.ts +10 -0
  34. package/dist/geometry/shape/create-circle.d.ts +13 -7
  35. package/dist/geometry/shape/great-circle-coordinates.d.ts +2 -0
  36. package/dist/geometry/shape/web-mercator-distortion.d.ts +2 -0
  37. package/dist/geometry/transform/rotate.d.ts +9 -2
  38. package/dist/geometry/transform/scale.d.ts +9 -2
  39. package/dist/geometry/web-mercator-centroid.d.ts +11 -0
  40. package/dist/modes/base.behavior.d.ts +21 -19
  41. package/dist/modes/base.mode.d.ts +66 -33
  42. package/dist/modes/circle/circle.mode.d.ts +66 -37
  43. package/dist/modes/click-bounding-box.behavior.d.ts +6 -7
  44. package/dist/modes/freehand/freehand.mode.d.ts +63 -43
  45. package/dist/modes/insert-coordinates.behavior.d.ts +9 -0
  46. package/dist/modes/linestring/linestring.mode.d.ts +78 -47
  47. package/dist/modes/pixel-distance.behavior.d.ts +7 -7
  48. package/dist/modes/point/point.mode.d.ts +44 -26
  49. package/dist/modes/polygon/behaviors/closing-points.behavior.d.ts +19 -19
  50. package/dist/modes/polygon/polygon.mode.d.ts +69 -51
  51. package/dist/modes/rectangle/rectangle.mode.d.ts +55 -0
  52. package/dist/modes/render/render.mode.d.ts +52 -23
  53. package/dist/modes/select/behaviors/drag-coordinate-resize.behavior.d.ts +62 -0
  54. package/dist/modes/select/behaviors/drag-coordinate.behavior.d.ts +20 -13
  55. package/dist/modes/select/behaviors/drag-feature.behavior.d.ts +20 -17
  56. package/dist/modes/select/behaviors/{features-at-mouse-event.behavior.d.ts → feature-at-pointer-event.behavior.d.ts} +15 -15
  57. package/dist/modes/select/behaviors/midpoint.behavior.d.ts +19 -18
  58. package/dist/modes/select/behaviors/rotate-feature.behavior.d.ts +14 -13
  59. package/dist/modes/select/behaviors/scale-feature.behavior.d.ts +14 -13
  60. package/dist/modes/select/behaviors/selection-point.behavior.d.ts +19 -18
  61. package/dist/modes/select/select.mode.d.ts +119 -78
  62. package/dist/modes/snapping.behavior.d.ts +16 -13
  63. package/dist/modes/static/static.mode.d.ts +32 -30
  64. package/dist/store/spatial-index/quickselect.d.ts +2 -2
  65. package/dist/store/spatial-index/rbush.d.ts +35 -35
  66. package/dist/store/spatial-index/spatial-index.d.ts +18 -18
  67. package/dist/store/store-feature-validation.d.ts +16 -0
  68. package/dist/store/store.d.ts +59 -48
  69. package/dist/terra-draw.cjs +1 -1
  70. package/dist/terra-draw.cjs.map +1 -1
  71. package/dist/terra-draw.d.ts +222 -48
  72. package/dist/terra-draw.modern.js +1 -1
  73. package/dist/terra-draw.modern.js.map +1 -1
  74. package/dist/terra-draw.module.js +1 -1
  75. package/dist/terra-draw.module.js.map +1 -1
  76. package/dist/terra-draw.umd.js +1 -1
  77. package/dist/terra-draw.umd.js.map +1 -1
  78. package/dist/util/geoms.d.ts +3 -3
  79. package/dist/util/id.d.ts +1 -1
  80. package/dist/util/styling.d.ts +2 -2
  81. package/dist/validations/linestring.validation.d.ts +2 -0
  82. package/dist/validations/max-size.validation.d.ts +2 -0
  83. package/dist/validations/min-size.validation.d.ts +2 -0
  84. package/dist/validations/not-self-intersecting.validation.d.ts +2 -0
  85. package/dist/validations/point.validation.d.ts +2 -0
  86. package/dist/validations/polygon.validation.d.ts +3 -0
  87. package/e2e/README.md +29 -0
  88. package/e2e/package-lock.json +4274 -0
  89. package/e2e/package.json +26 -0
  90. package/e2e/playwright.config.ts +77 -0
  91. package/e2e/public/favicon.ico +0 -0
  92. package/e2e/public/index.html +52 -0
  93. package/e2e/tests/leaflet.spec.ts +657 -0
  94. package/e2e/tests/setup.ts +181 -0
  95. package/e2e/webpack.config.js +36 -0
  96. package/jest.nocheck.config.ts +17 -0
  97. package/package.json +159 -87
  98. package/readme.gif +0 -0
  99. package/tsconfig.json +25 -12
  100. package/CODE_OF_CONDUCT.md +0 -36
  101. package/CONTRIBUTING.md +0 -17
  102. package/DEVELOPMENT.md +0 -77
  103. package/dist/bundle.js +0 -6
  104. package/dist/bundle.js.LICENSE.txt +0 -4
  105. package/dist/geometry/create-circle.d.ts +0 -6
  106. package/dist/geometry/get-pixel-distance-to-line.d.ts +0 -10
  107. package/dist/geometry/get-pixel-distance.d.ts +0 -7
  108. package/dist/geometry/haversine-distance.d.ts +0 -1
  109. package/dist/geometry/point-in-polygon.d.ts +0 -1
  110. package/dist/geometry/self-intersects.d.ts +0 -2
  111. package/dist/modes/circle.mode.d.ts +0 -18
  112. package/dist/modes/freehand.mode.d.ts +0 -20
  113. package/dist/modes/line-string.mode.d.ts +0 -21
  114. package/dist/modes/point.mode.d.ts +0 -14
  115. package/dist/modes/polygon/behaviors/start-end-point.behavior.d.ts +0 -11
  116. package/dist/modes/polygon.mode.d.ts +0 -21
  117. package/dist/modes/select.mode.d.ts +0 -21
  118. package/dist/modes/static.mode.d.ts +0 -10
  119. package/jest.config.ts +0 -27
@@ -0,0 +1,657 @@
1
+ import { test, expect } from "@playwright/test";
2
+ import {
3
+ changeMode,
4
+ drawTwoClickShape,
5
+ drawRectangularPolygon,
6
+ expectGroupPosition,
7
+ expectPathDimensions,
8
+ expectPaths,
9
+ pageUrl,
10
+ setupMap,
11
+ TestConfigOptions,
12
+ } from "./setup";
13
+
14
+ test.describe("page setup", () => {
15
+ test("loads map", async ({ page }) => {
16
+ await page.goto(pageUrl);
17
+
18
+ // Expect map application to exist
19
+ await expect(page.getByRole("application")).toBeVisible();
20
+ });
21
+
22
+ test("loads UI", async ({ page }) => {
23
+ await page.goto(pageUrl);
24
+
25
+ await expect(page.getByText("Point")).toBeVisible();
26
+ await expect(page.getByText("Linestring")).toBeVisible();
27
+ await expect(page.getByText("Polygon")).toBeVisible();
28
+ await expect(page.getByText("Select")).toBeVisible();
29
+ await expect(page.getByText("Clear")).toBeVisible();
30
+ });
31
+
32
+ test("there are no console errors", async ({ page }) => {
33
+ const errors: string[] = [];
34
+ page.on("console", (msg) => {
35
+ if (msg.type() === "error") {
36
+ errors.push(msg.text());
37
+ }
38
+ });
39
+ await page.goto(pageUrl);
40
+ await expect(page.getByRole("application")).toBeVisible();
41
+
42
+ expect(errors).toEqual([]);
43
+ });
44
+
45
+ test("there are no build issues", async ({ page }) => {
46
+ await page.goto(pageUrl);
47
+ await expect(
48
+ await page.locator("#webpack-dev-server-client-overlay").count(),
49
+ ).toBe(0);
50
+ });
51
+ });
52
+
53
+ test.describe("point mode", () => {
54
+ const mode = "point";
55
+
56
+ test("mode can set and can be used to create a point", async ({ page }) => {
57
+ const mapDiv = await setupMap({ page });
58
+ await changeMode({ page, mode });
59
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
60
+
61
+ await expectPaths({ page, count: 1 });
62
+ });
63
+
64
+ test("mode can set and can be used to create multiple points", async ({
65
+ page,
66
+ }) => {
67
+ const mapDiv = await setupMap({ page });
68
+ await changeMode({ page, mode });
69
+
70
+ await page.mouse.click(mapDiv.width / 4, mapDiv.height / 4);
71
+ await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
72
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
73
+
74
+ await expectPaths({ page, count: 3 });
75
+ });
76
+ });
77
+
78
+ test.describe("linestring mode", () => {
79
+ const mode = "linestring";
80
+
81
+ const options = [
82
+ { name: "", config: undefined },
83
+ {
84
+ name: " with insert coordinates for web mercator projection",
85
+ config: ["insertCoordinates"],
86
+ },
87
+ {
88
+ name: " with insert coordinates for globe projection",
89
+ config: ["insertCoordinatesGlobe"],
90
+ },
91
+ ] as { name: string; config: TestConfigOptions[] }[];
92
+
93
+ for (const { name, config } of options) {
94
+ test(`mode can set and can be used to create a linestring${name}`, async ({
95
+ page,
96
+ }) => {
97
+ const mapDiv = await setupMap({ page, configQueryParam: config });
98
+ await changeMode({ page, mode });
99
+
100
+ await page.mouse.move(mapDiv.width / 2, mapDiv.height / 2);
101
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
102
+ await page.mouse.move(mapDiv.width / 3, mapDiv.height / 3);
103
+ await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
104
+
105
+ // Close
106
+ await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
107
+
108
+ await expectPaths({ page, count: 1 });
109
+ });
110
+
111
+ test(`mode can set and can be used to create a linestring with multiple points${name}`, async ({
112
+ page,
113
+ }) => {
114
+ const mapDiv = await setupMap({ page, configQueryParam: config });
115
+ await changeMode({ page, mode });
116
+
117
+ await page.mouse.move(mapDiv.width / 2, mapDiv.height / 2);
118
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
119
+ await page.mouse.move(mapDiv.width / 3, mapDiv.height / 3);
120
+ await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
121
+
122
+ // Draw coordinate 2
123
+ await page.mouse.move(mapDiv.width / 3, mapDiv.height / 2);
124
+ await page.mouse.click(mapDiv.width / 3, mapDiv.height / 2);
125
+
126
+ // Draw coordinate 3
127
+ await page.mouse.move(mapDiv.width / 2, mapDiv.height / 3);
128
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 3);
129
+
130
+ // Close
131
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 3);
132
+
133
+ await expectPaths({ page, count: 1 });
134
+ });
135
+
136
+ test(`mode can set and can be used to create a linestring with multiple clicked points${name}`, async ({
137
+ page,
138
+ }) => {
139
+ const mapDiv = await setupMap({ page, configQueryParam: config });
140
+ await changeMode({ page, mode });
141
+
142
+ await page.mouse.move(mapDiv.width / 2, mapDiv.height / 2);
143
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
144
+ await page.mouse.move(mapDiv.width / 3, mapDiv.height / 3);
145
+ await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
146
+
147
+ // Draw coordinate 2
148
+ await page.mouse.move(mapDiv.width / 3, mapDiv.height / 2);
149
+ await page.mouse.click(mapDiv.width / 3, mapDiv.height / 2);
150
+
151
+ // Draw coordinate 3
152
+ await page.mouse.move(mapDiv.width / 2, mapDiv.height / 3);
153
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 3);
154
+
155
+ // Close
156
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 3);
157
+
158
+ await expectPaths({ page, count: 1 });
159
+ });
160
+
161
+ test(`mode can set and can be used to create multiple linestrings${name}`, async ({
162
+ page,
163
+ }) => {
164
+ const mapDiv = await setupMap({ page, configQueryParam: config });
165
+ await changeMode({ page, mode });
166
+
167
+ // First line
168
+ await page.mouse.move(mapDiv.width / 2, mapDiv.height / 2);
169
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
170
+ await page.mouse.move(mapDiv.width / 3, mapDiv.height / 3);
171
+ await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
172
+
173
+ // One point + one line
174
+ await expectPaths({ page, count: 2 });
175
+
176
+ // Close first line
177
+ await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
178
+
179
+ // One line
180
+ await expectPaths({ page, count: 1 });
181
+
182
+ // Second line
183
+ await page.mouse.move(mapDiv.width / 4, mapDiv.height / 4);
184
+ await page.mouse.click(mapDiv.width / 4, mapDiv.height / 4);
185
+ await page.mouse.move(mapDiv.width / 5, mapDiv.height / 5);
186
+ await page.mouse.click(mapDiv.width / 5, mapDiv.height / 5);
187
+
188
+ // Close second line
189
+ await page.mouse.click(mapDiv.width / 5, mapDiv.height / 5);
190
+
191
+ // Two lines
192
+ await expectPaths({ page, count: 2 });
193
+ });
194
+ }
195
+ });
196
+
197
+ test.describe("polygon mode", () => {
198
+ const mode = "polygon";
199
+
200
+ test("mode can set and can be used to create a polygon", async ({ page }) => {
201
+ const mapDiv = await setupMap({ page });
202
+ await changeMode({ page, mode });
203
+
204
+ // The length of the square sides in pixels
205
+ const sideLength = 100;
206
+
207
+ // Calculating the half of the side length
208
+ const halfLength = sideLength / 2;
209
+
210
+ // Coordinates of the center
211
+ const centerX = mapDiv.width / 2;
212
+ const centerY = mapDiv.height / 2;
213
+
214
+ // Coordinates of the four corners of the square
215
+ const topLeft = { x: centerX - halfLength, y: centerY - halfLength };
216
+ const topRight = { x: centerX + halfLength, y: centerY - halfLength };
217
+ const bottomLeft = { x: centerX - halfLength, y: centerY + halfLength };
218
+ const bottomRight = { x: centerX + halfLength, y: centerY + halfLength };
219
+
220
+ // Perform clicks at each corner
221
+ await page.mouse.click(topLeft.x, topLeft.y);
222
+ await page.mouse.click(topRight.x, topRight.y);
223
+ await page.mouse.click(bottomRight.x, bottomRight.y);
224
+ await page.mouse.click(bottomLeft.x, bottomLeft.y);
225
+
226
+ // Close the square
227
+ await page.mouse.click(bottomLeft.x, bottomLeft.y);
228
+
229
+ // One point + one line
230
+ await expectPaths({ page, count: 1 });
231
+ });
232
+
233
+ test("can use validation setting to prevent maximum size", async ({
234
+ page,
235
+ }) => {
236
+ const mapDiv = await setupMap({
237
+ page,
238
+ configQueryParam: ["validationFailure"],
239
+ });
240
+ await changeMode({ page, mode });
241
+
242
+ // The length of the square sides in pixels
243
+ const sideLength = 100;
244
+
245
+ // Calculating the half of the side length
246
+ const halfLength = sideLength / 2;
247
+
248
+ // Coordinates of the center
249
+ const centerX = mapDiv.width / 2;
250
+ const centerY = mapDiv.height / 2;
251
+
252
+ // Coordinates of the four corners of the square
253
+ const topLeft = { x: centerX - halfLength, y: centerY - halfLength };
254
+ const topRight = { x: centerX + halfLength, y: centerY - halfLength };
255
+ const bottomLeft = { x: centerX - halfLength, y: centerY + halfLength };
256
+ const bottomRight = { x: centerX + halfLength, y: centerY + halfLength };
257
+
258
+ // Perform clicks at each corner
259
+ await page.mouse.click(topLeft.x, topLeft.y);
260
+ await page.mouse.click(topRight.x, topRight.y);
261
+ await page.mouse.click(bottomRight.x, bottomRight.y);
262
+ await page.mouse.click(bottomLeft.x, bottomLeft.y);
263
+
264
+ // Attempt to close the square
265
+ await page.mouse.click(bottomLeft.x, bottomLeft.y);
266
+
267
+ // Square will fail, as triangle will be 705665 square meters, but square will be
268
+ // over the limit of 1000000 square meters.
269
+ await expectPaths({ page, count: 3 });
270
+ });
271
+
272
+ test("can use validation setting to draw underneath maximum size ", async ({
273
+ page,
274
+ }) => {
275
+ const mapDiv = await setupMap({
276
+ page,
277
+ configQueryParam: ["validationSuccess"],
278
+ });
279
+ await changeMode({ page, mode });
280
+
281
+ // The length of the square sides in pixels
282
+ const sideLength = 100;
283
+
284
+ // Calculating the half of the side length
285
+ const halfLength = sideLength / 2;
286
+
287
+ // Coordinates of the center
288
+ const centerX = mapDiv.width / 2;
289
+ const centerY = mapDiv.height / 2;
290
+
291
+ // Coordinates of the four corners of the square
292
+ const topLeft = { x: centerX - halfLength, y: centerY - halfLength };
293
+ const topRight = { x: centerX + halfLength, y: centerY - halfLength };
294
+ const bottomLeft = { x: centerX - halfLength, y: centerY + halfLength };
295
+ const bottomRight = { x: centerX + halfLength, y: centerY + halfLength };
296
+
297
+ // Perform clicks at each corner
298
+ await page.mouse.click(topLeft.x, topLeft.y);
299
+ await page.mouse.click(topRight.x, topRight.y);
300
+ await page.mouse.click(bottomRight.x, bottomRight.y);
301
+ await page.mouse.click(bottomLeft.x, bottomLeft.y);
302
+
303
+ // Attempt to close the square
304
+ await page.mouse.click(bottomLeft.x, bottomLeft.y);
305
+
306
+ // Square will fail, as triangle will be 705665 square meters, but square will be
307
+ // over the limit of 1000000 square meters.
308
+ await expectPaths({ page, count: 1 });
309
+ });
310
+ });
311
+
312
+ test.describe("rectangle mode", () => {
313
+ const mode = "rectangle";
314
+
315
+ test("mode can set and can be used to create a rectangle", async ({
316
+ page,
317
+ }) => {
318
+ const mapDiv = await setupMap({ page });
319
+ await changeMode({ page, mode });
320
+
321
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
322
+ await page.mouse.click(mapDiv.width / 2 + 50, mapDiv.height / 2 + 50);
323
+
324
+ // One point + one line
325
+ await expectPaths({ page, count: 1 });
326
+
327
+ await expectPathDimensions({ page, width: 54, height: 54 }); // Stroke width of 4
328
+ });
329
+ });
330
+
331
+ test.describe("circle mode", () => {
332
+ const mode = "circle";
333
+
334
+ test("mode can set and can be used to create a web mercator circle", async ({
335
+ page,
336
+ }) => {
337
+ const mapDiv = await setupMap({ page });
338
+ await changeMode({ page, mode });
339
+
340
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
341
+ await page.mouse.click(mapDiv.width / 2 + 50, mapDiv.height / 2 + 50);
342
+
343
+ // One point + one line
344
+ await expectPaths({ page, count: 1 });
345
+
346
+ await expectPathDimensions({ page, width: 146, height: 146 });
347
+ });
348
+
349
+ test("mode can set and can be used to create a geodesic circle", async ({
350
+ page,
351
+ }) => {
352
+ const mapDiv = await setupMap({ page, configQueryParam: ["globeCircle"] });
353
+ await changeMode({ page, mode });
354
+
355
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
356
+ await page.mouse.click(mapDiv.width / 2 + 50, mapDiv.height / 2 + 50);
357
+
358
+ // One point + one line
359
+ await expectPaths({ page, count: 1 });
360
+
361
+ await expectPathDimensions({ page, width: 146, height: 146 });
362
+ });
363
+ });
364
+
365
+ test.describe("select mode", () => {
366
+ const mode = "select";
367
+
368
+ const options = [
369
+ { name: "in web mercator projection", config: undefined },
370
+ {
371
+ name: "in globe projection",
372
+ config: ["globeSelect"],
373
+ },
374
+ ] as { name: string; config: TestConfigOptions[] }[];
375
+
376
+ for (const { name, config } of options) {
377
+ test(`mode can set and then polygon can be selected and deselected ${name}`, async ({
378
+ page,
379
+ }) => {
380
+ const mapDiv = await setupMap({ page, configQueryParam: config });
381
+
382
+ await changeMode({ page, mode: "polygon" });
383
+ const sideLength = 100;
384
+ const halfLength = sideLength / 2;
385
+ const centerX = mapDiv.width / 2;
386
+ const centerY = mapDiv.height / 2;
387
+ const topLeft = { x: centerX - halfLength, y: centerY - halfLength };
388
+ const topRight = { x: centerX + halfLength, y: centerY - halfLength };
389
+ const bottomLeft = { x: centerX - halfLength, y: centerY + halfLength };
390
+ const bottomRight = { x: centerX + halfLength, y: centerY + halfLength };
391
+ await page.mouse.click(topLeft.x, topLeft.y);
392
+ await page.mouse.click(topRight.x, topRight.y);
393
+ await page.mouse.click(bottomRight.x, bottomRight.y);
394
+ await page.mouse.click(bottomLeft.x, bottomLeft.y);
395
+ await page.mouse.click(bottomLeft.x, bottomLeft.y); // Closed
396
+
397
+ await changeMode({ page, mode });
398
+
399
+ // Select
400
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
401
+ await expectPaths({ page, count: 9 }); // 8 selection points and 1 square
402
+
403
+ // Deselect
404
+ await page.mouse.click(mapDiv.width - 10, mapDiv.height / 2);
405
+ await expectPaths({ page, count: 1 }); // 0 selection points and 1 square
406
+ });
407
+
408
+ test(`selected polygon can be dragged ${name}`, async ({ page }) => {
409
+ const mapDiv = await setupMap({ page, configQueryParam: config });
410
+
411
+ await changeMode({ page, mode: "polygon" });
412
+
413
+ // Draw a rectangle
414
+ const { topLeft } = await drawRectangularPolygon({ mapDiv, page });
415
+
416
+ // Change to select mode
417
+ await changeMode({ page, mode });
418
+
419
+ // Before drag
420
+ const x = topLeft.x - 2;
421
+ const y = topLeft.y - 2;
422
+ await expectGroupPosition({ page, x, y });
423
+
424
+ // Select
425
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
426
+ await expectPaths({ page, count: 9 }); // 8 selection points and 1 square
427
+
428
+ // Drag
429
+ await page.mouse.move(mapDiv.width / 2, mapDiv.height / 2);
430
+ await page.mouse.down();
431
+ await page.mouse.move(mapDiv.width / 2 + 50, mapDiv.height / 2 + 50, {
432
+ steps: 30,
433
+ }); // Steps is required
434
+ await page.mouse.up();
435
+
436
+ await page.mouse.click(mapDiv.width - 10, mapDiv.height / 2);
437
+
438
+ await expectGroupPosition({ page, x: x + 48, y: y + 48 });
439
+ });
440
+
441
+ test(`selected polygon can have individual coordinates dragged ${name}`, async ({
442
+ page,
443
+ }) => {
444
+ const mapDiv = await setupMap({ page, configQueryParam: config });
445
+
446
+ await changeMode({ page, mode: "polygon" });
447
+
448
+ // Draw a rectangle
449
+ const { topLeft } = await drawRectangularPolygon({ mapDiv, page });
450
+
451
+ // Change to select mode
452
+ await changeMode({ page, mode });
453
+
454
+ // Before drag
455
+ const x = topLeft.x - 2;
456
+ const y = topLeft.y - 2;
457
+ await expectGroupPosition({ page, x, y });
458
+
459
+ // Select
460
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
461
+ await expectPaths({ page, count: 9 }); // 8 selection points and 1 square
462
+
463
+ // Drag
464
+ await page.mouse.move(topLeft.x, topLeft.y);
465
+ await page.mouse.down();
466
+ await page.mouse.move(topLeft.x - 50, topLeft.y + 50, { steps: 30 }); // Steps is required
467
+ await page.mouse.up();
468
+
469
+ // Deselect
470
+ await page.mouse.click(mapDiv.width - 10, mapDiv.height / 2);
471
+
472
+ // Dragged the coordinate to the left and down slightly
473
+ await expectGroupPosition({ page, x: 538, y: 308 });
474
+ });
475
+
476
+ test(`selected polygon can have individual coordinates dragged and succeeds when validation succeeds ${name}`, async ({
477
+ page,
478
+ }) => {
479
+ const mapDiv = await setupMap({
480
+ page,
481
+ configQueryParam: config
482
+ ? [...config, "validationSuccess"]
483
+ : ["validationSuccess"],
484
+ });
485
+
486
+ await changeMode({ page, mode: "polygon" });
487
+
488
+ // Draw a rectangle
489
+ const { topLeft } = await drawRectangularPolygon({
490
+ mapDiv,
491
+ page,
492
+ size: "small",
493
+ });
494
+
495
+ // Change to select mode
496
+ await changeMode({ page, mode });
497
+
498
+ // Before drag
499
+ const x = topLeft.x - 2;
500
+ const y = topLeft.y - 2;
501
+ await expectGroupPosition({ page, x, y });
502
+
503
+ // Select
504
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
505
+ // await expectPaths({ page, count: 9 }); // 8 selection points and 1 square
506
+
507
+ // Drag
508
+ await page.mouse.move(topLeft.x, topLeft.y);
509
+ await page.mouse.down();
510
+ await page.mouse.move(topLeft.x - 50, topLeft.y - 50, { steps: 30 });
511
+ await page.mouse.up();
512
+
513
+ // Deselect
514
+ await page.mouse.click(mapDiv.width - 10, mapDiv.height / 2);
515
+
516
+ // We are attempting to dragg right tothe top left corner but it is not getting there
517
+ // because it is capped by the validation. If this was allowed x would be ~90
518
+ await expectGroupPosition({ page, x: 553, y: 273 });
519
+ });
520
+
521
+ test(`selected polygon can have individual coordinates dragged and fail when validation fails ${name}`, async ({
522
+ page,
523
+ }) => {
524
+ const mapDiv = await setupMap({
525
+ page,
526
+ configQueryParam: config
527
+ ? [...config, "validationFailure"]
528
+ : ["validationFailure"],
529
+ });
530
+
531
+ await changeMode({ page, mode: "polygon" });
532
+
533
+ // Draw a rectangle
534
+ const { topLeft } = await drawRectangularPolygon({
535
+ mapDiv,
536
+ page,
537
+ size: "small",
538
+ });
539
+
540
+ // Change to select mode
541
+ await changeMode({ page, mode });
542
+
543
+ // Before drag
544
+ const x = topLeft.x - 2;
545
+ const y = topLeft.y - 2;
546
+ await expectGroupPosition({ page, x, y });
547
+
548
+ // Select
549
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
550
+ // await expectPaths({ page, count: 9 }); // 8 selection points and 1 square
551
+
552
+ // Drag
553
+ await page.mouse.move(topLeft.x, topLeft.y);
554
+ await page.mouse.down();
555
+ await page.mouse.move(0, 0, { steps: 30 });
556
+ await page.mouse.up();
557
+
558
+ // Deselect
559
+ await page.mouse.click(mapDiv.width - 10, mapDiv.height / 2);
560
+
561
+ // We are attempting to dragg right tothe top left corner but it is not getting there
562
+ // because it is capped by the validation. If this was allowed x would be ~90
563
+ await expectGroupPosition({ page, x: 563, y: 301 });
564
+ });
565
+ }
566
+
567
+ test("selected rectangle has it's shape maintained when coordinates are dragged with resizable flag", async ({
568
+ page,
569
+ }) => {
570
+ const mapDiv = await setupMap({ page });
571
+
572
+ await changeMode({ page, mode: "rectangle" });
573
+
574
+ // Draw a rectangle
575
+ const { topLeft } = await drawTwoClickShape({ mapDiv, page });
576
+
577
+ // Change to select mode
578
+ await changeMode({ page, mode });
579
+
580
+ // Before drag
581
+ const x = topLeft.x - 2;
582
+ const y = topLeft.y - 2;
583
+ await expectGroupPosition({ page, x, y });
584
+
585
+ // Select
586
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
587
+ await expectPaths({ page, count: 5 }); // 4 selection points and 1 square
588
+
589
+ // Drag
590
+ await page.mouse.move(topLeft.x, topLeft.y);
591
+ await page.mouse.down();
592
+ await page.mouse.move(topLeft.x - 100, topLeft.y + 100, { steps: 50 }); // Steps is required
593
+ await page.mouse.up();
594
+
595
+ // Deselect
596
+ await page.mouse.click(mapDiv.width - 10, mapDiv.height / 2);
597
+
598
+ // Dragged the square up and to the left
599
+ await expectGroupPosition({ page, x: 490, y: 408 });
600
+ });
601
+
602
+ test("selected circle has it's shape maintained from center origin when coordinates are dragged with resizable flag", async ({
603
+ page,
604
+ }) => {
605
+ const mapDiv = await setupMap({ page });
606
+
607
+ await changeMode({ page, mode: "circle" });
608
+
609
+ // Draw a circle
610
+ await drawTwoClickShape({ mapDiv, page });
611
+
612
+ // Change to select mode
613
+ await changeMode({ page, mode });
614
+
615
+ // Select
616
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
617
+ await expectPaths({ page, count: 65 }); // 4 selection points and 1 square
618
+
619
+ // Drag
620
+ await page.mouse.move(mapDiv.width / 2, mapDiv.height / 2 + 50);
621
+ await page.mouse.down();
622
+ await page.mouse.move(mapDiv.width / 2, mapDiv.height / 2 + 100, {
623
+ steps: 50,
624
+ }); // Steps is required
625
+ await page.mouse.up();
626
+
627
+ // Deselect
628
+ await page.mouse.click(mapDiv.width - 10, mapDiv.height / 2);
629
+
630
+ // Dragged the square up and to the left
631
+ await expectGroupPosition({ page, x: 447, y: 138 });
632
+ });
633
+ });
634
+
635
+ test.describe("clear", () => {
636
+ test("drawn geometries can be cleared correctly", async ({ page }) => {
637
+ const mapDiv = await setupMap({ page });
638
+
639
+ await changeMode({ page, mode: "point" });
640
+ await page.mouse.click(mapDiv.width / 4, mapDiv.height / 4);
641
+
642
+ await changeMode({ page, mode: "linestring" });
643
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
644
+ await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
645
+ await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
646
+
647
+ await changeMode({ page, mode: "polygon" });
648
+ await drawRectangularPolygon({ mapDiv, page });
649
+
650
+ await expectPaths({ page, count: 3 });
651
+
652
+ const button = page.getByText("clear");
653
+ await button.click();
654
+
655
+ await expectPaths({ page, count: 0 });
656
+ });
657
+ });