@umituz/react-native-settings 4.20.62 → 4.21.2

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 (70) hide show
  1. package/package.json +6 -61
  2. package/src/domains/feedback/domain/entities/FeedbackEntity.ts +8 -8
  3. package/src/domains/gamification/components/AchievementCard.tsx +142 -0
  4. package/src/domains/gamification/components/AchievementItem.tsx +182 -0
  5. package/src/domains/gamification/components/AchievementToast.tsx +122 -0
  6. package/src/domains/gamification/components/GamificationScreen/AchievementsList.tsx +84 -0
  7. package/src/domains/gamification/components/GamificationScreen/Header.tsx +29 -0
  8. package/src/domains/gamification/components/GamificationScreen/StatsGrid.tsx +51 -0
  9. package/src/domains/gamification/components/GamificationScreen/index.tsx +111 -0
  10. package/src/domains/gamification/components/GamificationScreen/styles.ts +43 -0
  11. package/src/domains/gamification/components/GamificationScreen/types.ts +77 -0
  12. package/src/domains/gamification/components/GamificationScreenWrapper.tsx +4 -4
  13. package/src/domains/gamification/components/GamificationSettingsItem.tsx +1 -1
  14. package/src/domains/gamification/components/LevelProgress.tsx +129 -0
  15. package/src/domains/gamification/components/PointsBadge.tsx +60 -0
  16. package/src/domains/gamification/components/StatsCard.tsx +89 -0
  17. package/src/domains/gamification/components/StreakDisplay.tsx +119 -0
  18. package/src/domains/gamification/components/index.ts +13 -0
  19. package/src/domains/gamification/examples/gamification.config.example.ts +1 -1
  20. package/src/domains/gamification/hooks/useGamification.ts +91 -0
  21. package/src/domains/gamification/index.ts +46 -19
  22. package/src/domains/gamification/store/gamificationStore.ts +162 -0
  23. package/src/domains/gamification/types/index.ts +95 -23
  24. package/src/domains/gamification/types/settings.ts +28 -0
  25. package/src/domains/gamification/utils/calculations.ts +85 -0
  26. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -51
  27. package/.github/ISSUE_TEMPLATE/documentation.md +0 -52
  28. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -63
  29. package/.github/PULL_REQUEST_TEMPLATE.md +0 -84
  30. package/AI_AGENT_GUIDELINES.md +0 -367
  31. package/ARCHITECTURE.md +0 -246
  32. package/CHANGELOG.md +0 -67
  33. package/CODE_OF_CONDUCT.md +0 -75
  34. package/CONTRIBUTING.md +0 -107
  35. package/DOCUMENTATION_MIGRATION.md +0 -319
  36. package/DOCUMENTATION_TEMPLATE.md +0 -155
  37. package/SECURITY.md +0 -98
  38. package/SETTINGS_SCREEN_GUIDE.md +0 -185
  39. package/TESTING.md +0 -358
  40. package/src/__tests__/integration.test.tsx +0 -371
  41. package/src/__tests__/performance.test.tsx +0 -369
  42. package/src/__tests__/setup.test.tsx +0 -20
  43. package/src/__tests__/setup.ts +0 -154
  44. package/src/domains/about/__tests__/integration.test.tsx +0 -328
  45. package/src/domains/about/__tests__/types.d.ts +0 -5
  46. package/src/domains/about/domain/entities/__tests__/AppInfo.test.ts +0 -93
  47. package/src/domains/about/infrastructure/repositories/__tests__/AboutRepository.test.ts +0 -153
  48. package/src/domains/about/presentation/components/__tests__/AboutContent.simple.test.tsx +0 -178
  49. package/src/domains/about/presentation/components/__tests__/AboutContent.test.tsx +0 -293
  50. package/src/domains/about/presentation/components/__tests__/AboutHeader.test.tsx +0 -201
  51. package/src/domains/about/presentation/components/__tests__/AboutSettingItem.test.tsx +0 -71
  52. package/src/domains/about/presentation/hooks/__tests__/useAboutInfo.simple.test.tsx +0 -229
  53. package/src/domains/about/presentation/hooks/__tests__/useAboutInfo.test.tsx +0 -240
  54. package/src/domains/about/presentation/screens/__tests__/AboutScreen.simple.test.tsx +0 -199
  55. package/src/domains/about/presentation/screens/__tests__/AboutScreen.test.tsx +0 -366
  56. package/src/domains/about/utils/__tests__/index.test.ts +0 -408
  57. package/src/domains/appearance/__tests__/components/AppearanceScreen.test.tsx +0 -195
  58. package/src/domains/appearance/__tests__/hooks/index.test.tsx +0 -232
  59. package/src/domains/appearance/__tests__/integration/index.test.tsx +0 -207
  60. package/src/domains/appearance/__tests__/services/appearanceService.test.ts +0 -299
  61. package/src/domains/appearance/__tests__/setup.ts +0 -88
  62. package/src/domains/appearance/__tests__/stores/appearanceStore.test.tsx +0 -175
  63. package/src/domains/cloud-sync/presentation/components/__tests__/CloudSyncSetting.test.tsx +0 -78
  64. package/src/domains/legal/__tests__/ContentValidationService.test.ts +0 -195
  65. package/src/domains/legal/__tests__/StyleCacheService.test.ts +0 -110
  66. package/src/domains/legal/__tests__/UrlHandlerService.test.ts +0 -71
  67. package/src/domains/legal/__tests__/setup.ts +0 -82
  68. package/src/presentation/components/__tests__/SettingsErrorBoundary.test.tsx +0 -186
  69. package/src/presentation/screens/__tests__/SettingsScreen.test.tsx +0 -322
  70. package/src/presentation/screens/hooks/__tests__/useFeatureDetection.test.tsx +0 -261
