Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion jest.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ module.exports = {
},
collectCoverageFrom: [
'src/**/*.{ts,tsx}',
'!src/**/*example*.*'
'!src/**/*example*.*',
'!src/**/*.d.ts',
'!src/index.ts',
'!src/Context/MapContext/MapContext.tsx', // only a placeholder
'!src/Hook/useDropTargetMap.ts', // only a placeholder
'!src/Hook/useMap.ts' // only a placeholder
],
coverageDirectory: '<rootDir>/coverage',
testEnvironment: 'jsdom',
Expand Down
76 changes: 40 additions & 36 deletions src/BackgroundLayerChooser/BackgroundLayerChooser.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import OlLayerGroup from 'ol/layer/Group';
import OlSourceImageWMS from 'ol/source/ImageWMS';

import React from 'react';
import { render, fireEvent, screen, waitFor } from '@testing-library/react';
import { render, fireEvent, screen, waitFor, act, cleanup } from '@testing-library/react';

import { renderInMapContext } from '@terrestris/react-util/dist/Util/rtlTestUtils';
import TestUtil from '../Util/TestUtil';
import BackgroundLayerChooser from './BackgroundLayerChooser';

Expand All @@ -19,10 +20,10 @@ describe('BackgroundLayerChooser', () => {
beforeEach(() => {
layers = [
new OlLayerTile({
source: new OlSourceOsm()
source: new OlSourceOsm()
}),
new OlLayerTile({
source: new OlSourceOsm()
source: new OlSourceOsm()
})
];
layers[0].set('name', 'Layer 1');
Expand All @@ -33,54 +34,35 @@ describe('BackgroundLayerChooser', () => {
});

afterEach(() => {
cleanup();
map?.dispose();
layers = [];
});

it('renders button and preview', () => {
const { container } = render(<BackgroundLayerChooser layers={layers as any} />);
expect(container.querySelector('.bg-layer-chooser')).toBeInTheDocument();
expect(container.querySelector('.bg-preview')).toBeInTheDocument();
expect(container.querySelector('#overview-map')).toBeInTheDocument();
});

it('shows layer options when button is clicked', () => {
const { container } = render(<BackgroundLayerChooser layers={layers as any} />);
fireEvent.click(container.querySelector('.bg-layer-chooser') as HTMLElement);
waitFor(() => {
expect(container.querySelectorAll('.bg-preview').length).toBe(2);
it('selects a layer and updates preview', async () => {
const { container } = renderInMapContext(map, <BackgroundLayerChooser layers={layers as any} />);
const btn = container.querySelector('.change-bg-btn');
await act(async () => {
btn && fireEvent.click(btn);
});
});

it('selects a layer and updates preview', () => {
const { container } = render(<BackgroundLayerChooser layers={layers as any} />);
fireEvent.click(container.querySelector('.bg-layer-chooser') as HTMLElement);
waitFor(() => {
expect(container.querySelectorAll('.bg-preview').length).toBe(2);
fireEvent.click(container.querySelectorAll('.bg-preview')[1]);
});
waitFor(() => {
expect(screen.getByText('Layer 1')).toBeInTheDocument();
expect(screen.getByText('Layer 2')).toBeInTheDocument();
const previews = await waitFor(() => container.querySelectorAll('.bg-preview'));
await waitFor(() => {
expect(previews.length).toBeGreaterThan(0);
});
});

it('renders no background button if allowEmptyBackground is true', () => {
const { container } = render(<BackgroundLayerChooser layers={layers as any} allowEmptyBackground />);
fireEvent.click(container.querySelector('.bg-layer-chooser') as HTMLElement);
waitFor(() => {
expect(screen.getByText('No Background')).toBeInTheDocument();
await act(async () => {
previews[0] && fireEvent.click(previews[0]);
});
});

it('selects no background and updates preview', () => {
const { container } = render(<BackgroundLayerChooser layers={layers as any} allowEmptyBackground />);
fireEvent.click(container.querySelector('.bg-layer-chooser') as HTMLElement);
waitFor(() => {
const noBgButtons = screen.getAllByText('No Background');
fireEvent.click(noBgButtons[1]);
});
waitFor(() => {
expect(screen.getAllByText('No Background').length).toBeGreaterThan(0);
await waitFor(() => {
expect(container.querySelector('.bg-preview .layer-title')?.textContent).toBe('Layer 1');
});
});

Expand Down Expand Up @@ -142,4 +124,26 @@ describe('BackgroundLayerChooser', () => {
expect(screen.getAllByText('No Background').length).toBeGreaterThan(0);
});
});

it('filters layers using backgroundLayerFilter', async () => {
const filter = (l: any) => l.get('name') === 'Layer 2';
const { container } = renderInMapContext(
map,
<BackgroundLayerChooser
layers={layers}
allowEmptyBackground={false}
backgroundLayerFilter={filter}
/>
);
const btn = container.querySelector('.change-bg-btn');
await act(async () => {
btn && fireEvent.click(btn);
});
await waitFor(() => {
const previews = container.querySelectorAll('.layer-preview');
expect(previews.length).toBe(1);
const title = (previews[0] as Element).querySelector('.layer-title')?.textContent;
expect(title).toBe('Layer 2');
});
});
});
9 changes: 5 additions & 4 deletions src/BackgroundLayerChooser/BackgroundLayerChooser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,10 @@ export const BackgroundLayerChooser: React.FC<BackgroundLayerChooserProps> = ({
}, [map, layerOptionsVisible]);

useEffect(() => {
const activeLayerCand = layers.find(l => l.getVisible());

if (!initiallySelectedLayer) {
if (initiallySelectedLayer) {
setSelectedLayer(initiallySelectedLayer);
} else {
const activeLayerCand = layers.find(l => l.getVisible());
setSelectedLayer(activeLayerCand as OlLayer);
}
}, [initiallySelectedLayer, layers]);
Expand Down Expand Up @@ -227,7 +228,7 @@ export const BackgroundLayerChooser: React.FC<BackgroundLayerChooserProps> = ({
layerOptionsVisible && (
<div className="layer-cards">
{
layers.map(layer => (
layers.filter(backgroundLayerFilter).map(layer => (
<BackgroundLayerPreview
key={getUid(layer)}
activeLayer={selectedLayer}
Expand Down
70 changes: 70 additions & 0 deletions src/BackgroundLayerPreview/BackgroundLayerPreview.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import React from 'react';
import { render, fireEvent, screen, waitFor } from '@testing-library/react';
import OlLayerTile from 'ol/layer/Tile';
import OlLayerImage from 'ol/layer/Image';
import OlLayerGroup from 'ol/layer/Group';
import OlSourceOsm from 'ol/source/OSM';
import OlMap from 'ol/Map';
import ImageStatic from 'ol/source/ImageStatic';

import TestUtil from '../Util/TestUtil';
import BackgroundLayerPreview from './BackgroundLayerPreview';
Expand All @@ -28,6 +31,7 @@ describe('BackgroundLayerPreview', () => {
);
expect(screen.getByText('Test Layer')).toBeInTheDocument();
expect(container.querySelector('.map')).toBeInTheDocument();
expect(container.querySelector('.layer-preview')).toBeInTheDocument();
});

it('calls onClick when clicked', () => {
Expand Down Expand Up @@ -62,6 +66,19 @@ describe('BackgroundLayerPreview', () => {
});
});

it('renders the title from layer name', () => {
const onClick = jest.fn();
const backgroundLayerFilter = () => true;
const { getByText } = render(
<BackgroundLayerPreview
layer={layer}
onClick={onClick}
backgroundLayerFilter={backgroundLayerFilter}
/>
);
expect(getByText('Test Layer')).toBeInTheDocument();
});

it('renders custom title if titleRenderer is provided', () => {
render(
<BackgroundLayerPreview
Expand Down Expand Up @@ -99,4 +116,57 @@ describe('BackgroundLayerPreview', () => {
const mapDiv = container.querySelector('.map');
expect(mapDiv).toHaveStyle({ width: '200px', height: '150px' });
});

it('renders with an Image layer', () => {
// Use a minimal valid Image source for OlLayerImage
const layer = new OlLayerImage({
source: new ImageStatic({
url: '',
imageExtent: [0, 0, 1, 1],
projection: 'EPSG:3857'
})
});
layer.set('name', 'ImageLayer');
const onClick = jest.fn();
const backgroundLayerFilter = () => true;
const { getByText } = render(
<BackgroundLayerPreview
layer={layer as any}
onClick={onClick}
backgroundLayerFilter={backgroundLayerFilter}
/>
);
expect(getByText('ImageLayer')).toBeInTheDocument();
});

it('handles backgroundLayerFilter returning false', () => {
layer = new OlLayerTile({ source: new OlSourceOsm() });
layer.set('name', 'FilteredOut');
const onClick = jest.fn();
const backgroundLayerFilter = () => false;
const { getByText } = render(
<BackgroundLayerPreview
layer={layer as any}
onClick={onClick}
backgroundLayerFilter={backgroundLayerFilter}
/>
);
expect(getByText('FilteredOut')).toBeInTheDocument();
});

it('handles a layer that is not Tile or Image', () => {
// Use a LayerGroup as a non-Tile/Image layer
const group = new OlLayerGroup();
group.set('name', 'GroupLayer');
const onClick = jest.fn();
const backgroundLayerFilter = () => true;
const { getByText } = render(
<BackgroundLayerPreview
layer={group as any}
onClick={onClick}
backgroundLayerFilter={backgroundLayerFilter}
/>
);
expect(getByText('GroupLayer')).toBeInTheDocument();
});
});
1 change: 1 addition & 0 deletions src/FeatureLabelModal/FeatureLabelModal.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ describe('<CopyButton />', () => {
onCancel={onCancel}
/>
);
expect(screen.getByRole('dialog')).toBeInTheDocument();
expect(screen.getByText('Test label')).toBeInTheDocument();
});

Expand Down
13 changes: 11 additions & 2 deletions src/Field/SearchField/SearchField.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import OlFeature from 'ol/Feature';
import OlPoint from 'ol/geom/Point';
import OlMap from 'ol/Map';
import OlView from 'ol/View';
import { render, fireEvent, waitFor } from '@testing-library/react';
import { render, fireEvent, waitFor, screen } from '@testing-library/react';

import { SearchField, SearchProps } from './SearchField';

describe('<CopyButton />', () => {
const coord = [829729, 6708850];
const coord = [1, 2];
let map: OlMap;
let feature: OlFeature<OlPoint>;

Expand Down Expand Up @@ -82,4 +82,13 @@ describe('<CopyButton />', () => {
expect(mockProps.onSearchCompleted).toHaveBeenCalledWith(searchCollection);
});
});

it('disables autocomplete popup if autoCompleteDisabled is true', async () => {
render(<SearchField searchFunction={jest.fn()} autoCompleteDisabled={true} />);
const input = screen.getByRole('combobox');
fireEvent.change(input, { target: { value: 'A' } });
// Wait a bit to ensure popup would have rendered if enabled
await new Promise(res => setTimeout(res, 300));
expect(screen.queryByText('A')).not.toBeInTheDocument();
});
});