@umituz/react-native-settings 4.17.14 → 4.17.16

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 (103) hide show
  1. package/package.json +16 -15
  2. package/src/domains/about/__tests__/integration.test.tsx +328 -0
  3. package/src/domains/about/__tests__/types.d.ts +5 -0
  4. package/src/domains/about/domain/entities/AppInfo.ts +74 -0
  5. package/src/domains/about/domain/entities/__tests__/AppInfo.test.ts +93 -0
  6. package/src/domains/about/domain/repositories/IAboutRepository.ts +22 -0
  7. package/src/domains/about/index.ts +10 -0
  8. package/src/domains/about/infrastructure/repositories/AboutRepository.ts +68 -0
  9. package/src/domains/about/infrastructure/repositories/__tests__/AboutRepository.test.ts +153 -0
  10. package/src/domains/about/presentation/components/AboutContent.tsx +104 -0
  11. package/src/domains/about/presentation/components/AboutHeader.tsx +79 -0
  12. package/src/domains/about/presentation/components/AboutSection.tsx +134 -0
  13. package/src/domains/about/presentation/components/AboutSettingItem.tsx +208 -0
  14. package/src/domains/about/presentation/components/__tests__/AboutContent.simple.test.tsx +178 -0
  15. package/src/domains/about/presentation/components/__tests__/AboutContent.test.tsx +293 -0
  16. package/src/domains/about/presentation/components/__tests__/AboutHeader.test.tsx +201 -0
  17. package/src/domains/about/presentation/components/__tests__/AboutSettingItem.test.tsx +71 -0
  18. package/src/domains/about/presentation/hooks/__tests__/useAboutInfo.simple.test.tsx +229 -0
  19. package/src/domains/about/presentation/hooks/__tests__/useAboutInfo.test.tsx +240 -0
  20. package/src/domains/about/presentation/hooks/useAboutInfo.ts +262 -0
  21. package/src/domains/about/presentation/screens/AboutScreen.tsx +195 -0
  22. package/src/domains/about/presentation/screens/__tests__/AboutScreen.simple.test.tsx +199 -0
  23. package/src/domains/about/presentation/screens/__tests__/AboutScreen.test.tsx +366 -0
  24. package/src/domains/about/types/global.d.ts +15 -0
  25. package/src/domains/about/utils/__tests__/index.test.ts +408 -0
  26. package/src/domains/about/utils/index.ts +160 -0
  27. package/src/domains/appearance/__tests__/components/AppearanceScreen.test.tsx +195 -0
  28. package/src/domains/appearance/__tests__/hooks/index.test.tsx +232 -0
  29. package/src/domains/appearance/__tests__/integration/index.test.tsx +207 -0
  30. package/src/domains/appearance/__tests__/services/appearanceService.test.ts +299 -0
  31. package/src/domains/appearance/__tests__/setup.ts +96 -0
  32. package/src/domains/appearance/__tests__/stores/appearanceStore.test.tsx +175 -0
  33. package/src/domains/appearance/data/colorPalettes.ts +94 -0
  34. package/src/domains/appearance/hooks/index.ts +6 -0
  35. package/src/domains/appearance/hooks/useAppearance.ts +61 -0
  36. package/src/domains/appearance/hooks/useAppearanceActions.ts +144 -0
  37. package/src/domains/appearance/index.ts +7 -0
  38. package/src/domains/appearance/infrastructure/services/appearanceService.ts +301 -0
  39. package/src/domains/appearance/infrastructure/services/systemThemeDetection.ts +79 -0
  40. package/src/domains/appearance/infrastructure/services/validation.ts +91 -0
  41. package/src/domains/appearance/infrastructure/storage/appearanceStorage.ts +120 -0
  42. package/src/domains/appearance/infrastructure/stores/appearanceStore.ts +132 -0
  43. package/src/domains/appearance/presentation/components/AppearanceHeader.tsx +67 -0
  44. package/src/domains/appearance/presentation/components/AppearancePreview.tsx +141 -0
  45. package/src/domains/appearance/presentation/components/AppearanceSection.tsx +139 -0
  46. package/src/domains/appearance/presentation/components/ColorPicker.tsx +113 -0
  47. package/src/domains/appearance/presentation/components/CustomColorsSection.tsx +186 -0
  48. package/src/domains/appearance/presentation/components/ThemeModeSection.tsx +110 -0
  49. package/src/domains/appearance/presentation/components/ThemeOption.tsx +138 -0
  50. package/src/domains/appearance/presentation/components/index.ts +6 -0
  51. package/src/domains/appearance/presentation/screens/AppearanceScreen.tsx +226 -0
  52. package/src/domains/appearance/presentation/screens/index.ts +2 -0
  53. package/src/domains/appearance/types/index.ts +54 -0
  54. package/src/domains/faqs/domain/entities/FAQEntity.ts +16 -0
  55. package/src/domains/faqs/domain/services/FAQSearchService.ts +36 -0
  56. package/src/domains/faqs/domain/services/index.ts +1 -0
  57. package/src/domains/faqs/index.ts +7 -0
  58. package/src/domains/faqs/presentation/components/FAQCategory.tsx +71 -0
  59. package/src/domains/faqs/presentation/components/FAQEmptyState.tsx +75 -0
  60. package/src/domains/faqs/presentation/components/FAQItem.tsx +103 -0
  61. package/src/domains/faqs/presentation/components/FAQSearchBar.tsx +70 -0
  62. package/src/domains/faqs/presentation/components/FAQSection.tsx +50 -0
  63. package/src/domains/faqs/presentation/components/index.ts +18 -0
  64. package/src/domains/faqs/presentation/hooks/index.ts +6 -0
  65. package/src/domains/faqs/presentation/hooks/useFAQExpansion.ts +51 -0
  66. package/src/domains/faqs/presentation/hooks/useFAQSearch.ts +33 -0
  67. package/src/domains/faqs/presentation/screens/FAQScreen.tsx +129 -0
  68. package/src/domains/faqs/presentation/screens/index.ts +2 -0
  69. package/src/domains/feedback/domain/entities/FeedbackEntity.ts +92 -0
  70. package/src/domains/feedback/domain/repositories/IFeedbackRepository.ts +28 -0
  71. package/src/domains/feedback/index.ts +6 -0
  72. package/src/domains/feedback/presentation/components/FeedbackForm.tsx +189 -0
  73. package/src/domains/feedback/presentation/components/FeedbackModal.tsx +111 -0
  74. package/src/domains/feedback/presentation/components/SupportSection.tsx +160 -0
  75. package/src/domains/feedback/presentation/hooks/useDeleteFeedback.ts +25 -0
  76. package/src/domains/feedback/presentation/hooks/useFeedbackForm.ts +59 -0
  77. package/src/domains/feedback/presentation/hooks/useSubmitFeedback.ts +55 -0
  78. package/src/domains/feedback/presentation/hooks/useUserFeedback.ts +29 -0
  79. package/src/domains/legal/__tests__/ContentValidationService.test.ts +195 -0
  80. package/src/domains/legal/__tests__/StyleCacheService.test.ts +110 -0
  81. package/src/domains/legal/__tests__/UrlHandlerService.test.ts +71 -0
  82. package/src/domains/legal/__tests__/setup.ts +82 -0
  83. package/src/domains/legal/domain/entities/LegalConfig.ts +26 -0
  84. package/src/domains/legal/domain/services/ContentValidationService.ts +89 -0
  85. package/src/domains/legal/domain/services/StyleCacheService.ts +97 -0
  86. package/src/domains/legal/domain/services/UrlHandlerService.ts +128 -0
  87. package/src/domains/legal/index.ts +8 -0
  88. package/src/domains/legal/presentation/components/LegalItem.tsx +177 -0
  89. package/src/domains/legal/presentation/components/LegalLinks.tsx +154 -0
  90. package/src/domains/legal/presentation/components/LegalSection.tsx +134 -0
  91. package/src/domains/legal/presentation/screens/LegalScreen.tsx +237 -0
  92. package/src/domains/legal/presentation/screens/PrivacyPolicyScreen.tsx +214 -0
  93. package/src/domains/legal/presentation/screens/TermsOfServiceScreen.tsx +214 -0
  94. package/src/index.ts +19 -0
  95. package/src/presentation/components/DevSettingsSection.tsx +2 -2
  96. package/src/presentation/components/SettingItem.tsx +2 -2
  97. package/src/presentation/components/SettingsErrorBoundary.tsx +2 -2
  98. package/src/presentation/components/SettingsFooter.tsx +2 -2
  99. package/src/presentation/components/SettingsSection.tsx +2 -2
  100. package/src/presentation/navigation/SettingsStackNavigator.tsx +2 -2
  101. package/src/presentation/screens/SettingsScreen.tsx +2 -2
  102. package/src/presentation/screens/components/SettingsContent.tsx +2 -2
  103. package/src/presentation/screens/components/SettingsHeader.tsx +2 -2
