alessandro trinca tornidor commited on
Commit Β·
9fa8a0e
1
Parent(s): 4b31a4d
test: increase the test coverage after checking the "mutant" ones with stryker
Browse files- static/src/components/helpers.ts +2 -2
- static/tests/helpers.test.ts +245 -0
static/src/components/helpers.ts
CHANGED
|
@@ -104,7 +104,7 @@ const getUpdatedRectangle = (obj: IRectanglePrompt): IRectangleTable => {
|
|
| 104 |
}
|
| 105 |
|
| 106 |
/** get a custom icon given a PNG path with its anchor/size values */
|
| 107 |
-
const getCustomIconMarker = (
|
| 108 |
iconUrlNoExt: string,
|
| 109 |
shadowUrl = '/marker-shadow.png',
|
| 110 |
iconSize: ArrayNumber = [25, 41],
|
|
@@ -126,7 +126,7 @@ const getCustomIconMarker = (
|
|
| 126 |
}
|
| 127 |
|
| 128 |
/** get an the leaflet editor geoman.io toolbar with the custom actions to draw/edit/move point and rectangle layers */
|
| 129 |
-
const getCustomGeomanActionsObject = (
|
| 130 |
actionName: string, descriptionAction: string, arrayActions: Array<object>, customClassName: string
|
| 131 |
) => {
|
| 132 |
return {
|
|
|
|
| 104 |
}
|
| 105 |
|
| 106 |
/** get a custom icon given a PNG path with its anchor/size values */
|
| 107 |
+
export const getCustomIconMarker = (
|
| 108 |
iconUrlNoExt: string,
|
| 109 |
shadowUrl = '/marker-shadow.png',
|
| 110 |
iconSize: ArrayNumber = [25, 41],
|
|
|
|
| 126 |
}
|
| 127 |
|
| 128 |
/** get an the leaflet editor geoman.io toolbar with the custom actions to draw/edit/move point and rectangle layers */
|
| 129 |
+
export const getCustomGeomanActionsObject = (
|
| 130 |
actionName: string, descriptionAction: string, arrayActions: Array<object>, customClassName: string
|
| 131 |
) => {
|
| 132 |
return {
|
static/tests/helpers.test.ts
CHANGED
|
@@ -13,6 +13,9 @@ import {
|
|
| 13 |
getQueryParams,
|
| 14 |
getGeoJSONRequest,
|
| 15 |
getPopupContentPoint,
|
|
|
|
|
|
|
|
|
|
| 16 |
} from '@/components/helpers'
|
| 17 |
import {
|
| 18 |
currentMapBBoxRef,
|
|
@@ -590,3 +593,245 @@ describe('getPopupContentPoint', () => {
|
|
| 590 |
expect(result.textContent).toContain('lng:9.987654321')
|
| 591 |
})
|
| 592 |
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
getQueryParams,
|
| 14 |
getGeoJSONRequest,
|
| 15 |
getPopupContentPoint,
|
| 16 |
+
getCustomIconMarker,
|
| 17 |
+
getCustomGeomanActionsObject,
|
| 18 |
+
setGeomanControls,
|
| 19 |
} from '@/components/helpers'
|
| 20 |
import {
|
| 21 |
currentMapBBoxRef,
|
|
|
|
| 593 |
expect(result.textContent).toContain('lng:9.987654321')
|
| 594 |
})
|
| 595 |
})
|
| 596 |
+
|
| 597 |
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 598 |
+
// getCustomIconMarker
|
| 599 |
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 600 |
+
describe('getCustomIconMarker', () => {
|
| 601 |
+
/**
|
| 602 |
+
* Wraps Leaflet's `icon()` factory. Returns an Icon instance
|
| 603 |
+
* whose `options` reflect the passed (or default) parameters.
|
| 604 |
+
* We assert on `options` to verify args are forwarded correctly.
|
| 605 |
+
*/
|
| 606 |
+
|
| 607 |
+
it('builds iconUrl and iconRetinaUrl from base path', () => {
|
| 608 |
+
const result = getCustomIconMarker('/marker-icon-include')
|
| 609 |
+
expect(result.options.iconUrl).toBe('/marker-icon-include.png')
|
| 610 |
+
expect(result.options.iconRetinaUrl).toBe('/marker-icon-include-2x.png')
|
| 611 |
+
})
|
| 612 |
+
|
| 613 |
+
it('uses default shadowUrl when not provided', () => {
|
| 614 |
+
const result = getCustomIconMarker('/test')
|
| 615 |
+
expect(result.options.shadowUrl).toBe('/marker-shadow.png')
|
| 616 |
+
})
|
| 617 |
+
|
| 618 |
+
it('uses default iconSize [25, 41]', () => {
|
| 619 |
+
const result = getCustomIconMarker('/test')
|
| 620 |
+
expect(result.options.iconSize).toEqual([25, 41])
|
| 621 |
+
})
|
| 622 |
+
|
| 623 |
+
it('uses default iconAnchor [12, 41]', () => {
|
| 624 |
+
const result = getCustomIconMarker('/test')
|
| 625 |
+
expect(result.options.iconAnchor).toEqual([12, 41])
|
| 626 |
+
})
|
| 627 |
+
|
| 628 |
+
it('uses default popupAnchor [1, -34]', () => {
|
| 629 |
+
const result = getCustomIconMarker('/test')
|
| 630 |
+
expect(result.options.popupAnchor).toEqual([1, -34])
|
| 631 |
+
})
|
| 632 |
+
|
| 633 |
+
it('uses default tooltipAnchor [5, -25]', () => {
|
| 634 |
+
const result = getCustomIconMarker('/test')
|
| 635 |
+
expect(result.options.tooltipAnchor).toEqual([5, -25])
|
| 636 |
+
})
|
| 637 |
+
|
| 638 |
+
it('uses default shadowSize [41, 41]', () => {
|
| 639 |
+
const result = getCustomIconMarker('/test')
|
| 640 |
+
expect(result.options.shadowSize).toEqual([41, 41])
|
| 641 |
+
})
|
| 642 |
+
|
| 643 |
+
it('overrides shadowUrl when provided', () => {
|
| 644 |
+
const result = getCustomIconMarker('/test', '/custom-shadow.png')
|
| 645 |
+
expect(result.options.shadowUrl).toBe('/custom-shadow.png')
|
| 646 |
+
})
|
| 647 |
+
|
| 648 |
+
it('overrides iconSize when provided', () => {
|
| 649 |
+
const result = getCustomIconMarker('/test', undefined, [32, 32])
|
| 650 |
+
expect(result.options.iconSize).toEqual([32, 32])
|
| 651 |
+
})
|
| 652 |
+
|
| 653 |
+
it('overrides all params when provided', () => {
|
| 654 |
+
const result = getCustomIconMarker(
|
| 655 |
+
'/custom',
|
| 656 |
+
'/shadow.png',
|
| 657 |
+
[10, 20],
|
| 658 |
+
[5, 10],
|
| 659 |
+
[0, -10],
|
| 660 |
+
[3, -15],
|
| 661 |
+
[20, 20]
|
| 662 |
+
)
|
| 663 |
+
expect(result.options.iconUrl).toBe('/custom.png')
|
| 664 |
+
expect(result.options.iconRetinaUrl).toBe('/custom-2x.png')
|
| 665 |
+
expect(result.options.shadowUrl).toBe('/shadow.png')
|
| 666 |
+
expect(result.options.iconSize).toEqual([10, 20])
|
| 667 |
+
expect(result.options.iconAnchor).toEqual([5, 10])
|
| 668 |
+
expect(result.options.popupAnchor).toEqual([0, -10])
|
| 669 |
+
expect(result.options.tooltipAnchor).toEqual([3, -15])
|
| 670 |
+
expect(result.options.shadowSize).toEqual([20, 20])
|
| 671 |
+
})
|
| 672 |
+
})
|
| 673 |
+
|
| 674 |
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 675 |
+
// getCustomGeomanActionsObject
|
| 676 |
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 677 |
+
describe('getCustomGeomanActionsObject', () => {
|
| 678 |
+
/**
|
| 679 |
+
* Builds a Geoman custom control descriptor object.
|
| 680 |
+
* Pure function β returns { name, block, className, title, actions }.
|
| 681 |
+
*/
|
| 682 |
+
|
| 683 |
+
const actions = [{ onClick: () => {}, name: 'testAction' }]
|
| 684 |
+
|
| 685 |
+
it('returns object with correct name', () => {
|
| 686 |
+
const result = getCustomGeomanActionsObject('MyControl', 'desc', actions, 'my-class')
|
| 687 |
+
expect(result.name).toBe('MyControl')
|
| 688 |
+
})
|
| 689 |
+
|
| 690 |
+
it('sets block to "custom"', () => {
|
| 691 |
+
const result = getCustomGeomanActionsObject('MyControl', 'desc', actions, 'my-class')
|
| 692 |
+
expect(result.block).toBe('custom')
|
| 693 |
+
})
|
| 694 |
+
|
| 695 |
+
it('sets className from parameter', () => {
|
| 696 |
+
const result = getCustomGeomanActionsObject('MyControl', 'desc', actions, 'my-class')
|
| 697 |
+
expect(result.className).toBe('my-class')
|
| 698 |
+
})
|
| 699 |
+
|
| 700 |
+
it('sets title from descriptionAction parameter', () => {
|
| 701 |
+
const result = getCustomGeomanActionsObject('MyControl', 'My description', actions, 'my-class')
|
| 702 |
+
expect(result.title).toBe('My description')
|
| 703 |
+
})
|
| 704 |
+
|
| 705 |
+
it('passes actions array through', () => {
|
| 706 |
+
const result = getCustomGeomanActionsObject('MyControl', 'desc', actions, 'my-class')
|
| 707 |
+
expect(result.actions).toBe(actions)
|
| 708 |
+
})
|
| 709 |
+
})
|
| 710 |
+
|
| 711 |
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 712 |
+
// setGeomanControls
|
| 713 |
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 714 |
+
describe('setGeomanControls', () => {
|
| 715 |
+
/**
|
| 716 |
+
* Sets up Geoman drawing controls on a Leaflet map.
|
| 717 |
+
* We mock the map.pm API chain and verify all calls with exact args.
|
| 718 |
+
* The mock for copyDrawControl returns { drawInstance: { setOptions } }
|
| 719 |
+
* to match the fluent API used by the function.
|
| 720 |
+
*/
|
| 721 |
+
|
| 722 |
+
const makeSetOptions = () => vi.fn()
|
| 723 |
+
|
| 724 |
+
const makeMockMap = () => {
|
| 725 |
+
const includeSetOptions = makeSetOptions()
|
| 726 |
+
const excludeSetOptions = makeSetOptions()
|
| 727 |
+
let copyDrawCallCount = 0
|
| 728 |
+
|
| 729 |
+
return {
|
| 730 |
+
map: {
|
| 731 |
+
pm: {
|
| 732 |
+
addControls: vi.fn(),
|
| 733 |
+
setPathOptions: vi.fn(),
|
| 734 |
+
Toolbar: {
|
| 735 |
+
copyDrawControl: vi.fn((_type: string, _opts: object) => {
|
| 736 |
+
copyDrawCallCount++
|
| 737 |
+
// First two calls are Marker (include, exclude), third is Rectangle
|
| 738 |
+
if (copyDrawCallCount === 1) {
|
| 739 |
+
return { drawInstance: { setOptions: includeSetOptions } }
|
| 740 |
+
}
|
| 741 |
+
if (copyDrawCallCount === 2) {
|
| 742 |
+
return { drawInstance: { setOptions: excludeSetOptions } }
|
| 743 |
+
}
|
| 744 |
+
return { drawInstance: { setOptions: vi.fn() } }
|
| 745 |
+
}),
|
| 746 |
+
},
|
| 747 |
+
},
|
| 748 |
+
},
|
| 749 |
+
includeSetOptions,
|
| 750 |
+
excludeSetOptions,
|
| 751 |
+
}
|
| 752 |
+
}
|
| 753 |
+
|
| 754 |
+
it('calls pm.addControls with correct options', () => {
|
| 755 |
+
const { map } = makeMockMap()
|
| 756 |
+
setGeomanControls(map as any)
|
| 757 |
+
expect(map.pm.addControls).toHaveBeenCalledWith({
|
| 758 |
+
position: 'topleft',
|
| 759 |
+
drawControls: false,
|
| 760 |
+
rotateMode: false,
|
| 761 |
+
cutPolygon: false,
|
| 762 |
+
customControls: true,
|
| 763 |
+
})
|
| 764 |
+
})
|
| 765 |
+
|
| 766 |
+
it('calls copyDrawControl three times', () => {
|
| 767 |
+
const { map } = makeMockMap()
|
| 768 |
+
setGeomanControls(map as any)
|
| 769 |
+
expect(map.pm.Toolbar.copyDrawControl).toHaveBeenCalledTimes(3)
|
| 770 |
+
})
|
| 771 |
+
|
| 772 |
+
it('first copyDrawControl creates IncludeMarkerPrompt from Marker', () => {
|
| 773 |
+
const { map } = makeMockMap()
|
| 774 |
+
setGeomanControls(map as any)
|
| 775 |
+
const firstCall = map.pm.Toolbar.copyDrawControl.mock.calls[0]
|
| 776 |
+
expect(firstCall[0]).toBe('Marker')
|
| 777 |
+
expect(firstCall[1].name).toBe('IncludeMarkerPrompt')
|
| 778 |
+
expect(firstCall[1].block).toBe('custom')
|
| 779 |
+
expect(firstCall[1].title).toBe('Marker point that add recognition regions from SAM prompt requests')
|
| 780 |
+
expect(firstCall[1].className).toBe('control-icon leaflet-pm-icon-marker-include')
|
| 781 |
+
})
|
| 782 |
+
|
| 783 |
+
it('second copyDrawControl creates ExcludeMarkerPrompt from Marker', () => {
|
| 784 |
+
const { map } = makeMockMap()
|
| 785 |
+
setGeomanControls(map as any)
|
| 786 |
+
const secondCall = map.pm.Toolbar.copyDrawControl.mock.calls[1]
|
| 787 |
+
expect(secondCall[0]).toBe('Marker')
|
| 788 |
+
expect(secondCall[1].name).toBe('ExcludeMarkerPrompt')
|
| 789 |
+
expect(secondCall[1].block).toBe('custom')
|
| 790 |
+
expect(secondCall[1].title).toBe('Marker point that remove recognition regions from SAM prompt requests')
|
| 791 |
+
expect(secondCall[1].className).toBe('control-icon leaflet-pm-icon-marker-exclude')
|
| 792 |
+
})
|
| 793 |
+
|
| 794 |
+
it('third copyDrawControl creates RectanglePrompt from Rectangle', () => {
|
| 795 |
+
const { map } = makeMockMap()
|
| 796 |
+
setGeomanControls(map as any)
|
| 797 |
+
const thirdCall = map.pm.Toolbar.copyDrawControl.mock.calls[2]
|
| 798 |
+
expect(thirdCall[0]).toBe('Rectangle')
|
| 799 |
+
expect(thirdCall[1].name).toBe('RectanglePrompt')
|
| 800 |
+
expect(thirdCall[1].block).toBe('custom')
|
| 801 |
+
expect(thirdCall[1].title).toBe('Rectangular recognition regions for SAM prompt requests')
|
| 802 |
+
})
|
| 803 |
+
|
| 804 |
+
it('sets include marker icon via drawInstance.setOptions', () => {
|
| 805 |
+
const { map, includeSetOptions } = makeMockMap()
|
| 806 |
+
setGeomanControls(map as any)
|
| 807 |
+
expect(includeSetOptions).toHaveBeenCalledTimes(1)
|
| 808 |
+
const opts = includeSetOptions.mock.calls[0][0]
|
| 809 |
+
expect(opts.markerStyle.icon.options.iconUrl).toBe('/marker-icon-include.png')
|
| 810 |
+
})
|
| 811 |
+
|
| 812 |
+
it('sets exclude marker icon via drawInstance.setOptions', () => {
|
| 813 |
+
const { map, excludeSetOptions } = makeMockMap()
|
| 814 |
+
setGeomanControls(map as any)
|
| 815 |
+
expect(excludeSetOptions).toHaveBeenCalledTimes(1)
|
| 816 |
+
const opts = excludeSetOptions.mock.calls[0][0]
|
| 817 |
+
expect(opts.markerStyle.icon.options.iconUrl).toBe('/marker-icon-exclude.png')
|
| 818 |
+
})
|
| 819 |
+
|
| 820 |
+
it('calls pm.setPathOptions with green color and fillOpacity 0.15', () => {
|
| 821 |
+
const { map } = makeMockMap()
|
| 822 |
+
setGeomanControls(map as any)
|
| 823 |
+
expect(map.pm.setPathOptions).toHaveBeenCalledWith({
|
| 824 |
+
color: 'green',
|
| 825 |
+
fillColor: 'green',
|
| 826 |
+
fillOpacity: 0.15,
|
| 827 |
+
})
|
| 828 |
+
})
|
| 829 |
+
|
| 830 |
+
it('actionArray items have name "actionName"', () => {
|
| 831 |
+
const { map } = makeMockMap()
|
| 832 |
+
setGeomanControls(map as any)
|
| 833 |
+
const firstCall = map.pm.Toolbar.copyDrawControl.mock.calls[0]
|
| 834 |
+
expect(firstCall[1].actions).toHaveLength(1)
|
| 835 |
+
expect(firstCall[1].actions[0].name).toBe('actionName')
|
| 836 |
+
})
|
| 837 |
+
})
|