terra-draw 0.0.1-alpha.6 → 0.0.1-alpha.61

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 (112) hide show
  1. package/.devcontainer/Dockerfile +8 -0
  2. package/.devcontainer/devcontainer.json +21 -0
  3. package/.devcontainer/post-create.sh +16 -0
  4. package/README.md +30 -6
  5. package/dist/adapters/arcgis-maps-sdk.adapter.d.ts +105 -0
  6. package/dist/adapters/common/adapter-listener.d.ts +22 -0
  7. package/dist/adapters/common/base.adapter.d.ts +59 -0
  8. package/dist/adapters/google-maps.adapter.d.ts +90 -39
  9. package/dist/adapters/leaflet.adapter.d.ts +97 -33
  10. package/dist/adapters/mapbox-gl.adapter.d.ts +89 -37
  11. package/dist/adapters/maplibre-gl.adapter.d.ts +71 -0
  12. package/dist/adapters/openlayers.adapter.d.ts +118 -0
  13. package/dist/common.d.ts +103 -98
  14. package/dist/geometry/boolean/is-valid-coordinate.d.ts +4 -0
  15. package/dist/geometry/boolean/is-valid-linestring-feature.d.ts +2 -0
  16. package/dist/geometry/boolean/is-valid-point.d.ts +2 -0
  17. package/dist/geometry/boolean/is-valid-polygon-feature.d.ts +3 -0
  18. package/dist/geometry/boolean/point-in-polygon.d.ts +2 -2
  19. package/dist/geometry/boolean/self-intersects.d.ts +2 -2
  20. package/dist/geometry/centroid.d.ts +2 -2
  21. package/dist/geometry/coordinates-identical.d.ts +2 -2
  22. package/dist/geometry/get-coordinates-as-points.d.ts +6 -6
  23. package/dist/geometry/get-midpoints.d.ts +8 -7
  24. package/dist/geometry/helpers.d.ts +4 -4
  25. package/dist/geometry/limit-decimal-precision.d.ts +1 -1
  26. package/dist/geometry/measure/haversine-distance.d.ts +2 -2
  27. package/dist/geometry/measure/pixel-distance-to-line.d.ts +10 -10
  28. package/dist/geometry/measure/pixel-distance.d.ts +7 -7
  29. package/dist/geometry/measure/rhumb-bearing.d.ts +2 -2
  30. package/dist/geometry/measure/rhumb-destination.d.ts +2 -2
  31. package/dist/geometry/measure/rhumb-distance.d.ts +2 -2
  32. package/dist/geometry/midpoint-coordinate.d.ts +3 -2
  33. package/dist/geometry/shape/create-bbox.d.ts +10 -0
  34. package/dist/geometry/shape/create-circle.d.ts +7 -7
  35. package/dist/geometry/shape/great-circle-line.d.ts +12 -0
  36. package/dist/geometry/transform/rotate.d.ts +2 -2
  37. package/dist/geometry/transform/scale.d.ts +2 -2
  38. package/dist/modes/base.behavior.d.ts +19 -19
  39. package/dist/modes/base.mode.d.ts +62 -33
  40. package/dist/modes/circle/circle.mode.d.ts +55 -35
  41. package/dist/modes/click-bounding-box.behavior.d.ts +6 -7
  42. package/dist/modes/freehand/freehand.mode.d.ts +63 -37
  43. package/dist/modes/great-circle-snapping.behavior.d.ts +14 -0
  44. package/dist/modes/greatcircle/great-circle.mode.d.ts +64 -0
  45. package/dist/modes/linestring/linestring.mode.d.ts +67 -40
  46. package/dist/modes/pixel-distance.behavior.d.ts +7 -7
  47. package/dist/modes/point/point.mode.d.ts +44 -26
  48. package/dist/modes/polygon/behaviors/closing-points.behavior.d.ts +19 -19
  49. package/dist/modes/polygon/polygon.mode.d.ts +70 -49
  50. package/dist/modes/rectangle/rectangle.mode.d.ts +55 -0
  51. package/dist/modes/render/render.mode.d.ts +52 -23
  52. package/dist/modes/select/behaviors/drag-coordinate-resize.behavior.d.ts +28 -0
  53. package/dist/modes/select/behaviors/drag-coordinate.behavior.d.ts +20 -13
  54. package/dist/modes/select/behaviors/drag-feature.behavior.d.ts +20 -17
  55. package/dist/modes/select/behaviors/{features-at-mouse-event.behavior.d.ts → feature-at-pointer-event.behavior.d.ts} +15 -15
  56. package/dist/modes/select/behaviors/midpoint.behavior.d.ts +19 -18
  57. package/dist/modes/select/behaviors/rotate-feature.behavior.d.ts +14 -13
  58. package/dist/modes/select/behaviors/scale-feature.behavior.d.ts +14 -13
  59. package/dist/modes/select/behaviors/selection-point.behavior.d.ts +19 -18
  60. package/dist/modes/select/select.mode.d.ts +117 -78
  61. package/dist/modes/snapping.behavior.d.ts +16 -13
  62. package/dist/modes/static/static.mode.d.ts +32 -30
  63. package/dist/store/spatial-index/quickselect.d.ts +2 -2
  64. package/dist/store/spatial-index/rbush.d.ts +35 -35
  65. package/dist/store/spatial-index/spatial-index.d.ts +18 -18
  66. package/dist/store/store-feature-validation.d.ts +16 -0
  67. package/dist/store/store.d.ts +59 -48
  68. package/dist/terra-draw.cjs +1 -1
  69. package/dist/terra-draw.cjs.map +1 -1
  70. package/dist/terra-draw.d.ts +220 -48
  71. package/dist/terra-draw.modern.js +1 -1
  72. package/dist/terra-draw.modern.js.map +1 -1
  73. package/dist/terra-draw.module.js +1 -1
  74. package/dist/terra-draw.module.js.map +1 -1
  75. package/dist/terra-draw.umd.js +1 -1
  76. package/dist/terra-draw.umd.js.map +1 -1
  77. package/dist/util/geoms.d.ts +3 -3
  78. package/dist/util/id.d.ts +1 -1
  79. package/dist/util/styling.d.ts +2 -2
  80. package/e2e/README.md +29 -0
  81. package/e2e/package-lock.json +4249 -0
  82. package/e2e/package.json +26 -0
  83. package/e2e/playwright.config.ts +77 -0
  84. package/e2e/public/index.html +53 -0
  85. package/e2e/src/index.ts +165 -0
  86. package/e2e/tests/leaflet.spec.ts +413 -0
  87. package/e2e/tests/setup.ts +164 -0
  88. package/e2e/webpack.config.js +36 -0
  89. package/jest.nocheck.config.ts +17 -0
  90. package/package.json +157 -87
  91. package/readme.gif +0 -0
  92. package/tsconfig.json +17 -12
  93. package/CODE_OF_CONDUCT.md +0 -36
  94. package/CONTRIBUTING.md +0 -17
  95. package/DEVELOPMENT.md +0 -77
  96. package/dist/bundle.js +0 -6
  97. package/dist/bundle.js.LICENSE.txt +0 -4
  98. package/dist/geometry/create-circle.d.ts +0 -6
  99. package/dist/geometry/get-pixel-distance-to-line.d.ts +0 -10
  100. package/dist/geometry/get-pixel-distance.d.ts +0 -7
  101. package/dist/geometry/haversine-distance.d.ts +0 -1
  102. package/dist/geometry/point-in-polygon.d.ts +0 -1
  103. package/dist/geometry/self-intersects.d.ts +0 -2
  104. package/dist/modes/circle.mode.d.ts +0 -18
  105. package/dist/modes/freehand.mode.d.ts +0 -20
  106. package/dist/modes/line-string.mode.d.ts +0 -21
  107. package/dist/modes/point.mode.d.ts +0 -14
  108. package/dist/modes/polygon/behaviors/start-end-point.behavior.d.ts +0 -11
  109. package/dist/modes/polygon.mode.d.ts +0 -21
  110. package/dist/modes/select.mode.d.ts +0 -21
  111. package/dist/modes/static.mode.d.ts +0 -10
  112. package/jest.config.ts +0 -27
