@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.
- package/CHANGELOG.md +37 -1
- package/package.json +2 -1
- package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyCard.jsx +404 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyCard.test.jsx +366 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyExplorerView.jsx +192 -91
- package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyExplorerView.test.jsx +205 -58
- package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyMap.jsx +329 -178
- package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyMap.test.jsx +243 -123
- package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyMapLazy.jsx +61 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyMapLazy.test.jsx +89 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyResults.jsx +128 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyResults.test.jsx +160 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/FacetPopover.jsx +180 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/FacetPopover.test.jsx +125 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/FilterPanel.jsx +171 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/FilterPanel.test.jsx +181 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/Pagination.jsx +81 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/filters.js +350 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/filters.test.js +399 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/hooks.js +28 -4
- package/src/components/manage/Blocks/CaseStudyExplorer/hooks.test.js +73 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/messages.js +138 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/styles.less +1157 -317
- package/src/components/manage/Blocks/CaseStudyExplorer/testUtils.js +44 -46
- package/src/components/manage/Blocks/CaseStudyExplorer/utils.js +68 -184
- package/src/components/manage/Blocks/CaseStudyExplorer/utils.test.js +91 -158
- package/src/index.js +39 -0
- package/src/openlayers.js +51 -0
- package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyFilters.jsx +0 -383
- package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyFilters.test.jsx +0 -90
- package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyListing.jsx +0 -342
- package/src/components/manage/Blocks/CaseStudyExplorer/CaseStudyListing.test.jsx +0 -196
- package/src/components/manage/Blocks/CaseStudyExplorer/FeatureDisplay.jsx +0 -24
- package/src/components/manage/Blocks/CaseStudyExplorer/FeatureDisplay.test.jsx +0 -49
- package/src/components/manage/Blocks/CaseStudyExplorer/FeatureInteraction.jsx +0 -100
- package/src/components/manage/Blocks/CaseStudyExplorer/FeatureInteraction.test.jsx +0 -189
- package/src/components/manage/Blocks/CaseStudyExplorer/InfoOverlay.jsx +0 -111
- package/src/components/manage/Blocks/CaseStudyExplorer/InfoOverlay.test.jsx +0 -159
- package/src/components/manage/Blocks/CaseStudyExplorer/styles.less_old +0 -201
|
@@ -1,90 +1,237 @@
|
|
|
1
|
+
import './mockJsdom';
|
|
1
2
|
import React from 'react';
|
|
2
|
-
import { render } from '@testing-library/react';
|
|
3
3
|
import '@testing-library/jest-dom';
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
jest.mock('@plone/volto/helpers', () => ({
|
|
8
|
-
addAppURL: jest.fn((url) => url),
|
|
9
|
-
}));
|
|
4
|
+
import { render, screen, fireEvent, within } from '@testing-library/react';
|
|
5
|
+
import { IntlProvider } from 'react-intl';
|
|
10
6
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
default: {
|
|
14
|
-
settings: { prefixPath: '' },
|
|
15
|
-
},
|
|
16
|
-
}));
|
|
17
|
-
|
|
18
|
-
jest.mock('./CaseStudyMap', () =>
|
|
19
|
-
jest.fn(() => <div id="case-study-map-mock">CaseStudyMapMock</div>),
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
jest.mock('./CaseStudyFilters', () => ({
|
|
23
|
-
ActiveFilters: jest.fn(() => (
|
|
24
|
-
<div id="active-filters-mock">ActiveFiltersMock</div>
|
|
25
|
-
)),
|
|
26
|
-
CaseStudyFilters: jest.fn(() => (
|
|
27
|
-
<div id="case-study-fiters-mock">CaseStudyFiltersMock</div>
|
|
28
|
-
)),
|
|
29
|
-
SearchBox: jest.fn(() => <div id="search-box-mock">SearchBoxMock</div>),
|
|
30
|
-
}));
|
|
7
|
+
import CaseStudyExplorerView from './CaseStudyExplorerView';
|
|
8
|
+
import { useCases } from './hooks';
|
|
31
9
|
|
|
32
|
-
|
|
33
|
-
filterCases: jest.fn(() => [{ id: 1, title: 'Filtered Case' }]),
|
|
34
|
-
filterCasesByPath: jest.fn((cases) => cases),
|
|
35
|
-
getFilters: jest.fn(() => ['filter1', 'filter2']),
|
|
36
|
-
}));
|
|
10
|
+
global.__SERVER__ = false;
|
|
37
11
|
|
|
38
12
|
jest.mock('./hooks', () => ({
|
|
39
13
|
useCases: jest.fn(),
|
|
40
14
|
}));
|
|
41
15
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
})
|
|
16
|
+
// The real map needs OpenLayers: stand in for it with one button per item so
|
|
17
|
+
// tests can select a case study the way a map click would.
|
|
18
|
+
jest.mock('./CaseStudyMapLazy', () => ({ items, onSelect }) => (
|
|
19
|
+
<div data-testid="case-study-map">
|
|
20
|
+
{items.map((item) => (
|
|
21
|
+
<button
|
|
22
|
+
type="button"
|
|
23
|
+
key={item.properties.path}
|
|
24
|
+
onClick={() => onSelect(item.properties.path)}
|
|
25
|
+
>
|
|
26
|
+
{`Map pin: ${item.properties.title}`}
|
|
27
|
+
</button>
|
|
28
|
+
))}
|
|
29
|
+
</div>
|
|
30
|
+
));
|
|
31
|
+
|
|
32
|
+
const cases = [
|
|
33
|
+
{
|
|
34
|
+
geometry: { type: 'Point', coordinates: [14.4, 50.1] },
|
|
35
|
+
properties: {
|
|
36
|
+
title: 'Peatland rewetting',
|
|
37
|
+
path: '/case-peatland',
|
|
38
|
+
current_status: 'ongoing',
|
|
39
|
+
nrr_legislation: ['Article 4 - Terrestrial'],
|
|
40
|
+
typology: [{ code: 'NRPM_001', family: 'MA', title: 'Rewetting' }],
|
|
41
|
+
habitat_ecosystem_type: ['Inland wetlands'],
|
|
42
|
+
measures: [{ id: 'm-a', title: 'Restore peatlands', path: '/m/a' }],
|
|
43
|
+
effective: '2026-02-11T09:36:06+00:00',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
geometry: { type: 'Point', coordinates: [10.4, 51.1] },
|
|
48
|
+
properties: {
|
|
49
|
+
title: 'River connectivity',
|
|
50
|
+
path: '/case-rivers',
|
|
51
|
+
current_status: 'completed',
|
|
52
|
+
nrr_legislation: ['Article 9 - Rivers'],
|
|
53
|
+
habitat_ecosystem_type: ['Rivers and canals'],
|
|
54
|
+
measures: [{ id: 'm-b', title: 'Restore rivers', path: '/m/b' }],
|
|
55
|
+
effective: '2026-01-02T00:00:00+00:00',
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
const renderView = (props = {}) =>
|
|
61
|
+
render(
|
|
62
|
+
<IntlProvider locale="en">
|
|
63
|
+
<CaseStudyExplorerView {...props} />
|
|
64
|
+
</IntlProvider>,
|
|
65
|
+
);
|
|
45
66
|
|
|
46
67
|
describe('CaseStudyExplorerView', () => {
|
|
47
68
|
beforeEach(() => {
|
|
48
|
-
|
|
69
|
+
useCases.mockReturnValue({ cases, loading: false, error: false });
|
|
49
70
|
});
|
|
50
71
|
|
|
51
|
-
|
|
52
|
-
useCases.mockReturnValue(
|
|
72
|
+
test('shows a loader while the case studies are being fetched', () => {
|
|
73
|
+
useCases.mockReturnValue({ cases: [], loading: true, error: false });
|
|
53
74
|
|
|
54
|
-
|
|
75
|
+
renderView();
|
|
55
76
|
|
|
56
|
-
expect(
|
|
57
|
-
|
|
77
|
+
expect(screen.getByRole('status')).toHaveTextContent(
|
|
78
|
+
'Loading case studies',
|
|
79
|
+
);
|
|
80
|
+
expect(screen.queryByTestId('case-study-map')).not.toBeInTheDocument();
|
|
58
81
|
expect(
|
|
59
|
-
|
|
82
|
+
screen.queryByText(/No case studies match your filters/),
|
|
83
|
+
).not.toBeInTheDocument();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test('offers a retry when the case studies cannot be loaded', () => {
|
|
87
|
+
const reload = jest.fn();
|
|
88
|
+
useCases.mockReturnValue({
|
|
89
|
+
cases: [],
|
|
90
|
+
loading: false,
|
|
91
|
+
error: true,
|
|
92
|
+
reload,
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
renderView();
|
|
96
|
+
|
|
97
|
+
expect(screen.getByRole('alert')).toHaveTextContent(
|
|
98
|
+
'The case studies could not be loaded.',
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
fireEvent.click(screen.getByRole('button', { name: /Try again/ }));
|
|
102
|
+
expect(reload).toHaveBeenCalled();
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test('renders the filter panel, the map and both results', () => {
|
|
106
|
+
renderView();
|
|
107
|
+
|
|
108
|
+
expect(screen.getByText('Filter and explore')).toBeInTheDocument();
|
|
109
|
+
expect(screen.getByTestId('case-study-map')).toBeInTheDocument();
|
|
110
|
+
expect(screen.getByText('Found 2 case studies')).toBeInTheDocument();
|
|
111
|
+
expect(screen.getAllByRole('article')).toHaveLength(2);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test('applies a filter as soon as it is toggled', () => {
|
|
115
|
+
renderView();
|
|
116
|
+
|
|
117
|
+
expect(screen.getByText('Found 2 case studies')).toBeInTheDocument();
|
|
118
|
+
|
|
119
|
+
fireEvent.click(screen.getByRole('button', { name: /Ongoing/ }));
|
|
120
|
+
|
|
121
|
+
expect(screen.getByText('Found 1 case study')).toBeInTheDocument();
|
|
122
|
+
expect(screen.getByRole('button', { name: /Ongoing/ })).toHaveAttribute(
|
|
123
|
+
'aria-pressed',
|
|
124
|
+
'true',
|
|
125
|
+
);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test('searches the measures and the typology as free text', () => {
|
|
129
|
+
renderView();
|
|
130
|
+
const search = screen.getByRole('searchbox', {
|
|
131
|
+
name: /Search measures and typology/i,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
fireEvent.change(search, { target: { value: 'restore rivers' } });
|
|
135
|
+
expect(screen.getByText('Found 1 case study')).toBeInTheDocument();
|
|
136
|
+
expect(screen.getByText('River connectivity')).toBeInTheDocument();
|
|
137
|
+
|
|
138
|
+
fireEvent.change(search, { target: { value: 'nrpm_001' } });
|
|
139
|
+
expect(screen.getByText('Found 1 case study')).toBeInTheDocument();
|
|
140
|
+
expect(screen.getByText('Peatland rewetting')).toBeInTheDocument();
|
|
141
|
+
|
|
142
|
+
fireEvent.change(search, { target: { value: 'nothing matches this' } });
|
|
143
|
+
expect(
|
|
144
|
+
screen.getByText('No case studies match your filters'),
|
|
60
145
|
).toBeInTheDocument();
|
|
61
|
-
expect(container.querySelector('#case-study-map-mock')).toBeInTheDocument();
|
|
62
146
|
});
|
|
63
147
|
|
|
64
|
-
|
|
65
|
-
|
|
148
|
+
test('resets the filters', () => {
|
|
149
|
+
renderView();
|
|
66
150
|
|
|
67
|
-
|
|
68
|
-
|
|
151
|
+
fireEvent.click(screen.getByRole('button', { name: /Ongoing/ }));
|
|
152
|
+
expect(screen.getByText('Found 1 case study')).toBeInTheDocument();
|
|
153
|
+
|
|
154
|
+
fireEvent.click(screen.getByRole('button', { name: /Reset filters/ }));
|
|
155
|
+
|
|
156
|
+
expect(screen.getByText('Found 2 case studies')).toBeInTheDocument();
|
|
157
|
+
expect(screen.getByRole('button', { name: /Ongoing/ })).toHaveAttribute(
|
|
158
|
+
'aria-pressed',
|
|
159
|
+
'false',
|
|
69
160
|
);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test('turns "Show on map" into "Reset map" on the selected card', () => {
|
|
164
|
+
renderView();
|
|
70
165
|
|
|
71
|
-
|
|
166
|
+
const [card] = screen.getAllByRole('article');
|
|
167
|
+
fireEvent.click(within(card).getByRole('button', { name: 'Show on map' }));
|
|
168
|
+
|
|
169
|
+
expect(card).toHaveAttribute('data-selected', 'true');
|
|
72
170
|
expect(
|
|
73
|
-
|
|
74
|
-
).
|
|
171
|
+
within(card).queryByRole('button', { name: 'Show on map' }),
|
|
172
|
+
).toBeNull();
|
|
173
|
+
|
|
174
|
+
fireEvent.click(within(card).getByRole('button', { name: 'Reset map' }));
|
|
175
|
+
|
|
176
|
+
expect(card).not.toHaveAttribute('data-selected');
|
|
75
177
|
expect(
|
|
76
|
-
|
|
77
|
-
).
|
|
78
|
-
|
|
178
|
+
within(card).getByRole('button', { name: 'Show on map' }),
|
|
179
|
+
).toBeInTheDocument();
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
test('jumps to the page that holds a case study selected on the map', () => {
|
|
183
|
+
const withTitle = (title, path) => ({
|
|
184
|
+
geometry: { type: 'Point', coordinates: [14.4, 50.1] },
|
|
185
|
+
properties: { title, path, current_status: 'ongoing' },
|
|
186
|
+
});
|
|
187
|
+
useCases.mockReturnValue({
|
|
188
|
+
cases: [
|
|
189
|
+
withTitle('Alpine meadows', '/case-alpine'),
|
|
190
|
+
withTitle('Boreal forest', '/case-boreal'),
|
|
191
|
+
withTitle('Coastal dunes', '/case-coastal'),
|
|
192
|
+
withTitle('Peatland rewetting', '/case-peatland'),
|
|
193
|
+
withTitle('River connectivity', '/case-rivers'),
|
|
194
|
+
],
|
|
195
|
+
loading: false,
|
|
196
|
+
error: false,
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
renderView();
|
|
200
|
+
|
|
201
|
+
// Four cards per page: the last case study is on page 2.
|
|
202
|
+
expect(screen.queryByText('River connectivity')).not.toBeInTheDocument();
|
|
203
|
+
|
|
204
|
+
fireEvent.click(
|
|
205
|
+
screen.getByRole('button', { name: 'Map pin: River connectivity' }),
|
|
206
|
+
);
|
|
207
|
+
|
|
208
|
+
expect(screen.getByText('River connectivity')).toBeInTheDocument();
|
|
209
|
+
expect(screen.getByRole('article')).toHaveAttribute(
|
|
210
|
+
'data-selected',
|
|
211
|
+
'true',
|
|
212
|
+
);
|
|
213
|
+
expect(screen.getByRole('button', { name: 'Page 2' })).toHaveAttribute(
|
|
214
|
+
'aria-current',
|
|
215
|
+
'page',
|
|
216
|
+
);
|
|
79
217
|
});
|
|
80
218
|
|
|
81
|
-
|
|
82
|
-
|
|
219
|
+
test('sorts by newest using the effective date', () => {
|
|
220
|
+
renderView();
|
|
83
221
|
|
|
84
|
-
|
|
222
|
+
fireEvent.change(screen.getByLabelText('Sort by'), {
|
|
223
|
+
target: { value: 'newest' },
|
|
224
|
+
});
|
|
85
225
|
|
|
226
|
+
const cards = screen.getAllByRole('article');
|
|
86
227
|
expect(
|
|
87
|
-
|
|
88
|
-
).
|
|
228
|
+
within(cards[0]).getByText('Peatland rewetting'),
|
|
229
|
+
).toBeInTheDocument();
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
test('narrows the results to the case studies of one measure', () => {
|
|
233
|
+
renderView({ data: { filter_path: '/case-rivers' } });
|
|
234
|
+
|
|
235
|
+
expect(screen.getByText('Found 1 case study')).toBeInTheDocument();
|
|
89
236
|
});
|
|
90
237
|
});
|