@eeacms/volto-bise-policy 1.3.11 → 1.3.13

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +37 -1
  2. package/package.json +2 -1
  3. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyCard.jsx +404 -0
  4. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyCard.test.jsx +366 -0
  5. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyExplorerView.jsx +192 -91
  6. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyExplorerView.test.jsx +205 -58
  7. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyMap.jsx +329 -178
  8. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyMap.test.jsx +243 -123
  9. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyMapLazy.jsx +61 -0
  10. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyMapLazy.test.jsx +89 -0
  11. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyResults.jsx +128 -0
  12. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyResults.test.jsx +160 -0
  13. package/src/components/manage/Blocks/CaseStudyExplorer/FacetPopover.jsx +180 -0
  14. package/src/components/manage/Blocks/CaseStudyExplorer/FacetPopover.test.jsx +125 -0
  15. package/src/components/manage/Blocks/CaseStudyExplorer/FilterPanel.jsx +171 -0
  16. package/src/components/manage/Blocks/CaseStudyExplorer/FilterPanel.test.jsx +181 -0
  17. package/src/components/manage/Blocks/CaseStudyExplorer/Pagination.jsx +81 -0
  18. package/src/components/manage/Blocks/CaseStudyExplorer/filters.js +350 -0
  19. package/src/components/manage/Blocks/CaseStudyExplorer/filters.test.js +399 -0
  20. package/src/components/manage/Blocks/CaseStudyExplorer/hooks.js +28 -4
  21. package/src/components/manage/Blocks/CaseStudyExplorer/hooks.test.js +73 -0
  22. package/src/components/manage/Blocks/CaseStudyExplorer/messages.js +138 -0
  23. package/src/components/manage/Blocks/CaseStudyExplorer/styles.less +1157 -317
  24. package/src/components/manage/Blocks/CaseStudyExplorer/testUtils.js +44 -46
  25. package/src/components/manage/Blocks/CaseStudyExplorer/utils.js +68 -184
  26. package/src/components/manage/Blocks/CaseStudyExplorer/utils.test.js +91 -158
  27. package/src/index.js +39 -0
  28. package/src/openlayers.js +51 -0
  29. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyFilters.jsx +0 -383
  30. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyFilters.test.jsx +0 -90
  31. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyListing.jsx +0 -342
  32. package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyListing.test.jsx +0 -196
  33. package/src/components/manage/Blocks/CaseStudyExplorer/FeatureDisplay.jsx +0 -24
  34. package/src/components/manage/Blocks/CaseStudyExplorer/FeatureDisplay.test.jsx +0 -49
  35. package/src/components/manage/Blocks/CaseStudyExplorer/FeatureInteraction.jsx +0 -100
  36. package/src/components/manage/Blocks/CaseStudyExplorer/FeatureInteraction.test.jsx +0 -189
  37. package/src/components/manage/Blocks/CaseStudyExplorer/InfoOverlay.jsx +0 -111
  38. package/src/components/manage/Blocks/CaseStudyExplorer/InfoOverlay.test.jsx +0 -159
  39. package/src/components/manage/Blocks/CaseStudyExplorer/styles.less_old +0 -201
package/src/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { getBlocks } from '@plone/volto/helpers/Blocks/Blocks';
2
2
  import installLink from '@plone/volto-slate/editor/plugins/AdvancedLink';
3
+ import { clientOnly } from '@eeacms/volto-openlayers-map';
3
4
  import { addStylingFieldsetSchemaEnhancer } from '@eeacms/volto-bise-policy/components/manage/Blocks/schema';
4
5
 
5
6
  import installBlocks from './components/manage/Blocks';
@@ -40,6 +41,40 @@ import {
40
41
  } from './components/Widgets/NRRWidgets';
41
42
  import RichTextWidget from './components/Widgets/RichTextWidget';
42
43
 
