@umituz/react-native-settings 2.0.0 → 2.4.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.
Files changed (160) hide show
  1. package/README.md +129 -3
  2. package/lib/__tests__/setup.d.ts +5 -0
  3. package/lib/__tests__/setup.d.ts.map +1 -0
  4. package/lib/__tests__/setup.js +143 -0
  5. package/lib/__tests__/setup.js.map +1 -0
  6. package/lib/domain/repositories/ISettingsRepository.d.ts +51 -0
  7. package/lib/domain/repositories/ISettingsRepository.d.ts.map +1 -0
  8. package/lib/domain/repositories/ISettingsRepository.js +8 -0
  9. package/lib/domain/repositories/ISettingsRepository.js.map +1 -0
  10. package/lib/index.d.ts +35 -0
  11. package/lib/index.d.ts.map +1 -0
  12. package/lib/index.js +32 -0
  13. package/lib/index.js.map +1 -0
  14. package/lib/infrastructure/storage/SettingsStore.d.ts +36 -0
  15. package/lib/infrastructure/storage/SettingsStore.d.ts.map +1 -0
  16. package/lib/infrastructure/storage/SettingsStore.js +144 -0
  17. package/lib/infrastructure/storage/SettingsStore.js.map +1 -0
  18. package/lib/presentation/components/CloudSyncSetting.d.ts +16 -0
  19. package/lib/presentation/components/CloudSyncSetting.d.ts.map +1 -0
  20. package/lib/presentation/components/CloudSyncSetting.js +30 -0
  21. package/lib/presentation/components/CloudSyncSetting.js.map +1 -0
  22. package/lib/presentation/components/DisclaimerCard.d.ts +15 -0
  23. package/lib/presentation/components/DisclaimerCard.d.ts.map +1 -0
  24. package/lib/presentation/components/DisclaimerCard.js +73 -0
  25. package/lib/presentation/components/DisclaimerCard.js.map +1 -0
  26. package/lib/presentation/components/DisclaimerModal.d.ts +13 -0
  27. package/lib/presentation/components/DisclaimerModal.d.ts.map +1 -0
  28. package/lib/presentation/components/DisclaimerModal.js +62 -0
  29. package/lib/presentation/components/DisclaimerModal.js.map +1 -0
  30. package/lib/presentation/components/DisclaimerSetting.d.ts +39 -0
  31. package/lib/presentation/components/DisclaimerSetting.d.ts.map +1 -0
  32. package/lib/presentation/components/DisclaimerSetting.js +59 -0
  33. package/lib/presentation/components/DisclaimerSetting.js.map +1 -0
  34. package/lib/presentation/components/SettingItem.d.ts +45 -0
  35. package/lib/presentation/components/SettingItem.d.ts.map +1 -0
  36. package/lib/presentation/components/SettingItem.js +113 -0
  37. package/lib/presentation/components/SettingItem.js.map +1 -0
  38. package/lib/presentation/components/SettingsErrorBoundary.d.ts +23 -0
  39. package/lib/presentation/components/SettingsErrorBoundary.d.ts.map +1 -0
  40. package/lib/presentation/components/SettingsErrorBoundary.js +73 -0
  41. package/lib/presentation/components/SettingsErrorBoundary.js.map +1 -0
  42. package/lib/presentation/components/SettingsFooter.d.ts +11 -0
  43. package/lib/presentation/components/SettingsFooter.d.ts.map +1 -0
  44. package/lib/presentation/components/SettingsFooter.js +31 -0
  45. package/lib/presentation/components/SettingsFooter.js.map +1 -0
  46. package/lib/presentation/components/SettingsSection.d.ts +13 -0
  47. package/lib/presentation/components/SettingsSection.d.ts.map +1 -0
  48. package/lib/presentation/components/SettingsSection.js +37 -0
  49. package/lib/presentation/components/SettingsSection.js.map +1 -0
  50. package/lib/presentation/components/StorageClearSetting.d.ts +16 -0
  51. package/lib/presentation/components/StorageClearSetting.d.ts.map +1 -0
  52. package/lib/presentation/components/StorageClearSetting.js +21 -0
  53. package/lib/presentation/components/StorageClearSetting.js.map +1 -0
  54. package/lib/presentation/components/UserProfileHeader.d.ts +30 -0
  55. package/lib/presentation/components/UserProfileHeader.d.ts.map +1 -0
  56. package/lib/presentation/components/UserProfileHeader.js +119 -0
  57. package/lib/presentation/components/UserProfileHeader.js.map +1 -0
  58. package/lib/presentation/screens/AppearanceScreen.d.ts +8 -0
  59. package/lib/presentation/screens/AppearanceScreen.d.ts.map +1 -0
  60. package/lib/presentation/screens/AppearanceScreen.js +8 -0
  61. package/lib/presentation/screens/AppearanceScreen.js.map +1 -0
  62. package/lib/presentation/screens/SettingsScreen.d.ts +38 -0
  63. package/lib/presentation/screens/SettingsScreen.d.ts.map +1 -0
  64. package/lib/presentation/screens/SettingsScreen.js +37 -0
  65. package/lib/presentation/screens/SettingsScreen.js.map +1 -0
  66. package/lib/presentation/screens/components/AboutLegalSection.d.ts +15 -0
  67. package/lib/presentation/screens/components/AboutLegalSection.d.ts.map +1 -0
  68. package/lib/presentation/screens/components/AboutLegalSection.js +28 -0
  69. package/lib/presentation/screens/components/AboutLegalSection.js.map +1 -0
  70. package/lib/presentation/screens/components/AppearanceSection.d.ts +12 -0
  71. package/lib/presentation/screens/components/AppearanceSection.d.ts.map +1 -0
  72. package/lib/presentation/screens/components/AppearanceSection.js +21 -0
  73. package/lib/presentation/screens/components/AppearanceSection.js.map +1 -0
  74. package/lib/presentation/screens/components/LanguageSection.d.ts +12 -0
  75. package/lib/presentation/screens/components/LanguageSection.d.ts.map +1 -0
  76. package/lib/presentation/screens/components/LanguageSection.js +26 -0
  77. package/lib/presentation/screens/components/LanguageSection.js.map +1 -0
  78. package/lib/presentation/screens/components/NotificationsSection.d.ts +12 -0
  79. package/lib/presentation/screens/components/NotificationsSection.d.ts.map +1 -0
  80. package/lib/presentation/screens/components/NotificationsSection.js +58 -0
  81. package/lib/presentation/screens/components/NotificationsSection.js.map +1 -0
  82. package/lib/presentation/screens/components/SettingsContent.d.ts +36 -0
  83. package/lib/presentation/screens/components/SettingsContent.d.ts.map +1 -0
  84. package/lib/presentation/screens/components/SettingsContent.js +81 -0
  85. package/lib/presentation/screens/components/SettingsContent.js.map +1 -0
  86. package/lib/presentation/screens/components/SettingsHeader.d.ts +12 -0
  87. package/lib/presentation/screens/components/SettingsHeader.d.ts.map +1 -0
  88. package/lib/presentation/screens/components/SettingsHeader.js +59 -0
  89. package/lib/presentation/screens/components/SettingsHeader.js.map +1 -0
  90. package/lib/presentation/screens/components/index.d.ts +9 -0
  91. package/lib/presentation/screens/components/index.d.ts.map +1 -0
  92. package/lib/presentation/screens/components/index.js +9 -0
  93. package/lib/presentation/screens/components/index.js.map +1 -0
  94. package/lib/presentation/screens/hooks/useFeatureDetection.d.ts +21 -0
  95. package/lib/presentation/screens/hooks/useFeatureDetection.d.ts.map +1 -0
  96. package/lib/presentation/screens/hooks/useFeatureDetection.js +82 -0
  97. package/lib/presentation/screens/hooks/useFeatureDetection.js.map +1 -0
  98. package/lib/presentation/screens/types/CustomSection.d.ts +19 -0
  99. package/lib/presentation/screens/types/CustomSection.d.ts.map +1 -0
  100. package/lib/presentation/screens/types/CustomSection.js +6 -0
  101. package/lib/presentation/screens/types/CustomSection.js.map +1 -0
  102. package/lib/presentation/screens/types/ExtendedConfig.d.ts +68 -0
  103. package/lib/presentation/screens/types/ExtendedConfig.d.ts.map +1 -0
  104. package/lib/presentation/screens/types/ExtendedConfig.js +6 -0
  105. package/lib/presentation/screens/types/ExtendedConfig.js.map +1 -0
  106. package/lib/presentation/screens/types/FeatureConfig.d.ts +95 -0
  107. package/lib/presentation/screens/types/FeatureConfig.d.ts.map +1 -0
  108. package/lib/presentation/screens/types/FeatureConfig.js +6 -0
  109. package/lib/presentation/screens/types/FeatureConfig.js.map +1 -0
  110. package/lib/presentation/screens/types/SettingsConfig.d.ts +97 -0
  111. package/lib/presentation/screens/types/SettingsConfig.d.ts.map +1 -0
  112. package/lib/presentation/screens/types/SettingsConfig.js +6 -0
  113. package/lib/presentation/screens/types/SettingsConfig.js.map +1 -0
  114. package/lib/presentation/screens/types/index.d.ts +10 -0
  115. package/lib/presentation/screens/types/index.d.ts.map +1 -0
  116. package/lib/presentation/screens/types/index.js +6 -0
  117. package/lib/presentation/screens/types/index.js.map +1 -0
  118. package/lib/presentation/screens/utils/normalizeConfig.d.ts +44 -0
  119. package/lib/presentation/screens/utils/normalizeConfig.d.ts.map +1 -0
  120. package/lib/presentation/screens/utils/normalizeConfig.js +38 -0
  121. package/lib/presentation/screens/utils/normalizeConfig.js.map +1 -0
  122. package/package.json +46 -11
  123. package/src/__tests__/integration.test.tsx +371 -0
  124. package/src/__tests__/performance.test.tsx +369 -0
  125. package/src/__tests__/setup.test.tsx +20 -0
  126. package/src/__tests__/setup.ts +157 -0
  127. package/src/index.ts +9 -0
  128. package/src/infrastructure/storage/SettingsStore.ts +90 -45
  129. package/src/infrastructure/storage/__tests__/SettingsStore.test.tsx +302 -0
  130. package/src/presentation/components/CloudSyncSetting.tsx +11 -17
  131. package/src/presentation/components/DisclaimerCard.tsx +115 -0
  132. package/src/presentation/components/DisclaimerModal.tsx +104 -0
  133. package/src/presentation/components/DisclaimerSetting.tsx +77 -159
  134. package/src/presentation/components/SettingItem.tsx +11 -2
  135. package/src/presentation/components/SettingsErrorBoundary.tsx +126 -0
  136. package/src/presentation/components/StorageClearSetting.tsx +13 -8
  137. package/src/presentation/components/UserProfileHeader.tsx +48 -11
  138. package/src/presentation/components/__tests__/CloudSyncSetting.test.tsx +78 -0
  139. package/src/presentation/components/__tests__/DisclaimerCard.test.tsx +208 -0
  140. package/src/presentation/components/__tests__/DisclaimerModal.test.tsx +236 -0
  141. package/src/presentation/components/__tests__/DisclaimerSetting.test.tsx +74 -0
  142. package/src/presentation/components/__tests__/SettingItem.test.tsx +189 -0
  143. package/src/presentation/components/__tests__/SettingsErrorBoundary.test.tsx +186 -0
  144. package/src/presentation/screens/SettingsScreen.tsx +29 -159
  145. package/src/presentation/screens/__tests__/SettingsScreen.test.tsx +322 -0
  146. package/src/presentation/screens/components/AboutLegalSection.tsx +14 -5
  147. package/src/presentation/screens/components/AppearanceSection.tsx +1 -1
  148. package/src/presentation/screens/components/LanguageSection.tsx +2 -1
  149. package/src/presentation/screens/components/NotificationsSection.tsx +19 -14
  150. package/src/presentation/screens/components/SettingsContent.tsx +167 -0
  151. package/src/presentation/screens/components/SettingsHeader.tsx +79 -0
  152. package/src/presentation/screens/hooks/__tests__/useFeatureDetection.test.tsx +261 -0
  153. package/src/presentation/screens/hooks/useFeatureDetection.ts +15 -5
  154. package/src/presentation/screens/types/CustomSection.ts +20 -0
  155. package/src/presentation/screens/types/ExtendedConfig.ts +68 -0
  156. package/src/presentation/screens/types/FeatureConfig.ts +102 -0
  157. package/src/presentation/screens/types/SettingsConfig.ts +116 -0
  158. package/src/presentation/screens/types/index.ts +20 -0
  159. package/src/presentation/screens/utils/normalizeConfig.ts +2 -1
  160. package/src/presentation/screens/types.ts +0 -263
