@umituz/react-native-settings 2.0.0 → 2.4.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.
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,369 @@
1
+ /**
2
+ * Performance and Memory Leak Tests
3
+ * Tests for performance optimization and memory management
4
+ */
5
+
6
+ import React from 'react';
7
+ import { render, unmountComponentAtNode } from '@testing-library/react-native';
8
+ import { SettingsScreen } from '../../screens/SettingsScreen';
9
+ import { useSettings } from '../../../infrastructure/storage/SettingsStore';
10
+ import { DisclaimerSetting } from '../../components/DisclaimerSetting';
11
+ import { SettingItem } from '../../components/SettingItem';
12
+
13
+ // Mock dependencies
14
+ jest.mock('@umituz/react-native-design-system-theme', () => ({
15
+ useDesignSystemTheme: () => ({
16
+ themeMode: 'light',
17
+ }),
18
+ useAppDesignTokens: () => ({
19
+ colors: {
20
+ backgroundPrimary: '#ffffff',
21
+ },
22
+ }),
23
+ }));
24
+
25
+ jest.mock('@umituz/react-native-localization', () => ({
26
+ useLocalization: () => ({
27
+ t: (key: string) => key,
28
+ }),
29
+ }));
30
+
31
+ jest.mock('@umituz/react-native-storage', () => ({
32
+ storageRepository: {
33
+ getItem: jest.fn(),
34
+ setItem: jest.fn(),
35
+ },
36
+ StorageKey: {
37
+ SETTINGS: 'settings',
38
+ },
39
+ createUserKey: (key: string, userId: string) => `${key}_${userId}`,
40
+ unwrap: (result: any, defaultValue: any) => result.success ? result.data : defaultValue,
41
+ }));
42
+
43
+ jest.mock('../../components/SettingsHeader', () => 'SettingsHeader');
44
+ jest.mock('../../components/SettingsContent', () => 'SettingsContent');
45
+ jest.mock('../../components/SettingsErrorBoundary', () => 'SettingsErrorBoundary');
46
+ jest.mock('../../utils/normalizeConfig', () => ({
47
+ normalizeSettingsConfig: jest.fn(() => ({})),
48
+ }));
49
+ jest.mock('../../hooks/useFeatureDetection', () => ({
50
+ useFeatureDetection: jest.fn(() => ({})),
51
+ }));
52
+
53
+ jest.mock('@react-navigation/native', () => ({
54
+ useNavigation: () => ({
55
+ navigate: jest.fn(),
56
+ goBack: jest.fn(),
57
+ getState: jest.fn(() => ({ routes: [] })),
58
+ }),
59
+ }));
60
+
61
+ describe('Performance and Memory Tests', () => {
62
+ let container: any;
63
+
64
+ beforeEach(() => {
65
+ container = document.createElement('div');
66
+ document.body.appendChild(container);
67
+ jest.clearAllMocks();
68
+ });
69
+
70
+ afterEach(() => {
71
+ if (container) {
72
+ unmountComponentAtNode(container);
73
+ container.remove();
74
+ container = null;
75
+ }
76
+ jest.clearAllTimers();
77
+ jest.useRealTimers();
78
+ });
79
+
80
+ describe('Memory Leak Prevention', () => {
81
+ it('should not leak memory on SettingsScreen mount/unmount', () => {
82
+ const mockSetItem = jest.fn();
83
+ require('@umituz/react-native-storage').storageRepository.setItem = mockSetItem;
84
+
85
+ const { unmount } = render(<SettingsScreen />);
86
+
87
+ // Component should mount without issues
88
+ expect(() => unmount()).not.toThrow();
89
+
90
+ // Check if any timers or listeners are left
91
+ expect(jest.getTimerCount()).toBe(0);
92
+ });
93
+
94
+ it('should cleanup useEffect hooks properly', () => {
95
+ jest.useFakeTimers();
96
+
97
+ const { unmount } = render(<DisclaimerSetting />);
98
+
99
+ // Fast forward time
100
+ jest.advanceTimersByTime(1000);
101
+
102
+ // Unmount component
103
+ unmount();
104
+
105
+ // Clear any remaining timers
106
+ jest.clearAllTimers();
107
+
108
+ // Should not have any remaining timers
109
+ expect(jest.getTimerCount()).toBe(0);
110
+ });
111
+
112
+ it('should handle rapid mount/unmount cycles', () => {
113
+ for (let i = 0; i < 100; i++) {
114
+ const { unmount } = render(<SettingsScreen />);
115
+ unmount();
116
+ }
117
+
118
+ // Should not throw any errors
119
+ expect(true).toBe(true);
120
+ });
121
+
122
+ it('should cleanup event listeners', () => {
123
+ const addEventListenerSpy = jest.spyOn(document, 'addEventListener');
124
+ const removeEventListenerSpy = jest.spyOn(document, 'removeEventListener');
125
+
126
+ const { unmount } = render(<SettingsScreen />);
127
+
128
+ unmount();
129
+
130
+ // All added listeners should be removed
131
+ expect(removeEventListenerSpy.mock.calls.length).toBeGreaterThanOrEqual(
132
+ addEventListenerSpy.mock.calls.length
133
+ );
134
+
135
+ addEventListenerSpy.mockRestore();
136
+ removeEventListenerSpy.mockRestore();
137
+ });
138
+ });
139
+
140
+ describe('Performance Optimization', () => {
141
+ it('should render within acceptable time limits', () => {
142
+ const startTime = performance.now();
143
+
144
+ render(<SettingsScreen />);
145
+
146
+ const endTime = performance.now();
147
+ const renderTime = endTime - startTime;
148
+
149
+ // Should render within 100ms
150
+ expect(renderTime).toBeLessThan(100);
151
+ });
152
+
153
+ it('should handle large datasets efficiently', () => {
154
+ const largeCustomSections = Array.from({ length: 1000 }, (_, i) => ({
155
+ title: `Section ${i}`,
156
+ data: Array.from({ length: 100 }, (_, j) => ({
157
+ id: `item-${i}-${j}`,
158
+ title: `Item ${i}-${j}`,
159
+ })),
160
+ }));
161
+
162
+ const startTime = performance.now();
163
+
164
+ const { unmount } = render(
165
+ <SettingsScreen customSections={largeCustomSections} />
166
+ );
167
+
168
+ const endTime = performance.now();
169
+ const renderTime = endTime - startTime;
170
+
171
+ // Should handle large datasets within reasonable time
172
+ expect(renderTime).toBeLessThan(1000);
173
+
174
+ unmount();
175
+ });
176
+
177
+ it('should not cause unnecessary re-renders', () => {
178
+ const renderSpy = jest.fn();
179
+
180
+ const TestComponent = () => {
181
+ renderSpy();
182
+ return <SettingsScreen />;
183
+ };
184
+
185
+ const { rerender } = render(<TestComponent />);
186
+
187
+ expect(renderSpy).toHaveBeenCalledTimes(1);
188
+
189
+ // Rerender with same props
190
+ rerender(<TestComponent />);
191
+
192
+ // Should not cause unnecessary re-renders
193
+ expect(renderSpy).toHaveBeenCalledTimes(2);
194
+ });
195
+
196
+ it('should use React.memo effectively', () => {
197
+ const props = {
198
+ icon: 'Settings',
199
+ title: 'Test Setting',
200
+ };
201
+
202
+ const { rerender } = render(<SettingItem {...props} />);
203
+
204
+ const startTime = performance.now();
205
+
206
+ // Rerender with same props
207
+ rerender(<SettingItem {...props} />);
208
+
209
+ const endTime = performance.now();
210
+ const rerenderTime = endTime - startTime;
211
+
212
+ // Rerender should be fast due to memoization
213
+ expect(rerenderTime).toBeLessThan(50);
214
+ });
215
+ });
216
+
217
+ describe('Memory Usage', () => {
218
+ it('should not accumulate memory on repeated operations', () => {
219
+ const initialMemory = (performance as any).memory?.usedJSHeapSize || 0;
220
+
221
+ // Perform many operations
222
+ for (let i = 0; i < 1000; i++) {
223
+ const { unmount } = render(<SettingsScreen />);
224
+ unmount();
225
+ }
226
+
227
+ // Force garbage collection if available
228
+ if (global.gc) {
229
+ global.gc();
230
+ }
231
+
232
+ const finalMemory = (performance as any).memory?.usedJSHeapSize || 0;
233
+
234
+ // Memory usage should not increase significantly
235
+ if (initialMemory > 0 && finalMemory > 0) {
236
+ const memoryIncrease = finalMemory - initialMemory;
237
+ expect(memoryIncrease).toBeLessThan(10 * 1024 * 1024); // Less than 10MB
238
+ }
239
+ });
240
+
241
+ it('should cleanup large objects properly', () => {
242
+ const largeData = {
243
+ config: Array.from({ length: 10000 }, (_, i) => ({
244
+ id: i,
245
+ data: new Array(1000).fill('large data string'),
246
+ })),
247
+ };
248
+
249
+ const { unmount } = render(<SettingsScreen {...largeData} />);
250
+
251
+ unmount();
252
+
253
+ // Force garbage collection if available
254
+ if (global.gc) {
255
+ global.gc();
256
+ }
257
+
258
+ // Should not throw errors
259
+ expect(true).toBe(true);
260
+ });
261
+ });
262
+
263
+ describe('Timer and Interval Management', () => {
264
+ it('should cleanup timers on unmount', () => {
265
+ jest.useFakeTimers();
266
+
267
+ const { unmount } = render(<DisclaimerSetting />);
268
+
269
+ // Simulate some timers
270
+ jest.advanceTimersByTime(5000);
271
+
272
+ expect(jest.getTimerCount()).toBeGreaterThan(0);
273
+
274
+ unmount();
275
+
276
+ jest.clearAllTimers();
277
+
278
+ expect(jest.getTimerCount()).toBe(0);
279
+ });
280
+
281
+ it('should not have memory leaks from intervals', () => {
282
+ jest.useFakeTimers();
283
+
284
+ const { unmount } = render(<SettingsScreen />);
285
+
286
+ // Simulate time passing
287
+ for (let i = 0; i < 100; i++) {
288
+ jest.advanceTimersByTime(1000);
289
+ }
290
+
291
+ unmount();
292
+
293
+ jest.clearAllTimers();
294
+
295
+ expect(jest.getTimerCount()).toBe(0);
296
+ });
297
+ });
298
+
299
+ describe('Async Operation Cleanup', () => {
300
+ it('should cleanup async operations on unmount', async () => {
301
+ const mockGetItem = jest.fn(() => new Promise(resolve =>
302
+ setTimeout(() => resolve({ success: true, data: {} }), 1000)
303
+ ));
304
+
305
+ require('@umituz/react-native-storage').storageRepository.getItem = mockGetItem;
306
+
307
+ const { unmount } = render(<SettingsScreen />);
308
+
309
+ // Unmount before async operation completes
310
+ unmount();
311
+
312
+ // Should not cause memory leaks
313
+ expect(true).toBe(true);
314
+ });
315
+
316
+ it('should handle promise rejection on unmount', async () => {
317
+ const mockGetItem = jest.fn(() => new Promise((_, reject) =>
318
+ setTimeout(() => reject(new Error('Test error')), 1000)
319
+ ));
320
+
321
+ require('@umituz/react-native-storage').storageRepository.getItem = mockGetItem;
322
+
323
+ const { unmount } = render(<SettingsScreen />);
324
+
325
+ // Unmount before promise rejects
326
+ unmount();
327
+
328
+ // Should not cause unhandled promise rejection
329
+ await new Promise(resolve => setTimeout(resolve, 1100));
330
+
331
+ expect(true).toBe(true);
332
+ });
333
+ });
334
+
335
+ describe('Resource Cleanup', () => {
336
+ it('should cleanup subscriptions', () => {
337
+ const mockSubscribe = jest.fn(() => jest.fn());
338
+
339
+ // Mock subscription
340
+ const originalUseEffect = React.useEffect;
341
+ React.useEffect = (fn, deps) => {
342
+ const cleanup = fn();
343
+ return cleanup;
344
+ };
345
+
346
+ const { unmount } = render(<SettingsScreen />);
347
+
348
+ unmount();
349
+
350
+ React.useEffect = originalUseEffect;
351
+
352
+ expect(true).toBe(true);
353
+ });
354
+
355
+ it('should cleanup event emitters', () => {
356
+ const mockEmitter = {
357
+ addListener: jest.fn(() => jest.fn()),
358
+ removeListener: jest.fn(),
359
+ };
360
+
361
+ // Mock event emitter usage
362
+ const { unmount } = render(<SettingsScreen />);
363
+
364
+ unmount();
365
+
366
+ expect(true).toBe(true);
367
+ });
368
+ });
369
+ });
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Simple Test to Verify Jest Setup
3
+ */
4
+
5
+ describe('Jest Setup', () => {
6
+ it('should run a simple test', () => {
7
+ expect(1 + 1).toBe(2);
8
+ });
9
+
10
+ it('should handle async operations', async () => {
11
+ const result = await Promise.resolve(42);
12
+ expect(result).toBe(42);
13
+ });
14
+
15
+ it('should handle mocking', () => {
16
+ const mockFn = jest.fn();
17
+ mockFn('test');
18
+ expect(mockFn).toHaveBeenCalledWith('test');
19
+ });
20
+ });
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Jest Test Setup
3
+ * Mock all external dependencies
4
+ */
5
+
6
+ // Mock React Native modules
7
+ jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');
8
+
9
+ // Mock design system packages
10
+ jest.mock('@umituz/react-native-design-system-theme', () => ({
11
+ useDesignSystemTheme: () => ({
12
+ themeMode: 'light',
13
+ }),
14
+ useAppDesignTokens: () => ({
15
+ colors: {
16
+ backgroundPrimary: '#ffffff',
17
+ primary: '#007AFF',
18
+ textPrimary: '#000000',
19
+ textSecondary: '#666666',
20
+ surface: '#f5f5f5',
21
+ borderLight: '#e0e0e0',
22
+ warning: '#FF9800',
23
+ },
24
+ spacing: {
25
+ md: 16,
26
+ },
27
+ typography: {
28
+ labelLarge: {
29
+ fontWeight: '500',
30
+ fontSize: 14,
31
+ },
32
+ },
33
+ }),
34
+ withAlpha: jest.fn((color: string, alpha: number) => `${color}${alpha}`),
35
+ }));
36
+
37
+ jest.mock('@umituz/react-native-design-system-atoms', () => ({
38
+ AtomicText: ({ children, type, color, style, testID }: any) => {
39
+ const React = require('react');
40
+ const { Text } = require('react-native');
41
+ return React.createElement(Text, {
42
+ style,
43
+ testID: testID || `atomic-text-${type}-${color}`
44
+ }, children);
45
+ },
46
+ AtomicIcon: ({ name, color, size, style, testID }: any) => {
47
+ const React = require('react');
48
+ const { Text } = require('react-native');
49
+ return React.createElement(Text, {
50
+ style,
51
+ testID: testID || `atomic-icon-${name}-${color}-${size}`
52
+ }, `Icon: ${name}`);
53
+ },
54
+ }));
55
+
56
+ // Mock localization
57
+ jest.mock('@umituz/react-native-localization', () => ({
58
+ useLocalization: () => ({
59
+ t: (key: string) => key,
60
+ changeLanguage: jest.fn(),
61
+ currentLanguage: 'en-US',
62
+ }),
63
+ }));
64
+
65
+ // Mock storage
66
+ jest.mock('@umituz/react-native-storage', () => ({
67
+ storageRepository: {
68
+ getItem: jest.fn(),
69
+ setItem: jest.fn(),
70
+ removeItem: jest.fn(),
71
+ clear: jest.fn(),
72
+ },
73
+ StorageKey: {
74
+ SETTINGS: 'settings',
75
+ },
76
+ createUserKey: (key: string, userId: string) => `${key}_${userId}`,
77
+ unwrap: (result: any, defaultValue: any) => result.success ? result.data : defaultValue,
78
+ }));
79
+
80
+ // Mock lucide-react-native
81
+ jest.mock('lucide-react-native', () => ({
82
+ Cloud: 'Cloud',
83
+ Bell: 'Bell',
84
+ Palette: 'Palette',
85
+ ChevronRight: 'ChevronRight',
86
+ AlertTriangle: 'AlertTriangle',
87
+ Info: 'Info',
88
+ X: 'X',
89
+ ArrowRight: 'ArrowRight',
90
+ Settings: 'Settings',
91
+ }));
92
+
93
+
94
+
95
+ // Mock navigation
96
+ jest.mock('@react-navigation/native', () => ({
97
+ useNavigation: () => ({
98
+ navigate: jest.fn(),
99
+ goBack: jest.fn(),
100
+ getState: jest.fn(() => ({
101
+ routes: [{ name: 'Settings' }],
102
+ })),
103
+ setOptions: jest.fn(),
104
+ isFocused: jest.fn(() => true),
105
+ addListener: jest.fn(() => jest.fn()),
106
+ removeListener: jest.fn(),
107
+ }),
108
+ useFocusEffect: jest.fn(),
109
+ useIsFocused: jest.fn(() => true),
110
+ NavigationContainer: ({ children }: any) => children,
111
+ }));
112
+
113
+ // Mock safe area context
114
+ jest.mock('react-native-safe-area-context', () => ({
115
+ SafeAreaProvider: ({ children }: any) => children,
116
+ SafeAreaView: ({ children }: any) => children,
117
+ useSafeAreaInsets: () => ({
118
+ top: 0,
119
+ bottom: 0,
120
+ left: 0,
121
+ right: 0,
122
+ }),
123
+ }));
124
+
125
+ // Mock linear gradient
126
+ jest.mock('expo-linear-gradient', () => ({
127
+ LinearGradient: ({ children }: any) => children,
128
+ }));
129
+
130
+ // Mock notification service
131
+ jest.mock('@umituz/react-native-notifications', () => ({
132
+ notificationService: {
133
+ hasPermissions: jest.fn(() => Promise.resolve(true)),
134
+ requestPermissions: jest.fn(() => Promise.resolve()),
135
+ },
136
+ }));
137
+
138
+ // Mock appearance
139
+ jest.mock('@umituz/react-native-appearance', () => ({
140
+ useAppearance: () => ({
141
+ colorScheme: 'light',
142
+ setColorScheme: jest.fn(),
143
+ }),
144
+ }));
145
+
146
+ // Mock console methods in tests
147
+ global.console = {
148
+ ...console,
149
+ warn: jest.fn(),
150
+ error: jest.fn(),
151
+ };
152
+
153
+ // Set up __DEV__ mock
154
+ Object.defineProperty(global, '__DEV__', {
155
+ value: true,
156
+ writable: true,
157
+ });
package/src/index.ts CHANGED
@@ -59,6 +59,15 @@ export { UserProfileHeader } from './presentation/components/UserProfileHeader';
59
59
  export type { UserProfileHeaderProps } from './presentation/components/UserProfileHeader';
60
60
 
61
61
  export { DisclaimerSetting } from './presentation/components/DisclaimerSetting';
62
+ export type { DisclaimerSettingProps } from './presentation/components/DisclaimerSetting';
63
+
64
+ export { DisclaimerCard } from './presentation/components/DisclaimerCard';
65
+ export type { DisclaimerCardProps } from './presentation/components/DisclaimerCard';
66
+
67
+ export { DisclaimerModal } from './presentation/components/DisclaimerModal';
68
+ export type { DisclaimerModalProps } from './presentation/components/DisclaimerModal';
69
+
70
+ export { SettingsErrorBoundary } from './presentation/components/SettingsErrorBoundary';
62
71
 
63
72
  export { CloudSyncSetting } from './presentation/components/CloudSyncSetting';
64
73
  export type { CloudSyncSettingProps } from './presentation/components/CloudSyncSetting';