@@ -1,71 +0,0 @@
1
- /**
2
- * Tests for AboutSettingItem component
3
- */
4
- import React from 'react';
5
- import renderer from 'react-test-renderer';
6
- import { AboutSettingItem } from '../AboutSettingItem';
7
-
8
- describe('AboutSettingItem', () => {
9
- const defaultProps = {
10
- title: 'Test Title',
11
- testID: 'test-item',
12
- };
13
-
14
- it('should render correctly with minimal props', () => {
15
- const component = renderer.create(<AboutSettingItem {...defaultProps} />);
16
- const root = component.root;
17
-
18
- // Check if title is rendered
19
- // Note: implementation details might vary, finding by text content is safer
20
- const textNodes = root.findAllByType('span'); // Text mocks to span in setup
21
- const titleNode = textNodes.find(n => n.props.children === 'Test Title');
22
- expect(titleNode).toBeDefined();
23
- });
24
-
25
- it('should render with description', () => {
26
- const component = renderer.create(
27
- <AboutSettingItem {...defaultProps} description="Test Description" />
28
- );
29
- const root = component.root;
30
- const textNodes = root.findAllByType('span');
31
- const descNode = textNodes.find(n => n.props.children === 'Test Description');
32
- expect(descNode).toBeDefined();
33
- });
34
-
35
- it('should render with value', () => {
36
- const component = renderer.create(
37
- <AboutSettingItem {...defaultProps} value="Test Value" />
38
- );
39
- const root = component.root;
40
- const textNodes = root.findAllByType('span');
41
- const valueNode = textNodes.find(n => n.props.children === 'Test Value');
42
- expect(valueNode).toBeDefined();
43
- });
44
-
45
- it('should render chevron when onPress is provided', () => {
46
- const component = renderer.create(
47
- <AboutSettingItem {...defaultProps} onPress={jest.fn()} />
48
- );
49
- const root = component.root;
50
- const textNodes = root.findAllByType('span');
51
- // Chevron is rendered as text '›'
52
- const chevronNode = textNodes.find(n => n.props.children === '›');
53
- expect(chevronNode).toBeDefined();
54
- });
55
-
56
- it('should call onPress when pressed', () => {
57
- const mockOnPress = jest.fn();
58
- const component = renderer.create(
59
- <AboutSettingItem {...defaultProps} onPress={mockOnPress} />
60
- );
61
- const root = component.root;
62
-
63
- // Find the touchable element (div in mock)
64
- const touchable = root.findByProps({ 'data-testid': 'test-item' });
65
-
66
- // Trigger onPress
67
- touchable.props.onClick();
68
-
69
- expect(mockOnPress).toHaveBeenCalledTimes(1);
70
- });
71
- });
@@ -1,229 +0,0 @@
1
- /**
2
- * Simple test for useAboutInfo hook
3
- */
4
- import { renderHook, act, waitFor } from '@testing-library/react';
5
- import { useAboutInfo } from '../useAboutInfo';
6
- import { AppInfo, AboutConfig } from '../../domain/entities/AppInfo';
7
-
8
- // Mock repository
9
- let mockAppInfoData: AppInfo | null = null;
10
-
11
- jest.mock('../../../infrastructure/repositories/AboutRepository', () => ({
12
- AboutRepository: jest.fn().mockImplementation(() => ({
13
- getAppInfo: jest.fn(() => mockAppInfoData),
14
- saveAppInfo: jest.fn((info: AppInfo) => {
15
- mockAppInfoData = info;
16
- return Promise.resolve();
17
- }),
18
- updateAppInfo: jest.fn((updates: Partial<AppInfo>) => {
19
- if (mockAppInfoData) {
20
- mockAppInfoData = { ...mockAppInfoData, ...updates };
21
- }
22
- return Promise.resolve();
23
- }),
24
- destroy: jest.fn(),
25
- })),
26
- }));
27
-
28
- describe('useAboutInfo', () => {
29
- beforeEach(() => {
30
- mockAppInfoData = null;
31
- });
32
-
33
- const mockAppInfo: AppInfo = {
34
- name: 'Test App',
35
- version: '1.0.0',
36
- description: 'Test Description',
37
- developer: 'Test Developer',
38
- contactEmail: 'test@example.com',
39
- websiteUrl: 'https://example.com',
40
- websiteDisplay: 'example.com',
41
- moreAppsUrl: 'https://apps.example.com',
42
- };
43
-
44
- const mockConfig: AboutConfig = {
45
- appInfo: mockAppInfo,
46
- actions: {
47
- onEmailPress: jest.fn(),
48
- onWebsitePress: jest.fn(),
49
- onMoreAppsPress: jest.fn(),
50
- },
51
- };
52
-
53
- it('should initialize with default state', () => {
54
- const { result } = renderHook(() => useAboutInfo());
55
-
56
- expect(result.current.appInfo).toBeNull();
57
- expect(result.current.loading).toBe(false);
58
- expect(result.current.error).toBeNull();
59
- });
60
-
61
- it('should initialize with config', async () => {
62
- const { result } = renderHook(() => useAboutInfo({ initialConfig: mockConfig, autoInit: undefined }));
63
-
64
- // Wait for useEffect to run
65
- await act(async () => {
66
- await new Promise(resolve => setTimeout(resolve, 0));
67
- });
68
-
69
- expect(result.current.appInfo).toEqual(mockAppInfo);
70
- expect(result.current.loading).toBe(false);
71
- expect(result.current.error).toBeNull();
72
- });
73
-
74
- it('should handle auto initialization', async () => {
75
- const { result } = renderHook(() =>
76
- useAboutInfo({ autoInit: true, initialConfig: mockConfig })
77
- );
78
-
79
- expect(result.current.loading).toBe(true);
80
-
81
- await act(async () => {
82
- // Wait for initialization to complete
83
- await new Promise(resolve => setTimeout(resolve, 10));
84
- });
85
-
86
- expect(result.current.appInfo).toEqual(mockAppInfo);
87
- expect(result.current.loading).toBe(false);
88
- expect(result.current.error).toBeNull();
89
- });
90
-
91
- it('should handle manual initialization', async () => {
92
- const { result } = renderHook(() => useAboutInfo());
93
-
94
- await act(async () => {
95
- await result.current.initialize(mockConfig);
96
- });
97
-
98
- expect(result.current.appInfo).toEqual(mockAppInfo);
99
- expect(result.current.loading).toBe(false);
100
- expect(result.current.error).toBeNull();
101
- });
102
-
103
- it('should handle update', async () => {
104
- const { result } = renderHook(() => useAboutInfo({ initialConfig: mockConfig }));
105
-
106
- await act(async () => {
107
- // Wait for initialization to complete
108
- await new Promise(resolve => setTimeout(resolve, 10));
109
- });
110
-
111
- const updatedConfig = {
112
- ...mockConfig,
113
- appInfo: { ...mockAppInfo, name: 'Updated App' }
114
- };
115
-
116
- await act(async () => {
117
- await result.current.update(updatedConfig);
118
- });
119
-
120
- expect(result.current.appInfo?.name).toBe('Updated App');
121
- });
122
-
123
- it('should handle reset', async () => {
124
- const { result } = renderHook(() => useAboutInfo({ initialConfig: mockConfig, autoInit: undefined }));
125
-
126
- await waitFor(() => {
127
- expect(result.current.appInfo).toEqual(mockAppInfo);
128
- });
129
-
130
- act(() => {
131
- result.current.reset();
132
- });
133
-
134
- expect(result.current.appInfo).toBeNull();
135
- expect(result.current.loading).toBe(false);
136
- expect(result.current.error).toBeNull();
137
- });
138
-
139
- it('should handle refresh', async () => {
140
- const { result } = renderHook(() =>
141
- useAboutInfo({ autoInit: true, initialConfig: mockConfig })
142
- );
143
-
144
- await act(async () => {
145
- // Wait for initialization to complete
146
- await new Promise(resolve => setTimeout(resolve, 10));
147
- });
148
-
149
- // Refresh should not throw
150
- await act(async () => {
151
- await result.current.refresh();
152
- });
153
-
154
- // Should not crash and should have some app info state
155
- expect(result.current).toBeDefined();
156
- });
157
-
158
- it('should refresh app info', async () => {
159
- const { result } = renderHook(() => useAboutInfo());
160
-
161
- await act(async () => {
162
- await result.current.initialize(mockConfig);
163
- });
164
-
165
- await act(async () => {
166
- await result.current.refresh();
167
- });
168
-
169
- // Should still have app info after refresh
170
- expect(result.current.appInfo).toBeTruthy();
171
- });
172
-
173
- it('should handle errors during initialization', async () => {
174
- const { result } = renderHook(() =>
175
- useAboutInfo({ autoInit: true, initialConfig: null as unknown })
176
- );
177
-
178
- await act(async () => {
179
- // Wait for initialization to complete
180
- await new Promise(resolve => setTimeout(resolve, 10));
181
- });
182
-
183
- // With null config, no initialization occurs, so no error is set
184
- expect(result.current.error).toBeNull();
185
- expect(result.current.loading).toBe(false);
186
- expect(result.current.appInfo).toBeNull();
187
- });
188
-
189
- it('should handle errors during update', async () => {
190
- const { result } = renderHook(() => useAboutInfo({ initialConfig: mockConfig }));
191
-
192
- await act(async () => {
193
- await result.current.update(null as unknown);
194
- });
195
-
196
- expect(result.current.error).toBeTruthy();
197
- });
198
-
199
- it('should memoize values', () => {
200
- const { result, rerender } = renderHook(() => useAboutInfo({ initialConfig: mockConfig }));
201
-
202
- const initialAppInfo = result.current.appInfo;
203
- const initialLoading = result.current.loading;
204
- const initialError = result.current.error;
205
-
206
- rerender();
207
-
208
- expect(result.current.appInfo).toBe(initialAppInfo);
209
- expect(result.current.loading).toBe(initialLoading);
210
- expect(result.current.error).toBe(initialError);
211
- });
212
-
213
- it('should handle update on unmounted component', async () => {
214
- const { result, unmount } = renderHook(() =>
215
- useAboutInfo({ autoInit: true, initialConfig: mockConfig })
216
- );
217
-
218
- unmount();
219
-
220
- // Should not crash when updating after unmount
221
- await act(async () => {
222
- try {
223
- await result.current.update(mockConfig);
224
- } catch (error) {
225
- // Expected to not crash
226
- }
227
- });
228
- });
229
- });
@@ -1,240 +0,0 @@
1
- /**
2
- * Tests for useAboutInfo hook
3
- */
4
- import '../../../types/global.d.ts';
5
- import { renderHook, act, waitFor } from '@testing-library/react';
6
- import { useAboutInfo } from '../useAboutInfo';
7
- import { AboutConfig } from '../../../domain/entities/AppInfo';
8
-
9
- describe('useAboutInfo', () => {
10
- const mockConfig: AboutConfig = {
11
- appInfo: {
12
- name: 'Test App',
13
- version: '1.0.0',
14
- description: 'Test Description',
15
- developer: 'Test Developer',
16
- },
17
- };
18
-
19
- beforeEach(() => {
20
- jest.clearAllMocks();
21
- });
22
-
23
- describe('Initial State', () => {
24
- it('should return initial state', () => {
25
- const { result } = renderHook(() => useAboutInfo());
26
-
27
- expect(result.current.appInfo).toBeNull();
28
- expect(result.current.loading).toBe(false);
29
- expect(result.current.error).toBeNull();
30
- expect(typeof result.current.initialize).toBe('function');
31
- expect(typeof result.current.updateAppInfo).toBe('function');
32
- expect(typeof result.current.reset).toBe('function');
33
- });
34
-
35
- it('should auto-initialize when autoInit is true', async () => {
36
- const { result } = renderHook(() =>
37
- useAboutInfo({ autoInit: true, initialConfig: mockConfig })
38
- );
39
-
40
- expect(result.current.loading).toBe(true);
41
-
42
- await waitFor(() => {
43
- expect(result.current.loading).toBe(false);
44
- });
45
-
46
- expect(result.current.appInfo).toEqual({
47
- name: 'Test App',
48
- version: '1.0.0',
49
- description: 'Test Description',
50
- developer: 'Test Developer',
51
- contactEmail: undefined,
52
- websiteUrl: undefined,
53
- websiteDisplay: undefined,
54
- moreAppsUrl: undefined,
55
- privacyPolicyUrl: undefined,
56
- termsOfServiceUrl: undefined,
57
- });
58
- expect(result.current.loading).toBe(false);
59
- expect(result.current.error).toBeNull();
60
- });
61
-
62
- it('should not auto-initialize when autoInit is false', () => {
63
- const { result } = renderHook(() =>
64
- useAboutInfo({ autoInit: false, initialConfig: mockConfig })
65
- );
66
-
67
- expect(result.current.appInfo).toBeNull();
68
- expect(result.current.loading).toBe(false);
69
- expect(result.current.error).toBeNull();
70
- });
71
- });
72
-
73
- describe('initialize', () => {
74
- it('should initialize with config', async () => {
75
- const { result } = renderHook(() => useAboutInfo());
76
-
77
- await act(async () => {
78
- await result.current.initialize(mockConfig);
79
- });
80
-
81
- expect(result.current.appInfo).toEqual({
82
- name: 'Test App',
83
- version: '1.0.0',
84
- description: 'Test Description',
85
- developer: 'Test Developer',
86
- contactEmail: undefined,
87
- websiteUrl: undefined,
88
- websiteDisplay: undefined,
89
- moreAppsUrl: undefined,
90
- privacyPolicyUrl: undefined,
91
- termsOfServiceUrl: undefined,
92
- });
93
- expect(result.current.loading).toBe(false);
94
- expect(result.current.error).toBeNull();
95
- });
96
-
97
- it('should not initialize multiple times', async () => {
98
- const { result } = renderHook(() => useAboutInfo());
99
-
100
- await act(async () => {
101
- await result.current.initialize(mockConfig);
102
- });
103
-
104
- const firstAppInfo = result.current.appInfo;
105
-
106
- await act(async () => {
107
- await result.current.initialize({
108
- appInfo: { name: 'Different App', version: '2.0.0' }
109
- });
110
- });
111
-
112
- expect(result.current.appInfo).toEqual(firstAppInfo);
113
- });
114
-
115
- it('should handle initialization errors', async () => {
116
- const { result } = renderHook(() => useAboutInfo());
117
-
118
- await act(async () => {
119
- await result.current.initialize(null as unknown);
120
- });
121
-
122
- expect(result.current.appInfo).toBeNull();
123
- expect(result.current.loading).toBe(false);
124
- expect(result.current.error).toBeTruthy();
125
- });
126
- });
127
-
128
- describe('updateAppInfo', () => {
129
- beforeEach(async () => {
130
- const { result } = renderHook(() =>
131
- useAboutInfo({ autoInit: true, initialConfig: mockConfig })
132
- );
133
- await waitFor(() => {
134
- expect(result.current.loading).toBe(false);
135
- });
136
- });
137
-
138
- it('should update app info', async () => {
139
- const { result } = renderHook(() =>
140
- useAboutInfo({ autoInit: true, initialConfig: mockConfig })
141
- );
142
-
143
- // Wait for initialization
144
- await act(async () => {
145
- await new Promise(resolve => setTimeout(resolve, 0));
146
- });
147
-
148
- await act(async () => {
149
- await result.current.updateAppInfo({ name: 'Updated App', version: '2.0.0' });
150
- });
151
-
152
- expect(result.current.appInfo?.name).toBe('Updated App');
153
- expect(result.current.appInfo?.version).toBe('2.0.0');
154
- expect(result.current.appInfo?.description).toBe('Test Description'); // Unchanged
155
- expect(result.current.loading).toBe(false);
156
- expect(result.current.error).toBeNull();
157
- });
158
-
159
- it('should handle update when not initialized', async () => {
160
- const { result } = renderHook(() => useAboutInfo());
161
-
162
- await act(async () => {
163
- await result.current.updateAppInfo({ name: 'Updated App' });
164
- });
165
-
166
- expect(result.current.appInfo).toBeNull();
167
- expect(result.current.error).toBe('App info not initialized');
168
- });
169
-
170
- it('should handle update errors', async () => {
171
- const { result } = renderHook(() =>
172
- useAboutInfo({ autoInit: true, initialConfig: mockConfig })
173
- );
174
- await waitFor(() => {
175
- expect(result.current.loading).toBe(false);
176
- });
177
-
178
- await act(async () => {
179
- await result.current.updateAppInfo(null as unknown);
180
- });
181
-
182
- expect(result.current.error).toBeTruthy();
183
- });
184
- });
185
-
186
- describe('reset', () => {
187
- it('should reset state', async () => {
188
- const { result } = renderHook(() =>
189
- useAboutInfo({ autoInit: true, initialConfig: mockConfig })
190
- );
191
- await waitFor(() => {
192
- expect(result.current.loading).toBe(false);
193
- });
194
-
195
- expect(result.current.appInfo).toBeTruthy();
196
-
197
- act(() => {
198
- result.current.reset();
199
- });
200
-
201
- expect(result.current.appInfo).toBeNull();
202
- expect(result.current.loading).toBe(false);
203
- expect(result.current.error).toBeNull();
204
- });
205
- });
206
-
207
- describe('Memory Leak Prevention', () => {
208
- it('should handle unmounted component', async () => {
209
- const { result, unmount } = renderHook(() => useAboutInfo());
210
-
211
- // Start initialization
212
- const initPromise = act(async () => {
213
- await result.current.initialize(mockConfig);
214
- });
215
-
216
- // Unmount before initialization completes
217
- unmount();
218
-
219
- // Should not throw error
220
- await initPromise;
221
- });
222
-
223
- it('should handle update on unmounted component', async () => {
224
- const { result, unmount } = renderHook(() =>
225
- useAboutInfo({ autoInit: true, initialConfig: mockConfig })
226
- );
227
- await waitFor(() => {
228
- expect(result.current.loading).toBe(false);
229
- });
230
-
231
- unmount();
232
-
233
- // Should not throw error
234
- await act(async () => {
235
- await result.current.updateAppInfo({ name: 'Updated App' });
236
- });
237
- });
238
- });
239
-
240
- });