44
+ // @eeacms/volto-openlayers-map registers one lazy loadable per `ol/*`
45
+ // namespace, which makes webpack emit one async chunk (one script request)
46
+ // for each of them. Point every loadable at the single `./openlayers` chunk
47
+ // instead: see `src/openlayers.js` for the details.
48
+ const OPENLAYERS_BUNDLES = {
49
+ ol: 'ol',
50
+ olControl: 'control',
51
+ olCoordinate: 'coordinate',
52
+ olExtent: 'extent',
53
+ olFormat: 'format',
54
+ olGeom: 'geom',
55
+ olInteraction: 'interaction',
56
+ olLayer: 'layer',
57
+ olLoadingstrategy: 'loadingstrategy',
58
+ olProj: 'proj',
59
+ olSource: 'source',
60
+ olStyle: 'style',
61
+ olTilegrid: 'tilegrid',
62
+ olOverlay: 'overlay',
63
+ olEvents: 'events',
64
+ olCondition: 'condition',
65
+ olRender: 'render',
66
+ };
67
+
68
+ const openlayersLoadables = () =>
69
+ Object.fromEntries(
70
+ Object.entries(OPENLAYERS_BUNDLES).map(([name, bundle]) => [
71
+ name,
72
+ clientOnly(() =>
73
+ import('./openlayers').then((module) => module.bundles[bundle]),
74
+ ),
75
+ ]),
76
+ );
77
+
43
78
  const restrictedBlocks = ['imagecards', 'embed_eea_tableau_block'];
44
79
 
