@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.
- package/package.json +6 -61
- package/src/domains/feedback/domain/entities/FeedbackEntity.ts +8 -8
- package/src/domains/gamification/components/AchievementCard.tsx +142 -0
- package/src/domains/gamification/components/AchievementItem.tsx +182 -0
- package/src/domains/gamification/components/AchievementToast.tsx +122 -0
- package/src/domains/gamification/components/GamificationScreen/AchievementsList.tsx +84 -0
- package/src/domains/gamification/components/GamificationScreen/Header.tsx +29 -0
- package/src/domains/gamification/components/GamificationScreen/StatsGrid.tsx +51 -0
- package/src/domains/gamification/components/GamificationScreen/index.tsx +111 -0
- package/src/domains/gamification/components/GamificationScreen/styles.ts +43 -0
- package/src/domains/gamification/components/GamificationScreen/types.ts +77 -0
- package/src/domains/gamification/components/GamificationScreenWrapper.tsx +4 -4
- package/src/domains/gamification/components/GamificationSettingsItem.tsx +1 -1
- package/src/domains/gamification/components/LevelProgress.tsx +129 -0
- package/src/domains/gamification/components/PointsBadge.tsx +60 -0
- package/src/domains/gamification/components/StatsCard.tsx +89 -0
- package/src/domains/gamification/components/StreakDisplay.tsx +119 -0
- package/src/domains/gamification/components/index.ts +13 -0
- package/src/domains/gamification/examples/gamification.config.example.ts +1 -1
- package/src/domains/gamification/hooks/useGamification.ts +91 -0
- package/src/domains/gamification/index.ts +46 -19
- package/src/domains/gamification/store/gamificationStore.ts +162 -0
- package/src/domains/gamification/types/index.ts +95 -23
- package/src/domains/gamification/types/settings.ts +28 -0
- package/src/domains/gamification/utils/calculations.ts +85 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -51
- package/.github/ISSUE_TEMPLATE/documentation.md +0 -52
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -63
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -84
- package/AI_AGENT_GUIDELINES.md +0 -367
- package/ARCHITECTURE.md +0 -246
- package/CHANGELOG.md +0 -67
- package/CODE_OF_CONDUCT.md +0 -75
- package/CONTRIBUTING.md +0 -107
- package/DOCUMENTATION_MIGRATION.md +0 -319
- package/DOCUMENTATION_TEMPLATE.md +0 -155
- package/SECURITY.md +0 -98
- package/SETTINGS_SCREEN_GUIDE.md +0 -185
- package/TESTING.md +0 -358
- package/src/__tests__/integration.test.tsx +0 -371
- package/src/__tests__/performance.test.tsx +0 -369
- package/src/__tests__/setup.test.tsx +0 -20
- package/src/__tests__/setup.ts +0 -154
- package/src/domains/about/__tests__/integration.test.tsx +0 -328
- package/src/domains/about/__tests__/types.d.ts +0 -5
- package/src/domains/about/domain/entities/__tests__/AppInfo.test.ts +0 -93
- package/src/domains/about/infrastructure/repositories/__tests__/AboutRepository.test.ts +0 -153
- package/src/domains/about/presentation/components/__tests__/AboutContent.simple.test.tsx +0 -178
- package/src/domains/about/presentation/components/__tests__/AboutContent.test.tsx +0 -293
- package/src/domains/about/presentation/components/__tests__/AboutHeader.test.tsx +0 -201
- package/src/domains/about/presentation/components/__tests__/AboutSettingItem.test.tsx +0 -71
- package/src/domains/about/presentation/hooks/__tests__/useAboutInfo.simple.test.tsx +0 -229
- package/src/domains/about/presentation/hooks/__tests__/useAboutInfo.test.tsx +0 -240
- package/src/domains/about/presentation/screens/__tests__/AboutScreen.simple.test.tsx +0 -199
- package/src/domains/about/presentation/screens/__tests__/AboutScreen.test.tsx +0 -366
- package/src/domains/about/utils/__tests__/index.test.ts +0 -408
- package/src/domains/appearance/__tests__/components/AppearanceScreen.test.tsx +0 -195
- package/src/domains/appearance/__tests__/hooks/index.test.tsx +0 -232
- package/src/domains/appearance/__tests__/integration/index.test.tsx +0 -207
- package/src/domains/appearance/__tests__/services/appearanceService.test.ts +0 -299
- package/src/domains/appearance/__tests__/setup.ts +0 -88
- package/src/domains/appearance/__tests__/stores/appearanceStore.test.tsx +0 -175
- package/src/domains/cloud-sync/presentation/components/__tests__/CloudSyncSetting.test.tsx +0 -78
- package/src/domains/legal/__tests__/ContentValidationService.test.ts +0 -195
- package/src/domains/legal/__tests__/StyleCacheService.test.ts +0 -110
- package/src/domains/legal/__tests__/UrlHandlerService.test.ts +0 -71
- package/src/domains/legal/__tests__/setup.ts +0 -82
- package/src/presentation/components/__tests__/SettingsErrorBoundary.test.tsx +0 -186
- package/src/presentation/screens/__tests__/SettingsScreen.test.tsx +0 -322
- package/src/presentation/screens/hooks/__tests__/useFeatureDetection.test.tsx +0 -261
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hooks Tests
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { renderHook, act } from '@testing-library/react-native';
|
|
6
|
-
import { useAppearance, useAppearanceActions } from '../../hooks';
|
|
7
|
-
import type { ThemeMode, CustomThemeColors } from '../../types';
|
|
8
|
-
|
|
9
|
-
// Mock design system theme
|
|
10
|
-
jest.mock('@umituz/react-native-design-system', () => ({
|
|
11
|
-
useTheme: jest.fn(() => ({
|
|
12
|
-
getState: jest.fn(() => ({
|
|
13
|
-
setThemeMode: jest.fn(),
|
|
14
|
-
})),
|
|
15
|
-
})),
|
|
16
|
-
useDesignSystemTheme: jest.fn(() => ({
|
|
17
|
-
getState: jest.fn(() => ({
|
|
18
|
-
setThemeMode: jest.fn(),
|
|
19
|
-
setCustomColors: jest.fn(),
|
|
20
|
-
})),
|
|
21
|
-
})),
|
|
22
|
-
}));
|
|
23
|
-
|
|
24
|
-
const mockUseTheme = require('@umituz/react-native-design-system').useTheme;
|
|
25
|
-
const mockUseDesignSystemTheme = require('@umituz/react-native-design-system').useDesignSystemTheme;
|
|
26
|
-
|
|
27
|
-
describe('useAppearance', () => {
|
|
28
|
-
beforeEach(() => {
|
|
29
|
-
jest.clearAllMocks();
|
|
30
|
-
|
|
31
|
-
mockUseTheme.getState.mockReturnValue({
|
|
32
|
-
setThemeMode: jest.fn(),
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
mockUseDesignSystemTheme.getState.mockReturnValue({
|
|
36
|
-
setThemeMode: jest.fn(),
|
|
37
|
-
setCustomColors: jest.fn(),
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
afterEach(() => {
|
|
42
|
-
jest.restoreAllMocks();
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('should return appearance state and actions', () => {
|
|
46
|
-
const { result } = renderHook(() => useAppearance());
|
|
47
|
-
|
|
48
|
-
expect(result.current).toHaveProperty('themeMode');
|
|
49
|
-
expect(result.current).toHaveProperty('customColors');
|
|
50
|
-
expect(result.current).toHaveProperty('isInitialized');
|
|
51
|
-
expect(result.current).toHaveProperty('setThemeMode');
|
|
52
|
-
expect(result.current).toHaveProperty('toggleTheme');
|
|
53
|
-
expect(result.current).toHaveProperty('setCustomColors');
|
|
54
|
-
expect(result.current).toHaveProperty('resetCustomColors');
|
|
55
|
-
expect(result.current).toHaveProperty('reset');
|
|
56
|
-
|
|
57
|
-
expect(typeof result.current.setThemeMode).toBe('function');
|
|
58
|
-
expect(typeof result.current.toggleTheme).toBe('function');
|
|
59
|
-
expect(typeof result.current.setCustomColors).toBe('function');
|
|
60
|
-
expect(typeof result.current.resetCustomColors).toBe('function');
|
|
61
|
-
expect(typeof result.current.reset).toBe('function');
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('should have stable function references', () => {
|
|
65
|
-
const { result: result1 } = renderHook(() => useAppearance());
|
|
66
|
-
const { result: result2 } = renderHook(() => useAppearance());
|
|
67
|
-
|
|
68
|
-
// Functions should be stable across renders
|
|
69
|
-
expect(result1.current.setThemeMode).toBe(result2.current.setThemeMode);
|
|
70
|
-
expect(result1.current.toggleTheme).toBe(result2.current.toggleTheme);
|
|
71
|
-
expect(result1.current.setCustomColors).toBe(result2.current.setCustomColors);
|
|
72
|
-
expect(result1.current.resetCustomColors).toBe(result2.current.resetCustomColors);
|
|
73
|
-
expect(result1.current.reset).toBe(result2.current.reset);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('should call service methods correctly', async () => {
|
|
77
|
-
const { result } = renderHook(() => useAppearance());
|
|
78
|
-
|
|
79
|
-
const mockSetThemeMode = mockUseTheme.getState().setThemeMode;
|
|
80
|
-
const mockSetCustomColors = mockUseDesignSystemTheme.getState().setCustomColors;
|
|
81
|
-
|
|
82
|
-
await act(async () => {
|
|
83
|
-
await result.current.setThemeMode('light');
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
expect(mockSetThemeMode).toHaveBeenCalledWith('light');
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it('should handle errors gracefully', async () => {
|
|
90
|
-
const { result } = renderHook(() => useAppearance());
|
|
91
|
-
|
|
92
|
-
const mockSetThemeMode = mockUseTheme.getState().setThemeMode;
|
|
93
|
-
const error = new Error('Service error');
|
|
94
|
-
mockSetThemeMode.mockImplementation(() => {
|
|
95
|
-
throw error;
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
await expect(result.current.setThemeMode('light')).rejects.toThrow(error);
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
describe('useAppearanceActions', () => {
|
|
103
|
-
beforeEach(() => {
|
|
104
|
-
jest.clearAllMocks();
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
afterEach(() => {
|
|
108
|
-
jest.restoreAllMocks();
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it('should return actions and local state', () => {
|
|
112
|
-
const { result } = renderHook(() => useAppearanceActions());
|
|
113
|
-
|
|
114
|
-
expect(result.current).toHaveProperty('localCustomColors');
|
|
115
|
-
expect(result.current).toHaveProperty('handleThemeSelect');
|
|
116
|
-
expect(result.current).toHaveProperty('handleColorChange');
|
|
117
|
-
expect(result.current).toHaveProperty('handleResetColors');
|
|
118
|
-
|
|
119
|
-
expect(typeof result.current.handleThemeSelect).toBe('function');
|
|
120
|
-
expect(typeof result.current.handleColorChange).toBe('function');
|
|
121
|
-
expect(typeof result.current.handleResetColors).toBe('function');
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it('should initialize with empty custom colors', () => {
|
|
125
|
-
const { result } = renderHook(() => useAppearanceActions());
|
|
126
|
-
|
|
127
|
-
expect(result.current.localCustomColors).toEqual({});
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
it('should handle theme selection', async () => {
|
|
131
|
-
const { result } = renderHook(() => useAppearanceActions());
|
|
132
|
-
|
|
133
|
-
const mockSetThemeMode = mockUseTheme.getState().setThemeMode;
|
|
134
|
-
|
|
135
|
-
await act(async () => {
|
|
136
|
-
await result.current.handleThemeSelect('light');
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
expect(mockSetThemeMode).toHaveBeenCalledWith('light');
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
it('should handle color change', () => {
|
|
143
|
-
const { result } = renderHook(() => useAppearanceActions());
|
|
144
|
-
|
|
145
|
-
const mockSetCustomColors = mockUseDesignSystemTheme.getState().setCustomColors;
|
|
146
|
-
|
|
147
|
-
act(() => {
|
|
148
|
-
result.current.handleColorChange('primary', '#FF0000');
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
expect(mockSetCustomColors).toHaveBeenCalledWith({
|
|
152
|
-
primary: '#FF0000',
|
|
153
|
-
});
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it('should not update if color is same', () => {
|
|
157
|
-
const { result } = renderHook(() => useAppearanceActions());
|
|
158
|
-
|
|
159
|
-
const mockSetCustomColors = mockUseDesignSystemTheme.getState().setCustomColors;
|
|
160
|
-
|
|
161
|
-
act(() => {
|
|
162
|
-
result.current.handleColorChange('primary', '#FF0000');
|
|
163
|
-
result.current.handleColorChange('primary', '#FF0000'); // Same color
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
// Should only be called once due to optimization
|
|
167
|
-
expect(mockSetCustomColors).toHaveBeenCalledTimes(1);
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
it('should handle reset colors', () => {
|
|
171
|
-
const { result } = renderHook(() => useAppearanceActions());
|
|
172
|
-
|
|
173
|
-
const mockResetCustomColors = mockUseDesignSystemTheme.getState().setCustomColors;
|
|
174
|
-
|
|
175
|
-
act(() => {
|
|
176
|
-
result.current.handleResetColors();
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
expect(mockResetCustomColors).toHaveBeenCalled();
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
it('should handle reset colors with config', () => {
|
|
183
|
-
const onConfirm = jest.fn();
|
|
184
|
-
const config = { onResetConfirm };
|
|
185
|
-
|
|
186
|
-
const { result } = renderHook(() => useAppearanceActions(config));
|
|
187
|
-
|
|
188
|
-
const mockResetCustomColors = mockUseDesignSystemTheme.getState().setCustomColors;
|
|
189
|
-
|
|
190
|
-
act(() => {
|
|
191
|
-
result.current.handleResetColors();
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
expect(mockResetCustomColors).toHaveBeenCalled();
|
|
195
|
-
expect(onConfirm).toHaveBeenCalled();
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
it('should sync local colors with store changes', () => {
|
|
199
|
-
const { result, rerender } = renderHook(
|
|
200
|
-
() => useAppearanceActions(),
|
|
201
|
-
{
|
|
202
|
-
initialProps: { customColors: { primary: '#FF0000' } }
|
|
203
|
-
}
|
|
204
|
-
);
|
|
205
|
-
|
|
206
|
-
expect(result.current.localCustomColors).toEqual({ primary: '#FF0000' });
|
|
207
|
-
|
|
208
|
-
// Simulate store change
|
|
209
|
-
rerender({ customColors: { primary: '#00FF00' } });
|
|
210
|
-
|
|
211
|
-
expect(result.current.localCustomColors).toEqual({ primary: '#00FF00' });
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
it('should have stable function references', () => {
|
|
215
|
-
const { result: result1 } = renderHook(() => useAppearanceActions());
|
|
216
|
-
const { result: result2 } = renderHook(() => useAppearanceActions());
|
|
217
|
-
|
|
218
|
-
// Functions should be stable across renders
|
|
219
|
-
expect(result1.current.handleThemeSelect).toBe(result2.current.handleThemeSelect);
|
|
220
|
-
expect(result1.current.handleColorChange).toBe(result2.current.handleColorChange);
|
|
221
|
-
expect(result1.current.handleResetColors).toBe(result2.current.handleResetColors);
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
it('should cleanup on unmount', () => {
|
|
225
|
-
const { unmount } = renderHook(() => useAppearanceActions());
|
|
226
|
-
|
|
227
|
-
unmount();
|
|
228
|
-
|
|
229
|
-
// Should not throw any errors during cleanup
|
|
230
|
-
expect(true).toBe(true);
|
|
231
|
-
});
|
|
232
|
-
});
|
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Integration Tests
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import React from 'react';
|
|
6
|
-
import { render, fireEvent, act } from '@testing-library/react-native';
|
|
7
|
-
import { AppearanceService, appearanceService } from '../../infrastructure/services/appearanceService';
|
|
8
|
-
import { useAppearanceStore } from '../../infrastructure/stores/appearanceStore';
|
|
9
|
-
import { AppearanceScreen } from '../../presentation/screens/AppearanceScreen';
|
|
10
|
-
import type { ThemeMode, CustomThemeColors } from '../../types';
|
|
11
|
-
|
|
12
|
-
// Mock design system theme
|
|
13
|
-
jest.mock('@umituz/react-native-design-system', () => ({
|
|
14
|
-
useTheme: {
|
|
15
|
-
getState: jest.fn(() => ({
|
|
16
|
-
setThemeMode: jest.fn(),
|
|
17
|
-
})),
|
|
18
|
-
},
|
|
19
|
-
useDesignSystemTheme: {
|
|
20
|
-
getState: jest.fn(() => ({
|
|
21
|
-
setThemeMode: jest.fn(),
|
|
22
|
-
setCustomColors: jest.fn(),
|
|
23
|
-
})),
|
|
24
|
-
},
|
|
25
|
-
}));
|
|
26
|
-
|
|
27
|
-
// Mock storage
|
|
28
|
-
jest.mock('../../infrastructure/storage/appearanceStorage', () => ({
|
|
29
|
-
AppearanceStorage: {
|
|
30
|
-
getSettings: jest.fn(() => Promise.resolve(null)),
|
|
31
|
-
setSettings: jest.fn(() => Promise.resolve()),
|
|
32
|
-
clear: jest.fn(() => Promise.resolve()),
|
|
33
|
-
},
|
|
34
|
-
}));
|
|
35
|
-
|
|
36
|
-
const mockUseTheme = require('@umituz/react-native-design-system').useTheme;
|
|
37
|
-
const mockUseDesignSystemTheme = require('@umituz/react-native-design-system').useDesignSystemTheme;
|
|
38
|
-
const mockAppearanceStorage = require('../../infrastructure/storage/appearanceStorage').AppearanceStorage;
|
|
39
|
-
|
|
40
|
-
describe('Appearance Integration Tests', () => {
|
|
41
|
-
beforeEach(() => {
|
|
42
|
-
jest.clearAllMocks();
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
afterEach(() => {
|
|
46
|
-
jest.restoreAllMocks();
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it('should initialize and render correctly', async () => {
|
|
50
|
-
const { getByTestId } = render(<AppearanceScreen />);
|
|
51
|
-
|
|
52
|
-
// Should render without crashing
|
|
53
|
-
expect(getByTestId('appearance-screen')).toBeTruthy();
|
|
54
|
-
|
|
55
|
-
// Should initialize service
|
|
56
|
-
await act(async () => {
|
|
57
|
-
await appearanceService.initialize();
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
expect(mockAppearanceStorage.getSettings).toHaveBeenCalled();
|
|
61
|
-
expect(mockUseTheme.getState().setThemeMode).toHaveBeenCalled();
|
|
62
|
-
expect(mockUseDesignSystemTheme.getState().setThemeMode).toHaveBeenCalled();
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('should handle theme mode changes end-to-end', async () => {
|
|
66
|
-
const { getByTestId } = render(<AppearanceScreen />);
|
|
67
|
-
|
|
68
|
-
// Initialize service
|
|
69
|
-
await act(async () => {
|
|
70
|
-
await appearanceService.initialize();
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
// Change theme mode
|
|
74
|
-
await act(async () => {
|
|
75
|
-
await appearanceService.setThemeMode('light');
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
// Verify all systems are updated
|
|
79
|
-
expect(mockUseTheme.getState().setThemeMode).toHaveBeenCalledWith('light');
|
|
80
|
-
expect(mockUseDesignSystemTheme.getState().setThemeMode).toHaveBeenCalledWith('light');
|
|
81
|
-
expect(mockAppearanceStorage.setSettings).toHaveBeenCalledWith({
|
|
82
|
-
themeMode: 'light',
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('should handle custom color changes end-to-end', async () => {
|
|
87
|
-
const { getByTestId } = render(<AppearanceScreen />);
|
|
88
|
-
|
|
89
|
-
// Initialize service
|
|
90
|
-
await act(async () => {
|
|
91
|
-
await appearanceService.initialize();
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
// Change custom colors
|
|
95
|
-
const newColors: CustomThemeColors = {
|
|
96
|
-
primary: '#FF0000',
|
|
97
|
-
secondary: '#00FF00',
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
await act(async () => {
|
|
101
|
-
await appearanceService.setCustomColors(newColors);
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
// Verify all systems are updated
|
|
105
|
-
expect(mockUseDesignSystemTheme.getState().setCustomColors).toHaveBeenCalledWith(newColors);
|
|
106
|
-
expect(mockAppearanceStorage.setSettings).toHaveBeenCalledWith({
|
|
107
|
-
themeMode: 'dark', // Default theme
|
|
108
|
-
customColors: newColors,
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
it('should handle reset end-to-end', async () => {
|
|
113
|
-
const { getByTestId } = render(<AppearanceScreen />);
|
|
114
|
-
|
|
115
|
-
// Initialize with custom settings
|
|
116
|
-
await act(async () => {
|
|
117
|
-
await appearanceService.setThemeMode('light');
|
|
118
|
-
await appearanceService.setCustomColors({
|
|
119
|
-
primary: '#FF0000',
|
|
120
|
-
secondary: '#00FF00',
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
// Reset everything
|
|
125
|
-
await act(async () => {
|
|
126
|
-
await appearanceService.reset();
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
// Verify reset
|
|
130
|
-
expect(mockAppearanceStorage.clear).toHaveBeenCalled();
|
|
131
|
-
expect(mockUseTheme.getState().setThemeMode).toHaveBeenCalledWith('dark');
|
|
132
|
-
expect(mockUseDesignSystemTheme.getState().setThemeMode).toHaveBeenCalledWith('dark');
|
|
133
|
-
expect(mockUseDesignSystemTheme.getState().setCustomColors).toHaveBeenCalledWith(undefined);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it('should handle errors gracefully', async () => {
|
|
137
|
-
const { getByTestId } = render(<AppearanceScreen />);
|
|
138
|
-
|
|
139
|
-
// Mock storage to throw error
|
|
140
|
-
mockAppearanceStorage.setSettings.mockRejectedValue(new Error('Storage failed'));
|
|
141
|
-
|
|
142
|
-
// Should still render without crashing
|
|
143
|
-
expect(getByTestId('appearance-screen')).toBeTruthy();
|
|
144
|
-
|
|
145
|
-
// Should handle error gracefully
|
|
146
|
-
await act(async () => {
|
|
147
|
-
await appearanceService.setThemeMode('light');
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
// Should still attempt to update despite storage error
|
|
151
|
-
expect(mockUseTheme.getState().setThemeMode).toHaveBeenCalled();
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
it('should prevent memory leaks during rapid updates', async () => {
|
|
155
|
-
const { getByTestId } = render(<AppearanceScreen />);
|
|
156
|
-
|
|
157
|
-
// Initialize service
|
|
158
|
-
await act(async () => {
|
|
159
|
-
await appearanceService.initialize();
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
// Rapid theme changes
|
|
163
|
-
const promises = [];
|
|
164
|
-
for (let i = 0; i < 10; i++) {
|
|
165
|
-
promises.push(
|
|
166
|
-
act(async () => {
|
|
167
|
-
await appearanceService.setThemeMode(i % 2 === 0 ? 'light' : 'dark');
|
|
168
|
-
})
|
|
169
|
-
);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
await Promise.all(promises);
|
|
173
|
-
|
|
174
|
-
// Should handle rapid changes without memory leaks
|
|
175
|
-
expect(getByTestId('appearance-screen')).toBeTruthy();
|
|
176
|
-
|
|
177
|
-
// Verify final state
|
|
178
|
-
const finalTheme = i % 2 === 0 ? 'dark' : 'light';
|
|
179
|
-
expect(mockUseTheme.getState().setThemeMode).toHaveBeenLastCalledWith(finalTheme);
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
it('should maintain performance during heavy usage', async () => {
|
|
183
|
-
const { getByTestId } = render(<AppearanceScreen />);
|
|
184
|
-
|
|
185
|
-
const startTime = performance.now();
|
|
186
|
-
|
|
187
|
-
// Heavy usage simulation
|
|
188
|
-
await act(async () => {
|
|
189
|
-
await appearanceService.initialize();
|
|
190
|
-
|
|
191
|
-
// Rapid color changes
|
|
192
|
-
for (let i = 0; i < 20; i++) {
|
|
193
|
-
const colors: CustomThemeColors = {
|
|
194
|
-
primary: `#${i.toString(16).padStart(6, '0')}`,
|
|
195
|
-
};
|
|
196
|
-
await appearanceService.setCustomColors(colors);
|
|
197
|
-
}
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
const endTime = performance.now();
|
|
201
|
-
const duration = endTime - startTime;
|
|
202
|
-
|
|
203
|
-
// Should complete within reasonable time
|
|
204
|
-
expect(duration).toBeLessThan(1000); // 1 second for 20 color changes
|
|
205
|
-
expect(getByTestId('appearance-screen')).toBeTruthy();
|
|
206
|
-
});
|
|
207
|
-
});
|