@eeacms/volto-eea-website-theme 3.18.1 → 3.19.1
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 +20 -0
- package/README.md +8 -8
- package/docker-compose.yml +0 -1
- package/package.json +1 -1
- package/src/components/theme/Banner/View.jsx +2 -2
- package/src/components/theme/Widgets/ContributorsViewWidget.jsx +9 -9
- package/src/components/theme/Widgets/CreatorsViewWidget.jsx +9 -9
- package/src/components/theme/Widgets/NavigationBehaviorWidget.test.jsx +1 -1
- package/src/customizations/@plone/volto-slate/blocks/Table/TableBlockView.jsx +165 -0
- package/src/customizations/@plone/volto-slate/editor/plugins/Table/less/public.less +43 -0
- package/src/customizations/volto/components/manage/History/History.jsx +58 -52
- package/src/customizations/volto/components/theme/Comments/Comments.jsx +2 -2
- package/src/customizations/volto/components/theme/Header/Header.test.jsx +15 -0
- package/src/helpers/setupPrintView.test.js +1 -17
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,26 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
+
### [3.19.1](https://github.com/eea/volto-eea-website-theme/compare/3.19.0...3.19.1) - 24 February 2026
|
|
8
|
+
|
|
9
|
+
#### :bug: Bug Fixes
|
|
10
|
+
|
|
11
|
+
- fix: History in indicators when copied_to or copied_from are not valid URLs - refs #297683 [Teodor Voicu - [`ccd5dad`](https://github.com/eea/volto-eea-website-theme/commit/ccd5dad4c4700d43d0697a1fb49df83d4ee96c83)]
|
|
12
|
+
|
|
13
|
+
#### :house: Internal changes
|
|
14
|
+
|
|
15
|
+
- chore: [JENKINSFILE] add package version in sonarqube [valentinab25 - [`b15b302`](https://github.com/eea/volto-eea-website-theme/commit/b15b302ff88ec6afa6901ee7e1726cc4e04a8739)]
|
|
16
|
+
- chore: [JENKINSFILE] use sonarqube branches [EEA Jenkins - [`36f2e1e`](https://github.com/eea/volto-eea-website-theme/commit/36f2e1e176471b3753d77ab8aaf0cba577b43b36)]
|
|
17
|
+
|
|
18
|
+
### [3.19.0](https://github.com/eea/volto-eea-website-theme/compare/3.18.1...3.19.0) - 11 February 2026
|
|
19
|
+
|
|
20
|
+
#### :house: Internal changes
|
|
21
|
+
|
|
22
|
+
- style: Automated code fix [eea-jenkins - [`26e2fec`](https://github.com/eea/volto-eea-website-theme/commit/26e2fec974c85b5221730215650d049e3deefbad)]
|
|
23
|
+
|
|
24
|
+
#### :hammer_and_wrench: Others
|
|
25
|
+
|
|
26
|
+
- fix formating [Teodor - [`7131bcf`](https://github.com/eea/volto-eea-website-theme/commit/7131bcf73f9b561c87599e590941419bf6c23c67)]
|
|
7
27
|
### [3.18.1](https://github.com/eea/volto-eea-website-theme/compare/3.18.0...3.18.1) - 20 January 2026
|
|
8
28
|
|
|
9
29
|
#### :bug: Bug Fixes
|
package/README.md
CHANGED
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
[](https://github.com/eea/volto-eea-website-theme/releases)
|
|
4
4
|
|
|
5
5
|
[](https://ci.eionet.europa.eu/view/Github/job/volto-addons/job/volto-eea-website-theme/job/master/display/redirect)
|
|
6
|
-
[](https://sonarqube.eea.europa.eu/api/project_badges/measure?project=volto-eea-website-theme
|
|
6
|
+
[](https://sonarqube.eea.europa.eu/dashboard?id=volto-eea-website-theme)
|
|
7
|
+
[](https://sonarqube.eea.europa.eu/dashboard?id=volto-eea-website-theme)
|
|
8
|
+
[](https://sonarqube.eea.europa.eu/dashboard?id=volto-eea-website-theme)
|
|
9
|
+
[](https://sonarqube.eea.europa.eu/dashboard?id=volto-eea-website-theme)
|
|
10
10
|
|
|
11
11
|
[](https://ci.eionet.europa.eu/view/Github/job/volto-addons/job/volto-eea-website-theme/job/develop/display/redirect)
|
|
12
|
-
[](https://sonarqube.eea.europa.eu/api/project_badges/measure?project=volto-eea-website-theme
|
|
12
|
+
[](https://sonarqube.eea.europa.eu/dashboard?id=volto-eea-website-theme&branch=develop)
|
|
13
|
+
[](https://sonarqube.eea.europa.eu/dashboard?id=volto-eea-website-theme&branch=develop)
|
|
14
|
+
[](https://sonarqube.eea.europa.eu/dashboard?id=volto-eea-website-theme&branch=develop)
|
|
15
|
+
[](https://sonarqube.eea.europa.eu/dashboard?id=volto-eea-website-theme&branch=develop)
|
|
16
16
|
|
|
17
17
|
EEA Website [Volto](https://github.com/plone/volto) Theme
|
|
18
18
|
|
package/docker-compose.yml
CHANGED
package/package.json
CHANGED
|
@@ -183,7 +183,7 @@ const View = (props) => {
|
|
|
183
183
|
/>
|
|
184
184
|
)}
|
|
185
185
|
{rssLinks?.map((rssLink, index) => (
|
|
186
|
-
|
|
186
|
+
<React.Fragment key={rssLink.href || index}>
|
|
187
187
|
<Helmet
|
|
188
188
|
link={[
|
|
189
189
|
{
|
|
@@ -205,7 +205,7 @@ const View = (props) => {
|
|
|
205
205
|
href={rssLink.href}
|
|
206
206
|
target="_blank"
|
|
207
207
|
/>
|
|
208
|
-
|
|
208
|
+
</React.Fragment>
|
|
209
209
|
))}
|
|
210
210
|
</>
|
|
211
211
|
}
|
|
@@ -4,16 +4,16 @@ const ContributorsViewWidget = ({ value, content, children, className }) => {
|
|
|
4
4
|
const resolvedValue = content?.contributors_fullname || value || [];
|
|
5
5
|
return resolvedValue ? (
|
|
6
6
|
<span className={cx(className, 'array', 'widget')}>
|
|
7
|
-
{resolvedValue.map((item,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
{resolvedValue.map((item, index) => {
|
|
8
|
+
const label = item?.title || item?.token || item;
|
|
9
|
+
const key = `${label}-${index}`;
|
|
10
|
+
return (
|
|
11
|
+
<span key={key}>
|
|
12
|
+
{index ? ', ' : ''}
|
|
13
|
+
{children ? children(label) : label}
|
|
14
14
|
</span>
|
|
15
|
-
|
|
16
|
-
)
|
|
15
|
+
);
|
|
16
|
+
})}
|
|
17
17
|
</span>
|
|
18
18
|
) : (
|
|
19
19
|
''
|
|
@@ -4,16 +4,16 @@ const CreatorsViewWidget = ({ value, content, children, className }) => {
|
|
|
4
4
|
const resolvedValue = content?.creators_fullname || value || [];
|
|
5
5
|
return resolvedValue ? (
|
|
6
6
|
<span className={cx(className, 'array', 'widget')}>
|
|
7
|
-
{resolvedValue.map((item,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
{resolvedValue.map((item, index) => {
|
|
8
|
+
const label = item?.title || item?.token || item;
|
|
9
|
+
const key = `${label}-${index}`;
|
|
10
|
+
return (
|
|
11
|
+
<span key={key}>
|
|
12
|
+
{index ? ', ' : ''}
|
|
13
|
+
{children ? children(label) : label}
|
|
14
14
|
</span>
|
|
15
|
-
|
|
16
|
-
)
|
|
15
|
+
);
|
|
16
|
+
})}
|
|
17
17
|
</span>
|
|
18
18
|
) : (
|
|
19
19
|
''
|
|
@@ -101,7 +101,7 @@ jest.mock('@plone/volto/components/manage/Widgets/ObjectWidget', () => {
|
|
|
101
101
|
|
|
102
102
|
// Mock semantic-ui-react components
|
|
103
103
|
jest.mock('semantic-ui-react', () => {
|
|
104
|
-
const MockAccordion = ({ children, ...props }) => (
|
|
104
|
+
const MockAccordion = ({ children, fluid, styled, ...props }) => (
|
|
105
105
|
<div className="ui accordion" data-testid="accordion" {...props}>
|
|
106
106
|
{children}
|
|
107
107
|
</div>
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slate Table block's View component.
|
|
3
|
+
* @module volto-slate/blocks/Table/View
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React, { useState, useMemo } from 'react';
|
|
7
|
+
import PropTypes from 'prop-types';
|
|
8
|
+
import { Table } from 'semantic-ui-react';
|
|
9
|
+
import { map } from 'lodash';
|
|
10
|
+
import {
|
|
11
|
+
serializeNodes,
|
|
12
|
+
serializeNodesToText,
|
|
13
|
+
} from '@plone/volto-slate/editor/render';
|
|
14
|
+
import { Node } from 'slate';
|
|
15
|
+
|
|
16
|
+
// TODO: loading LESS files with `volto-slate/...` paths does not work currently
|
|
17
|
+
import '../../editor/plugins/Table/less/public.less';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Slate Table block's View class.
|
|
21
|
+
* @class View
|
|
22
|
+
* @extends Component
|
|
23
|
+
* @param {object} data The table data to render as a table.
|
|
24
|
+
*/
|
|
25
|
+
const View = ({ data }) => {
|
|
26
|
+
const [state, setState] = useState({
|
|
27
|
+
column: null,
|
|
28
|
+
direction: null,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const headers = useMemo(() => {
|
|
32
|
+
return data.table.rows?.[0]?.cells;
|
|
33
|
+
}, [data.table.rows]);
|
|
34
|
+
|
|
35
|
+
const rows = useMemo(() => {
|
|
36
|
+
const items = [];
|
|
37
|
+
if (!data.table.rows) return [];
|
|
38
|
+
data.table.rows.forEach((row, index) => {
|
|
39
|
+
if (index > 0) {
|
|
40
|
+
items[index] = [];
|
|
41
|
+
row.cells.forEach((cell, cellIndex) => {
|
|
42
|
+
items[index][cellIndex] = {
|
|
43
|
+
...cell,
|
|
44
|
+
value:
|
|
45
|
+
cell.value && Node.string({ children: cell.value }).length > 0
|
|
46
|
+
? serializeNodes(cell.value)
|
|
47
|
+
: '\u00A0',
|
|
48
|
+
valueText:
|
|
49
|
+
cell.value && Node.string({ children: cell.value }).length > 0
|
|
50
|
+
? serializeNodesToText(cell.value)
|
|
51
|
+
: '\u00A0',
|
|
52
|
+
align: cell.value?.[0]?.align || 'left',
|
|
53
|
+
};
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return items;
|
|
58
|
+
}, [data.table.rows]);
|
|
59
|
+
|
|
60
|
+
const sortedRows = useMemo(() => {
|
|
61
|
+
if (state.column === null) return Object.keys(rows);
|
|
62
|
+
return Object.keys(rows).sort((a, b) => {
|
|
63
|
+
const a_text = rows[a][state.column].valueText;
|
|
64
|
+
const b_text = rows[b][state.column].valueText;
|
|
65
|
+
if (state.direction === 'ascending' ? a_text < b_text : a_text > b_text) {
|
|
66
|
+
return -1;
|
|
67
|
+
}
|
|
68
|
+
if (state.direction === 'ascending' ? a_text > b_text : a_text < b_text) {
|
|
69
|
+
return 1;
|
|
70
|
+
}
|
|
71
|
+
return 0;
|
|
72
|
+
});
|
|
73
|
+
}, [state, rows]);
|
|
74
|
+
|
|
75
|
+
const handleSort = (index) => {
|
|
76
|
+
if (!data.table.sortable) return;
|
|
77
|
+
setState({
|
|
78
|
+
column: index,
|
|
79
|
+
direction:
|
|
80
|
+
state.column !== index
|
|
81
|
+
? 'ascending'
|
|
82
|
+
: state.direction === 'ascending'
|
|
83
|
+
? 'descending'
|
|
84
|
+
: 'ascending',
|
|
85
|
+
});
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<>
|
|
90
|
+
{data && data.table && (
|
|
91
|
+
<Table
|
|
92
|
+
fixed={data.table.fixed}
|
|
93
|
+
compact={data.table.compact}
|
|
94
|
+
basic={data.table.basic ? 'very' : false}
|
|
95
|
+
celled={data.table.celled}
|
|
96
|
+
inverted={data.table.inverted}
|
|
97
|
+
striped={data.table.striped}
|
|
98
|
+
sortable={data.table.sortable}
|
|
99
|
+
className="slate-table-block"
|
|
100
|
+
>
|
|
101
|
+
{!data.table.hideHeaders ? (
|
|
102
|
+
<Table.Header>
|
|
103
|
+
<Table.Row>
|
|
104
|
+
{headers.map((cell, index) => (
|
|
105
|
+
<Table.HeaderCell
|
|
106
|
+
key={cell.key}
|
|
107
|
+
textAlign={cell.value?.[0]?.align || 'left'}
|
|
108
|
+
verticalAlign="middle"
|
|
109
|
+
tabIndex={data.table.sortable ? '0' : '-1'}
|
|
110
|
+
sorted={state.column === index ? state.direction : null}
|
|
111
|
+
onClick={() => {
|
|
112
|
+
handleSort(index);
|
|
113
|
+
}}
|
|
114
|
+
onKeyDown={(e) => {
|
|
115
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
116
|
+
e.preventDefault();
|
|
117
|
+
handleSort(index);
|
|
118
|
+
}
|
|
119
|
+
}}
|
|
120
|
+
aria-sort={
|
|
121
|
+
state.column === index ? state.direction : 'none'
|
|
122
|
+
}
|
|
123
|
+
>
|
|
124
|
+
{cell.value &&
|
|
125
|
+
Node.string({ children: cell.value }).length > 0
|
|
126
|
+
? serializeNodes(cell.value)
|
|
127
|
+
: '\u00A0'}
|
|
128
|
+
</Table.HeaderCell>
|
|
129
|
+
))}
|
|
130
|
+
</Table.Row>
|
|
131
|
+
</Table.Header>
|
|
132
|
+
) : (
|
|
133
|
+
''
|
|
134
|
+
)}
|
|
135
|
+
<Table.Body>
|
|
136
|
+
{map(sortedRows, (row) => (
|
|
137
|
+
<Table.Row key={row}>
|
|
138
|
+
{map(rows[row], (cell) => (
|
|
139
|
+
<Table.Cell
|
|
140
|
+
key={cell.key}
|
|
141
|
+
textAlign={cell.align}
|
|
142
|
+
verticalAlign="middle"
|
|
143
|
+
>
|
|
144
|
+
{cell.value}
|
|
145
|
+
</Table.Cell>
|
|
146
|
+
))}
|
|
147
|
+
</Table.Row>
|
|
148
|
+
))}
|
|
149
|
+
</Table.Body>
|
|
150
|
+
</Table>
|
|
151
|
+
)}
|
|
152
|
+
</>
|
|
153
|
+
);
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Property types.
|
|
158
|
+
* @property {Object} propTypes Property types.
|
|
159
|
+
* @static
|
|
160
|
+
*/
|
|
161
|
+
View.propTypes = {
|
|
162
|
+
data: PropTypes.objectOf(PropTypes.any).isRequired,
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export default View;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
@brown: #826a6a;
|
|
2
|
+
|
|
3
|
+
table.slate-table {
|
|
4
|
+
width: 100%;
|
|
5
|
+
border: 0.025rem solid @brown;
|
|
6
|
+
margin-top: 1rem;
|
|
7
|
+
margin-bottom: 1rem;
|
|
8
|
+
border-collapse: collapse;
|
|
9
|
+
border-spacing: 30px;
|
|
10
|
+
|
|
11
|
+
th,
|
|
12
|
+
td {
|
|
13
|
+
padding: 0.5rem;
|
|
14
|
+
border: 0.05rem solid @brown;
|
|
15
|
+
vertical-align: middle;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
th {
|
|
19
|
+
border-bottom: 0.15rem solid @brown;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
table.slate-table-block {
|
|
24
|
+
th p,
|
|
25
|
+
td p {
|
|
26
|
+
margin-top: 0;
|
|
27
|
+
margin-bottom: 0;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
table.slate-table-block.sortable {
|
|
32
|
+
tr th {
|
|
33
|
+
position: relative;
|
|
34
|
+
padding-right: 1.5em;
|
|
35
|
+
|
|
36
|
+
&::after {
|
|
37
|
+
position: absolute !important;
|
|
38
|
+
top: 50%;
|
|
39
|
+
right: 0.5em;
|
|
40
|
+
transform: translateY(-50%);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -42,6 +42,14 @@ import config from '@plone/volto/registry';
|
|
|
42
42
|
|
|
43
43
|
import backSVG from '@plone/volto/icons/back.svg';
|
|
44
44
|
|
|
45
|
+
const getPathname = (url) => {
|
|
46
|
+
try {
|
|
47
|
+
return new URL(url).pathname;
|
|
48
|
+
} catch {
|
|
49
|
+
return typeof url === 'string' && url.startsWith('/') ? url : null;
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
45
53
|
const messages = defineMessages({
|
|
46
54
|
back: {
|
|
47
55
|
id: 'Back',
|
|
@@ -213,32 +221,31 @@ class History extends Component {
|
|
|
213
221
|
defaultMessage="You can view the history of your item below."
|
|
214
222
|
/>
|
|
215
223
|
</Segment>
|
|
216
|
-
{
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
<Message
|
|
221
|
-
<
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
)}
|
|
224
|
+
{(() => {
|
|
225
|
+
const copiedToPath = getPathname(this.props.content?.copied_to);
|
|
226
|
+
return (
|
|
227
|
+
copiedToPath && (
|
|
228
|
+
<Message info icon attached="top">
|
|
229
|
+
<Icon name="arrow right" />
|
|
230
|
+
<Message.Content>
|
|
231
|
+
<Message.Header>
|
|
232
|
+
<FormattedMessage {...messages.newerVersionAvailable} />
|
|
233
|
+
</Message.Header>
|
|
234
|
+
<FormattedMessage
|
|
235
|
+
{...messages.thereIsNewerVersionAt}
|
|
236
|
+
values={{
|
|
237
|
+
link: (
|
|
238
|
+
<a href={`${copiedToPath}/historyview`}>
|
|
239
|
+
{copiedToPath.split('/').pop() || 'newer version'}
|
|
240
|
+
</a>
|
|
241
|
+
),
|
|
242
|
+
}}
|
|
243
|
+
/>
|
|
244
|
+
</Message.Content>
|
|
245
|
+
</Message>
|
|
246
|
+
)
|
|
247
|
+
);
|
|
248
|
+
})()}
|
|
242
249
|
<Table
|
|
243
250
|
selectable
|
|
244
251
|
compact
|
|
@@ -371,32 +378,31 @@ class History extends Component {
|
|
|
371
378
|
))}
|
|
372
379
|
</Table.Body>
|
|
373
380
|
</Table>
|
|
374
|
-
{
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
<Message
|
|
379
|
-
<
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
)}
|
|
381
|
+
{(() => {
|
|
382
|
+
const copiedFromPath = getPathname(this.props.content?.copied_from);
|
|
383
|
+
return (
|
|
384
|
+
copiedFromPath && (
|
|
385
|
+
<Message warning icon attached="bottom">
|
|
386
|
+
<Icon name="arrow left" />
|
|
387
|
+
<Message.Content>
|
|
388
|
+
<Message.Header>
|
|
389
|
+
<FormattedMessage {...messages.olderVersionAvailable} />
|
|
390
|
+
</Message.Header>
|
|
391
|
+
<FormattedMessage
|
|
392
|
+
{...messages.thereIsOlderVersionAt}
|
|
393
|
+
values={{
|
|
394
|
+
link: (
|
|
395
|
+
<a href={`${copiedFromPath}/historyview`}>
|
|
396
|
+
{copiedFromPath.split('/').pop() || 'older version'}
|
|
397
|
+
</a>
|
|
398
|
+
),
|
|
399
|
+
}}
|
|
400
|
+
/>
|
|
401
|
+
</Message.Content>
|
|
402
|
+
</Message>
|
|
403
|
+
)
|
|
404
|
+
);
|
|
405
|
+
})()}
|
|
400
406
|
</Segment.Group>
|
|
401
407
|
{this.state.isClient &&
|
|
402
408
|
createPortal(
|
|
@@ -438,8 +438,8 @@ class Comments extends Component {
|
|
|
438
438
|
open={this.state.showEdit}
|
|
439
439
|
onCancel={this.onEditCancel}
|
|
440
440
|
onOk={this.onEditOk}
|
|
441
|
-
id={this.state.editId}
|
|
442
|
-
text={this.state.editText}
|
|
441
|
+
id={this.state.editId ?? ''}
|
|
442
|
+
text={this.state.editText ?? ''}
|
|
443
443
|
/>
|
|
444
444
|
{permissions.can_reply && (
|
|
445
445
|
<div id="comment-add-id">
|
|
@@ -26,6 +26,21 @@ beforeAll(
|
|
|
26
26
|
await require('@plone/volto/helpers/Loadable/Loadable').__setLoadables(),
|
|
27
27
|
);
|
|
28
28
|
|
|
29
|
+
jest.mock('semantic-ui-react', () => {
|
|
30
|
+
const React = require('react');
|
|
31
|
+
const actual = jest.requireActual('semantic-ui-react');
|
|
32
|
+
const Dropdown = React.forwardRef(({ text, trigger, ...props }, ref) => {
|
|
33
|
+
const resolvedTrigger =
|
|
34
|
+
trigger || (typeof text === 'function' ? text() : text);
|
|
35
|
+
return <actual.Dropdown {...props} ref={ref} trigger={resolvedTrigger} />;
|
|
36
|
+
});
|
|
37
|
+
Dropdown.Menu = actual.Dropdown.Menu;
|
|
38
|
+
Dropdown.Item = actual.Dropdown.Item;
|
|
39
|
+
Dropdown.Header = actual.Dropdown.Header;
|
|
40
|
+
Dropdown.Divider = actual.Dropdown.Divider;
|
|
41
|
+
return { ...actual, Dropdown };
|
|
42
|
+
});
|
|
43
|
+
|
|
29
44
|
describe('Header', () => {
|
|
30
45
|
it('renders a header component with homepage_inverse_view layout', () => {
|
|
31
46
|
const store = mockStore({
|
|
@@ -383,24 +383,11 @@ describe('setupPrintView', () => {
|
|
|
383
383
|
});
|
|
384
384
|
document.body.appendChild(iframe);
|
|
385
385
|
|
|
386
|
-
// Mock the iframe to never fire load event, causing timeout
|
|
387
|
-
const originalSetTimeout = global.setTimeout;
|
|
388
|
-
let timeoutCallback;
|
|
389
|
-
global.setTimeout = jest.fn((callback, delay) => {
|
|
390
|
-
if (delay === 5000) {
|
|
391
|
-
// This is the iframe timeout
|
|
392
|
-
timeoutCallback = callback;
|
|
393
|
-
}
|
|
394
|
-
return originalSetTimeout(callback, delay);
|
|
395
|
-
});
|
|
396
|
-
|
|
397
386
|
await act(async () => {
|
|
398
387
|
setupPrintView(dispatch);
|
|
399
388
|
|
|
400
389
|
// Trigger the iframe timeout to simulate error condition
|
|
401
|
-
|
|
402
|
-
timeoutCallback();
|
|
403
|
-
}
|
|
390
|
+
jest.advanceTimersByTime(5000);
|
|
404
391
|
|
|
405
392
|
for (let i = 0; i < 10; i++) {
|
|
406
393
|
jest.runAllTimers();
|
|
@@ -410,9 +397,6 @@ describe('setupPrintView', () => {
|
|
|
410
397
|
|
|
411
398
|
// Should still call print even with timeout
|
|
412
399
|
expect(window.print).toHaveBeenCalled();
|
|
413
|
-
|
|
414
|
-
// Restore original setTimeout
|
|
415
|
-
global.setTimeout = originalSetTimeout;
|
|
416
400
|
});
|
|
417
401
|
|
|
418
402
|
it('prevents multiple resets of print state', async () => {
|