@umituz/react-native-settings 4.20.62 → 4.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/package.json +6 -61
  2. package/src/domains/gamification/components/AchievementCard.tsx +142 -0
  3. package/src/domains/gamification/components/AchievementItem.tsx +182 -0
  4. package/src/domains/gamification/components/AchievementToast.tsx +122 -0
  5. package/src/domains/gamification/components/GamificationScreen/AchievementsList.tsx +84 -0
  6. package/src/domains/gamification/components/GamificationScreen/Header.tsx +29 -0
  7. package/src/domains/gamification/components/GamificationScreen/StatsGrid.tsx +51 -0
  8. package/src/domains/gamification/components/GamificationScreen/index.tsx +111 -0
  9. package/src/domains/gamification/components/GamificationScreen/styles.ts +43 -0
  10. package/src/domains/gamification/components/GamificationScreen/types.ts +77 -0
  11. package/src/domains/gamification/components/GamificationScreenWrapper.tsx +4 -4
  12. package/src/domains/gamification/components/GamificationSettingsItem.tsx +1 -1
  13. package/src/domains/gamification/components/LevelProgress.tsx +129 -0
  14. package/src/domains/gamification/components/PointsBadge.tsx +60 -0
  15. package/src/domains/gamification/components/StatsCard.tsx +89 -0
  16. package/src/domains/gamification/components/StreakDisplay.tsx +119 -0
  17. package/src/domains/gamification/components/index.ts +13 -0
  18. package/src/domains/gamification/examples/gamification.config.example.ts +1 -1
  19. package/src/domains/gamification/hooks/useGamification.ts +91 -0
  20. package/src/domains/gamification/index.ts +46 -19
  21. package/src/domains/gamification/store/gamificationStore.ts +162 -0
  22. package/src/domains/gamification/types/index.ts +95 -23
  23. package/src/domains/gamification/types/settings.ts +28 -0
  24. package/src/domains/gamification/utils/calculations.ts +85 -0
  25. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -51
  26. package/.github/ISSUE_TEMPLATE/documentation.md +0 -52
  27. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -63
  28. package/.github/PULL_REQUEST_TEMPLATE.md +0 -84
  29. package/AI_AGENT_GUIDELINES.md +0 -367
  30. package/ARCHITECTURE.md +0 -246
  31. package/CHANGELOG.md +0 -67
  32. package/CODE_OF_CONDUCT.md +0 -75
  33. package/CONTRIBUTING.md +0 -107
  34. package/DOCUMENTATION_MIGRATION.md +0 -319
  35. package/DOCUMENTATION_TEMPLATE.md +0 -155
  36. package/SECURITY.md +0 -98
  37. package/SETTINGS_SCREEN_GUIDE.md +0 -185
  38. package/TESTING.md +0 -358
  39. package/src/__tests__/integration.test.tsx +0 -371
  40. package/src/__tests__/performance.test.tsx +0 -369
  41. package/src/__tests__/setup.test.tsx +0 -20
  42. package/src/__tests__/setup.ts +0 -154
  43. package/src/domains/about/__tests__/integration.test.tsx +0 -328
  44. package/src/domains/about/__tests__/types.d.ts +0 -5
  45. package/src/domains/about/domain/entities/__tests__/AppInfo.test.ts +0 -93
  46. package/src/domains/about/infrastructure/repositories/__tests__/AboutRepository.test.ts +0 -153
  47. package/src/domains/about/presentation/components/__tests__/AboutContent.simple.test.tsx +0 -178
  48. package/src/domains/about/presentation/components/__tests__/AboutContent.test.tsx +0 -293
  49. package/src/domains/about/presentation/components/__tests__/AboutHeader.test.tsx +0 -201
  50. package/src/domains/about/presentation/components/__tests__/AboutSettingItem.test.tsx +0 -71
  51. package/src/domains/about/presentation/hooks/__tests__/useAboutInfo.simple.test.tsx +0 -229
  52. package/src/domains/about/presentation/hooks/__tests__/useAboutInfo.test.tsx +0 -240
  53. package/src/domains/about/presentation/screens/__tests__/AboutScreen.simple.test.tsx +0 -199
  54. package/src/domains/about/presentation/screens/__tests__/AboutScreen.test.tsx +0 -366
  55. package/src/domains/about/utils/__tests__/index.test.ts +0 -408
  56. package/src/domains/appearance/__tests__/components/AppearanceScreen.test.tsx +0 -195
  57. package/src/domains/appearance/__tests__/hooks/index.test.tsx +0 -232
  58. package/src/domains/appearance/__tests__/integration/index.test.tsx +0 -207
  59. package/src/domains/appearance/__tests__/services/appearanceService.test.ts +0 -299
  60. package/src/domains/appearance/__tests__/setup.ts +0 -88
  61. package/src/domains/appearance/__tests__/stores/appearanceStore.test.tsx +0 -175
  62. package/src/domains/cloud-sync/presentation/components/__tests__/CloudSyncSetting.test.tsx +0 -78
  63. package/src/domains/legal/__tests__/ContentValidationService.test.ts +0 -195
  64. package/src/domains/legal/__tests__/StyleCacheService.test.ts +0 -110
  65. package/src/domains/legal/__tests__/UrlHandlerService.test.ts +0 -71
  66. package/src/domains/legal/__tests__/setup.ts +0 -82
  67. package/src/presentation/components/__tests__/SettingsErrorBoundary.test.tsx +0 -186
  68. package/src/presentation/screens/__tests__/SettingsScreen.test.tsx +0 -322
  69. 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
- });