@eeacms/volto-eea-website-theme 3.15.0 → 3.16.0

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 CHANGED
@@ -4,15 +4,21 @@ 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.15.0](https://github.com/eea/volto-eea-website-theme/compare/3.14.1...3.15.0) - 3 December 2025
7
+ ### [3.16.0](https://github.com/eea/volto-eea-website-theme/compare/3.15.0...3.16.0) - 4 December 2025
8
8
 
9
9
  #### :rocket: New Features
10
10
 
11
- - feat: Add restricted options for group block - refs #294358 [dobri1408 - [`e23808d`](https://github.com/eea/volto-eea-website-theme/commit/e23808d2fa6ca252032b5a82915fe175b26be913)]
11
+ - feat: Custom Error boundary - refs #291209 [Nilesh - [`6d0cf06`](https://github.com/eea/volto-eea-website-theme/commit/6d0cf06d5c3603359eda6986c69e131e0265b8d9)]
12
12
 
13
13
  #### :hammer_and_wrench: Others
14
14
 
15
- - Release 3.15.0 [Alin Voinea - [`7ee262b`](https://github.com/eea/volto-eea-website-theme/commit/7ee262b0bcb09b221358bcc1d7c6b43464a86731)]
15
+ - Release 3.16.0 [Alin Voinea - [`d947957`](https://github.com/eea/volto-eea-website-theme/commit/d947957b1597a3b651da1b9581ce661fd441109f)]
16
+ ### [3.15.0](https://github.com/eea/volto-eea-website-theme/compare/3.14.1...3.15.0) - 3 December 2025
17
+
18
+ #### :rocket: New Features
19
+
20
+ - feat: Add restricted options for group block - refs #294358 [dobri1408 - [`e23808d`](https://github.com/eea/volto-eea-website-theme/commit/e23808d2fa6ca252032b5a82915fe175b26be913)]
21
+
16
22
  ### [3.14.1](https://github.com/eea/volto-eea-website-theme/compare/3.14.0...3.14.1) - 17 November 2025
17
23
 
18
24
  ### [3.14.0](https://github.com/eea/volto-eea-website-theme/compare/3.13.0...3.14.0) - 6 November 2025
@@ -11,6 +11,11 @@ msgstr ""
11
11
  "Content-Transfer-Encoding: \n"
12
12
  "Plural-Forms: \n"
13
13
 
14
+ #. Default: "Add"
15
+ #: components/theme/Widgets/SimpleArrayWidget
16
+ msgid "Add"
17
+ msgstr ""
18
+
14
19
  #. Default: "Choices"
15
20
  #: components/theme/Widgets/CreatableSelectWidget
16
21
  msgid "Choices"
@@ -51,11 +56,31 @@ msgstr ""
51
56
  msgid "Group"
52
57
  msgstr ""
53
58
 
59
+ #. Default: "Hide Children From Navigation"
60
+ #: components/theme/Widgets/NavigationBehaviorWidget
61
+ msgid "Hide Children From Navigation"
62
+ msgstr ""
63
+
54
64
  #. Default: "Invalid block - Will be removed on saving"
55
65
  #: components/manage/Blocks/GroupBlockTemplate/FlexGroup/RenderBlocks
56
66
  msgid "Invalid Block"
57
67
  msgstr ""
58
68
 
69
+ #. Default: "Load Main Navigation Routes"
70
+ #: components/theme/Widgets/NavigationBehaviorWidget
71
+ msgid "Load Main Navigation Routes"
72
+ msgstr ""
73
+
74
+ #. Default: "Menu Item Children List Columns"
75
+ #: components/theme/Widgets/NavigationBehaviorWidget
76
+ msgid "Menu Item Children List Columns"
77
+ msgstr ""
78
+
79
+ #. Default: "Menu Item Columns"
80
+ #: components/theme/Widgets/NavigationBehaviorWidget
81
+ msgid "Menu Item Columns"
82
+ msgstr ""
83
+
59
84
  #. Default: "Modified"
60
85
  #: components/theme/Banner/View
61
86
  msgid "Modified"
@@ -78,11 +103,21 @@ msgstr ""
78
103
  msgid "No value"
79
104
  msgstr ""
80
105
 
106
+ #. Default: "Preparing download"
107
+ #: components/theme/PrintLoader/PrintLoader
108
+ msgid "Preparing download"
109
+ msgstr ""
110
+
81
111
  #. Default: "Published"
82
112
  #: components/theme/Banner/View
83
113
  msgid "Published"
84
114
  msgstr ""
85
115
 
116
+ #. Default: "Remove"
117
+ #: components/theme/Widgets/SimpleArrayWidget
118
+ msgid "Remove"
119
+ msgstr ""
120
+
86
121
  #. Default: "Required"
87
122
  #: components/theme/Widgets/CreatableSelectWidget
88
123
  msgid "Required"
@@ -146,6 +181,16 @@ msgstr ""
146
181
  msgid "User"
147
182
  msgstr ""
148
183
 
184
+ #. Default: "Restrict access to this block based on user permissions"
185
+ #: index
186
+ msgid "restrictedBlockDescription"
187
+ msgstr ""
188
+
189
+ #. Default: "Restricted block"
190
+ #: index
191
+ msgid "restrictedBlockTitle"
192
+ msgstr ""
193
+
149
194
  #. Default: "RSS Feed"
150
195
  #: components/theme/Banner/View
151
196
  msgid "rssFeed"
@@ -11,6 +11,11 @@ msgstr ""
11
11
  "Content-Transfer-Encoding: \n"
12
12
  "Plural-Forms: \n"
13
13
 
14
+ #. Default: "Add"
15
+ #: components/theme/Widgets/SimpleArrayWidget
16
+ msgid "Add"
17
+ msgstr ""
18
+
14
19
  #. Default: "Choices"
15
20
  #: components/theme/Widgets/CreatableSelectWidget
16
21
  msgid "Choices"
@@ -51,11 +56,31 @@ msgstr ""
51
56
  msgid "Group"
52
57
  msgstr ""
53
58
 
59
+ #. Default: "Hide Children From Navigation"
60
+ #: components/theme/Widgets/NavigationBehaviorWidget
61
+ msgid "Hide Children From Navigation"
62
+ msgstr ""
63
+
54
64
  #. Default: "Invalid block - Will be removed on saving"
55
65
  #: components/manage/Blocks/GroupBlockTemplate/FlexGroup/RenderBlocks
56
66
  msgid "Invalid Block"
57
67
  msgstr ""
58
68
 
69
+ #. Default: "Load Main Navigation Routes"
70
+ #: components/theme/Widgets/NavigationBehaviorWidget
71
+ msgid "Load Main Navigation Routes"
72
+ msgstr ""
73
+
74
+ #. Default: "Menu Item Children List Columns"
75
+ #: components/theme/Widgets/NavigationBehaviorWidget
76
+ msgid "Menu Item Children List Columns"
77
+ msgstr ""
78
+
79
+ #. Default: "Menu Item Columns"
80
+ #: components/theme/Widgets/NavigationBehaviorWidget
81
+ msgid "Menu Item Columns"
82
+ msgstr ""
83
+
59
84
  #. Default: "Modified"
60
85
  #: components/theme/Banner/View
61
86
  msgid "Modified"
@@ -78,11 +103,21 @@ msgstr ""
78
103
  msgid "No value"
79
104
  msgstr ""
80
105
 
106
+ #. Default: "Preparing download"
107
+ #: components/theme/PrintLoader/PrintLoader
108
+ msgid "Preparing download"
109
+ msgstr ""
110
+
81
111
  #. Default: "Published"
82
112
  #: components/theme/Banner/View
83
113
  msgid "Published"
84
114
  msgstr ""
85
115
 
116
+ #. Default: "Remove"
117
+ #: components/theme/Widgets/SimpleArrayWidget
118
+ msgid "Remove"
119
+ msgstr ""
120
+
86
121
  #. Default: "Required"
87
122
  #: components/theme/Widgets/CreatableSelectWidget
88
123
  msgid "Required"
@@ -146,6 +181,16 @@ msgstr ""
146
181
  msgid "User"
147
182
  msgstr ""
148
183
 
184
+ #. Default: "Restrict access to this block based on user permissions"
185
+ #: index
186
+ msgid "restrictedBlockDescription"
187
+ msgstr ""
188
+
189
+ #. Default: "Restricted block"
190
+ #: index
191
+ msgid "restrictedBlockTitle"
192
+ msgstr ""
193
+
149
194
  #. Default: "RSS Feed"
150
195
  #: components/theme/Banner/View
151
196
  msgid "rssFeed"
@@ -11,6 +11,11 @@ msgstr ""
11
11
  "Content-Transfer-Encoding: \n"
12
12
  "Plural-Forms: \n"
13
13
 
14
+ #. Default: "Add"
15
+ #: components/theme/Widgets/SimpleArrayWidget
16
+ msgid "Add"
17
+ msgstr ""
18
+
14
19
  #. Default: "Choices"
15
20
  #: components/theme/Widgets/CreatableSelectWidget
16
21
  msgid "Choices"
@@ -51,11 +56,31 @@ msgstr ""
51
56
  msgid "Group"
52
57
  msgstr ""
53
58
 
59
+ #. Default: "Hide Children From Navigation"
60
+ #: components/theme/Widgets/NavigationBehaviorWidget
61
+ msgid "Hide Children From Navigation"
62
+ msgstr ""
63
+
54
64
  #. Default: "Invalid block - Will be removed on saving"
55
65
  #: components/manage/Blocks/GroupBlockTemplate/FlexGroup/RenderBlocks
56
66
  msgid "Invalid Block"
57
67
  msgstr ""
58
68
 
69
+ #. Default: "Load Main Navigation Routes"
70
+ #: components/theme/Widgets/NavigationBehaviorWidget
71
+ msgid "Load Main Navigation Routes"
72
+ msgstr ""
73
+
74
+ #. Default: "Menu Item Children List Columns"
75
+ #: components/theme/Widgets/NavigationBehaviorWidget
76
+ msgid "Menu Item Children List Columns"
77
+ msgstr ""
78
+
79
+ #. Default: "Menu Item Columns"
80
+ #: components/theme/Widgets/NavigationBehaviorWidget
81
+ msgid "Menu Item Columns"
82
+ msgstr ""
83
+
59
84
  #. Default: "Modified"
60
85
  #: components/theme/Banner/View
61
86
  msgid "Modified"
@@ -78,11 +103,21 @@ msgstr ""
78
103
  msgid "No value"
79
104
  msgstr ""
80
105
 
106
+ #. Default: "Preparing download"
107
+ #: components/theme/PrintLoader/PrintLoader
108
+ msgid "Preparing download"
109
+ msgstr ""
110
+
81
111
  #. Default: "Published"
82
112
  #: components/theme/Banner/View
83
113
  msgid "Published"
84
114
  msgstr ""
85
115
 
116
+ #. Default: "Remove"
117
+ #: components/theme/Widgets/SimpleArrayWidget
118
+ msgid "Remove"
119
+ msgstr ""
120
+
86
121
  #. Default: "Required"
87
122
  #: components/theme/Widgets/CreatableSelectWidget
88
123
  msgid "Required"
@@ -146,6 +181,16 @@ msgstr ""
146
181
  msgid "User"
147
182
  msgstr ""
148
183
 
184
+ #. Default: "Restrict access to this block based on user permissions"
185
+ #: index
186
+ msgid "restrictedBlockDescription"
187
+ msgstr ""
188
+
189
+ #. Default: "Restricted block"
190
+ #: index
191
+ msgid "restrictedBlockTitle"
192
+ msgstr ""
193
+
149
194
  #. Default: "RSS Feed"
150
195
  #: components/theme/Banner/View
151
196
  msgid "rssFeed"
@@ -11,6 +11,11 @@ msgstr ""
11
11
  "Content-Transfer-Encoding: \n"
12
12
  "Plural-Forms: \n"
13
13
 
14
+ #. Default: "Add"
15
+ #: components/theme/Widgets/SimpleArrayWidget
16
+ msgid "Add"
17
+ msgstr ""
18
+
14
19
  #. Default: "Choices"
15
20
  #: components/theme/Widgets/CreatableSelectWidget
16
21
  msgid "Choices"
@@ -51,11 +56,31 @@ msgstr ""
51
56
  msgid "Group"
52
57
  msgstr ""
53
58
 
59
+ #. Default: "Hide Children From Navigation"
60
+ #: components/theme/Widgets/NavigationBehaviorWidget
61
+ msgid "Hide Children From Navigation"
62
+ msgstr ""
63
+
54
64
  #. Default: "Invalid block - Will be removed on saving"
55
65
  #: components/manage/Blocks/GroupBlockTemplate/FlexGroup/RenderBlocks
56
66
  msgid "Invalid Block"
57
67
  msgstr ""
58
68
 
69
+ #. Default: "Load Main Navigation Routes"
70
+ #: components/theme/Widgets/NavigationBehaviorWidget
71
+ msgid "Load Main Navigation Routes"
72
+ msgstr ""
73
+
74
+ #. Default: "Menu Item Children List Columns"
75
+ #: components/theme/Widgets/NavigationBehaviorWidget
76
+ msgid "Menu Item Children List Columns"
77
+ msgstr ""
78
+
79
+ #. Default: "Menu Item Columns"
80
+ #: components/theme/Widgets/NavigationBehaviorWidget
81
+ msgid "Menu Item Columns"
82
+ msgstr ""
83
+
59
84
  #. Default: "Modified"
60
85
  #: components/theme/Banner/View
61
86
  msgid "Modified"
@@ -78,11 +103,21 @@ msgstr ""
78
103
  msgid "No value"
79
104
  msgstr ""
80
105
 
106
+ #. Default: "Preparing download"
107
+ #: components/theme/PrintLoader/PrintLoader
108
+ msgid "Preparing download"
109
+ msgstr ""
110
+
81
111
  #. Default: "Published"
82
112
  #: components/theme/Banner/View
83
113
  msgid "Published"
84
114
  msgstr ""
85
115
 
116
+ #. Default: "Remove"
117
+ #: components/theme/Widgets/SimpleArrayWidget
118
+ msgid "Remove"
119
+ msgstr ""
120
+
86
121
  #. Default: "Required"
87
122
  #: components/theme/Widgets/CreatableSelectWidget
88
123
  msgid "Required"
@@ -146,6 +181,16 @@ msgstr ""
146
181
  msgid "User"
147
182
  msgstr ""
148
183
 
184
+ #. Default: "Restrict access to this block based on user permissions"
185
+ #: index
186
+ msgid "restrictedBlockDescription"
187
+ msgstr ""
188
+
189
+ #. Default: "Restricted block"
190
+ #: index
191
+ msgid "restrictedBlockTitle"
192
+ msgstr ""
193
+
149
194
  #. Default: "RSS Feed"
150
195
  #: components/theme/Banner/View
151
196
  msgid "rssFeed"
package/locales/volto.pot CHANGED
@@ -1,7 +1,7 @@
1
1
  msgid ""
2
2
  msgstr ""
3
3
  "Project-Id-Version: Plone\n"
4
- "POT-Creation-Date: 2025-06-01T18:42:16.532Z\n"
4
+ "POT-Creation-Date: 2025-12-04T18:19:53.476Z\n"
5
5
  "Last-Translator: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
6
6
  "Language-Team: Plone i18n <plone-i18n@lists.sourceforge.net>\n"
7
7
  "Content-Type: text/plain; charset=utf-8\n"
@@ -13,6 +13,11 @@ msgstr ""
13
13
  "Preferred-Encodings: utf-8\n"
14
14
  "Domain: volto\n"
15
15
 
16
+ #. Default: "Add"
17
+ #: components/theme/Widgets/SimpleArrayWidget
18
+ msgid "Add"
19
+ msgstr ""
20
+
16
21
  #. Default: "Choices"
17
22
  #: components/theme/Widgets/CreatableSelectWidget
18
23
  msgid "Choices"
@@ -53,11 +58,31 @@ msgstr ""
53
58
  msgid "Group"
54
59
  msgstr ""
55
60
 
61
+ #. Default: "Hide Children From Navigation"
62
+ #: components/theme/Widgets/NavigationBehaviorWidget
63
+ msgid "Hide Children From Navigation"
64
+ msgstr ""
65
+
56
66
  #. Default: "Invalid block - Will be removed on saving"
57
67
  #: components/manage/Blocks/GroupBlockTemplate/FlexGroup/RenderBlocks
58
68
  msgid "Invalid Block"
59
69
  msgstr ""
60
70
 
71
+ #. Default: "Load Main Navigation Routes"
72
+ #: components/theme/Widgets/NavigationBehaviorWidget
73
+ msgid "Load Main Navigation Routes"
74
+ msgstr ""
75
+
76
+ #. Default: "Menu Item Children List Columns"
77
+ #: components/theme/Widgets/NavigationBehaviorWidget
78
+ msgid "Menu Item Children List Columns"
79
+ msgstr ""
80
+
81
+ #. Default: "Menu Item Columns"
82
+ #: components/theme/Widgets/NavigationBehaviorWidget
83
+ msgid "Menu Item Columns"
84
+ msgstr ""
85
+
61
86
  #. Default: "Modified"
62
87
  #: components/theme/Banner/View
63
88
  msgid "Modified"
@@ -80,11 +105,21 @@ msgstr ""
80
105
  msgid "No value"
81
106
  msgstr ""
82
107
 
108
+ #. Default: "Preparing download"
109
+ #: components/theme/PrintLoader/PrintLoader
110
+ msgid "Preparing download"
111
+ msgstr ""
112
+
83
113
  #. Default: "Published"
84
114
  #: components/theme/Banner/View
85
115
  msgid "Published"
86
116
  msgstr ""
87
117
 
118
+ #. Default: "Remove"
119
+ #: components/theme/Widgets/SimpleArrayWidget
120
+ msgid "Remove"
121
+ msgstr ""
122
+
88
123
  #. Default: "Required"
89
124
  #: components/theme/Widgets/CreatableSelectWidget
90
125
  msgid "Required"
@@ -148,6 +183,16 @@ msgstr ""
148
183
  msgid "User"
149
184
  msgstr ""
150
185
 
186
+ #. Default: "Restrict access to this block based on user permissions"
187
+ #: index
188
+ msgid "restrictedBlockDescription"
189
+ msgstr ""
190
+
191
+ #. Default: "Restricted block"
192
+ #: index
193
+ msgid "restrictedBlockTitle"
194
+ msgstr ""
195
+
151
196
  #. Default: "RSS Feed"
152
197
  #: components/theme/Banner/View
153
198
  msgid "rssFeed"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-eea-website-theme",
3
- "version": "3.15.0",
3
+ "version": "3.16.0",
4
4
  "description": "@eeacms/volto-eea-website-theme: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -0,0 +1,47 @@
1
+ import React from 'react';
2
+ import config from '@plone/volto/registry';
3
+
4
+ class ErrorBoundary extends React.Component {
5
+ constructor(props) {
6
+ super(props);
7
+ this.state = { hasError: false, error: null };
8
+ }
9
+
10
+ static getDerivedStateFromError(error) {
11
+ return { hasError: true, error };
12
+ }
13
+
14
+ componentDidCatch(error, errorInfo) {
15
+ if (this.props.error) {
16
+ //pass error to error-reporting service
17
+ config.settings.errorHandlers?.forEach((handler) => {
18
+ if (typeof handler === 'function') {
19
+ handler(error);
20
+ }
21
+ });
22
+ if (this.props.onError) {
23
+ this.props.onError(error, errorInfo);
24
+ }
25
+ } else {
26
+ // eslint-disable-next-line
27
+ console.error(error, errorInfo);
28
+ }
29
+ }
30
+
31
+ render() {
32
+ const ErrorPage =
33
+ this.props.fallback || config.getComponent('ErrorBoundary')?.component;
34
+ if (this.state.hasError) {
35
+ if (ErrorPage) {
36
+ // You can render any custom fallback UI
37
+ return <ErrorPage name={this.props.name} error={this.state.error} />;
38
+ } else {
39
+ return <pre className="error">{`<error: ${this.props.name}>`}</pre>;
40
+ }
41
+ }
42
+
43
+ return this.props.children;
44
+ }
45
+ }
46
+
47
+ export default ErrorBoundary;
@@ -80,10 +80,16 @@ if (middleware.length) server.use('/', middleware);
80
80
  server.use(function (err, req, res, next) {
81
81
  if (err) {
82
82
  const { store } = res.locals;
83
+ const ErrorComponent =
84
+ config.getComponent('ErrorBoundary')?.component || null;
83
85
  const errorPage = (
84
86
  <Provider store={store} onError={reactIntlErrorHandler}>
85
87
  <StaticRouter context={{}} location={req.url}>
86
- <ErrorPage message={err.message} />
88
+ {ErrorComponent ? (
89
+ <ErrorComponent error={err} />
90
+ ) : (
91
+ <ErrorPage message={err.message} />
92
+ )}
87
93
  </StaticRouter>
88
94
  </Provider>
89
95
  );
@@ -157,10 +163,16 @@ function setupServer(req, res, next) {
157
163
  const store = configureStore(initialState, history, api);
158
164
 
159
165
  function errorHandler(error) {
166
+ const ErrorComponent =
167
+ config.getComponent('ErrorBoundary').component || null;
160
168
  const errorPage = (
161
169
  <Provider store={store} onError={reactIntlErrorHandler}>
162
170
  <StaticRouter context={{}} location={req.url}>
163
- <ErrorPage message={error.message} />
171
+ {ErrorComponent ? (
172
+ <ErrorComponent error={error} />
173
+ ) : (
174
+ <ErrorPage message={error.message} />
175
+ )}
164
176
  </StaticRouter>
165
177
  </Provider>
166
178
  );
@@ -0,0 +1,29 @@
1
+ import React from 'react';
2
+ import { ErrorBoundary } from '@plone/volto/components';
3
+
4
+ export default function withErrorBoundary(WrappedComponent, options = {}) {
5
+ // Handle backward compatibility - if second param is a component, treat as fallback
6
+ const config =
7
+ React.isValidElement(options) || typeof options === 'function'
8
+ ? { fallback: options }
9
+ : {
10
+ fallback: null,
11
+ onError: null,
12
+ ...options,
13
+ };
14
+
15
+ const ErrorBoundaryWrapper = React.memo(function ErrorBoundaryWrapper(props) {
16
+ const { fallback, onError } = config;
17
+
18
+ return (
19
+ <ErrorBoundary fallback={fallback} onError={onError}>
20
+ <WrappedComponent {...props} />
21
+ </ErrorBoundary>
22
+ );
23
+ });
24
+
25
+ const wrappedComponentName = WrappedComponent.displayName || 'Component';
26
+ ErrorBoundaryWrapper.displayName = `withErrorBoundary(${wrappedComponentName})`;
27
+
28
+ return ErrorBoundaryWrapper;
29
+ }
@@ -0,0 +1,104 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import '@testing-library/jest-dom';
3
+ import { ErrorBoundary } from '@plone/volto/components';
4
+ import withErrorBoundary from './withErrorBoundary';
5
+
6
+ // Mock the ErrorBoundary component from Volto
7
+ jest.mock('@plone/volto/components', () => ({
8
+ ErrorBoundary: jest.fn(({ children, fallback, onError }) => {
9
+ try {
10
+ return children;
11
+ } catch (error) {
12
+ if (onError) onError(error, { componentStack: 'test-stack' });
13
+ return fallback || <div>Error occurred</div>;
14
+ }
15
+ }),
16
+ }));
17
+
18
+ // Test components
19
+ const TestComponent = ({ shouldThrow, message = 'Hello World' }) => {
20
+ if (shouldThrow) {
21
+ throw new Error('Test error');
22
+ }
23
+ return <div>{message}</div>;
24
+ };
25
+
26
+ const CustomFallback = () => <div>Custom error fallback</div>;
27
+
28
+ describe('withErrorBoundary HOC', () => {
29
+ beforeEach(() => {
30
+ jest.clearAllMocks();
31
+ });
32
+
33
+ describe('Basic functionality', () => {
34
+ it('should render the wrapped component normally', () => {
35
+ const WrappedComponent = withErrorBoundary(TestComponent);
36
+ render(<WrappedComponent message="Test message" />);
37
+
38
+ expect(screen.getByText('Test message')).toBeInTheDocument();
39
+ });
40
+
41
+ it('should pass through all props to the wrapped component', () => {
42
+ const WrappedComponent = withErrorBoundary(TestComponent);
43
+ render(<WrappedComponent message="Test props" data-testid="test" />);
44
+
45
+ expect(screen.getByText('Test props')).toBeInTheDocument();
46
+ });
47
+ });
48
+
49
+ describe('Error boundary configuration', () => {
50
+ it('should use default ErrorBoundary when no fallback is provided', () => {
51
+ const WrappedComponent = withErrorBoundary(TestComponent);
52
+ render(<WrappedComponent />);
53
+
54
+ expect(ErrorBoundary).toHaveBeenCalledWith(
55
+ expect.objectContaining({
56
+ fallback: null,
57
+ onError: null,
58
+ }),
59
+ expect.any(Object),
60
+ );
61
+ });
62
+
63
+ it('should accept a custom fallback component', () => {
64
+ const WrappedComponent = withErrorBoundary(TestComponent, {
65
+ fallback: CustomFallback,
66
+ });
67
+ render(<WrappedComponent />);
68
+
69
+ expect(ErrorBoundary).toHaveBeenCalledWith(
70
+ expect.objectContaining({
71
+ fallback: CustomFallback,
72
+ }),
73
+ expect.any(Object),
74
+ );
75
+ });
76
+
77
+ it('should handle backward compatibility with fallback as second parameter', () => {
78
+ const WrappedComponent = withErrorBoundary(TestComponent, CustomFallback);
79
+ render(<WrappedComponent />);
80
+
81
+ expect(ErrorBoundary).toHaveBeenCalledWith(
82
+ expect.objectContaining({
83
+ fallback: CustomFallback,
84
+ }),
85
+ expect.any(Object),
86
+ );
87
+ });
88
+
89
+ it('should call onError callback when provided', () => {
90
+ const onErrorMock = jest.fn();
91
+ const WrappedComponent = withErrorBoundary(TestComponent, {
92
+ onError: onErrorMock,
93
+ });
94
+ render(<WrappedComponent />);
95
+
96
+ expect(ErrorBoundary).toHaveBeenCalledWith(
97
+ expect.objectContaining({
98
+ onError: onErrorMock,
99
+ }),
100
+ expect.any(Object),
101
+ );
102
+ });
103
+ });
104
+ });