terra-draw 1.0.0-beta.0 → 1.0.0-beta.10
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.
- package/README.md +10 -3
- package/dist/adapters/common/adapter-listener.d.ts +22 -0
- package/dist/adapters/common/base.adapter.d.ts +59 -0
- package/dist/adapters/mapbox-gl.adapter.d.ts +0 -1
- package/dist/adapters/openlayers.adapter.d.ts +14 -13
- package/dist/common.d.ts +11 -9
- package/dist/extend.d.ts +4 -0
- package/dist/geometry/calculate-relative-angle.d.ts +9 -0
- package/dist/geometry/clockwise.d.ts +2 -0
- package/dist/geometry/determine-halfplane.d.ts +2 -0
- package/dist/geometry/measure/bearing.d.ts +3 -7
- package/dist/geometry/measure/destination.d.ts +2 -0
- package/dist/geometry/measure/pixel-distance-to-line.d.ts +2 -10
- package/dist/geometry/measure/pixel-distance.d.ts +2 -7
- package/dist/geometry/point-on-line.d.ts +5 -0
- package/dist/geometry/project/web-mercator.d.ts +2 -4
- package/dist/geometry/web-mercator-centroid.d.ts +2 -4
- package/dist/geometry/web-mercator-point-on-line.d.ts +11 -0
- package/dist/modes/angled-rectangle/angled-rectangle.mode.d.ts +57 -0
- package/dist/modes/base.mode.d.ts +3 -1
- package/dist/modes/circle/circle.mode.d.ts +3 -2
- package/dist/modes/coordinate-snapping.behavior.d.ts +16 -0
- package/dist/modes/freehand/freehand.mode.d.ts +8 -2
- package/dist/modes/{snapping.behavior.d.ts → line-snapping.behavior.d.ts} +1 -1
- package/dist/modes/linestring/linestring.mode.d.ts +11 -4
- package/dist/modes/point/point.mode.d.ts +2 -2
- package/dist/modes/polygon/polygon.mode.d.ts +14 -4
- package/dist/modes/rectangle/rectangle.mode.d.ts +2 -2
- package/dist/modes/render/render.mode.d.ts +2 -1
- package/dist/modes/sector/sector.mode.d.ts +60 -0
- package/dist/modes/select/behaviors/drag-feature.behavior.d.ts +2 -2
- package/dist/modes/sensor/sensor.mode.d.ts +69 -0
- package/dist/store/store-feature-validation.d.ts +8 -2
- package/dist/store/store.d.ts +7 -3
- package/dist/terra-draw.cjs +1 -1
- package/dist/terra-draw.cjs.map +1 -1
- package/dist/terra-draw.d.ts +13 -13
- package/dist/terra-draw.modern.js +1 -1
- package/dist/terra-draw.modern.js.map +1 -1
- package/dist/terra-draw.module.js +1 -1
- package/dist/terra-draw.module.js.map +1 -1
- package/dist/terra-draw.umd.js +1 -1
- package/dist/terra-draw.umd.js.map +1 -1
- package/dist/validation-reasons.d.ts +13 -0
- package/dist/validations/common-validations.d.ts +2 -0
- package/dist/validations/linestring.validation.d.ts +4 -1
- package/dist/validations/max-size.validation.d.ts +3 -1
- package/dist/validations/min-size.validation.d.ts +3 -1
- package/dist/validations/not-self-intersecting.validation.d.ts +4 -1
- package/dist/validations/point.validation.d.ts +4 -1
- package/dist/validations/polygon.validation.d.ts +8 -2
- package/e2e/package-lock.json +5 -4
- package/e2e/package.json +1 -1
- package/e2e/public/index.html +3 -0
- package/e2e/tests/leaflet.spec.ts +490 -14
- package/e2e/tests/setup.ts +34 -6
- package/eslint.config.js +31 -0
- package/package.json +30 -30
- package/tsconfig.json +2 -1
- package/readme.gif +0 -0
|
@@ -53,7 +53,7 @@ test.describe("page setup", () => {
|
|
|
53
53
|
test.describe("point mode", () => {
|
|
54
54
|
const mode = "point";
|
|
55
55
|
|
|
56
|
-
test("mode can set and
|
|
56
|
+
test("mode can set and used to create a point", async ({ page }) => {
|
|
57
57
|
const mapDiv = await setupMap({ page });
|
|
58
58
|
await changeMode({ page, mode });
|
|
59
59
|
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
@@ -61,9 +61,7 @@ test.describe("point mode", () => {
|
|
|
61
61
|
await expectPaths({ page, count: 1 });
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
-
test("mode can set and
|
|
65
|
-
page,
|
|
66
|
-
}) => {
|
|
64
|
+
test("mode can set and used to create multiple points", async ({ page }) => {
|
|
67
65
|
const mapDiv = await setupMap({ page });
|
|
68
66
|
await changeMode({ page, mode });
|
|
69
67
|
|
|
@@ -91,7 +89,7 @@ test.describe("linestring mode", () => {
|
|
|
91
89
|
] as { name: string; config: TestConfigOptions[] }[];
|
|
92
90
|
|
|
93
91
|
for (const { name, config } of options) {
|
|
94
|
-
test(`mode can set and
|
|
92
|
+
test(`mode can set and used to create a linestring${name}`, async ({
|
|
95
93
|
page,
|
|
96
94
|
}) => {
|
|
97
95
|
const mapDiv = await setupMap({ page, configQueryParam: config });
|
|
@@ -108,7 +106,7 @@ test.describe("linestring mode", () => {
|
|
|
108
106
|
await expectPaths({ page, count: 1 });
|
|
109
107
|
});
|
|
110
108
|
|
|
111
|
-
test(`mode can set and
|
|
109
|
+
test(`mode can set and used to create a linestring with multiple points${name}`, async ({
|
|
112
110
|
page,
|
|
113
111
|
}) => {
|
|
114
112
|
const mapDiv = await setupMap({ page, configQueryParam: config });
|
|
@@ -133,7 +131,7 @@ test.describe("linestring mode", () => {
|
|
|
133
131
|
await expectPaths({ page, count: 1 });
|
|
134
132
|
});
|
|
135
133
|
|
|
136
|
-
test(`mode can set and
|
|
134
|
+
test(`mode can set and used to create a linestring with multiple clicked points${name}`, async ({
|
|
137
135
|
page,
|
|
138
136
|
}) => {
|
|
139
137
|
const mapDiv = await setupMap({ page, configQueryParam: config });
|
|
@@ -158,7 +156,7 @@ test.describe("linestring mode", () => {
|
|
|
158
156
|
await expectPaths({ page, count: 1 });
|
|
159
157
|
});
|
|
160
158
|
|
|
161
|
-
test(`mode can set and
|
|
159
|
+
test(`mode can set and used to create multiple linestrings${name}`, async ({
|
|
162
160
|
page,
|
|
163
161
|
}) => {
|
|
164
162
|
const mapDiv = await setupMap({ page, configQueryParam: config });
|
|
@@ -191,13 +189,52 @@ test.describe("linestring mode", () => {
|
|
|
191
189
|
// Two lines
|
|
192
190
|
await expectPaths({ page, count: 2 });
|
|
193
191
|
});
|
|
192
|
+
|
|
193
|
+
test(`mode can set with snapping enabled used to create multiple linestrings${name}`, async ({
|
|
194
|
+
page,
|
|
195
|
+
}) => {
|
|
196
|
+
const mapDiv = await setupMap({
|
|
197
|
+
page,
|
|
198
|
+
configQueryParam: config
|
|
199
|
+
? [...config, "snappingCoordinate"]
|
|
200
|
+
: undefined,
|
|
201
|
+
});
|
|
202
|
+
await changeMode({ page, mode });
|
|
203
|
+
|
|
204
|
+
// First line
|
|
205
|
+
await page.mouse.move(mapDiv.width / 2, mapDiv.height / 2);
|
|
206
|
+
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
207
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 3);
|
|
208
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
|
|
209
|
+
|
|
210
|
+
// One point + one line
|
|
211
|
+
await expectPaths({ page, count: 2 });
|
|
212
|
+
|
|
213
|
+
// Close first line
|
|
214
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
|
|
215
|
+
|
|
216
|
+
// One line
|
|
217
|
+
await expectPaths({ page, count: 1 });
|
|
218
|
+
|
|
219
|
+
// Second line
|
|
220
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 3);
|
|
221
|
+
|
|
222
|
+
// Should see snapping point
|
|
223
|
+
await expectPaths({ page, count: 2 });
|
|
224
|
+
|
|
225
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
|
|
226
|
+
await page.mouse.move(mapDiv.width / 4, mapDiv.height / 4);
|
|
227
|
+
|
|
228
|
+
// Snapping point disappears but the second line is created so it is still 2
|
|
229
|
+
await expectPaths({ page, count: 2 });
|
|
230
|
+
});
|
|
194
231
|
}
|
|
195
232
|
});
|
|
196
233
|
|
|
197
234
|
test.describe("polygon mode", () => {
|
|
198
235
|
const mode = "polygon";
|
|
199
236
|
|
|
200
|
-
test("mode can set and
|
|
237
|
+
test("mode can set and used to create a polygon", async ({ page }) => {
|
|
201
238
|
const mapDiv = await setupMap({ page });
|
|
202
239
|
await changeMode({ page, mode });
|
|
203
240
|
|
|
@@ -307,14 +344,66 @@ test.describe("polygon mode", () => {
|
|
|
307
344
|
// over the limit of 1000000 square meters.
|
|
308
345
|
await expectPaths({ page, count: 1 });
|
|
309
346
|
});
|
|
347
|
+
|
|
348
|
+
test("mode can set and used to create a polygon with snapping enabled", async ({
|
|
349
|
+
page,
|
|
350
|
+
}) => {
|
|
351
|
+
const mapDiv = await setupMap({
|
|
352
|
+
page,
|
|
353
|
+
configQueryParam: ["snappingCoordinate"],
|
|
354
|
+
});
|
|
355
|
+
await changeMode({ page, mode });
|
|
356
|
+
|
|
357
|
+
// The length of the square sides in pixels
|
|
358
|
+
const sideLength = 100;
|
|
359
|
+
|
|
360
|
+
// Calculating the half of the side length
|
|
361
|
+
const halfLength = sideLength / 2;
|
|
362
|
+
|
|
363
|
+
// Coordinates of the center
|
|
364
|
+
const centerX = mapDiv.width / 2;
|
|
365
|
+
const centerY = mapDiv.height / 2;
|
|
366
|
+
|
|
367
|
+
// Coordinates of the four corners of the square
|
|
368
|
+
const topLeft = { x: centerX - halfLength, y: centerY - halfLength };
|
|
369
|
+
const topRight = { x: centerX + halfLength, y: centerY - halfLength };
|
|
370
|
+
const bottomLeft = { x: centerX - halfLength, y: centerY + halfLength };
|
|
371
|
+
const bottomRight = { x: centerX + halfLength, y: centerY + halfLength };
|
|
372
|
+
|
|
373
|
+
// Perform clicks at each corner
|
|
374
|
+
await page.mouse.click(topLeft.x, topLeft.y);
|
|
375
|
+
await page.mouse.click(topRight.x, topRight.y);
|
|
376
|
+
await page.mouse.click(bottomRight.x, bottomRight.y);
|
|
377
|
+
await page.mouse.click(bottomLeft.x, bottomLeft.y);
|
|
378
|
+
|
|
379
|
+
// Close the square
|
|
380
|
+
await page.mouse.click(bottomLeft.x, bottomLeft.y);
|
|
381
|
+
|
|
382
|
+
// One point + one line
|
|
383
|
+
await expectPaths({ page, count: 1 });
|
|
384
|
+
|
|
385
|
+
// Let's create a new polygon attached to the square, snapping to it
|
|
386
|
+
await page.mouse.click(bottomLeft.x, bottomLeft.y);
|
|
387
|
+
await page.mouse.click(bottomRight.x, bottomRight.y);
|
|
388
|
+
await page.mouse.click(bottomRight.x, bottomRight.y + 50);
|
|
389
|
+
|
|
390
|
+
await expectPaths({ page, count: 4 });
|
|
391
|
+
|
|
392
|
+
await page.mouse.click(bottomRight.x, bottomRight.y + 50);
|
|
393
|
+
|
|
394
|
+
await expectPaths({ page, count: 2 });
|
|
395
|
+
|
|
396
|
+
// Go to another corner and it should snap with a point appearing
|
|
397
|
+
await page.mouse.click(topLeft.x, topLeft.y);
|
|
398
|
+
|
|
399
|
+
await expectPaths({ page, count: 3 });
|
|
400
|
+
});
|
|
310
401
|
});
|
|
311
402
|
|
|
312
403
|
test.describe("rectangle mode", () => {
|
|
313
404
|
const mode = "rectangle";
|
|
314
405
|
|
|
315
|
-
test("mode can set and
|
|
316
|
-
page,
|
|
317
|
-
}) => {
|
|
406
|
+
test("mode can set and used to create a rectangle", async ({ page }) => {
|
|
318
407
|
const mapDiv = await setupMap({ page });
|
|
319
408
|
await changeMode({ page, mode });
|
|
320
409
|
|
|
@@ -328,10 +417,397 @@ test.describe("rectangle mode", () => {
|
|
|
328
417
|
});
|
|
329
418
|
});
|
|
330
419
|
|
|
420
|
+
test.describe("angled rectangle mode", () => {
|
|
421
|
+
const mode = "angled-rectangle";
|
|
422
|
+
|
|
423
|
+
test("mode can set and used to create an angled rectangle (horizontal up)", async ({
|
|
424
|
+
page,
|
|
425
|
+
}) => {
|
|
426
|
+
const mapDiv = await setupMap({ page });
|
|
427
|
+
await changeMode({ page, mode });
|
|
428
|
+
|
|
429
|
+
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
430
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 2, { steps: 30 });
|
|
431
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 2);
|
|
432
|
+
await page.mouse.move(mapDiv.width / 3 + 50, mapDiv.height / 3 + 50, {
|
|
433
|
+
steps: 30,
|
|
434
|
+
});
|
|
435
|
+
await page.mouse.click(mapDiv.width / 3 + 50, mapDiv.height / 3 + 50);
|
|
436
|
+
|
|
437
|
+
await expectPaths({ page, count: 1 });
|
|
438
|
+
|
|
439
|
+
await expectPathDimensions({ page, width: 217, height: 74 });
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
test("mode can set and used to create an angled rectangle (horizontal down)", async ({
|
|
443
|
+
page,
|
|
444
|
+
}) => {
|
|
445
|
+
const mapDiv = await setupMap({ page });
|
|
446
|
+
await changeMode({ page, mode });
|
|
447
|
+
|
|
448
|
+
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
449
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 2, { steps: 30 });
|
|
450
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 2);
|
|
451
|
+
await page.mouse.move(mapDiv.width / 3 + 50, mapDiv.height / 3 + 200, {
|
|
452
|
+
steps: 30,
|
|
453
|
+
});
|
|
454
|
+
await page.mouse.click(mapDiv.width / 3 + 50, mapDiv.height / 3 + 200);
|
|
455
|
+
|
|
456
|
+
await expectPaths({ page, count: 1 });
|
|
457
|
+
|
|
458
|
+
await expectPathDimensions({ page, width: 217, height: 84 });
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
test("mode can set and used to create an angled (diagonal)", async ({
|
|
462
|
+
page,
|
|
463
|
+
}) => {
|
|
464
|
+
const mapDiv = await setupMap({ page });
|
|
465
|
+
await changeMode({ page, mode });
|
|
466
|
+
|
|
467
|
+
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
468
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 3, { steps: 30 });
|
|
469
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
|
|
470
|
+
await page.mouse.move(mapDiv.width / 3 + 150, mapDiv.height / 3 + 150, {
|
|
471
|
+
steps: 30,
|
|
472
|
+
});
|
|
473
|
+
await page.mouse.click(mapDiv.width / 3 + 150, mapDiv.height / 3 + 150);
|
|
474
|
+
|
|
475
|
+
await expectPaths({ page, count: 1 });
|
|
476
|
+
|
|
477
|
+
await expectPathDimensions({ page, width: 245, height: 174 });
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
test("mode can set and used to create an angled (diagonal 2)", async ({
|
|
481
|
+
page,
|
|
482
|
+
}) => {
|
|
483
|
+
const mapDiv = await setupMap({ page });
|
|
484
|
+
await changeMode({ page, mode });
|
|
485
|
+
|
|
486
|
+
await page.mouse.click(mapDiv.width / 1.8, mapDiv.height / 1.8);
|
|
487
|
+
await page.mouse.move(mapDiv.width / 2.5, mapDiv.height / 1.3, {
|
|
488
|
+
steps: 30,
|
|
489
|
+
});
|
|
490
|
+
await page.mouse.click(mapDiv.width / 2.5, mapDiv.height / 1.3);
|
|
491
|
+
await page.mouse.move(mapDiv.width / 2.5 + 50, mapDiv.height / 1.3 + 50, {
|
|
492
|
+
steps: 30,
|
|
493
|
+
});
|
|
494
|
+
await page.mouse.click(mapDiv.width / 2.5 + 50, mapDiv.height / 1.3 + 50);
|
|
495
|
+
|
|
496
|
+
await expectPaths({ page, count: 1 });
|
|
497
|
+
|
|
498
|
+
await expectPathDimensions({ page, width: 246, height: 213 });
|
|
499
|
+
});
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
test.describe("sector mode", () => {
|
|
503
|
+
const mode = "sector";
|
|
504
|
+
|
|
505
|
+
test("mode can set and used to create a sector less than 90 degrees (clockwise)", async ({
|
|
506
|
+
page,
|
|
507
|
+
}) => {
|
|
508
|
+
const mapDiv = await setupMap({ page });
|
|
509
|
+
await changeMode({ page, mode });
|
|
510
|
+
|
|
511
|
+
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
512
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 2, { steps: 30 });
|
|
513
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 2);
|
|
514
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 3, {
|
|
515
|
+
steps: 30,
|
|
516
|
+
});
|
|
517
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
|
|
518
|
+
|
|
519
|
+
await expectPaths({ page, count: 1 });
|
|
520
|
+
|
|
521
|
+
await expectPathDimensions({ page, width: 217, height: 109 });
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
test("mode can set and used to create a sector more than 90 degrees (clockwise)", async ({
|
|
525
|
+
page,
|
|
526
|
+
}) => {
|
|
527
|
+
const mapDiv = await setupMap({ page });
|
|
528
|
+
await changeMode({ page, mode });
|
|
529
|
+
|
|
530
|
+
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
531
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 2, { steps: 30 });
|
|
532
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 2);
|
|
533
|
+
await page.mouse.move(mapDiv.width * 0.75, mapDiv.height / 3, {
|
|
534
|
+
steps: 30,
|
|
535
|
+
});
|
|
536
|
+
await page.mouse.click(mapDiv.width * 0.75, mapDiv.height / 3);
|
|
537
|
+
|
|
538
|
+
await expectPaths({ page, count: 1 });
|
|
539
|
+
|
|
540
|
+
await expectPathDimensions({ page, width: 417, height: 217 });
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
test("mode can set and used to create a sector more than 180 degrees (clockwise)", async ({
|
|
544
|
+
page,
|
|
545
|
+
}) => {
|
|
546
|
+
const mapDiv = await setupMap({ page });
|
|
547
|
+
await changeMode({ page, mode });
|
|
548
|
+
|
|
549
|
+
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
550
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 2, { steps: 30 });
|
|
551
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 2);
|
|
552
|
+
await page.mouse.move(mapDiv.width * 0.75, mapDiv.height / 3, {
|
|
553
|
+
steps: 10,
|
|
554
|
+
});
|
|
555
|
+
await page.mouse.move(mapDiv.width * 0.4, mapDiv.height / 1.5, {
|
|
556
|
+
steps: 10,
|
|
557
|
+
});
|
|
558
|
+
await page.mouse.click(mapDiv.width * 0.4, mapDiv.height / 1.5);
|
|
559
|
+
|
|
560
|
+
await expectPaths({ page, count: 1 });
|
|
561
|
+
|
|
562
|
+
await expectPathDimensions({ page, width: 430, height: 430 });
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
test("mode can set and used to create a sector less than 90 degrees (anticlockwise)", async ({
|
|
566
|
+
page,
|
|
567
|
+
}) => {
|
|
568
|
+
const mapDiv = await setupMap({ page });
|
|
569
|
+
await changeMode({ page, mode });
|
|
570
|
+
|
|
571
|
+
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
572
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 2, { steps: 30 });
|
|
573
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 2);
|
|
574
|
+
await page.mouse.move(mapDiv.width * 0.4, mapDiv.height / 1.5, {
|
|
575
|
+
steps: 30,
|
|
576
|
+
});
|
|
577
|
+
await page.mouse.click(mapDiv.width * 0.4, mapDiv.height / 1.5);
|
|
578
|
+
|
|
579
|
+
await expectPaths({ page, count: 1 });
|
|
580
|
+
|
|
581
|
+
await expectPathDimensions({ page, width: 217, height: 150 });
|
|
582
|
+
});
|
|
583
|
+
|
|
584
|
+
test("mode can set and used to create a sector more than 90 degrees (anticlockwise)", async ({
|
|
585
|
+
page,
|
|
586
|
+
}) => {
|
|
587
|
+
const mapDiv = await setupMap({ page });
|
|
588
|
+
await changeMode({ page, mode });
|
|
589
|
+
|
|
590
|
+
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
591
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 2, { steps: 30 });
|
|
592
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 2);
|
|
593
|
+
await page.mouse.move(mapDiv.width * 0.75, mapDiv.height / 1.5, {
|
|
594
|
+
steps: 30,
|
|
595
|
+
});
|
|
596
|
+
await page.mouse.click(mapDiv.width * 0.75, mapDiv.height / 1.5);
|
|
597
|
+
|
|
598
|
+
await expectPaths({ page, count: 1 });
|
|
599
|
+
|
|
600
|
+
await expectPathDimensions({ page, width: 417, height: 217 });
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
test("mode can set and used to create a sector more than 180 degrees (anticlockwise)", async ({
|
|
604
|
+
page,
|
|
605
|
+
}) => {
|
|
606
|
+
const mapDiv = await setupMap({ page });
|
|
607
|
+
await changeMode({ page, mode });
|
|
608
|
+
|
|
609
|
+
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
610
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 2, { steps: 30 });
|
|
611
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 2);
|
|
612
|
+
await page.mouse.move(mapDiv.width * 0.75, mapDiv.height / 1.5, {
|
|
613
|
+
steps: 30,
|
|
614
|
+
});
|
|
615
|
+
await page.mouse.move(mapDiv.width * 0.75, mapDiv.height / 3, {
|
|
616
|
+
steps: 30,
|
|
617
|
+
});
|
|
618
|
+
await page.mouse.click(mapDiv.width * 0.75, mapDiv.height / 3);
|
|
619
|
+
|
|
620
|
+
await expectPaths({ page, count: 1 });
|
|
621
|
+
|
|
622
|
+
await expectPathDimensions({ page, width: 430, height: 292 });
|
|
623
|
+
});
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
test.describe("sensor mode", () => {
|
|
627
|
+
const mode = "sensor";
|
|
628
|
+
|
|
629
|
+
test("mode can set and creates center point on first click", async ({
|
|
630
|
+
page,
|
|
631
|
+
}) => {
|
|
632
|
+
const mapDiv = await setupMap({ page });
|
|
633
|
+
await changeMode({ page, mode });
|
|
634
|
+
|
|
635
|
+
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
636
|
+
|
|
637
|
+
await expectPaths({ page, count: 1 });
|
|
638
|
+
|
|
639
|
+
await expectPathDimensions({ page, width: 12, height: 12 });
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
test("mode can set and but won't close if the mouse goes behind the initial arc", async ({
|
|
643
|
+
page,
|
|
644
|
+
}) => {
|
|
645
|
+
const mapDiv = await setupMap({ page });
|
|
646
|
+
await changeMode({ page, mode });
|
|
647
|
+
|
|
648
|
+
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
649
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 2, { steps: 30 });
|
|
650
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 2);
|
|
651
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 3, { steps: 30 });
|
|
652
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
|
|
653
|
+
|
|
654
|
+
// The cursor is now behind the initial arc and so wont close the sensor
|
|
655
|
+
await page.mouse.move(mapDiv.width / 1, mapDiv.height / 3, { steps: 30 });
|
|
656
|
+
await page.mouse.click(mapDiv.width / 1, mapDiv.height / 3);
|
|
657
|
+
|
|
658
|
+
// We expect the count to be 2 because the sensor polygon is not finished
|
|
659
|
+
// and we are left with the center point and the arc line
|
|
660
|
+
await expectPaths({ page, count: 2 });
|
|
661
|
+
|
|
662
|
+
await expectPathDimensions({ page, width: 12, height: 12, item: 0 });
|
|
663
|
+
await expectPathDimensions({ page, width: 31, height: 109, item: 1 });
|
|
664
|
+
});
|
|
665
|
+
|
|
666
|
+
test("mode can set and used to create a sensor less than 90 degrees (clockwise)", async ({
|
|
667
|
+
page,
|
|
668
|
+
}) => {
|
|
669
|
+
const mapDiv = await setupMap({ page });
|
|
670
|
+
await changeMode({ page, mode });
|
|
671
|
+
|
|
672
|
+
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
673
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 2, { steps: 30 });
|
|
674
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 2);
|
|
675
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 3, { steps: 30 });
|
|
676
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 3);
|
|
677
|
+
|
|
678
|
+
// Finalise the sensor polygon
|
|
679
|
+
await page.mouse.move(mapDiv.width / 5, mapDiv.height / 3, { steps: 30 });
|
|
680
|
+
await page.mouse.click(mapDiv.width / 5, mapDiv.height / 3);
|
|
681
|
+
|
|
682
|
+
await expectPaths({ page, count: 1 });
|
|
683
|
+
|
|
684
|
+
await expectPathDimensions({ page, width: 220, height: 201 });
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
test("mode can set and used to create a sensor more than 90 degrees (clockwise)", async ({
|
|
688
|
+
page,
|
|
689
|
+
}) => {
|
|
690
|
+
const mapDiv = await setupMap({ page });
|
|
691
|
+
await changeMode({ page, mode });
|
|
692
|
+
|
|
693
|
+
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
694
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 2, { steps: 30 });
|
|
695
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 2);
|
|
696
|
+
await page.mouse.move(mapDiv.width * 0.75, mapDiv.height / 2.5, {
|
|
697
|
+
steps: 30,
|
|
698
|
+
});
|
|
699
|
+
await page.mouse.click(mapDiv.width * 0.75, mapDiv.height / 2.5);
|
|
700
|
+
|
|
701
|
+
// Finalise the sensor polygon
|
|
702
|
+
await page.mouse.move(mapDiv.width * 0.75, mapDiv.height / 5, {
|
|
703
|
+
steps: 30,
|
|
704
|
+
});
|
|
705
|
+
await page.mouse.click(mapDiv.width * 0.75, mapDiv.height / 5);
|
|
706
|
+
|
|
707
|
+
await expectPathDimensions({ page, width: 767, height: 390 });
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
test("mode can set and used to create a sensor more than 180 degrees (clockwise)", async ({
|
|
711
|
+
page,
|
|
712
|
+
}) => {
|
|
713
|
+
const mapDiv = await setupMap({ page });
|
|
714
|
+
await changeMode({ page, mode });
|
|
715
|
+
|
|
716
|
+
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
717
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 2, { steps: 30 });
|
|
718
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 2);
|
|
719
|
+
await page.mouse.move(mapDiv.width * 0.75, mapDiv.height / 3, {
|
|
720
|
+
steps: 10,
|
|
721
|
+
});
|
|
722
|
+
await page.mouse.move(mapDiv.width * 0.4, mapDiv.height / 1.5, {
|
|
723
|
+
steps: 10,
|
|
724
|
+
});
|
|
725
|
+
await page.mouse.click(mapDiv.width * 0.4, mapDiv.height / 1.5);
|
|
726
|
+
|
|
727
|
+
// Finalise the sensor polygon
|
|
728
|
+
await page.mouse.move(mapDiv.width * 0.4, mapDiv.height / 1.25);
|
|
729
|
+
await page.mouse.click(mapDiv.width * 0.4, mapDiv.height / 1.25);
|
|
730
|
+
|
|
731
|
+
await expectPaths({ page, count: 1 });
|
|
732
|
+
|
|
733
|
+
await expectPathDimensions({ page, width: 506, height: 506 });
|
|
734
|
+
});
|
|
735
|
+
|
|
736
|
+
test("mode can set and used to create a sensor less than 90 degrees (anticlockwise)", async ({
|
|
737
|
+
page,
|
|
738
|
+
}) => {
|
|
739
|
+
const mapDiv = await setupMap({ page });
|
|
740
|
+
await changeMode({ page, mode });
|
|
741
|
+
|
|
742
|
+
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
743
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 2, { steps: 30 });
|
|
744
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 2);
|
|
745
|
+
await page.mouse.move(mapDiv.width * 0.4, mapDiv.height / 1.5, {
|
|
746
|
+
steps: 30,
|
|
747
|
+
});
|
|
748
|
+
await page.mouse.click(mapDiv.width * 0.4, mapDiv.height / 1.5);
|
|
749
|
+
|
|
750
|
+
// Finalise the sensor polygon
|
|
751
|
+
await page.mouse.move(mapDiv.width * 0.3, mapDiv.height / 1.25);
|
|
752
|
+
await page.mouse.click(mapDiv.width * 0.3, mapDiv.height / 1.25);
|
|
753
|
+
|
|
754
|
+
await expectPaths({ page, count: 1 });
|
|
755
|
+
|
|
756
|
+
await expectPathDimensions({ page, width: 183, height: 233 });
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
test("mode can set and used to create a sensor more than 90 degrees (anticlockwise)", async ({
|
|
760
|
+
page,
|
|
761
|
+
}) => {
|
|
762
|
+
const mapDiv = await setupMap({ page });
|
|
763
|
+
await changeMode({ page, mode });
|
|
764
|
+
|
|
765
|
+
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
766
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 2, { steps: 30 });
|
|
767
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 2);
|
|
768
|
+
await page.mouse.move(mapDiv.width * 0.75, mapDiv.height / 1.5, {
|
|
769
|
+
steps: 30,
|
|
770
|
+
});
|
|
771
|
+
await page.mouse.click(mapDiv.width * 0.75, mapDiv.height / 1.5);
|
|
772
|
+
|
|
773
|
+
// Finalise the sensor polygon
|
|
774
|
+
await page.mouse.move(mapDiv.width * 0.75, mapDiv.height / 1.3);
|
|
775
|
+
await page.mouse.click(mapDiv.width * 0.75, mapDiv.height / 1.3);
|
|
776
|
+
|
|
777
|
+
await expectPathDimensions({ page, width: 728, height: 378 });
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
test("mode can set and used to create a sensor more than 180 degrees (anticlockwise)", async ({
|
|
781
|
+
page,
|
|
782
|
+
}) => {
|
|
783
|
+
const mapDiv = await setupMap({ page });
|
|
784
|
+
await changeMode({ page, mode });
|
|
785
|
+
|
|
786
|
+
await page.mouse.click(mapDiv.width / 2, mapDiv.height / 2);
|
|
787
|
+
await page.mouse.move(mapDiv.width / 3, mapDiv.height / 2, { steps: 30 });
|
|
788
|
+
await page.mouse.click(mapDiv.width / 3, mapDiv.height / 2);
|
|
789
|
+
await page.mouse.move(mapDiv.width * 0.75, mapDiv.height / 1.5, {
|
|
790
|
+
steps: 30,
|
|
791
|
+
});
|
|
792
|
+
await page.mouse.move(mapDiv.width * 0.75, mapDiv.height / 3, {
|
|
793
|
+
steps: 30,
|
|
794
|
+
});
|
|
795
|
+
await page.mouse.click(mapDiv.width * 0.75, mapDiv.height / 3);
|
|
796
|
+
|
|
797
|
+
// Finalise the sensor polygon
|
|
798
|
+
await page.mouse.move(mapDiv.width * 0.8, mapDiv.height / 3, { steps: 30 });
|
|
799
|
+
await page.mouse.click(mapDiv.width * 0.8, mapDiv.height / 3);
|
|
800
|
+
|
|
801
|
+
await expectPaths({ page, count: 1 });
|
|
802
|
+
|
|
803
|
+
await expectPathDimensions({ page, width: 808, height: 547 });
|
|
804
|
+
});
|
|
805
|
+
});
|
|
806
|
+
|
|
331
807
|
test.describe("circle mode", () => {
|
|
332
808
|
const mode = "circle";
|
|
333
809
|
|
|
334
|
-
test("mode can set and
|
|
810
|
+
test("mode can set and used to create a web mercator circle", async ({
|
|
335
811
|
page,
|
|
336
812
|
}) => {
|
|
337
813
|
const mapDiv = await setupMap({ page });
|
|
@@ -346,7 +822,7 @@ test.describe("circle mode", () => {
|
|
|
346
822
|
await expectPathDimensions({ page, width: 146, height: 146 });
|
|
347
823
|
});
|
|
348
824
|
|
|
349
|
-
test("mode can set and
|
|
825
|
+
test("mode can set and used to create a geodesic circle", async ({
|
|
350
826
|
page,
|
|
351
827
|
}) => {
|
|
352
828
|
const mapDiv = await setupMap({ page, configQueryParam: ["globeCircle"] });
|
package/e2e/tests/setup.ts
CHANGED
|
@@ -8,7 +8,8 @@ export type TestConfigOptions =
|
|
|
8
8
|
| "insertCoordinates"
|
|
9
9
|
| "insertCoordinatesGlobe"
|
|
10
10
|
| "globeCircle"
|
|
11
|
-
| "globeSelect"
|
|
11
|
+
| "globeSelect"
|
|
12
|
+
| "snappingCoordinate";
|
|
12
13
|
|
|
13
14
|
export const setupMap = async ({
|
|
14
15
|
page,
|
|
@@ -53,9 +54,28 @@ export const changeMode = async ({
|
|
|
53
54
|
mode,
|
|
54
55
|
}: {
|
|
55
56
|
page: Page;
|
|
56
|
-
mode:
|
|
57
|
+
mode:
|
|
58
|
+
| "point"
|
|
59
|
+
| "polygon"
|
|
60
|
+
| "linestring"
|
|
61
|
+
| "select"
|
|
62
|
+
| "rectangle"
|
|
63
|
+
| "circle"
|
|
64
|
+
| "angled-rectangle"
|
|
65
|
+
| "sector"
|
|
66
|
+
| "sensor";
|
|
57
67
|
}) => {
|
|
58
|
-
|
|
68
|
+
let modeText = mode.charAt(0).toUpperCase() + mode.slice(1);
|
|
69
|
+
|
|
70
|
+
if (mode.includes("-")) {
|
|
71
|
+
modeText = mode
|
|
72
|
+
.split("-")
|
|
73
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
74
|
+
.join(" ");
|
|
75
|
+
} else {
|
|
76
|
+
modeText = mode.charAt(0).toUpperCase() + mode.slice(1);
|
|
77
|
+
}
|
|
78
|
+
|
|
59
79
|
const buttons = page.getByTestId("buttons");
|
|
60
80
|
const button = buttons.getByText(modeText, { exact: true });
|
|
61
81
|
|
|
@@ -66,7 +86,10 @@ export const changeMode = async ({
|
|
|
66
86
|
const color = await button.evaluate((el) =>
|
|
67
87
|
window.getComputedStyle(el).getPropertyValue("color"),
|
|
68
88
|
);
|
|
69
|
-
expect(
|
|
89
|
+
expect(
|
|
90
|
+
color,
|
|
91
|
+
"Text rgb color should match the expected selected button color",
|
|
92
|
+
).toBe("rgb(39, 204, 255)"); // We set hex but it gets computed to rgb
|
|
70
93
|
};
|
|
71
94
|
|
|
72
95
|
export const expectPaths = async ({
|
|
@@ -82,7 +105,10 @@ export const expectPaths = async ({
|
|
|
82
105
|
await page.waitForSelector(selector);
|
|
83
106
|
expect(await page.locator(selector).count()).toBe(count);
|
|
84
107
|
} else {
|
|
85
|
-
await expect(
|
|
108
|
+
await expect(
|
|
109
|
+
await page.locator(selector).count(),
|
|
110
|
+
`locator count should be greater than 0 for selector ${selector}`,
|
|
111
|
+
).toBe(0);
|
|
86
112
|
}
|
|
87
113
|
};
|
|
88
114
|
|
|
@@ -90,14 +116,16 @@ export const expectPathDimensions = async ({
|
|
|
90
116
|
page,
|
|
91
117
|
width,
|
|
92
118
|
height,
|
|
119
|
+
item = 0,
|
|
93
120
|
}: {
|
|
94
121
|
page: Page;
|
|
95
122
|
width: number;
|
|
96
123
|
height: number;
|
|
124
|
+
item?: number;
|
|
97
125
|
}) => {
|
|
98
126
|
const selector = "svg > g > path";
|
|
99
127
|
|
|
100
|
-
const boundingBox = await page.locator(selector).boundingBox();
|
|
128
|
+
const boundingBox = await page.locator(selector).nth(item).boundingBox();
|
|
101
129
|
|
|
102
130
|
expect(boundingBox?.width).toBe(width);
|
|
103
131
|
expect(boundingBox?.height).toBe(height);
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import typescriptEslint from "@typescript-eslint/eslint-plugin";
|
|
2
|
+
import tsParser from "@typescript-eslint/parser";
|
|
3
|
+
import eslintPluginPrettier from "eslint-plugin-prettier";
|
|
4
|
+
import prettierConfig from "eslint-config-prettier";
|
|
5
|
+
|
|
6
|
+
export default [
|
|
7
|
+
{
|
|
8
|
+
name: "prettier", // Configuration name
|
|
9
|
+
files: ["**/*.{js,jsx,ts,tsx,json,md,yml,yaml,html,css}"],
|
|
10
|
+
plugins: {
|
|
11
|
+
prettier: eslintPluginPrettier, // Include Prettier plugin
|
|
12
|
+
},
|
|
13
|
+
rules: {
|
|
14
|
+
...prettierConfig.rules, // Disable ESLint rules that conflict with Prettier
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: "typescript", // Configuration name
|
|
19
|
+
files: ["**/*.ts"], // TypeScript-specific configuration
|
|
20
|
+
plugins: {
|
|
21
|
+
"@typescript-eslint": typescriptEslint, // Include TypeScript ESLint plugin
|
|
22
|
+
},
|
|
23
|
+
languageOptions: {
|
|
24
|
+
parser: tsParser,
|
|
25
|
+
},
|
|
26
|
+
rules: {
|
|
27
|
+
"@typescript-eslint/no-empty-function": "warn",
|
|
28
|
+
"@typescript-eslint/no-explicit-any": "warn",
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
];
|