From e27152349a72b34a8a7ec83610747a050d4b4002 Mon Sep 17 00:00:00 2001 From: Benedikt Seidl Date: Wed, 19 Jun 2024 11:13:08 +0200 Subject: [PATCH] Add basic tests for some components --- components/StandardApp.jsx | 7 +- tests/components/CoordinateDisplayer.test.jsx | 24 ++++++ tests/components/SearchBox.test.jsx | 76 +++++++++++++++++++ tests/components/StandardApp.test.jsx | 28 +++++++ tests/jest.setup.js | 11 +++ tests/mocks/MockMap.js | 5 ++ 6 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 tests/components/CoordinateDisplayer.test.jsx create mode 100644 tests/components/SearchBox.test.jsx create mode 100644 tests/components/StandardApp.test.jsx create mode 100644 tests/mocks/MockMap.js 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'); +}