diff --git a/components/StandardApp.jsx b/components/StandardApp.jsx
index 5f773882a..a8ae3f561 100644
--- a/components/StandardApp.jsx
+++ b/components/StandardApp.jsx
@@ -130,7 +130,8 @@ class AppInitComponent extends React.Component {
initialView = {
center: coords,
zoom: zoom,
- crs: params.crs || theme.mapCrs};
+ crs: params.crs || theme.mapCrs
+ };
}
} else if (params.e) {
const bounds = params.e.split(/[;,]/g).map(x => parseFloat(x));
@@ -223,6 +224,10 @@ export default class StandardApp extends React.Component {
);
}
setupTouchEvents = (el) => {
+ if (el === null) {
+ // Do nothing when unmounting
+ return;
+ }
el.addEventListener('touchstart', ev => {
this.touchY = ev.targetTouches[0].clientY;
}, { passive: false });
diff --git a/tests/components/CoordinateDisplayer.test.jsx b/tests/components/CoordinateDisplayer.test.jsx
new file mode 100644
index 000000000..63d7746e7
--- /dev/null
+++ b/tests/components/CoordinateDisplayer.test.jsx
@@ -0,0 +1,24 @@
+import React from 'react';
+import {Provider} from "react-redux";
+
+import {render, screen} from '@testing-library/react';
+import configureStore from 'redux-mock-store';
+
+import CoordinateDisplayer from '../../components/CoordinateDisplayer';
+
+const mockStore = configureStore();
+
+test('current coordinates are shown', () => {
+ const store = mockStore({
+ map: { projection: 'EPSG:4326' },
+ mousePosition: { position: { coordinate: [123, 456] } }
+ });
+
+ render(
+
+
+
+ );
+
+ expect(screen.getByRole('textbox')).toHaveValue('123.0000 456.0000');
+});
diff --git a/tests/components/SearchBox.test.jsx b/tests/components/SearchBox.test.jsx
new file mode 100644
index 000000000..f67665b3e
--- /dev/null
+++ b/tests/components/SearchBox.test.jsx
@@ -0,0 +1,76 @@
+import React from 'react';
+import {Provider} from "react-redux";
+
+import {act, fireEvent, render, screen} from '@testing-library/react';
+import configureStore from 'redux-mock-store';
+
+import SearchBox from '../../components/SearchBox';
+
+const mockStore = configureStore();
+
+const searchProviders = {
+ testing: {
+ onSearch: (text, searchParams, callback) => callback({
+ results: [
+ {
+ id: 'layer1',
+ title: 'Layer 1',
+ items: [
+ {
+ id: 'item1',
+ text: 'Item 1'
+ },
+ {
+ id: 'item2',
+ text: 'Item 2'
+ }
+ ]
+ },
+ {
+ id: 'layer2',
+ title: 'Layer 2',
+ items: [
+ {
+ id: 'item3',
+ text: 'Item 3'
+ }
+ ]
+ }
+ ]
+ })
+ }
+};
+
+// eslint-disable-next-line
+const Search = SearchBox(searchProviders);
+
+test('search results are visible', () => {
+ const store = mockStore({
+ map: { projection: 'EPSG:4326' },
+ layers: { flat: [] },
+ theme: { current: { searchProviders: ['testing'] } }
+ });
+
+ const searchOptions = {
+ allowSearchFilters: false
+ };
+
+ render(
+
+
+
+ );
+
+ const input = screen.getByRole('input');
+ expect(input).toHaveValue('');
+
+ fireEvent.change(input, { target: { value: 'Test' } });
+ act(() => input.focus());
+
+ expect(input).toHaveValue('Test');
+ expect(screen.getByText('Layer 1')).toBeInTheDocument();
+ expect(screen.getByText('Layer 2')).toBeInTheDocument();
+ expect(screen.getByText('Item 1')).toBeInTheDocument();
+ expect(screen.getByText('Item 2')).toBeInTheDocument();
+ expect(screen.getByText('Item 3')).toBeInTheDocument();
+});
diff --git a/tests/components/StandardApp.test.jsx b/tests/components/StandardApp.test.jsx
new file mode 100644
index 000000000..7227d9257
--- /dev/null
+++ b/tests/components/StandardApp.test.jsx
@@ -0,0 +1,28 @@
+import React from 'react';
+import {Provider} from "react-redux";
+
+import {render} from '@testing-library/react';
+import configureStore from 'redux-mock-store';
+
+import StandardApp from "../../components/StandardApp";
+
+const mockStore = configureStore();
+
+test('app is running w/o plugins', () => {
+ const store = mockStore({});
+
+ const appConfig = {
+ initialState: {
+ defaultState: {}
+ },
+ pluginsDef: {
+ plugins: {}
+ }
+ };
+
+ render(
+
+
+
+ );
+});
diff --git a/tests/jest.setup.js b/tests/jest.setup.js
index 7b0828bfa..a9cf5db4f 100644
--- a/tests/jest.setup.js
+++ b/tests/jest.setup.js
@@ -1 +1,12 @@
+import LocaleUtils from "../utils/LocaleUtils";
+import MapUtils from "../utils/MapUtils";
+import MockMap from "./mocks/MockMap";
+
import '@testing-library/jest-dom';
+
+// Mock translation function, just return the message key
+LocaleUtils.tr = (key) => key;
+LocaleUtils.lang = () => 'en';
+
+// Mock the Map object globally
+MapUtils.registerHook(MapUtils.GET_MAP, new MockMap());
diff --git a/tests/mocks/MockMap.js b/tests/mocks/MockMap.js
new file mode 100644
index 000000000..a66cb3b30
--- /dev/null
+++ b/tests/mocks/MockMap.js
@@ -0,0 +1,5 @@
+export default class MockMap {
+ addLayer = () => null;
+ removeLayer = () => null;
+ getViewport = () => document.createElement('div');
+}