@@ -0,0 +1,413 @@
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
+ } from "./setup";
12
+
13
+ test.describe("page setup", () => {
14
+ test("loads map", async ({ page }) => {
15
+ await page.goto(pageUrl);
16
+
17
+ // Expect map application to exist
18
+ await expect(page.getByRole("application")).toBeVisible();
19
+ });
20
+
21
+ test("loads UI", async ({ page }) => {
22
+ await page.goto(pageUrl);
23
+
24
+ await expect(page.getByText("Point")).toBeVisible();
25
+ await expect(page.getByText("Linestring")).toBeVisible();
26
+ await expect(page.getByText("Polygon")).toBeVisible();
27
+ await expect(page.getByText("Select")).toBeVisible();
28
+ await expect(page.getByText("Clear")).toBeVisible();
29
+ });
30
+
31
+ test("there are no console errors", async ({ page }) => {
32
+ const errors: string[] = [];
33
+ page.on("console", (msg) => {
34
+ if (msg.type() === "error") {
35
+ errors.push(msg.text());
36
+ }
37
+ });
38
+ await page.goto(pageUrl);
39
+ await expect(page.getByRole("application")).toBeVisible();
40
+
41
+ expect(errors).toEqual([]);
42
+ });
43
+
44
+ test("there are no build issues", async ({ page }) => {
45
+ await page.goto(pageUrl);
46
+ await expect(
47
+ await page.locator("#webpack-dev-server-client-overlay").count(),
48
+ ).toBe(0);
49
+ });
50
+ });
51
+
52
+ test.describe("point mode", () => {
53
+ const mode = "point";
54
+
55
+ test("mode can set and can be used to create a point", async ({ page }) => {
56
+ const mapDiv = await setupMap({ page });
57
+ await changeMode({ page, mode });
58
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
59
+
60
+ await expectPaths({ page, count: 1 });
61
+ });
62
+
63
+ test("mode can set and can be used to create multiple points", async ({
64
+ page,
65
+ }) => {
66
+ const mapDiv = await setupMap({ page });
67
+ await changeMode({ page, mode });
68
+
69
+ await page.mouse.click(mapDiv.width / 4, mapDiv.height / 4);
70
+ await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
71
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
72
+
73
+ await expectPaths({ page, count: 3 });
74
+ });
75
+ });
76
+
77
+ test.describe("linestring mode", () => {
78
+ const mode = "linestring";
79
+
80
+ test("mode can set and can be used to create a linestring", async ({
81
+ page,
82
+ }) => {
83
+ const mapDiv = await setupMap({ page });
84
+ await changeMode({ page, mode });
85
+
86
+ await page.mouse.move(mapDiv.width / 2, mapDiv.height / 2);
87
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
88
+ await page.mouse.move(mapDiv.width / 3, mapDiv.height / 3);
89
+ await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
90
+
91
+ await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
92
+
93
+ await expectPaths({ page, count: 1 });
94
+ });
95
+
96
+ test("mode can set and can be used to create multiple linestrings", async ({
97
+ page,
98
+ }) => {
99
+ const mapDiv = await setupMap({ page });
100
+ await changeMode({ page, mode });
101
+
102
+ // First line
103
+ await page.mouse.move(mapDiv.width / 2, mapDiv.height / 2);
104
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
105
+ await page.mouse.move(mapDiv.width / 3, mapDiv.height / 3);
106
+ await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
107
+
108
+ // One point + one line
109
+ await expectPaths({ page, count: 2 });
110
+
111
+ // Close first line
112
+ await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
113
+
114
+ // One line
115
+ await expectPaths({ page, count: 1 });
116
+
117
+ // Second line
118
+ await page.mouse.move(mapDiv.width / 4, mapDiv.height / 4);
119
+ await page.mouse.click(mapDiv.width / 4, mapDiv.height / 4);
120
+ await page.mouse.move(mapDiv.width / 5, mapDiv.height / 5);
121
+ await page.mouse.click(mapDiv.width / 5, mapDiv.height / 5);
122
+
123
+ // Close second line
124
+ await page.mouse.click(mapDiv.width / 5, mapDiv.height / 5);
125
+
126
+ // Two lines
127
+ await expectPaths({ page, count: 2 });
128
+ });
129
+ });
130
+
131
+ test.describe("polygon mode", () => {
132
+ const mode = "polygon";
133
+
134
+ test("mode can set and can be used to create a polygon", async ({ page }) => {
135
+ const mapDiv = await setupMap({ page });
136
+ await changeMode({ page, mode });
137
+
138
+ // The length of the square sides in pixels
139
+ const sideLength = 100;
140
+
141
+ // Calculating the half of the side length
142
+ const halfLength = sideLength / 2;
143
+
144
+ // Coordinates of the center
145
+ const centerX = mapDiv.width / 2;
146
+ const centerY = mapDiv.height / 2;
147
+
148
+ // Coordinates of the four corners of the square
149
+ const topLeft = { x: centerX - halfLength, y: centerY - halfLength };
150
+ const topRight = { x: centerX + halfLength, y: centerY - halfLength };
151
+ const bottomLeft = { x: centerX - halfLength, y: centerY + halfLength };
152
+ const bottomRight = { x: centerX + halfLength, y: centerY + halfLength };
153
+
154
+ // Perform clicks at each corner
155
+ await page.mouse.click(topLeft.x, topLeft.y);
156
+ await page.mouse.click(topRight.x, topRight.y);
157
+ await page.mouse.click(bottomRight.x, bottomRight.y);
158
+ await page.mouse.click(bottomLeft.x, bottomLeft.y);
159
+
160
+ // Close the square
161
+ await page.mouse.click(bottomLeft.x, bottomLeft.y);
162
+
163
+ // One point + one line
164
+ await expectPaths({ page, count: 1 });
165
+ });
166
+ });
167
+
168
+ test.describe("rectangle mode", () => {
169
+ const mode = "rectangle";
170
+
171
+ test("mode can set and can be used to create a rectangle", async ({
172
+ page,
173
+ }) => {
174
+ const mapDiv = await setupMap({ page });
175
+ await changeMode({ page, mode });
176
+
177
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
178
+ await page.mouse.click(mapDiv.width / 2 + 50, mapDiv.height / 2 + 50);
179
+
180
+ // One point + one line
181
+ await expectPaths({ page, count: 1 });
182
+
183
+ await expectPathDimensions({ page, width: 54, height: 54 }); // Stroke width of 4
184
+ });
185
+ });
186
+
187
+ test.describe("circle mode", () => {
188
+ const mode = "circle";
189
+
190
+ test("mode can set and can be used to create a circle", async ({ page }) => {
191
+ const mapDiv = await setupMap({ page });
192
+ await changeMode({ page, mode });
193
+
194
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
195
+ await page.mouse.click(mapDiv.width / 2 + 50, mapDiv.height / 2 + 50);
196
+
197
+ // One point + one line
198
+ await expectPaths({ page, count: 1 });
199
+
200
+ await expectPathDimensions({ page, width: 146, height: 146 });
201
+ });
202
+ });
203
+
204
+ test.describe("greatcircle mode", () => {
205
+ const mode = "greatcircle";
206
+
207
+ test("mode can set and can be used to create a greatcircle", async ({
208
+ page,
209
+ }) => {
210
+ const mapDiv = await setupMap({ page });
211
+ await changeMode({ page, mode });
212
+
213
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
214
+ await page.mouse.click(mapDiv.width / 2 + 50, mapDiv.height / 2 + 50);
215
+
216
+ // One point + one line
217
+ await expectPaths({ page, count: 1 });
218
+ });
219
+ });
220
+
221
+ test.describe("select mode", () => {
222
+ const mode = "select";
223
+
224
+ test("mode can set and then polygon can be selected and deselected", async ({
225
+ page,
226
+ }) => {
227
+ const mapDiv = await setupMap({ page });
228
+
229
+ await changeMode({ page, mode: "polygon" });
230
+ const sideLength = 100;
231
+ const halfLength = sideLength / 2;
232
+ const centerX = mapDiv.width / 2;
233
+ const centerY = mapDiv.height / 2;
234
+ const topLeft = { x: centerX - halfLength, y: centerY - halfLength };
235
+ const topRight = { x: centerX + halfLength, y: centerY - halfLength };
236
+ const bottomLeft = { x: centerX - halfLength, y: centerY + halfLength };
237
+ const bottomRight = { x: centerX + halfLength, y: centerY + halfLength };
238
+ await page.mouse.click(topLeft.x, topLeft.y);
239
+ await page.mouse.click(topRight.x, topRight.y);
240
+ await page.mouse.click(bottomRight.x, bottomRight.y);
241
+ await page.mouse.click(bottomLeft.x, bottomLeft.y);
242
+ await page.mouse.click(bottomLeft.x, bottomLeft.y); // Closed
243
+
244
+ await changeMode({ page, mode });
245
+
246
+ // Select
247
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
248
+ await expectPaths({ page, count: 9 }); // 8 selection points and 1 square
249
+
250
+ // Deselect
251
+ await page.mouse.click(mapDiv.width - 10, mapDiv.height / 2);
252
+ await expectPaths({ page, count: 1 }); // 0 selection points and 1 square
253
+ });
254
+
255
+ test("selected polygon can be dragged", async ({ page }) => {
256
+ const mapDiv = await setupMap({ page });
257
+
258
+ await changeMode({ page, mode: "polygon" });
259
+
260
+ // Draw a rectangle
261
+ const { topLeft } = await drawRectangularPolygon({ mapDiv, page });
262
+
263
+ // Change to select mode
264
+ await changeMode({ page, mode });
265
+
266
+ // Before drag
267
+ const x = topLeft.x - 2;
268
+ const y = topLeft.y - 2;
269
+ await expectGroupPosition({ page, x, y });
270
+
271
+ // Select
272
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
273
+ await expectPaths({ page, count: 9 }); // 8 selection points and 1 square
274
+
275
+ // Drag
276
+ await page.mouse.move(mapDiv.width / 2, mapDiv.height / 2);
277
+ await page.mouse.down();
278
+ await page.mouse.move(mapDiv.width / 2 + 50, mapDiv.height / 2 + 50, {
279
+ steps: 30,
280
+ }); // Steps is required
281
+ await page.mouse.up();
282
+
283
+ await page.mouse.click(mapDiv.width - 10, mapDiv.height / 2);
284
+
285
+ await expectGroupPosition({ page, x: x + 48, y: y + 48 });
286
+ });
287
+
288
+ test("selected polygon can have individual coordinates dragged", async ({
289
+ page,
290
+ }) => {
291
+ const mapDiv = await setupMap({ page });
292
+
293
+ await changeMode({ page, mode: "polygon" });
294
+
295
+ // Draw a rectangle
296
+ const { topLeft } = await drawRectangularPolygon({ mapDiv, page });
297
+
298
+ // Change to select mode
299
+ await changeMode({ page, mode });
300
+
301
+ // Before drag
302
+ const x = topLeft.x - 2;
303
+ const y = topLeft.y - 2;
304
+ await expectGroupPosition({ page, x, y });
305
+
306
+ // Select
307
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
308
+ await expectPaths({ page, count: 9 }); // 8 selection points and 1 square
309
+
310
+ // Drag
311
+ await page.mouse.move(topLeft.x, topLeft.y);
312
+ await page.mouse.down();
313
+ await page.mouse.move(topLeft.x - 50, topLeft.y + 50, { steps: 30 }); // Steps is required
314
+ await page.mouse.up();
315
+
316
+ // Deselect
317
+ await page.mouse.click(mapDiv.width - 10, mapDiv.height / 2);
318
+
319
+ // Dragged the coordinate to the left and down slightly
320
+ await expectGroupPosition({ page, x: 538, y: 308 });
321
+ });
322
+
323
+ test("selected rectangle can has it's shape maintained when coordinates are dragged", async ({
324
+ page,
325
+ }) => {
326
+ const mapDiv = await setupMap({ page });
327
+
328
+ await changeMode({ page, mode: "rectangle" });
329
+
330
+ // Draw a rectangle
331
+ const { topLeft } = await drawTwoClickShape({ mapDiv, page });
332
+
333
+ // Change to select mode
334
+ await changeMode({ page, mode });
335
+
336
+ // Before drag
337
+ const x = topLeft.x - 2;
338
+ const y = topLeft.y - 2;
339
+ await expectGroupPosition({ page, x, y });
340
+
341
+ // Select
342
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
343
+ await expectPaths({ page, count: 5 }); // 4 selection points and 1 square
344
+
345
+ // Drag
346
+ await page.mouse.move(topLeft.x, topLeft.y);
347
+ await page.mouse.down();
348
+ await page.mouse.move(topLeft.x - 100, topLeft.y + 100, { steps: 50 }); // Steps is required
349
+ await page.mouse.up();
350
+
351
+ // Deselect
352
+ await page.mouse.click(mapDiv.width - 10, mapDiv.height / 2);
353
+
354
+ // Dragged the square up and to the left
355
+ await expectGroupPosition({ page, x: 584, y: 304 });
356
+ });
357
+
358
+ test("selected circle can has it's shape maintained from center origin when coordinates are dragged", async ({
359
+ page,
360
+ }) => {
361
+ const mapDiv = await setupMap({ page });
362
+
363
+ await changeMode({ page, mode: "circle" });
364
+
365
+ // Draw a circle
366
+ await drawTwoClickShape({ mapDiv, page });
367
+
368
+ // Change to select mode
369
+ await changeMode({ page, mode });
370
+
371
+ // Select
372
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
373
+ await expectPaths({ page, count: 65 }); // 4 selection points and 1 square
374
+
375
+ // Drag
376
+ await page.mouse.move(mapDiv.width / 2, mapDiv.height / 2 + 50);
377
+ await page.mouse.down();
378
+ await page.mouse.move(mapDiv.width / 2, mapDiv.height / 2 + 100, {
379
+ steps: 50,
380
+ }); // Steps is required
381
+ await page.mouse.up();
382
+
383
+ // Deselect
384
+ await page.mouse.click(mapDiv.width - 10, mapDiv.height / 2);
385
+
386
+ // Dragged the square up and to the left
387
+ await expectGroupPosition({ page, x: 430, y: 150 });
388
+ });
389
+ });
390
+
391
+ test.describe("clear", () => {
392
+ test("drawn geometries can be cleared correctly", async ({ page }) => {
393
+ const mapDiv = await setupMap({ page });
394
+
395
+ await changeMode({ page, mode: "point" });
396
+ await page.mouse.click(mapDiv.width / 4, mapDiv.height / 4);
397
+
398
+ await changeMode({ page, mode: "linestring" });
399
+ await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
400
+ await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
401
+ await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
402
+
403
+ await changeMode({ page, mode: "polygon" });
404
+ await drawRectangularPolygon({ mapDiv, page });
405
+
406
+ await expectPaths({ page, count: 3 });
407
+
408
+ const button = page.getByText("clear");
409
+ await button.click();
410
+
411
+ await expectPaths({ page, count: 0 });
412
+ });
413
+ });
@@ -0,0 +1,164 @@
1
+ import { Page, expect } from "@playwright/test";
2
+
3
+ export const pageUrl = "http://localhost:3000/";
4
+
5
+ export const setupMap = async ({
6
+ page,
7
+ }: {
8
+ page: Page;
9
+ }): Promise<{
10
+ x: number;
11
+ y: number;
12
+ width: number;
13
+ height: number;
14
+ }> => {
15
+ await page.goto(pageUrl);
16
+
17
+ const mapDiv = await page.getByRole("application");
18
+
19
+ // Get the bounding box of the div
20
+ const mapBoundingBox = await mapDiv.boundingBox();
21
+
22
+ if (!mapBoundingBox) {
23
+ throw new Error();
24
+ }
25
+
26
+ return mapBoundingBox;
27
+ };
28
+
29
+ export const changeMode = async ({
30
+ page,
31
+ mode,
32
+ }: {
33
+ page: Page;
34
+ mode:
35
+ | "point"
36
+ | "polygon"
37
+ | "linestring"
38
+ | "select"
39
+ | "rectangle"
40
+ | "circle"
41
+ | "greatcircle";
42
+ }) => {
43
+ const modeText = mode.charAt(0).toUpperCase() + mode.slice(1);
44
+ const buttons = page.getByTestId("buttons");
45
+ const button = buttons.getByText(modeText, { exact: true });
46
+
47
+ // Click the mode button
48
+ await button.click();
49
+
50
+ // Ensure it has been clickde and updatedc correctly
51
+ const color = await button.evaluate((el) =>
52
+ window.getComputedStyle(el).getPropertyValue("color"),
53
+ );
54
+ expect(color).toBe("rgb(39, 204, 255)"); // We set hex but it gets computed to rgb
55
+ };
56
+
57
+ export const expectPaths = async ({
58
+ page,
59
+ count,
60
+ }: {
61
+ page: Page;
62
+ count: number;
63
+ }) => {
64
+ const selector = "svg > g > path";
65
+
66
+ if (count > 0) {
67
+ await page.waitForSelector(selector);
68
+ expect(await page.locator(selector).count()).toBe(count);
69
+ } else {
70
+ await expect(await page.locator(selector).count()).toBe(0);
71
+ }
72
+ };
73
+
74
+ export const expectPathDimensions = async ({
75
+ page,
76
+ width,
77
+ height,
78
+ }: {
79
+ page: Page;
80
+ width: number;
81
+ height: number;
82
+ }) => {
83
+ const selector = "svg > g > path";
84
+
85
+ const boundingBox = await page.locator(selector).boundingBox();
86
+
87
+ expect(boundingBox?.width).toBe(width);
88
+ expect(boundingBox?.height).toBe(height);
89
+ };
90
+
91
+ export const expectGroupPosition = async ({
92
+ page,
93
+ x,
94
+ y,
95
+ }: {
96
+ page: Page;
97
+ x: number;
98
+ y: number;
99
+ }) => {
100
+ const selector = "svg > g > path";
101
+
102
+ const boundingBox = await page.locator(selector).boundingBox();
103
+
104
+ expect(boundingBox?.x).toBe(x);
105
+ expect(boundingBox?.y).toBe(y);
106
+ };
107
+
108
+ export const drawRectangularPolygon = async ({
109
+ mapDiv,
110
+ page,
111
+ }: {
112
+ mapDiv: {
113
+ x: number;
114
+ y: number;
115
+ width: number;
116
+ height: number;
117
+ };
118
+ page: Page;
119
+ }) => {
120
+ // Draw a rectangle
121
+ const sideLength = 100;
122
+ const halfLength = sideLength / 2;
123
+ const centerX = mapDiv.width / 2;
124
+ const centerY = mapDiv.height / 2;
125
+ const topLeft = { x: centerX - halfLength, y: centerY - halfLength };
126
+ const topRight = { x: centerX + halfLength, y: centerY - halfLength };
127
+ const bottomLeft = { x: centerX - halfLength, y: centerY + halfLength };
128
+ const bottomRight = { x: centerX + halfLength, y: centerY + halfLength };
129
+ await page.mouse.click(topLeft.x, topLeft.y);
130
+ await page.mouse.click(topRight.x, topRight.y);
131
+ await page.mouse.click(bottomRight.x, bottomRight.y);
132
+ await page.mouse.click(bottomLeft.x, bottomLeft.y);
133
+ await page.mouse.click(bottomLeft.x, bottomLeft.y); // Closed
134
+
135
+ return { topLeft, topRight, bottomRight, bottomLeft };
136
+ };
137
+
138
+ export const drawTwoClickShape = async ({
139
+ mapDiv,
140
+ page,
141
+ }: {
142
+ mapDiv: {
143
+ x: number;
144
+ y: number;
145
+ width: number;
146
+ height: number;
147
+ };
148
+ page: Page;
149
+ }) => {
150
+ // Draw a rectangle
151
+ const sideLength = 100;
152
+ const halfLength = sideLength / 2;
153
+ const centerX = mapDiv.width / 2;
154
+ const centerY = mapDiv.height / 2;
155
+ const topLeft = { x: centerX - halfLength, y: centerY - halfLength };
156
+ const topRight = { x: centerX + halfLength, y: centerY - halfLength };
157
+ const bottomLeft = { x: centerX - halfLength, y: centerY + halfLength };
158
+ const bottomRight = { x: centerX + halfLength, y: centerY + halfLength };
159
+ await page.mouse.click(topLeft.x, topLeft.y);
160
+
161
+ await page.mouse.click(bottomRight.x, bottomRight.y); // Closed
162
+
163
+ return { topLeft, topRight, bottomRight, bottomLeft };
164
+ };
@@ -0,0 +1,36 @@
1
+ const path = require("path");
2
+ const Dotenv = require("dotenv-webpack");
3
+
4
+ module.exports = {
5
+ mode: "development",
6
+ entry: "./src/index.ts",
7
+ devtool: "inline-source-map",
8
+ plugins: [new Dotenv()],
9
+ module: {
10
+ rules: [
11
+ {
12
+ test: /\.tsx?$/,
13
+ use: "ts-loader",
14
+ exclude: /node_modules/,
15
+ },
16
+ ],
17
+ },
18
+ resolve: {
19
+ extensions: [".tsx", ".ts", ".js"],
20
+ },
21
+ output: {
22
+ filename: "bundle.js",
23
+ path: path.resolve(__dirname, "dist"),
24
+ },
25
+ devServer: {
26
+ static: {
27
+ directory: path.join(__dirname, "public"),
28
+ },
29
+ liveReload: !process.env.CI,
30
+ watchFiles: !process.env.CI
31
+ ? ["./src", "./*.{js,json,ts,html}", "../src", "../*.{js,json,ts,html}"]
32
+ : [],
33
+ compress: true,
34
+ port: 3000,
35
+ },
36
+ };
@@ -0,0 +1,17 @@
1
+ console.log("===== Using @swc/jest ======");
2
+
3
+ module.exports = {
4
+ transform: {
5
+ "^.+\\.(t|j)sx?$": "@swc/jest",
6
+ },
7
+ testPathIgnorePatterns: [
8
+ "<rootDir>/node_modules/",
9
+ "<rootDir>/e2e/",
10
+ "<rootDir>/docs/",
11
+ "<rootDir>/coverage/",
12
+ "<rootDir>/scripts/",
13
+ "<rootDir>/guides/",
14
+ ],
15
+ coveragePathIgnorePatterns: ["<rootDir>/src/test/", "<rootDir>/e2e/"],
16
+ setupFilesAfterEnv: ["<rootDir>/src/test/jest.matchers.ts"],
17
+ };