@@ -0,0 +1,371 @@
1
+ /**
2
+ * Integration Tests for Settings Package
3
+ * Tests component interactions and data flow
4
+ */
5
+
6
+ import React from 'react';
7
+ import { render, fireEvent, waitFor } from '@testing-library/react-native';
8
+ import { NavigationContainer } from '@react-navigation/native';
9
+ import { SettingsScreen } from '../../screens/SettingsScreen';
10
+ import { useSettings } from '../../../infrastructure/storage/SettingsStore';
11
+
12
+ // Mock all dependencies
13
+ jest.mock('@umituz/react-native-design-system-theme', () => ({
14
+ useDesignSystemTheme: () => ({
15
+ themeMode: 'light',
16
+ }),
17
+ useAppDesignTokens: () => ({
18
+ colors: {
19
+ backgroundPrimary: '#ffffff',
20
+ },
21
+ }),
22
+ }));
23
+
24
+ jest.mock('@umituz/react-native-localization', () => ({
25
+ useLocalization: () => ({
26
+ t: (key: string) => key,
27
+ }),
28
+ }));
29
+
30
+ jest.mock('@umituz/react-native-storage', () => ({
31
+ storageRepository: {
32
+ getItem: jest.fn(),
33
+ setItem: jest.fn(),
34
+ },
35
+ StorageKey: {
36
+ SETTINGS: 'settings',
37
+ },
38
+ createUserKey: (key: string, userId: string) => `${key}_${userId}`,
39
+ unwrap: (result: any, defaultValue: any) => result.success ? result.data : defaultValue,
40
+ }));
41
+
42
+ jest.mock('../../components/SettingsHeader', () => {
43
+ const { View } = require('react-native');
44
+ return {
45
+ SettingsHeader: ({ showCloseButton, onClose }: any) => (
46
+ <View testID="settings-header">
47
+ {showCloseButton && <View testID="close-button" onTouchEnd={onClose} />}
48
+ </View>
49
+ ),
50
+ };
51
+ });
52
+
53
+ jest.mock('../../components/SettingsContent', () => {
54
+ const { View } = require('react-native');
55
+ return {
56
+ SettingsContent: ({ normalizedConfig, features, showUserProfile, userProfile, showFooter, footerText, customSections, showCloseButton }: any) => (
57
+ <View testID="settings-content">
58
+ <View testID="config-data">{JSON.stringify(normalizedConfig)}</View>
59
+ <View testID="features-data">{JSON.stringify(features)}</View>
60
+ {showUserProfile && <View testID="user-profile">{JSON.stringify(userProfile)}</View>}
61
+ {showFooter && <View testID="footer">{footerText || 'default-footer'}</View>}
62
+ {customSections && <View testID="custom-sections">{JSON.stringify(customSections)}</View>}
63
+ {showCloseButton && <View testID="content-close-button" />}
64
+ </View>
65
+ ),
66
+ };
67
+ });
68
+
69
+ jest.mock('../../components/SettingsErrorBoundary', () => {
70
+ const { View } = require('react-native');
71
+ return {
72
+ SettingsErrorBoundary: ({ children, fallbackTitle, fallbackMessage }: any) => (
73
+ <View testID="error-boundary">
74
+ {children}
75
+ {fallbackTitle && <View testID="fallback-title">{fallbackTitle}</View>}
76
+ {fallbackMessage && <View testID="fallback-message">{fallbackMessage}</View>}
77
+ </View>
78
+ ),
79
+ };
80
+ });
81
+
82
+ jest.mock('../../utils/normalizeConfig', () => ({
83
+ normalizeSettingsConfig: jest.fn((config) => ({
84
+ appearance: { enabled: config.appearance !== false, config: { enabled: true } },
85
+ language: { enabled: config.language !== false, config: { enabled: true } },
86
+ notifications: { enabled: config.notifications !== false, config: { enabled: true } },
87
+ about: { enabled: config.about !== false, config: { enabled: true } },
88
+ legal: { enabled: config.legal !== false, config: { enabled: true } },
89
+ account: { enabled: config.account !== false, config: { enabled: true } },
90
+ support: { enabled: config.support !== false, config: { enabled: true } },
91
+ developer: { enabled: config.developer !== false, config: { enabled: true } },
92
+ })),
93
+ }));
94
+
95
+ jest.mock('../../hooks/useFeatureDetection', () => ({
96
+ useFeatureDetection: jest.fn((config, navigation, options) => ({
97
+ appearance: config.appearance?.enabled !== false,
98
+ language: config.language?.enabled !== false,
99
+ notifications: config.notifications?.enabled !== false && options?.notificationServiceAvailable !== false,
100
+ about: config.about?.enabled !== false,
101
+ legal: config.legal?.enabled !== false,
102
+ account: config.account?.enabled !== false,
103
+ support: config.support?.enabled !== false,
104
+ developer: config.developer?.enabled !== false && __DEV__,
105
+ })),
106
+ }));
107
+
108
+ jest.mock('@react-navigation/native', () => ({
109
+ useNavigation: () => ({
110
+ navigate: jest.fn(),
111
+ goBack: jest.fn(),
112
+ getState: jest.fn(() => ({
113
+ routes: [{ name: 'Settings' }],
114
+ })),
115
+ }),
116
+ }));
117
+
118
+ const TestWrapper = ({ children }: { children: React.ReactNode }) => (
119
+ <NavigationContainer>
120
+ {children}
121
+ </NavigationContainer>
122
+ );
123
+
124
+ describe('Settings Integration Tests', () => {
125
+ beforeEach(() => {
126
+ jest.clearAllMocks();
127
+ });
128
+
129
+ describe('SettingsScreen Integration', () => {
130
+ it('integrates all components correctly', () => {
131
+ const config = {
132
+ appearance: true,
133
+ notifications: true,
134
+ about: true,
135
+ };
136
+
137
+ const userProfile = {
138
+ displayName: 'John Doe',
139
+ userId: 'user123',
140
+ };
141
+
142
+ const customSections = [
143
+ {
144
+ title: 'Custom Section',
145
+ data: [{ id: '1', title: 'Custom Item' }],
146
+ },
147
+ ];
148
+
149
+ const { getByTestId } = render(
150
+ <TestWrapper>
151
+ <SettingsScreen
152
+ config={config}
153
+ showUserProfile={true}
154
+ userProfile={userProfile}
155
+ showFooter={true}
156
+ footerText="Custom Footer"
157
+ customSections={customSections}
158
+ showCloseButton={true}
159
+ />
160
+ </TestWrapper>
161
+ );
162
+
163
+ expect(getByTestId('settings-header')).toBeTruthy();
164
+ expect(getByTestId('error-boundary')).toBeTruthy();
165
+ expect(getByTestId('settings-content')).toBeTruthy();
166
+ expect(getByTestId('user-profile')).toBeTruthy();
167
+ expect(getByTestId('footer')).toBeTruthy();
168
+ expect(getByTestId('custom-sections')).toBeTruthy();
169
+ expect(getByTestId('close-button')).toBeTruthy();
170
+ expect(getByTestId('content-close-button')).toBeTruthy();
171
+ });
172
+
173
+ it('passes config through normalization correctly', () => {
174
+ const config = {
175
+ appearance: true,
176
+ notifications: false,
177
+ about: true,
178
+ };
179
+
180
+ const { getByTestId } = render(
181
+ <TestWrapper>
182
+ <SettingsScreen config={config} />
183
+ </TestWrapper>
184
+ );
185
+
186
+ const configData = JSON.parse(getByTestId('config-data').props.children);
187
+ expect(configData.appearance.enabled).toBe(true);
188
+ expect(configData.notifications.enabled).toBe(false);
189
+ expect(configData.about.enabled).toBe(true);
190
+ });
191
+
192
+ it('integrates feature detection correctly', () => {
193
+ const config = {
194
+ appearance: true,
195
+ notifications: true,
196
+ about: true,
197
+ };
198
+
199
+ const featureOptions = {
200
+ notificationServiceAvailable: false,
201
+ };
202
+
203
+ const { getByTestId } = render(
204
+ <TestWrapper>
205
+ <SettingsScreen
206
+ config={config}
207
+ featureOptions={featureOptions}
208
+ />
209
+ </TestWrapper>
210
+ );
211
+
212
+ const featuresData = JSON.parse(getByTestId('features-data').props.children);
213
+ expect(featuresData.appearance).toBe(true);
214
+ expect(featuresData.notifications).toBe(false); // Disabled due to service unavailable
215
+ expect(featuresData.about).toBe(true);
216
+ });
217
+
218
+ it('handles close button integration', () => {
219
+ const mockOnClose = jest.fn();
220
+
221
+ const { getByTestId } = render(
222
+ <TestWrapper>
223
+ <SettingsScreen
224
+ showCloseButton={true}
225
+ onClose={mockOnClose}
226
+ />
227
+ </TestWrapper>
228
+ );
229
+
230
+ fireEvent.press(getByTestId('close-button'));
231
+ expect(mockOnClose).toHaveBeenCalled();
232
+ });
233
+
234
+ it('integrates error boundary correctly', () => {
235
+ const { getByTestId } = render(
236
+ <TestWrapper>
237
+ <SettingsScreen
238
+ fallbackTitle="custom.error.title"
239
+ fallbackMessage="custom.error.message"
240
+ />
241
+ </TestWrapper>
242
+ );
243
+
244
+ expect(getByTestId('fallback-title')).toBeTruthy();
245
+ expect(getByTestId('fallback-message')).toBeTruthy();
246
+ });
247
+ });
248
+
249
+ describe('Data Flow Integration', () => {
250
+ it('maintains data consistency through component tree', () => {
251
+ const config = {
252
+ appearance: true,
253
+ language: true,
254
+ notifications: true,
255
+ };
256
+
257
+ const userProfile = {
258
+ displayName: 'Test User',
259
+ userId: 'test123',
260
+ isGuest: false,
261
+ };
262
+
263
+ const { getByTestId } = render(
264
+ <TestWrapper>
265
+ <SettingsScreen
266
+ config={config}
267
+ showUserProfile={true}
268
+ userProfile={userProfile}
269
+ />
270
+ </TestWrapper>
271
+ );
272
+
273
+ // Verify config data flows correctly
274
+ const configData = JSON.parse(getByTestId('config-data').props.children);
275
+ expect(configData.appearance.enabled).toBe(true);
276
+ expect(configData.language.enabled).toBe(true);
277
+ expect(configData.notifications.enabled).toBe(true);
278
+
279
+ // Verify user profile data flows correctly
280
+ const profileData = JSON.parse(getByTestId('user-profile').props.children);
281
+ expect(profileData.displayName).toBe('Test User');
282
+ expect(profileData.userId).toBe('test123');
283
+ expect(profileData.isGuest).toBe(false);
284
+ });
285
+
286
+ it('handles empty and null states gracefully', () => {
287
+ const { getByTestId, queryByTestId } = render(
288
+ <TestWrapper>
289
+ <SettingsScreen
290
+ config={{}}
291
+ userProfile={{}}
292
+ customSections={[]}
293
+ showFooter={false}
294
+ />
295
+ </TestWrapper>
296
+ );
297
+
298
+ expect(getByTestId('settings-content')).toBeTruthy();
299
+ expect(queryByTestId('user-profile')).toBeNull();
300
+ expect(queryByTestId('footer')).toBeNull();
301
+ expect(queryByTestId('custom-sections')).toBeTruthy();
302
+ });
303
+ });
304
+
305
+ describe('Theme Integration', () => {
306
+ it('applies theme consistently across components', () => {
307
+ const { getByTestId } = render(
308
+ <TestWrapper>
309
+ <SettingsScreen />
310
+ </TestWrapper>
311
+ );
312
+
313
+ // All components should receive the same theme context
314
+ expect(getByTestId('settings-screen')).toBeTruthy();
315
+ });
316
+ });
317
+
318
+ describe('Navigation Integration', () => {
319
+ it('integrates with navigation system correctly', () => {
320
+ const { getByTestId } = render(
321
+ <TestWrapper>
322
+ <SettingsScreen />
323
+ </TestWrapper>
324
+ );
325
+
326
+ // Navigation should be available to all child components
327
+ expect(getByTestId('settings-screen')).toBeTruthy();
328
+ });
329
+ });
330
+
331
+ describe('Performance Integration', () => {
332
+ it('renders efficiently with large datasets', () => {
333
+ const largeCustomSections = Array.from({ length: 100 }, (_, i) => ({
334
+ title: `Section ${i}`,
335
+ data: Array.from({ length: 50 }, (_, j) => ({
336
+ id: `item-${i}-${j}`,
337
+ title: `Item ${i}-${j}`,
338
+ })),
339
+ }));
340
+
341
+ const startTime = performance.now();
342
+
343
+ const { getByTestId } = render(
344
+ <TestWrapper>
345
+ <SettingsScreen
346
+ customSections={largeCustomSections}
347
+ />
348
+ </TestWrapper>
349
+ );
350
+
351
+ const endTime = performance.now();
352
+ const renderTime = endTime - startTime;
353
+
354
+ expect(getByTestId('settings-screen')).toBeTruthy();
355
+ expect(renderTime).toBeLessThan(1000); // Should render within 1 second
356
+ });
357
+ });
358
+
359
+ describe('Error Handling Integration', () => {
360
+ it('handles errors gracefully across component boundaries', () => {
361
+ const { getByTestId } = render(
362
+ <TestWrapper>
363
+ <SettingsScreen />
364
+ </TestWrapper>
365
+ );
366
+
367
+ // Error boundary should catch and handle errors
368
+ expect(getByTestId('error-boundary')).toBeTruthy();
369
+ });
370
+ });
371
+ });