@@ -96,6 +96,122 @@ describe('withErrorBoundary', () => {
96
96
const Component = withErrorBoundary ( ( ) => < h1 > Hello World</ h1 > , { fallback : < h1 > fallback</ h1 > } ) ;
97
97
expect ( Component . displayName ) . toBe ( `errorBoundary(${ UNKNOWN_COMPONENT } )` ) ;
98
98
} ) ;
99
+
100
+ it ( 'does not rerender when props are identical' , ( ) => {
101
+ let renderCount = 0 ;
102
+ const TestComponent = ( { title } : { title : string } ) => {
103
+ renderCount ++ ;
104
+ return < h1 > { title } </ h1 > ;
105
+ } ;
106
+
107
+ const WrappedComponent = withErrorBoundary ( TestComponent , { fallback : < h1 > fallback</ h1 > } ) ;
108
+ const { rerender } = render ( < WrappedComponent title = "test" /> ) ;
109
+
110
+ expect ( renderCount ) . toBe ( 1 ) ;
111
+
112
+ // Rerender with identical props - should not cause TestComponent to rerender
113
+ rerender ( < WrappedComponent title = "test" /> ) ;
114
+ expect ( renderCount ) . toBe ( 1 ) ;
115
+
116
+ // Rerender with different props - should cause TestComponent to rerender
117
+ rerender ( < WrappedComponent title = "different" /> ) ;
118
+ expect ( renderCount ) . toBe ( 2 ) ;
119
+ } ) ;
120
+
121
+ it ( 'does not rerender when complex props are identical' , ( ) => {
122
+ let renderCount = 0 ;
123
+ const TestComponent = ( { data } : { data : { id : number ; name : string } } ) => {
124
+ renderCount ++ ;
125
+ return < h1 > { data . name } </ h1 > ;
126
+ } ;
127
+
128
+ const WrappedComponent = withErrorBoundary ( TestComponent , { fallback : < h1 > fallback</ h1 > } ) ;
129
+ const props = { data : { id : 1 , name : 'test' } } ;
130
+ const { rerender } = render ( < WrappedComponent { ...props } /> ) ;
131
+
132
+ expect ( renderCount ) . toBe ( 1 ) ;
133
+
134
+ // Rerender with same object reference - should not cause TestComponent to rerender
135
+ rerender ( < WrappedComponent { ...props } /> ) ;
136
+ expect ( renderCount ) . toBe ( 1 ) ;
137
+
138
+ // Rerender with different object but same values - should cause rerender
139
+ rerender ( < WrappedComponent data = { { id : 1 , name : 'test' } } /> ) ;
140
+ expect ( renderCount ) . toBe ( 2 ) ;
141
+
142
+ // Rerender with different values - should cause rerender
143
+ rerender ( < WrappedComponent data = { { id : 2 , name : 'different' } } /> ) ;
144
+ expect ( renderCount ) . toBe ( 3 ) ;
145
+ } ) ;
146
+
147
+ it ( 'does not rerender when errorBoundaryOptions are the same' , ( ) => {
148
+ let renderCount = 0 ;
149
+ const TestComponent = ( { title } : { title : string } ) => {
150
+ renderCount ++ ;
151
+ return < h1 > { title } </ h1 > ;
152
+ } ;
153
+
154
+ const errorBoundaryOptions = { fallback : < h1 > fallback</ h1 > } ;
155
+ const WrappedComponent = withErrorBoundary ( TestComponent , errorBoundaryOptions ) ;
156
+ const { rerender } = render ( < WrappedComponent title = "test" /> ) ;
157
+
158
+ expect ( renderCount ) . toBe ( 1 ) ;
159
+
160
+ // Rerender with identical props - should not cause TestComponent to rerender
161
+ rerender ( < WrappedComponent title = "test" /> ) ;
162
+ expect ( renderCount ) . toBe ( 1 ) ;
163
+ } ) ;
164
+
165
+ it ( 'preserves function component behavior with React.memo' , ( ) => {
166
+ const TestComponent = ( { title } : { title : string } ) => < h1 > { title } </ h1 > ;
167
+ const WrappedComponent = withErrorBoundary ( TestComponent , { fallback : < h1 > fallback</ h1 > } ) ;
168
+
169
+ expect ( WrappedComponent ) . toBeDefined ( ) ;
170
+ expect ( typeof WrappedComponent ) . toBe ( 'object' ) ;
171
+ expect ( WrappedComponent . displayName ) . toBe ( 'errorBoundary(TestComponent)' ) ;
172
+
173
+ const { container } = render ( < WrappedComponent title = "test" /> ) ;
174
+ expect ( container . innerHTML ) . toContain ( 'test' ) ;
175
+ } ) ;
176
+
177
+ it ( 'does not rerender parent component unnecessarily' , ( ) => {
178
+ let parentRenderCount = 0 ;
179
+ let childRenderCount = 0 ;
180
+
181
+ const ChildComponent = ( { value } : { value : number } ) => {
182
+ childRenderCount ++ ;
183
+ return < div > Child: { value } </ div > ;
184
+ } ;
185
+
186
+ const WrappedChild = withErrorBoundary ( ChildComponent , { fallback : < div > Error</ div > } ) ;
187
+
188
+ const ParentComponent = ( { childValue, otherProp } : { childValue : number ; otherProp : string } ) => {
189
+ parentRenderCount ++ ;
190
+ return (
191
+ < div >
192
+ < div > Parent: { otherProp } </ div >
193
+ < WrappedChild value = { childValue } />
194
+ </ div >
195
+ ) ;
196
+ } ;
197
+
198
+ const { rerender } = render ( < ParentComponent childValue = { 1 } otherProp = "test" /> ) ;
199
+
200
+ expect ( parentRenderCount ) . toBe ( 1 ) ;
201
+ expect ( childRenderCount ) . toBe ( 1 ) ;
202
+
203
+ // Change otherProp but keep childValue the same
204
+ rerender ( < ParentComponent childValue = { 1 } otherProp = "changed" /> ) ;
205
+
206
+ expect ( parentRenderCount ) . toBe ( 2 ) ; // Parent should rerender
207
+ expect ( childRenderCount ) . toBe ( 1 ) ; // Child should NOT rerender due to memo
208
+
209
+ // Change childValue
210
+ rerender ( < ParentComponent childValue = { 2 } otherProp = "changed" /> ) ;
211
+
212
+ expect ( parentRenderCount ) . toBe ( 3 ) ; // Parent should rerender
213
+ expect ( childRenderCount ) . toBe ( 2 ) ; // Child should rerender due to changed props
214
+ } ) ;
99
215
} ) ;
100
216
101
217
describe ( 'ErrorBoundary' , ( ) => {
0 commit comments