@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,178 +0,0 @@
1
- /**
2
- * Simple test for AboutContent component
3
- */
4
- import React from 'react';
5
- import { AboutContent } from '../AboutContent';
6
- import { AppInfo, AboutConfig } from '../../../domain/entities/AppInfo';
7
-
8
- describe('AboutContent', () => {
9
- const mockAppInfo: AppInfo = {
10
- name: 'Test App',
11
- version: '1.0.0',
12
- description: 'Test Description',
13
- developer: 'Test Developer',
14
- contactEmail: 'test@example.com',
15
- websiteUrl: 'https://example.com',
16
- websiteDisplay: 'example.com',
17
- moreAppsUrl: 'https://apps.example.com',
18
- privacyPolicyUrl: 'https://example.com/privacy',
19
- termsOfServiceUrl: 'https://example.com/terms',
20
- };
21
-
22
- const mockConfig: AboutConfig = {
23
- appInfo: mockAppInfo,
24
- actions: {
25
- onEmailPress: jest.fn(),
26
- onWebsitePress: jest.fn(),
27
- onPrivacyPress: jest.fn(),
28
- onTermsPress: jest.fn(),
29
- onMoreAppsPress: jest.fn(),
30
- },
31
- };
32
-
33
- it('should render without crashing', () => {
34
- const element = React.createElement(AboutContent, { appInfo: mockAppInfo, config: mockConfig });
35
- expect(element).toBeTruthy();
36
- });
37
-
38
- it('should render developer when provided', () => {
39
- const element = React.createElement(AboutContent, { appInfo: mockAppInfo, config: mockConfig });
40
- expect(element).toBeTruthy();
41
- expect(mockAppInfo.developer).toBe('Test Developer');
42
- });
43
-
44
- it('should render contact email when provided', () => {
45
- const element = React.createElement(AboutContent, { appInfo: mockAppInfo, config: mockConfig });
46
- expect(element).toBeTruthy();
47
- expect(mockAppInfo.contactEmail).toBe('test@example.com');
48
- });
49
-
50
- it('should render website when provided', () => {
51
- const element = React.createElement(AboutContent, { appInfo: mockAppInfo, config: mockConfig });
52
- expect(element).toBeTruthy();
53
- expect(mockAppInfo.websiteUrl).toBe('https://example.com');
54
- });
55
-
56
- it('should render more apps when provided', () => {
57
- const element = React.createElement(AboutContent, { appInfo: mockAppInfo, config: mockConfig });
58
- expect(element).toBeTruthy();
59
- expect(mockAppInfo.moreAppsUrl).toBe('https://apps.example.com');
60
- });
61
-
62
- it('should render privacy policy when provided', () => {
63
- const element = React.createElement(AboutContent, { appInfo: mockAppInfo, config: mockConfig });
64
- expect(element).toBeTruthy();
65
- expect(mockAppInfo.privacyPolicyUrl).toBe('https://example.com/privacy');
66
- });
67
-
68
- it('should render terms of service when provided', () => {
69
- const element = React.createElement(AboutContent, { appInfo: mockAppInfo, config: mockConfig });
70
- expect(element).toBeTruthy();
71
- expect(mockAppInfo.termsOfServiceUrl).toBe('https://example.com/terms');
72
- });
73
-
74
- it('should not render developer when not provided', () => {
75
- const appInfoWithoutDeveloper = {
76
- ...mockAppInfo,
77
- developer: '',
78
- };
79
-
80
- const element = React.createElement(AboutContent, { appInfo: appInfoWithoutDeveloper, config: mockConfig });
81
- expect(element).toBeTruthy();
82
- expect(appInfoWithoutDeveloper.developer).toBe('');
83
- });
84
-
85
- it('should not render contact email when not provided', () => {
86
- const appInfoWithoutEmail = {
87
- ...mockAppInfo,
88
- contactEmail: '',
89
- };
90
-
91
- const element = React.createElement(AboutContent, { appInfo: appInfoWithoutEmail, config: mockConfig });
92
- expect(element).toBeTruthy();
93
- expect(appInfoWithoutEmail.contactEmail).toBe('');
94
- });
95
-
96
- it('should not render website when not provided', () => {
97
- const appInfoWithoutWebsite = {
98
- ...mockAppInfo,
99
- websiteUrl: '',
100
- websiteDisplay: '',
101
- };
102
-
103
- const element = React.createElement(AboutContent, { appInfo: appInfoWithoutWebsite, config: mockConfig });
104
- expect(element).toBeTruthy();
105
- expect(appInfoWithoutWebsite.websiteUrl).toBe('');
106
- });
107
-
108
- it('should use websiteDisplay when provided', () => {
109
- const appInfoWithDisplay = {
110
- ...mockAppInfo,
111
- websiteDisplay: 'Custom Display',
112
- };
113
-
114
- const element = React.createElement(AboutContent, { appInfo: appInfoWithDisplay, config: mockConfig });
115
- expect(element).toBeTruthy();
116
- expect(appInfoWithDisplay.websiteDisplay).toBe('Custom Display');
117
- });
118
-
119
- it('should use websiteUrl when websiteDisplay not provided', () => {
120
- const appInfoWithoutDisplay = {
121
- ...mockAppInfo,
122
- websiteDisplay: '',
123
- };
124
-
125
- const element = React.createElement(AboutContent, { appInfo: appInfoWithoutDisplay, config: mockConfig });
126
- expect(element).toBeTruthy();
127
- expect(appInfoWithoutDisplay.websiteDisplay).toBe('');
128
- });
129
-
130
- it('should handle empty app info', () => {
131
- const emptyAppInfo: AppInfo = {
132
- name: '',
133
- version: '',
134
- description: '',
135
- developer: '',
136
- contactEmail: '',
137
- websiteUrl: '',
138
- websiteDisplay: '',
139
- moreAppsUrl: '',
140
- privacyPolicyUrl: '',
141
- termsOfServiceUrl: '',
142
- };
143
-
144
- const element = React.createElement(AboutContent, { appInfo: emptyAppInfo, config: mockConfig });
145
- expect(element).toBeTruthy();
146
- });
147
-
148
- it('should handle app info with only required fields', () => {
149
- const minimalAppInfo: AppInfo = {
150
- name: 'Minimal App',
151
- version: '1.0.0',
152
- description: '',
153
- developer: '',
154
- contactEmail: '',
155
- websiteUrl: '',
156
- websiteDisplay: '',
157
- moreAppsUrl: '',
158
- privacyPolicyUrl: '',
159
- termsOfServiceUrl: '',
160
- };
161
-
162
- const element = React.createElement(AboutContent, { appInfo: minimalAppInfo, config: mockConfig });
163
- expect(element).toBeTruthy();
164
- expect(minimalAppInfo.name).toBe('Minimal App');
165
- });
166
-
167
- it('should handle special characters in text', () => {
168
- const appInfoWithSpecialChars: AppInfo = {
169
- ...mockAppInfo,
170
- developer: 'Test & Developer <script>',
171
- contactEmail: 'test+special@example.com',
172
- };
173
-
174
- const element = React.createElement(AboutContent, { appInfo: appInfoWithSpecialChars, config: mockConfig });
175
- expect(element).toBeTruthy();
176
- expect(appInfoWithSpecialChars.developer).toBe('Test & Developer <script>');
177
- });
178
- });
@@ -1,293 +0,0 @@
1
- /**
2
- * Tests for AboutContent component
3
- */
4
- import React from 'react';
5
- import { render, fireEvent } from '@testing-library/react';
6
- import { AboutContent } from '../AboutContent';
7
- import { AppInfo, AboutConfig } from '../../../domain/entities/AppInfo';
8
-
9
- describe('AboutContent', () => {
10
- const mockAppInfo: AppInfo = {
11
- name: 'Test App',
12
- version: '1.0.0',
13
- description: 'Test Description',
14
- developer: 'Test Developer',
15
- contactEmail: 'test@example.com',
16
- websiteUrl: 'https://example.com',
17
- websiteDisplay: 'example.com',
18
- moreAppsUrl: 'https://apps.example.com',
19
- };
20
-
21
- const mockConfig: AboutConfig = {
22
- appInfo: mockAppInfo,
23
- actions: {
24
- onEmailPress: jest.fn(),
25
- onWebsitePress: jest.fn(),
26
- onMoreAppsPress: jest.fn(),
27
- },
28
- };
29
-
30
- beforeEach(() => {
31
- jest.clearAllMocks();
32
- });
33
-
34
- describe('Rendering', () => {
35
- it('should render developer when provided', () => {
36
- const { getByText } = render(
37
- <AboutContent appInfo={mockAppInfo} config={mockConfig} />
38
- );
39
-
40
- expect(getByText('Developer')).toBeTruthy();
41
- expect(getByText('Test Developer')).toBeTruthy();
42
- });
43
-
44
- it('should render contact email when provided', () => {
45
- const { getByText } = render(
46
- <AboutContent appInfo={mockAppInfo} config={mockConfig} />
47
- );
48
-
49
- expect(getByText('Contact')).toBeTruthy();
50
- expect(getByText('test@example.com')).toBeTruthy();
51
- });
52
-
53
- it('should render website when provided', () => {
54
- const { getByText } = render(
55
- <AboutContent appInfo={mockAppInfo} config={mockConfig} />
56
- );
57
-
58
- expect(getByText('Website')).toBeTruthy();
59
- expect(getByText('example.com')).toBeTruthy();
60
- });
61
-
62
- it('should render more apps when provided', () => {
63
- const { getByText } = render(
64
- <AboutContent appInfo={mockAppInfo} config={mockConfig} />
65
- );
66
-
67
- expect(getByText('More Apps')).toBeTruthy();
68
- });
69
-
70
- it('should not render developer when not provided', () => {
71
- const appInfoWithoutDeveloper: AppInfo = {
72
- name: 'Test App',
73
- version: '1.0.0',
74
- };
75
-
76
- const { queryByText } = render(
77
- <AboutContent appInfo={appInfoWithoutDeveloper} config={mockConfig} />
78
- );
79
-
80
- expect(queryByText('Developer')).toBeFalsy();
81
- });
82
-
83
- it('should not render contact email when not provided', () => {
84
- const appInfoWithoutEmail: AppInfo = {
85
- name: 'Test App',
86
- version: '1.0.0',
87
- };
88
-
89
- const { queryByText } = render(
90
- <AboutContent appInfo={appInfoWithoutEmail} config={mockConfig} />
91
- );
92
-
93
- expect(queryByText('Contact')).toBeFalsy();
94
- });
95
-
96
- it('should not render website when not provided', () => {
97
- const appInfoWithoutWebsite: AppInfo = {
98
- name: 'Test App',
99
- version: '1.0.0',
100
- };
101
-
102
- const { queryByText } = render(
103
- <AboutContent appInfo={appInfoWithoutWebsite} config={mockConfig} />
104
- );
105
-
106
- expect(queryByText('Website')).toBeFalsy();
107
- });
108
-
109
- it('should use websiteDisplay when provided', () => {
110
- const appInfoWithDisplay: AppInfo = {
111
- name: 'Test App',
112
- version: '1.0.0',
113
- websiteUrl: 'https://example.com',
114
- websiteDisplay: 'Custom Display',
115
- };
116
-
117
- const { getByText, queryByText } = render(
118
- <AboutContent appInfo={appInfoWithDisplay} config={mockConfig} />
119
- );
120
-
121
- expect(getByText('Custom Display')).toBeTruthy();
122
- expect(queryByText('https://example.com')).toBeFalsy();
123
- });
124
-
125
- it('should use websiteUrl when websiteDisplay not provided', () => {
126
- const appInfoWithoutDisplay: AppInfo = {
127
- name: 'Test App',
128
- version: '1.0.0',
129
- websiteUrl: 'https://example.com',
130
- };
131
-
132
- const { getByText } = render(
133
- <AboutContent appInfo={appInfoWithoutDisplay} config={mockConfig} />
134
- );
135
-
136
- expect(getByText('https://example.com')).toBeTruthy();
137
- });
138
- });
139
-
140
- describe('Interactions', () => {
141
- it('should call onEmailPress when email item is pressed', () => {
142
- const { getByTestId } = render(
143
- <AboutContent appInfo={mockAppInfo} config={mockConfig} />
144
- );
145
-
146
- fireEvent.click(getByTestId('email-item'));
147
- expect(mockConfig.actions!.onEmailPress).toHaveBeenCalledTimes(1);
148
- });
149
-
150
- it('should call onWebsitePress when website item is pressed', () => {
151
- const { getByTestId } = render(
152
- <AboutContent appInfo={mockAppInfo} config={mockConfig} />
153
- );
154
-
155
- fireEvent.click(getByTestId('website-item'));
156
- expect(mockConfig.actions!.onWebsitePress).toHaveBeenCalledTimes(1);
157
- });
158
-
159
- it('should call onMoreAppsPress when more apps item is pressed', () => {
160
- const { getByTestId } = render(
161
- <AboutContent appInfo={mockAppInfo} config={mockConfig} />
162
- );
163
-
164
- fireEvent.click(getByTestId('more-apps-item'));
165
- expect(mockConfig.actions!.onMoreAppsPress).toHaveBeenCalledTimes(1);
166
- });
167
-
168
- it('should not crash when actions are not provided', () => {
169
- const configWithoutActions: AboutConfig = {
170
- appInfo: mockAppInfo,
171
- };
172
-
173
- const { getByTestId } = render(
174
- <AboutContent appInfo={mockAppInfo} config={configWithoutActions} />
175
- );
176
-
177
- expect(() => {
178
- fireEvent.click(getByTestId('email-item'));
179
- fireEvent.click(getByTestId('website-item'));
180
- }).not.toThrow();
181
- });
182
-
183
- it('should not call actions when they are undefined', () => {
184
- const configWithUndefinedActions: AboutConfig = {
185
- appInfo: mockAppInfo,
186
- actions: {
187
- onEmailPress: undefined,
188
- onWebsitePress: undefined,
189
- },
190
- };
191
-
192
- const { getByTestId } = render(
193
- <AboutContent appInfo={mockAppInfo} config={configWithUndefinedActions} />
194
- );
195
-
196
- fireEvent.click(getByTestId('email-item'));
197
- fireEvent.click(getByTestId('website-item'));
198
-
199
- // Should not throw and should not call any undefined functions
200
- expect(true).toBe(true);
201
- });
202
- });
203
-
204
- describe('Performance', () => {
205
- it('should memoize render functions', () => {
206
- const { rerender } = render(
207
- <AboutContent appInfo={mockAppInfo} config={mockConfig} />
208
- );
209
-
210
- // Re-render with same props
211
- rerender(
212
- <AboutContent appInfo={mockAppInfo} config={mockConfig} />
213
- );
214
-
215
- // Should not throw and should render correctly
216
- expect(() => {
217
- rerender(
218
- <AboutContent appInfo={mockAppInfo} config={mockConfig} />
219
- );
220
- }).not.toThrow();
221
- });
222
-
223
- it('should handle rapid prop changes', () => {
224
- const { rerender } = render(
225
- <AboutContent appInfo={mockAppInfo} config={mockConfig} />
226
- );
227
-
228
- // Rapid prop changes
229
- for (let i = 0; i < 10; i++) {
230
- const newAppInfo = { ...mockAppInfo, name: `App ${i}` };
231
- rerender(
232
- <AboutContent appInfo={newAppInfo} config={mockConfig} />
233
- );
234
- }
235
-
236
- expect(() => {
237
- rerender(
238
- <AboutContent appInfo={{ ...mockAppInfo, name: 'Final App' }} config={mockConfig} />
239
- );
240
- }).not.toThrow();
241
- });
242
- });
243
-
244
- describe('Edge Cases', () => {
245
- it('should handle empty app info', () => {
246
- const emptyAppInfo: AppInfo = {
247
- name: '',
248
- version: '1.0.0',
249
- };
250
-
251
- const { queryByText } = render(
252
- <AboutContent appInfo={emptyAppInfo} config={mockConfig} />
253
- );
254
-
255
- expect(queryByText('Developer')).toBeFalsy();
256
- expect(queryByText('Contact')).toBeFalsy();
257
- expect(queryByText('Website')).toBeFalsy();
258
- });
259
-
260
- it('should handle app info with only required fields', () => {
261
- const minimalAppInfo: AppInfo = {
262
- name: 'Minimal App',
263
- version: '1.0.0',
264
- };
265
-
266
- const { queryByText } = render(
267
- <AboutContent appInfo={minimalAppInfo} config={mockConfig} />
268
- );
269
-
270
- expect(queryByText('Developer')).toBeFalsy();
271
- expect(queryByText('Contact')).toBeFalsy();
272
- expect(queryByText('Website')).toBeFalsy();
273
- });
274
-
275
- it('should handle special characters in text', () => {
276
- const appInfoWithSpecialChars: AppInfo = {
277
- name: 'Test App',
278
- version: '1.0.0',
279
- developer: 'Developer & Co. <test>',
280
- contactEmail: 'test+special@example.com',
281
- websiteUrl: 'https://example.com/path?param=value&other=test',
282
- };
283
-
284
- const { getByText } = render(
285
- <AboutContent appInfo={appInfoWithSpecialChars} config={mockConfig} />
286
- );
287
-
288
- expect(getByText('Developer & Co. <test>')).toBeTruthy();
289
- expect(getByText('test+special@example.com')).toBeTruthy();
290
- expect(getByText('https://example.com/path?param=value&other=test')).toBeTruthy();
291
- });
292
- });
293
- });
@@ -1,201 +0,0 @@
1
- /**
2
- * Tests for AboutHeader component
3
- */
4
- import React from 'react';
5
- import { render } from '@testing-library/react';
6
- import { AboutHeader } from '../AboutHeader';
7
- import { AppInfo } from '../../../domain/entities/AppInfo';
8
-
9
- describe('AboutHeader', () => {
10
- const mockAppInfo: AppInfo = {
11
- name: 'Test App',
12
- version: '1.0.0',
13
- description: 'Test Description',
14
- developer: 'Test Developer',
15
- };
16
-
17
- beforeEach(() => {
18
- jest.clearAllMocks();
19
- });
20
-
21
- describe('Rendering', () => {
22
- it('should render correctly with required props', () => {
23
- const { getByText } = render(
24
- <AboutHeader appInfo={mockAppInfo} />
25
- );
26
-
27
- expect(getByText('Test App')).toBeTruthy();
28
- expect(getByText('Version 1.0.0')).toBeTruthy();
29
- });
30
-
31
- it('should render description when provided', () => {
32
- const { getByText } = render(
33
- <AboutHeader appInfo={mockAppInfo} />
34
- );
35
-
36
- expect(getByText('Test Description')).toBeTruthy();
37
- });
38
-
39
- it('should not render description when not provided', () => {
40
- const appInfoWithoutDescription: AppInfo = {
41
- name: 'Test App',
42
- version: '1.0.0',
43
- };
44
-
45
- const { queryByText } = render(
46
- <AboutHeader appInfo={appInfoWithoutDescription} />
47
- );
48
-
49
- expect(queryByText('Test Description')).toBeFalsy();
50
- });
51
-
52
- it('should render with all optional fields', () => {
53
- const fullAppInfo: AppInfo = {
54
- name: 'Full App',
55
- version: '2.0.0',
56
- description: 'Full Description',
57
- developer: 'Full Developer',
58
- contactEmail: 'full@example.com',
59
- websiteUrl: 'https://full.example.com',
60
- };
61
-
62
- const { getByText } = render(
63
- <AboutHeader appInfo={fullAppInfo} />
64
- );
65
-
66
- expect(getByText('Full App')).toBeTruthy();
67
- expect(getByText('Version 2.0.0')).toBeTruthy();
68
- expect(getByText('Full Description')).toBeTruthy();
69
- });
70
- });
71
-
72
- describe('Custom Styles', () => {
73
- it('should apply custom container style', () => {
74
- const customStyle = { backgroundColor: 'red' };
75
-
76
- const { getByTestId } = render(
77
- <AboutHeader appInfo={mockAppInfo} containerStyle={customStyle} testID="header" />
78
- );
79
-
80
- const header = getByTestId('header');
81
- expect(header).toBeInTheDocument();
82
- });
83
-
84
- it('should apply custom title style', () => {
85
- const customStyle = { color: 'blue' };
86
-
87
- const { getByText } = render(
88
- <AboutHeader appInfo={mockAppInfo} titleStyle={customStyle} />
89
- );
90
-
91
- const title = getByText('Test App');
92
- expect(title).toBeInTheDocument();
93
- });
94
-
95
- it('should apply custom version style', () => {
96
- const customStyle = { color: 'purple' };
97
-
98
- const { getByText } = render(
99
- <AboutHeader appInfo={mockAppInfo} versionStyle={customStyle} />
100
- );
101
-
102
- const version = getByText('Version 1.0.0');
103
- expect(version).toBeInTheDocument();
104
- });
105
-
106
- it('should apply custom description style', () => {
107
- const customStyle = { color: 'green' };
108
-
109
- const { getByText } = render(
110
- <AboutHeader appInfo={mockAppInfo} descriptionStyle={customStyle} />
111
- );
112
-
113
- const description = getByText('Test Description');
114
- expect(description).toBeInTheDocument();
115
- });
116
- });
117
-
118
- describe('Performance', () => {
119
- it('should memoize render functions', () => {
120
- const { rerender } = render(
121
- <AboutHeader appInfo={mockAppInfo} />
122
- );
123
-
124
- expect(() => {
125
- rerender(
126
- <AboutHeader appInfo={mockAppInfo} />
127
- );
128
- }).not.toThrow();
129
- });
130
-
131
- it('should handle rapid prop changes', () => {
132
- const { rerender } = render(
133
- <AboutHeader appInfo={mockAppInfo} />
134
- );
135
-
136
- for (let i = 0; i < 10; i++) {
137
- const newAppInfo = { ...mockAppInfo, name: `App ${i}` };
138
- rerender(
139
- <AboutHeader appInfo={newAppInfo} />
140
- );
141
- }
142
-
143
- expect(() => {
144
- rerender(
145
- <AboutHeader appInfo={{ ...mockAppInfo, name: 'Final App' }} />
146
- );
147
- }).not.toThrow();
148
- });
149
- });
150
-
151
- describe('Edge Cases', () => {
152
- it('should handle empty description', () => {
153
- const appInfoWithEmptyDescription: AppInfo = {
154
- name: 'Test App',
155
- version: '1.0.0',
156
- description: '',
157
- };
158
-
159
- const { getByText, container } = render(
160
- <AboutHeader appInfo={appInfoWithEmptyDescription} />
161
- );
162
-
163
- expect(getByText('Test App')).toBeTruthy();
164
- expect(getByText('Version 1.0.0')).toBeTruthy();
165
- expect(container.textContent).toContain('');
166
- });
167
-
168
- it('should handle very long text', () => {
169
- const longName = 'A'.repeat(100);
170
- const longDescription = 'B'.repeat(200);
171
-
172
- const appInfoWithLongText: AppInfo = {
173
- name: longName,
174
- version: '1.0.0',
175
- description: longDescription,
176
- };
177
-
178
- const { getByText } = render(
179
- <AboutHeader appInfo={appInfoWithLongText} />
180
- );
181
-
182
- expect(getByText(longName)).toBeTruthy();
183
- expect(getByText(longDescription)).toBeTruthy();
184
- });
185
-
186
- it('should handle special characters', () => {
187
- const appInfoWithSpecialChars: AppInfo = {
188
- name: 'Test & App <script>',
189
- version: '1.0.0',
190
- description: 'Description with émojis 🎉 and ñ',
191
- };
192
-
193
- const { getByText } = render(
194
- <AboutHeader appInfo={appInfoWithSpecialChars} />
195
- );
196
-
197
- expect(getByText('Test & App <script>')).toBeTruthy();
198
- expect(getByText('Description with émojis 🎉 and ñ')).toBeTruthy();
199
- });
200
- });
201
- });