45
80
  const customBlocks = [
@@ -84,6 +119,10 @@ const applyConfig = (config) => {
84
119
  config.settings = {
85
120
  ...config.settings,
86
121
  navDepth: 3,
122
+ loadables: {
123
+ ...config.settings.loadables,
124
+ ...openlayersLoadables(),
125
+ },
87
126
  };
88
127
 
89
128
  // Multi-lingual
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Single code-split entry point for OpenLayers.
3
+ *
4
+ * `@eeacms/volto-openlayers-map` registers one lazy loadable per `ol/*`
5
+ * namespace (17 of them). Webpack emits a separate async chunk for each
6
+ * `import()`, so the first map on a page costs 17 extra script requests.
7
+ *
8
+ * Every loadable is pointed at this module instead (see `src/index.js`), so
9
+ * webpack emits a single chunk that they all share. Keeping the namespaces in
10
+ * one module preserves the module shape the add-on's components expect
11
+ * (`withOpenLayers` reads `ol.*`, `olOverlay.default`, etc.).
12
+ */
13
+ import * as ol from 'ol';
14
+ import * as control from 'ol/control';
15
+ import * as coordinate from 'ol/coordinate';
16
+ import * as extent from 'ol/extent';
17
+ import * as format from 'ol/format';
18
+ import * as geom from 'ol/geom';
19
+ import * as interaction from 'ol/interaction';
20
+ import * as layer from 'ol/layer';
21
+ import * as loadingstrategy from 'ol/loadingstrategy';
22
+ import * as proj from 'ol/proj';
23
+ import * as source from 'ol/source';
24
+ import * as style from 'ol/style';
25
+ import * as tilegrid from 'ol/tilegrid';
26
+ import Overlay from 'ol/Overlay';
27
+ import * as events from 'ol/events';
28
+ import * as condition from 'ol/events/condition';
29
+ import * as render from 'ol/render';
30
+
31
+ export const bundles = {
32
+ ol,
33
+ control,
34
+ coordinate,
35
+ extent,
36
+ format,
37
+ geom,
38
+ interaction,
39
+ layer,
40
+ loadingstrategy,
41
+ proj,
42
+ source,
43
+ style,
44
+ tilegrid,
45
+ // `withOpenLayers` reads `loaded.olOverlay.default`, so keep the ES module
46
+ // shape the `import('ol/Overlay')` loadable used to provide.
47
+ overlay: { default: Overlay },
48
+ events,
49
+ condition,
50
+ render,
51
+ };
@@ -1,383 +0,0 @@
1
- import React from 'react';
2
-
3
- import { centerAndResetMapZoom, scrollToElement } from './utils';
4
- import { withOpenLayers } from '@eeacms/volto-openlayers-map';
5
-
6
- const normalizeSearchInput = (searchInput) => searchInput.trim().toLowerCase();
7
-
8
- export function CaseStudyFilter(props) {
9
- const {
10
- filterTitle,
11
- filters,
12
- activeFilters,
13
- setActiveFilters,
14
- filterName,
15
- map,
16
- ol,
17
- } = props;
18
- const filterEntries = Object.entries(filters?.[filterName] || {});
19
-
20
- const showInputs = (event) => {
21
- event.currentTarget.parentElement.classList.add('active');
22
- };
23
-
24
- return (
25
- <div className="filter-wrapper">
26
- <button
27
- className="ui basic button facet-btn"
28
- disabled={!filterEntries.length}
29
- onClick={(e) => showInputs(e)}
30
- >
31
- <span>
32
- {filterTitle}
33
- <i aria-hidden="true" className="icon angle down"></i>
34
- </span>
35
- </button>
36
- <div className="filter-inputs-wrapper">
37
- {!filterEntries.length ? (
38
- <div className="filter-empty">No options available</div>
39
- ) : filterEntries.length > 7 ? (
40
- <input
41
- type="text"
42
- className="filterInputText"
43
- onKeyUp={(e) => {
44
- const filterValue = e.currentTarget.value.toUpperCase();
45
- const inputs = e.currentTarget.nextSibling.children;
46
-
47
- for (let i = 0; i < inputs.length; i++) {
48
- let inputValue = inputs[i].textContent || inputs[i].innerText;
49
- if (inputValue.toUpperCase().indexOf(filterValue) > -1) {
50
- inputs[i].style.display = 'block';
51
- } else {
52
- inputs[i].style.display = 'none';
53
- }
54
- }
55
- }}
56
- placeholder="Quick search"
57
- title="Type in a name"
58
- />
59
- ) : (
60
- ''
61
- )}
62
-
63
- <div className="filter-inputs">
64
- {filterEntries
65
- .sort((item1, item2) => item1[1].localeCompare(item2[1]))
66
- .map(([value, label], index) => (
67
- <label
68
- htmlFor={label + index}
69
- className="filter-input"
70
- key={value}
71
- >
72
- <input
73
- value={value}
74
- type="checkbox"
75
- id={label + index}
76
- onChange={(e) => {
77
- const temp = JSON.parse(JSON.stringify(activeFilters));
78
- if (e.target.checked) {
79
- temp[filterName].push(e.target.value);
80
- } else {
81
- temp[filterName] = temp[filterName].filter((value) => {
82
- if (value !== e.target.value) return value;
83
- return null;
84
- });
85
- }
86
- setActiveFilters(temp);
87
- scrollToElement('search-input');
88
- centerAndResetMapZoom({ map, ol });
89
- }}
90
- />
91
- <span>{label}</span>
92
- </label>
93
- ))}
94
- </div>
95
- </div>
96
- </div>
97
- );
98
- }
99
-
100
- function CaseStudyFiltersComponent(props) {
101
- const { filters, activeFilters, setActiveFilters, map, ol } = props;
102
-
103
- React.useEffect(() => {
104
- window.addEventListener('click', (event) => {
105
- const filters = document.getElementsByClassName('filter-wrapper');
106
-
107
- for (let i = 0; i < filters.length; i++) {
108
- if (!filters[i].contains(event.target)) {
109
- filters[i].classList.remove('active');
110
- }
111
- }
112
- });
113
- }, []);
114
-
115
- return (
116
- <>
117
- <CaseStudyFilter
118
- filterTitle="Legislation"
119
- filterName="nrr_legislation"
120
- {...props}
121
- />
122
- <CaseStudyFilter
123
- filterTitle="Biogeographical region"
124
- filterName="nrr_biogeographical_region"
125
- {...props}
126
- />
127
- <CaseStudyFilter
128
- filterTitle="Measures"
129
- filterName="measures_implemented"
130
- filters={filters}
131
- activeFilters={activeFilters}
132
- setActiveFilters={setActiveFilters}
133
- map={map}
134
- ol={ol}
135
- />
136
-
137
- <CaseStudyFilter
138
- filterTitle="Typology of measure"
139
- filterName="typology_of_measures"
140
- filters={filters}
141
- activeFilters={activeFilters}
142
- setActiveFilters={setActiveFilters}
143
- map={map}
144
- ol={ol}
145
- />
146
-
147
- <CaseStudyFilter
148
- filterTitle="Current status"
149
- filterName="current_status"
150
- {...props}
151
- />
152
- <CaseStudyFilter
153
- filterTitle="Habitat/ecosystem type"
154
- filterName="habitat_ecosystem_type"
155
- {...props}
156
- />
157
- <CaseStudyFilter
158
- filterTitle="Scale of Planning"
159
- filterName="scale_of_planning"
160
- {...props}
161
- />
162
- </>
163
- );
164
- }
165
-
166
- function SearchBoxComponent(props) {
167
- const { setSearchInput, map, ol } = props;
168
- const [showClearButton, setShowClearButton] = React.useState(false);
169
-
170
- return (
171
- <div className="header-content">
172
- <div className="sui-search-box">
173
- <div className="search-input">
174
- <div className="terms-box">
175
- <input
176
- id="search-input"
177
- placeholder="Search with a keyword..."
178
- onChange={(event) => {
179
- const _showClearButton = event.target.value ? true : false;
180
- setShowClearButton(_showClearButton);
181
- }}
182
- onKeyDown={(event) => {
183
- if (event.code !== 'Enter') {
184
- return;
185
- }
186
- let searchInput = normalizeSearchInput(event.target.value);
187
-
188
- setSearchInput(searchInput);
189
- scrollToElement('search-input');
190
- centerAndResetMapZoom({ map, ol });
191
- }}
192
- ></input>
193
- <div className="terms-box-left">
194
- <div className="input-controls">
195
- {showClearButton ? (
196
- <div className="ui button basic clear-button">
197
- <i
198
- aria-hidden="true"
199
- className="close icon"
200
- role="button"
201
- onClick={() => {
202
- const searchInputElement =
203
- document.getElementById('search-input');
204
- searchInputElement.value = '';
205
- setSearchInput('');
206
- setShowClearButton(false);
207
- scrollToElement('search-input');
208
- centerAndResetMapZoom({ map, ol });
209
- }}
210
- ></i>
211
- </div>
212
- ) : (
213
- ''
214
- )}
215
- </div>
216
- <div
217
- className="search-icon"
218
- role="button"
219
- onClick={() => {
220
- const searchInputElement =
221
- document.getElementById('search-input');
222
- const searchInputVal = normalizeSearchInput(
223
- searchInputElement.value,
224
- );
225
-
226
- setSearchInput(searchInputVal);
227
- scrollToElement('search-input');
228
- centerAndResetMapZoom({ map, ol });
229
- }}
230
- onKeyDown={() => {}}
231
- tabIndex="0"
232
- >
233
- <svg viewBox="0 0 38 38" xmlns="http://www.w3.org/2000/svg">
234
- <path d="M37.3757 34.3789L30.2003 27.2246C32.5154 24.2751 33.7716 20.633 33.7669 16.8835C33.7669 13.5442 32.7767 10.28 30.9215 7.50351C29.0663 4.72705 26.4295 2.56305 23.3445 1.28518C20.2594 0.00731515 16.8647 -0.327033 13.5897 0.324418C10.3146 0.97587 7.30625 2.58386 4.94506 4.94506C2.58386 7.30625 0.97587 10.3146 0.324418 13.5897C-0.327033 16.8647 0.00731528 20.2594 1.28518 23.3445C2.56305 26.4295 4.72705 29.0664 7.50351 30.9215C10.28 32.7767 13.5442 33.7669 16.8835 33.7669C20.633 33.7716 24.2751 32.5154 27.2246 30.2003L34.3789 37.3757C34.5751 37.5735 34.8085 37.7306 35.0657 37.8377C35.3229 37.9448 35.5987 38 35.8773 38C36.1559 38 36.4318 37.9448 36.689 37.8377C36.9461 37.7306 37.1795 37.5735 37.3757 37.3757C37.5735 37.1795 37.7305 36.9461 37.8377 36.689C37.9448 36.4318 38 36.1559 38 35.8773C38 35.5987 37.9448 35.3229 37.8377 35.0657C37.7305 34.8085 37.5735 34.5751 37.3757 34.3789ZM4.22087 16.8835C4.22087 14.379 4.96352 11.9309 6.3549 9.8485C7.74628 7.76615 9.72391 6.14315 12.0377 5.18475C14.3515 4.22635 16.8975 3.97559 19.3538 4.46418C21.8101 4.95277 24.0664 6.15876 25.8373 7.92966C27.6081 9.70055 28.8141 11.9568 29.3027 14.4131C29.7913 16.8694 29.5406 19.4154 28.5822 21.7292C27.6238 24.043 26.0008 26.0206 23.9184 27.412C21.8361 28.8034 19.3879 29.546 16.8835 29.546C13.5251 29.546 10.3043 28.2119 7.92966 25.8373C5.55496 23.4626 4.22087 20.2418 4.22087 16.8835Z" />
235
- </svg>
236
- </div>
237
- </div>
238
- </div>
239
- </div>
240
- </div>
241
- </div>
242
- );
243
- }
244
-
245
- function FilterGroup({
246
- filterName,
247
- filterLabel,
248
- activeFilterCodes,
249
- filters,
250
- onRemoveFilter,
251
- }) {
252
- return activeFilterCodes.length > 0 ? (
253
- <div className="filter-wrapper">
254
- <div className="filter-label">{filterLabel}</div>
255
- {activeFilterCodes.map((filterCode) => {
256
- const label = filters[filterName][filterCode];
257
- return (
258
- <div className="ui basic label filter-value" key={filterCode}>
259
- <span>{label}</span>
260
- <i
261
- tabIndex="0"
262
- onKeyPress={() => {}}
263
- onClick={() => {
264
- onRemoveFilter(filterName, filterCode);
265
- scrollToElement('search-input');
266
- }}
267
- role="button"
268
- className="close icon"
269
- ></i>
270
- </div>
271
- );
272
- })}
273
- </div>
274
- ) : null;
275
- }
276
-
277
- function ActiveFiltersComponent(props) {
278
- const { filters, activeFilters, setActiveFilters } = props;
279
- const hasActiveFilters = Object.entries(activeFilters).some(
280
- ([_, filterList]) => filterList.length > 0,
281
- );
282
-
283
- const clearFilters = () => {
284
- const filterInputs = document.querySelectorAll(
285
- '#cse-filter .filter-input input',
286
- );
287
- for (let i = 0; i < filterInputs.length; i++) {
288
- filterInputs[i].checked = false;
289
- }
290
- setActiveFilters(
291
- Object.fromEntries(Object.keys(activeFilters).map((key) => [key, []])),
292
- );
293
- scrollToElement('search-input');
294
- };
295
-
296
- const removeFilter = (filterName, filterCode) => {
297
- const temp = JSON.parse(JSON.stringify(activeFilters));
298
- temp[filterName] = temp[filterName].filter((value) => value !== filterCode);
299
-
300
- const filterInputs = document.querySelectorAll(
301
- '#cse-filter .filter-input input',
302
- );
303
-
304
- for (let i = 0; i < filterInputs.length; i++) {
305
- if (filterInputs[i].value === filterCode) {
306
- filterInputs[i].checked = false;
307
- }
308
- }
309
-
310
- setActiveFilters(temp);
311
- };
312
-
313
- return hasActiveFilters ? (
314
- <div className="ui segment active-filter-list">
315
- <div className="filter-list-header">
316
- <h4 className="filter-list-title">Active filters</h4>
317
- <button
318
- onClick={clearFilters}
319
- className="ui mini basic compact button clear-btn"
320
- >
321
- clear all
322
- </button>
323
- </div>
324
- <div className="filter-list-content">
325
- <div className="filter">
326
- <FilterGroup
327
- filterName="measures_implemented"
328
- filterLabel="Measures implemented:"
329
- activeFilterCodes={activeFilters.measures_implemented}
330
- filters={filters}
331
- onRemoveFilter={removeFilter}
332
- />
333
- <FilterGroup
334
- filterName="typology_of_measures"
335
- filterLabel="Typology of measures:"
336
- activeFilterCodes={activeFilters.typology_of_measures}
337
- filters={filters}
338
- onRemoveFilter={removeFilter}
339
- />
340
- <FilterGroup
341
- filterName="current_status"
342
- filterLabel="Current status:"
343
- activeFilterCodes={activeFilters.current_status}
344
- filters={filters}
345
- onRemoveFilter={removeFilter}
346
- />
347
- <FilterGroup
348
- filterName="habitat_ecosystem_type"
349
- filterLabel="Habitat/ecosystem type:"
350
- activeFilterCodes={activeFilters.habitat_ecosystem_type}
351
- filters={filters}
352
- onRemoveFilter={removeFilter}
353
- />
354
- <FilterGroup
355
- filterName="nrr_legislation"
356
- filterLabel="Legislation:"
357
- activeFilterCodes={activeFilters.nrr_legislation}
358
- filters={filters}
359
- onRemoveFilter={removeFilter}
360
- />
361
- <FilterGroup
362
- filterName="nrr_biogeographical_region"
363
- filterLabel="Biogeographical region:"
364
- activeFilterCodes={activeFilters.nrr_biogeographical_region}
365
- filters={filters}
366
- onRemoveFilter={removeFilter}
367
- />
368
- <FilterGroup
369
- filterName="scale_of_planning"
370
- filterLabel="Scale of Planning:"
371
- activeFilterCodes={activeFilters.scale_of_planning}
372
- filters={filters}
373
- onRemoveFilter={removeFilter}
374
- />
375
- </div>
376
- </div>
377
- </div>
378
- ) : null;
379
- }
380
-
381
- export const CaseStudyFilters = withOpenLayers(CaseStudyFiltersComponent);
382
- export const SearchBox = withOpenLayers(SearchBoxComponent);
383
- export const ActiveFilters = withOpenLayers(ActiveFiltersComponent);
@@ -1,90 +0,0 @@
1
- import './mockJsdom';
2
- import React from 'react';
3
- import '@testing-library/jest-dom';
4
- import { render } from '@testing-library/react';
5
-
6
- import {
7
- CaseStudyFilters,
8
- ActiveFilters,
9
- SearchBox,
10
- CaseStudyFilter,
11
- } from './CaseStudyFilters';
12
- import { createMockFilters } from './testUtils';
13
-
14
- jest.mock('@eeacms/volto-openlayers-map', () => ({
15
- openlayers: {
16
- proj: {
17
- transform: jest.fn().mockReturnValue([0, 0]),
18
- },
19
- },
20
- withOpenLayers: (Component) => (props) => (
21
- <Component
22
- {...props}
23
- ol={{
24
- proj: {
25
- transform: jest.fn().mockReturnValue([0, 0]),
26
- },
27
- }}
28
- />
29
- ),
30
- }));
31
-
32
- window.URL.createObjectURL = function () {};
33
- global.URL.createObjectURL = jest.fn();
34
-
35
- const mockFilters = createMockFilters();
36
- const mockSetActiveFilters = jest.fn();
37
-
38
- describe('CaseStudyFilters', () => {
39
- it('renders without crashing', () => {
40
- const { container } = render(
41
- <CaseStudyFilters
42
- filters={mockFilters}
43
- activeFilters={{ measures_implemented: [], typology_of_measures: [] }}
44
- setActiveFilters={mockSetActiveFilters}
45
- />,
46
- );
47
-
48
- expect(container).toBeTruthy();
49
- });
50
- });
51
-
52
- describe('ActiveFilters', () => {
53
- it('renders without crashing', () => {
54
- render(
55
- <ActiveFilters
56
- filters={mockFilters}
57
- activeFilters={{ measures_implemented: [], typology_of_measures: [] }}
58
- setActiveFilters={mockSetActiveFilters}
59
- />,
60
- );
61
- });
62
- });
63
-
64
- describe('SearchBox', () => {
65
- it('renders without crashing', () => {
66
- render(
67
- <SearchBox
68
- filters={mockFilters}
69
- activeFilters={{ measures_implemented: [], typology_of_measures: [] }}
70
- setActiveFilters={mockSetActiveFilters}
71
- searchInput="bise"
72
- setSearchInput={jest.fn()}
73
- />,
74
- );
75
- });
76
- });
77
-
78
- describe('CaseStudyFilter', () => {
79
- it('renders without crashing', () => {
80
- render(
81
- <CaseStudyFilter
82
- filterTitle="Case study filter"
83
- filters={mockFilters}
84
- activeFilters={{ measures_implemented: [], typology_of_measures: [] }}
85
- setActiveFilters={mockSetActiveFilters}
86
- filterName="measures_implemented"
87
- />,
88
- );
89
- });
90
- });