@@ -0,0 +1,366 @@
1
+ /**
2
+ * Tests for AboutScreen component
3
+ */
4
+ import React from 'react';
5
+ import { View, Text, TextStyle } from 'react-native';
6
+ import { render, waitFor, fireEvent } from '@testing-library/react';
7
+ import { AboutScreen } from '../AboutScreen';
8
+ import { AboutConfig } from '../../../domain/entities/AppInfo';
9
+
10
+ // Mock console methods
11
+ const mockConsoleLog = jest.spyOn(console, 'log').mockImplementation();
12
+ const mockConsoleError = jest.spyOn(console, 'error').mockImplementation();
13
+
14
+ describe('AboutScreen', () => {
15
+ const mockConfig: AboutConfig = {
16
+ appInfo: {
17
+ name: 'Test App',
18
+ version: '1.0.0',
19
+ description: 'Test Description',
20
+ developer: 'Test Developer',
21
+ contactEmail: 'test@example.com',
22
+ websiteUrl: 'https://example.com',
23
+ websiteDisplay: 'example.com',
24
+ moreAppsUrl: 'https://apps.example.com',
25
+ },
26
+ actions: {
27
+ onEmailPress: jest.fn(),
28
+ onWebsitePress: jest.fn(),
29
+ onMoreAppsPress: jest.fn(),
30
+ },
31
+ };
32
+
33
+ beforeEach(() => {
34
+ jest.clearAllMocks();
35
+ });
36
+
37
+ afterEach(() => {
38
+ mockConsoleLog.mockClear();
39
+ mockConsoleError.mockClear();
40
+ });
41
+
42
+ describe('Rendering', () => {
43
+ it('should render loading state initially', () => {
44
+ const { getByText } = render(
45
+ <AboutScreen config={mockConfig} />
46
+ );
47
+
48
+ expect(getByText('Loading...')).toBeTruthy();
49
+ });
50
+
51
+ it('should render app info after loading', async () => {
52
+ const { getByText, queryByText } = render(
53
+ <AboutScreen config={mockConfig} />
54
+ );
55
+
56
+ // Wait for loading to complete
57
+ await waitFor(() => {
58
+ expect(queryByText('Loading...')).toBeFalsy();
59
+ });
60
+
61
+ // Check for app info
62
+ expect(getByText('Test App')).toBeTruthy();
63
+ expect(getByText('Version 1.0.0')).toBeTruthy();
64
+ expect(getByText('Test Description')).toBeTruthy();
65
+ expect(getByText('Test Developer')).toBeTruthy();
66
+ expect(getByText('test@example.com')).toBeTruthy();
67
+ expect(getByText('example.com')).toBeTruthy();
68
+ });
69
+
70
+ it('should render error state when initialization fails', async () => {
71
+ const invalidConfig = null as unknown;
72
+
73
+ const { getByText, queryByText } = render(
74
+ <AboutScreen config={invalidConfig} />
75
+ );
76
+
77
+ await waitFor(() => {
78
+ expect(queryByText('Loading...')).toBeFalsy();
79
+ });
80
+
81
+ expect(getByText('No app information available')).toBeTruthy();
82
+ });
83
+
84
+ it('should render no app info message when app info is null', async () => {
85
+ const emptyConfig: AboutConfig = {
86
+ appInfo: {},
87
+ };
88
+
89
+ const { getByText, queryByText } = render(
90
+ <AboutScreen config={emptyConfig} />
91
+ );
92
+
93
+ await waitFor(() => {
94
+ expect(queryByText('Loading...')).toBeFalsy();
95
+ });
96
+
97
+ // With empty appInfo, it should show empty name and default version
98
+ expect(getByText('Version 1.0.0')).toBeTruthy();
99
+ });
100
+
101
+ it('should not render header when showHeader is false', async () => {
102
+ const { queryByText } = render(
103
+ <AboutScreen config={mockConfig} showHeader={false} />
104
+ );
105
+
106
+ await waitFor(() => {
107
+ expect(queryByText('Loading...')).toBeFalsy();
108
+ });
109
+
110
+ expect(queryByText('Test App')).toBeFalsy();
111
+ expect(queryByText('Version 1.0.0')).toBeFalsy();
112
+ expect(queryByText('Test Description')).toBeFalsy();
113
+ });
114
+
115
+ it('should render custom header component when provided', async () => {
116
+ const CustomHeader = () => <View testID="custom-header"><Text>Custom Header</Text></View>;
117
+
118
+ const { getByTestId, queryByText } = render(
119
+ <AboutScreen config={mockConfig} headerComponent={<CustomHeader />} />
120
+ );
121
+
122
+ await waitFor(() => {
123
+ expect(queryByText('Loading...')).toBeFalsy();
124
+ });
125
+
126
+ expect(getByTestId('custom-header')).toBeTruthy();
127
+ expect(queryByText('Test App')).toBeFalsy(); // Default header should not render
128
+ });
129
+
130
+ it('should render custom footer component when provided', async () => {
131
+ const CustomFooter = () => <View testID="custom-footer"><Text>Custom Footer</Text></View>;
132
+
133
+ const { getByTestId } = render(
134
+ <AboutScreen config={mockConfig} footerComponent={<CustomFooter />} />
135
+ );
136
+
137
+ await waitFor(() => {
138
+ expect(getByTestId('custom-footer')).toBeTruthy();
139
+ });
140
+ });
141
+ });
142
+
143
+ describe('Custom Styles', () => {
144
+ it('should apply custom container style', async () => {
145
+ const customStyle = { backgroundColor: 'red' };
146
+
147
+ const { queryByText, container } = render(
148
+ <AboutScreen config={mockConfig} containerStyle={customStyle} testID="screen" />
149
+ );
150
+
151
+ await waitFor(() => {
152
+ expect(queryByText('Loading...')).toBeFalsy();
153
+ });
154
+
155
+ // Test that custom container style is applied (component renders without error)
156
+ expect(container).toBeTruthy();
157
+ });
158
+
159
+ it('should apply custom header style', async () => {
160
+ const customStyle = { backgroundColor: 'blue' };
161
+
162
+ const { getByText, queryByText } = render(
163
+ <AboutScreen config={mockConfig} headerStyle={customStyle} />
164
+ );
165
+
166
+ await waitFor(() => {
167
+ expect(queryByText('Loading...')).toBeFalsy();
168
+ });
169
+
170
+ const header = getByText('Test App');
171
+ // Check that header renders with custom style (component renders without error)
172
+ expect(header).toBeTruthy();
173
+ });
174
+
175
+ it('should apply custom title style', async () => {
176
+ const customStyle: TextStyle = { color: 'green' };
177
+
178
+ const { getByText, queryByText } = render(
179
+ <AboutScreen config={mockConfig} titleStyle={customStyle} />
180
+ );
181
+
182
+ await waitFor(() => {
183
+ expect(queryByText('Loading...')).toBeFalsy();
184
+ });
185
+
186
+ const title = getByText('Test App');
187
+ // Check that title renders with custom style (component renders without error)
188
+ expect(title).toBeTruthy();
189
+ });
190
+
191
+ it('should apply custom version style', async () => {
192
+ const customStyle = { color: 'purple' };
193
+
194
+ const { getByText, queryByText } = render(
195
+ <AboutScreen config={mockConfig} versionStyle={customStyle} />
196
+ );
197
+
198
+ await waitFor(() => {
199
+ expect(queryByText('Loading...')).toBeFalsy();
200
+ });
201
+
202
+ const version = getByText('Version 1.0.0');
203
+ // Check that version renders with custom style (component renders without error)
204
+ expect(version).toBeTruthy();
205
+ });
206
+ });
207
+
208
+ describe('Interactions', () => {
209
+ it('should call action handlers when items are pressed', async () => {
210
+ const { getByTestId } = render(
211
+ <AboutScreen config={mockConfig} />
212
+ );
213
+
214
+ await waitFor(() => {
215
+ expect(getByTestId('email-item')).toBeTruthy();
216
+ expect(getByTestId('website-item')).toBeTruthy();
217
+ expect(getByTestId('more-apps-item')).toBeTruthy();
218
+ });
219
+
220
+ // Test interactions
221
+ fireEvent.click(getByTestId('email-item'));
222
+ fireEvent.click(getByTestId('website-item'));
223
+ fireEvent.click(getByTestId('more-apps-item'));
224
+
225
+ expect(mockConfig.actions!.onEmailPress).toHaveBeenCalledTimes(1);
226
+ expect(mockConfig.actions!.onWebsitePress).toHaveBeenCalledTimes(1);
227
+ expect(mockConfig.actions!.onMoreAppsPress).toHaveBeenCalledTimes(1);
228
+ });
229
+ });
230
+
231
+ describe('Performance', () => {
232
+ it('should memoize render functions', async () => {
233
+ const { rerender } = render(
234
+ <AboutScreen config={mockConfig} />
235
+ );
236
+
237
+ // Wait for initial render
238
+ await waitFor(() => {
239
+ expect(() => { }).not.toThrow();
240
+ });
241
+
242
+ // Re-render with same props
243
+ rerender(
244
+ <AboutScreen config={mockConfig} />
245
+ );
246
+
247
+ // Should not throw and should render correctly
248
+ await waitFor(() => {
249
+ expect(() => {
250
+ rerender(
251
+ <AboutScreen config={mockConfig} />
252
+ );
253
+ }).not.toThrow();
254
+ });
255
+ });
256
+
257
+ it('should handle rapid prop changes', async () => {
258
+ const { rerender } = render(
259
+ <AboutScreen config={mockConfig} />
260
+ );
261
+
262
+ // Rapid prop changes
263
+ for (let i = 0; i < 5; i++) {
264
+ const newConfig = {
265
+ ...mockConfig,
266
+ appInfo: { ...mockConfig.appInfo, name: `App ${i}` }
267
+ };
268
+ rerender(<AboutScreen config={newConfig} />);
269
+
270
+ await waitFor(() => {
271
+ expect(() => { }).not.toThrow();
272
+ });
273
+ }
274
+
275
+ expect(() => {
276
+ rerender(
277
+ <AboutScreen config={{ ...mockConfig, appInfo: { ...mockConfig.appInfo, name: 'Final App' } }} />
278
+ );
279
+ }).not.toThrow();
280
+ });
281
+ });
282
+
283
+ describe('Edge Cases', () => {
284
+ it('should handle empty config', async () => {
285
+ const emptyConfig: AboutConfig = {
286
+ appInfo: {},
287
+ };
288
+
289
+ const { getByText, queryByText } = render(
290
+ <AboutScreen config={emptyConfig} />
291
+ );
292
+
293
+ await waitFor(() => {
294
+ expect(queryByText('Loading...')).toBeFalsy();
295
+ });
296
+
297
+ // With empty appInfo, it should show empty name and default version
298
+ expect(getByText('Version 1.0.0')).toBeTruthy();
299
+ });
300
+
301
+ it('should handle config with only required fields', async () => {
302
+ const minimalConfig: AboutConfig = {
303
+ appInfo: {
304
+ name: 'Minimal App',
305
+ version: '1.0.0',
306
+ },
307
+ };
308
+
309
+ const { getByText, queryByText } = render(
310
+ <AboutScreen config={minimalConfig} />
311
+ );
312
+
313
+ await waitFor(() => {
314
+ expect(queryByText('Loading...')).toBeFalsy();
315
+ });
316
+
317
+ expect(getByText('Minimal App')).toBeTruthy();
318
+ expect(getByText('Version 1.0.0')).toBeTruthy();
319
+ expect(queryByText('Test Developer')).toBeFalsy();
320
+ expect(queryByText('test@example.com')).toBeFalsy();
321
+ });
322
+
323
+ it('should handle special characters in text', async () => {
324
+ const configWithSpecialChars: AboutConfig = {
325
+ appInfo: {
326
+ name: 'Test & App <script>',
327
+ version: '1.0.0',
328
+ description: 'Description with émojis 🎉 and ñ',
329
+ developer: 'Developer & Co.',
330
+ },
331
+ };
332
+
333
+ const { getByText } = render(
334
+ <AboutScreen config={configWithSpecialChars} />
335
+ );
336
+
337
+ await waitFor(() => {
338
+ expect(getByText('Test & App <script>')).toBeTruthy();
339
+ expect(getByText('Description with émojis 🎉 and ñ')).toBeTruthy();
340
+ expect(getByText('Developer & Co.')).toBeTruthy();
341
+ });
342
+ });
343
+
344
+ it('should handle very long text', async () => {
345
+ const longName = 'A'.repeat(100);
346
+ const longDescription = 'B'.repeat(200);
347
+
348
+ const configWithLongText: AboutConfig = {
349
+ appInfo: {
350
+ name: longName,
351
+ version: '1.0.0',
352
+ description: longDescription,
353
+ },
354
+ };
355
+
356
+ const { getByText } = render(
357
+ <AboutScreen config={configWithLongText} />
358
+ );
359
+
360
+ await waitFor(() => {
361
+ expect(getByText(longName)).toBeTruthy();
362
+ expect(getByText(longDescription)).toBeTruthy();
363
+ });
364
+ });
365
+ });
366
+ });
@@ -0,0 +1,15 @@
1
+ /// <reference types="react-native" />
2
+
3
+ declare global {
4
+ const __DEV__: boolean;
5
+ }
6
+
7
+ export {};
8
+
9
+ declare namespace React {
10
+ interface HTMLAttributes<T> extends DOMAttributes<T> {
11
+ testID?: string;
12
+ }
13
+ }
14
+
15
+ export {};