@qlover/create-app 0.6.2 → 0.7.0

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 (81) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/templates/react-app/README.en.md +257 -0
  5. package/dist/templates/react-app/README.md +29 -231
  6. package/dist/templates/react-app/__tests__/__mocks__/I18nService.ts +13 -0
  7. package/dist/templates/react-app/__tests__/__mocks__/MockAppConfit.ts +48 -0
  8. package/dist/templates/react-app/__tests__/__mocks__/MockDialogHandler.ts +16 -0
  9. package/dist/templates/react-app/__tests__/__mocks__/MockLogger.ts +14 -0
  10. package/dist/templates/react-app/__tests__/__mocks__/createMockGlobals.ts +92 -0
  11. package/dist/templates/react-app/__tests__/setup/index.ts +51 -0
  12. package/dist/templates/react-app/__tests__/src/App.test.tsx +139 -0
  13. package/dist/templates/react-app/__tests__/src/base/cases/AppConfig.test.ts +288 -0
  14. package/dist/templates/react-app/__tests__/src/base/cases/AppError.test.ts +102 -0
  15. package/dist/templates/react-app/__tests__/src/base/cases/DialogHandler.test.ts +228 -0
  16. package/dist/templates/react-app/__tests__/src/base/cases/I18nKeyErrorPlugin.test.ts +207 -0
  17. package/dist/templates/react-app/__tests__/src/base/cases/InversifyContainer.test.ts +181 -0
  18. package/dist/templates/react-app/__tests__/src/base/cases/PublicAssetsPath.test.ts +61 -0
  19. package/dist/templates/react-app/__tests__/src/base/cases/RequestLogger.test.ts +199 -0
  20. package/dist/templates/react-app/__tests__/src/base/cases/RequestStatusCatcher.test.ts +192 -0
  21. package/dist/templates/react-app/__tests__/src/base/cases/RouterLoader.test.ts +235 -0
  22. package/dist/templates/react-app/__tests__/src/base/services/I18nService.test.ts +224 -0
  23. package/dist/templates/react-app/__tests__/src/core/IOC.test.ts +257 -0
  24. package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapsApp.test.ts +72 -0
  25. package/dist/templates/react-app/__tests__/src/main.integration.test.tsx +62 -0
  26. package/dist/templates/react-app/__tests__/src/main.test.tsx +46 -0
  27. package/dist/templates/react-app/__tests__/src/uikit/components/BaseHeader.test.tsx +88 -0
  28. package/dist/templates/react-app/config/app.router.ts +155 -0
  29. package/dist/templates/react-app/config/common.ts +9 -1
  30. package/dist/templates/react-app/docs/en/bootstrap.md +562 -0
  31. package/dist/templates/react-app/docs/en/development-guide.md +523 -0
  32. package/dist/templates/react-app/docs/en/env.md +482 -0
  33. package/dist/templates/react-app/docs/en/global.md +509 -0
  34. package/dist/templates/react-app/docs/en/i18n.md +268 -0
  35. package/dist/templates/react-app/docs/en/index.md +173 -0
  36. package/dist/templates/react-app/docs/en/ioc.md +424 -0
  37. package/dist/templates/react-app/docs/en/project-structure.md +434 -0
  38. package/dist/templates/react-app/docs/en/request.md +425 -0
  39. package/dist/templates/react-app/docs/en/router.md +404 -0
  40. package/dist/templates/react-app/docs/en/store.md +321 -0
  41. package/dist/templates/react-app/docs/en/test-guide.md +782 -0
  42. package/dist/templates/react-app/docs/en/theme.md +424 -0
  43. package/dist/templates/react-app/docs/en/typescript-guide.md +473 -0
  44. package/dist/templates/react-app/docs/zh/bootstrap.md +7 -0
  45. package/dist/templates/react-app/docs/zh/development-guide.md +523 -0
  46. package/dist/templates/react-app/docs/zh/env.md +24 -25
  47. package/dist/templates/react-app/docs/zh/global.md +28 -27
  48. package/dist/templates/react-app/docs/zh/i18n.md +268 -0
  49. package/dist/templates/react-app/docs/zh/index.md +173 -0
  50. package/dist/templates/react-app/docs/zh/ioc.md +44 -32
  51. package/dist/templates/react-app/docs/zh/project-structure.md +434 -0
  52. package/dist/templates/react-app/docs/zh/request.md +429 -0
  53. package/dist/templates/react-app/docs/zh/router.md +408 -0
  54. package/dist/templates/react-app/docs/zh/store.md +321 -0
  55. package/dist/templates/react-app/docs/zh/test-guide.md +782 -0
  56. package/dist/templates/react-app/docs/zh/theme.md +424 -0
  57. package/dist/templates/react-app/docs/zh/typescript-guide.md +473 -0
  58. package/dist/templates/react-app/package.json +9 -20
  59. package/dist/templates/react-app/src/base/cases/AppConfig.ts +16 -9
  60. package/dist/templates/react-app/src/base/cases/PublicAssetsPath.ts +7 -1
  61. package/dist/templates/react-app/src/base/services/I18nService.ts +15 -4
  62. package/dist/templates/react-app/src/base/services/RouteService.ts +43 -7
  63. package/dist/templates/react-app/src/core/bootstraps/BootstrapApp.ts +31 -10
  64. package/dist/templates/react-app/src/core/bootstraps/BootstrapsRegistry.ts +1 -1
  65. package/dist/templates/react-app/src/core/globals.ts +1 -3
  66. package/dist/templates/react-app/src/core/registers/RegisterCommon.ts +5 -3
  67. package/dist/templates/react-app/src/main.tsx +6 -1
  68. package/dist/templates/react-app/src/pages/404.tsx +0 -1
  69. package/dist/templates/react-app/src/pages/500.tsx +1 -1
  70. package/dist/templates/react-app/src/pages/base/RedirectPathname.tsx +3 -1
  71. package/dist/templates/react-app/src/styles/css/antd-themes/dark.css +3 -1
  72. package/dist/templates/react-app/src/styles/css/antd-themes/index.css +1 -1
  73. package/dist/templates/react-app/src/styles/css/antd-themes/pink.css +6 -1
  74. package/dist/templates/react-app/src/styles/css/page.css +1 -1
  75. package/dist/templates/react-app/src/uikit/components/BaseHeader.tsx +9 -2
  76. package/dist/templates/react-app/src/uikit/components/LocaleLink.tsx +5 -3
  77. package/dist/templates/react-app/src/uikit/hooks/useI18nGuard.ts +4 -6
  78. package/dist/templates/react-app/tsconfig.json +2 -1
  79. package/dist/templates/react-app/tsconfig.test.json +13 -0
  80. package/dist/templates/react-app/vite.config.ts +3 -2
  81. package/package.json +1 -1
@@ -0,0 +1,288 @@
1
+ /**
2
+ * AppConfig test suite
3
+ *
4
+ * Coverage:
5
+ * 1. constructor - Constructor initialization
6
+ * 2. basic properties - App name, version, etc.
7
+ * 3. OpenAI configuration
8
+ * 4. Login configuration
9
+ * 5. API endpoints
10
+ * 6. Environment detection
11
+ * 7. Default values
12
+ * 8. Configuration validation
13
+ */
14
+
15
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
16
+ import { AppConfig } from '@/base/cases/AppConfig';
17
+ import { InjectEnv } from '@qlover/corekit-bridge';
18
+ import { envBlackList, envPrefix } from '@config/common';
19
+
20
+ // Mock import.meta.env
21
+ const mockImportMetaEnv = {
22
+ VITE_USER_NODE_ENV: 'test',
23
+ VITE_APP_NAME: 'TestApp',
24
+ VITE_APP_VERSION: '1.0.0',
25
+ VITE_USER_TOKEN_STORAGE_KEY: 'test_user_token',
26
+ VITE_USER_INFO_STORAGE_KEY: 'test_user_info',
27
+ VITE_OPEN_AI_BASE_URL: 'https://api.openai.com',
28
+ VITE_OPEN_AI_TOKEN: 'test_openai_token',
29
+ VITE_OPEN_AI_TOKEN_PREFIX: 'Bearer',
30
+ VITE_OPEN_AI_REQUIRE_TOKEN: 'true',
31
+ VITE_LOGIN_USER: 'testuser',
32
+ VITE_LOGIN_PASSWORD: 'testpass',
33
+ VITE_FE_API_BASE_URL: 'https://api.fe.com',
34
+ VITE_USER_API_BASE_URL: 'https://api.user.com',
35
+ VITE_AI_API_BASE_URL: 'https://api.ai.com',
36
+ VITE_AI_API_TOKEN: 'test_ai_token',
37
+ VITE_AI_API_TOKEN_PREFIX: 'Bearer',
38
+ VITE_AI_API_REQUIRE_TOKEN: 'true',
39
+ VITE_BOOT_HREF: 'https://test.com'
40
+ };
41
+
42
+ // Mock window.location
43
+ const mockLocation = {
44
+ href: 'https://test.com/app'
45
+ };
46
+
47
+ // Helper function to inject environment variables using InjectEnv plugin
48
+ function injectEnvVariables(
49
+ config: AppConfig,
50
+ envVars: Record<string, string>
51
+ ) {
52
+ const injectEnv = new InjectEnv({
53
+ target: config,
54
+ source: envVars,
55
+ prefix: envPrefix,
56
+ blackList: envBlackList
57
+ });
58
+
59
+ injectEnv.onBefore();
60
+ }
61
+
62
+ describe('AppConfig', () => {
63
+ let appConfig: AppConfig;
64
+ let originalImportMetaEnv: Record<string, string>;
65
+ let originalLocation: Location;
66
+
67
+ beforeEach(() => {
68
+ // Save original values
69
+ originalImportMetaEnv = { ...import.meta.env };
70
+ originalLocation = window.location;
71
+
72
+ // Mock import.meta.env
73
+ Object.defineProperty(import.meta, 'env', {
74
+ value: { ...mockImportMetaEnv },
75
+ writable: true
76
+ });
77
+
78
+ // Mock window.location
79
+ Object.defineProperty(window, 'location', {
80
+ value: mockLocation,
81
+ writable: true
82
+ });
83
+
84
+ appConfig = new AppConfig();
85
+
86
+ // Simulate environment variable injection
87
+ injectEnvVariables(appConfig, mockImportMetaEnv);
88
+ });
89
+
90
+ afterEach(() => {
91
+ // Restore original values
92
+ Object.defineProperty(import.meta, 'env', {
93
+ value: originalImportMetaEnv,
94
+ writable: true
95
+ });
96
+ Object.defineProperty(window, 'location', {
97
+ value: originalLocation,
98
+ writable: true
99
+ });
100
+ });
101
+
102
+ describe('Basic Properties', () => {
103
+ it('should have correct appName', () => {
104
+ expect(appConfig.appName).toBe('TestApp');
105
+ });
106
+
107
+ it('should have correct appVersion', () => {
108
+ expect(appConfig.appVersion).toBe('1.0.0');
109
+ });
110
+
111
+ it('should have correct env', () => {
112
+ // because blackList
113
+ expect(appConfig.env).toBeUndefined();
114
+ });
115
+
116
+ it('should have correct userTokenStorageKey', () => {
117
+ expect(appConfig.userTokenStorageKey).toBe('test_user_token');
118
+ });
119
+
120
+ it('should have correct userInfoStorageKey', () => {
121
+ expect(appConfig.userInfoStorageKey).toBe('test_user_info');
122
+ });
123
+ });
124
+
125
+ describe('OpenAI Configuration', () => {
126
+ it('should have correct openAiModels', () => {
127
+ const expectedModels = [
128
+ 'gpt-4o-mini',
129
+ 'gpt-3.5-turbo',
130
+ 'gpt-3.5-turbo-2',
131
+ 'gpt-4',
132
+ 'gpt-4-32k'
133
+ ];
134
+ expect(appConfig.openAiModels).toEqual(expectedModels);
135
+ });
136
+
137
+ it('should have correct openAiBaseUrl', () => {
138
+ expect(appConfig.openAiBaseUrl).toBe('https://api.openai.com');
139
+ });
140
+
141
+ it('should have correct openAiToken', () => {
142
+ expect(appConfig.openAiToken).toBe('test_openai_token');
143
+ });
144
+
145
+ it('should have correct openAiTokenPrefix', () => {
146
+ expect(appConfig.openAiTokenPrefix).toBe('Bearer');
147
+ });
148
+
149
+ it('should have correct openAiRequireToken', () => {
150
+ expect(appConfig.openAiRequireToken).toBe(true);
151
+ });
152
+ });
153
+
154
+ describe('Login Configuration', () => {
155
+ it('should have correct loginUser', () => {
156
+ expect(appConfig.loginUser).toBe('testuser');
157
+ });
158
+
159
+ it('should have correct loginPassword', () => {
160
+ expect(appConfig.loginPassword).toBe('testpass');
161
+ });
162
+ });
163
+
164
+ describe('API Configuration', () => {
165
+ it('should have correct feApiBaseUrl', () => {
166
+ expect(appConfig.feApiBaseUrl).toBe('https://api.fe.com');
167
+ });
168
+
169
+ it('should have correct userApiBaseUrl', () => {
170
+ expect(appConfig.userApiBaseUrl).toBe('https://api.user.com');
171
+ });
172
+
173
+ it('should have correct aiApiBaseUrl', () => {
174
+ expect(appConfig.aiApiBaseUrl).toBe('https://api.ai.com');
175
+ });
176
+
177
+ it('should have correct aiApiToken', () => {
178
+ expect(appConfig.aiApiToken).toBe('test_ai_token');
179
+ });
180
+
181
+ it('should have correct aiApiTokenPrefix', () => {
182
+ expect(appConfig.aiApiTokenPrefix).toBe('Bearer');
183
+ });
184
+
185
+ it('should have correct aiApiRequireToken', () => {
186
+ expect(appConfig.aiApiRequireToken).toBe(true);
187
+ });
188
+ });
189
+
190
+ describe('Boot Configuration', () => {
191
+ it('should have correct bootHref', () => {
192
+ expect(appConfig.bootHref).toBe('https://test.com');
193
+ });
194
+ });
195
+
196
+ describe('Environment Detection', () => {
197
+ it('should correctly identify production environment', () => {
198
+ const productionConfig = new AppConfig('production');
199
+ expect(productionConfig.isProduction).toBe(true);
200
+ });
201
+
202
+ it('should correctly identify non-production environment', () => {
203
+ // Mock development environment
204
+ Object.defineProperty(import.meta, 'env', {
205
+ value: { ...mockImportMetaEnv, VITE_USER_NODE_ENV: 'development' },
206
+ writable: true
207
+ });
208
+
209
+ const developmentConfig = new AppConfig();
210
+ expect(developmentConfig.isProduction).toBe(false);
211
+ });
212
+
213
+ it('should correctly identify test environment', () => {
214
+ expect(appConfig.isProduction).toBe(false);
215
+ });
216
+ });
217
+
218
+ describe('Property Types', () => {
219
+ it('should have correct property types', () => {
220
+ expect(typeof appConfig.appName).toBe('string');
221
+ expect(typeof appConfig.appVersion).toBe('string');
222
+ expect(appConfig.env).toBeUndefined(); // because blackList
223
+ expect(typeof appConfig.userInfoStorageKey).toBe('string');
224
+ });
225
+ });
226
+
227
+ describe('Default Values', () => {
228
+ it('should have sensible default values when environment variables are not set', () => {
229
+ // Mock empty environment
230
+ Object.defineProperty(import.meta, 'env', {
231
+ value: {},
232
+ writable: true
233
+ });
234
+
235
+ const defaultConfig = new AppConfig();
236
+ // Don't inject environment variables to test defaults
237
+
238
+ expect(defaultConfig.appName).toBe('');
239
+ expect(defaultConfig.appVersion).toBe('');
240
+ expect(defaultConfig.userTokenStorageKey).toBe('__fe_user_token__');
241
+ expect(defaultConfig.userInfoStorageKey).toBe('__fe_user_info__');
242
+ expect(defaultConfig.openAiRequireToken).toBe(true);
243
+ expect(defaultConfig.aiApiBaseUrl).toBe('https://api.openai.com/v1');
244
+ expect(defaultConfig.aiApiTokenPrefix).toBe('Bearer');
245
+ expect(defaultConfig.aiApiRequireToken).toBe(true);
246
+ });
247
+ });
248
+
249
+ describe('Configuration Validation', () => {
250
+ it('should have valid OpenAI models configuration', () => {
251
+ expect(Array.isArray(appConfig.openAiModels)).toBe(true);
252
+ expect(appConfig.openAiModels.length).toBeGreaterThan(0);
253
+
254
+ // Check that all models are strings
255
+ appConfig.openAiModels.forEach((model) => {
256
+ expect(typeof model).toBe('string');
257
+ expect(model.length).toBeGreaterThan(0);
258
+ });
259
+ });
260
+
261
+ it('should have valid storage keys', () => {
262
+ expect(typeof appConfig.userTokenStorageKey).toBe('string');
263
+ expect(typeof appConfig.userInfoStorageKey).toBe('string');
264
+ expect(appConfig.userTokenStorageKey.length).toBeGreaterThan(0);
265
+ expect(appConfig.userInfoStorageKey.length).toBeGreaterThan(0);
266
+ });
267
+
268
+ it('should have valid API URLs when provided', () => {
269
+ // Test with valid URLs
270
+ const validUrlConfig = new AppConfig();
271
+ if (validUrlConfig.aiApiBaseUrl) {
272
+ expect(validUrlConfig.aiApiBaseUrl).toMatch(/^https?:\/\//);
273
+ }
274
+ });
275
+ });
276
+
277
+ describe('Instance Creation', () => {
278
+ it('should create new instance with default values', () => {
279
+ const newConfig = new AppConfig();
280
+ expect(newConfig).toBeInstanceOf(AppConfig);
281
+ });
282
+
283
+ it('should create new instance with custom environment', () => {
284
+ const customConfig = new AppConfig('custom');
285
+ expect(customConfig.env).toBe('custom');
286
+ });
287
+ });
288
+ });
@@ -0,0 +1,102 @@
1
+ /**
2
+ * AppError test suite
3
+ *
4
+ * Coverage:
5
+ * 1. constructor - Constructor initialization with different source types
6
+ * 2. inheritance - Verify inheritance from ExecutorError
7
+ * 3. error properties - Verify error properties are set correctly
8
+ */
9
+
10
+ import { describe, it, expect } from 'vitest';
11
+ import { AppError } from '@/base/cases/AppError';
12
+ import { ExecutorError } from '@qlover/fe-corekit';
13
+
14
+ describe('AppError', () => {
15
+ describe('constructor', () => {
16
+ it('should create instance with id only', () => {
17
+ const error = new AppError('TEST_ERROR');
18
+ expect(error).toBeInstanceOf(AppError);
19
+ expect(error).toBeInstanceOf(ExecutorError);
20
+ expect(error).toBeInstanceOf(Error);
21
+ expect(error.id).toBe('TEST_ERROR');
22
+ expect(error.message).toBe('TEST_ERROR');
23
+ expect(error.source).toBeUndefined();
24
+ });
25
+
26
+ it('should create instance with string source', () => {
27
+ const source = 'Test error message';
28
+ const error = new AppError('TEST_ERROR', source);
29
+ expect(error.id).toBe('TEST_ERROR');
30
+ expect(error.message).toBe(source);
31
+ expect(error.source).toBe(source);
32
+ });
33
+
34
+ it('should create instance with Error source', () => {
35
+ const source = new Error('Original error');
36
+ const error = new AppError('TEST_ERROR', source);
37
+ expect(error.id).toBe('TEST_ERROR');
38
+ expect(error.message).toBe('Original error');
39
+ expect(error.source).toBe(source);
40
+ });
41
+ });
42
+
43
+ describe('error properties', () => {
44
+ it('should have correct error type', () => {
45
+ const error = new AppError('TEST_ERROR');
46
+ expect(error.id).toBe('TEST_ERROR');
47
+ });
48
+
49
+ it('should maintain id property', () => {
50
+ const error = new AppError('TEST_ERROR');
51
+ Object.defineProperty(error, 'id', { value: 'NEW_ID' });
52
+ expect(error.id).toBe('NEW_ID');
53
+ });
54
+
55
+ it('should maintain source property', () => {
56
+ const source = 'source';
57
+ const error = new AppError('TEST_ERROR', source);
58
+ Object.defineProperty(error, 'source', { value: 'new source' });
59
+ expect(error.source).toBe('new source');
60
+ });
61
+ });
62
+
63
+ describe('error handling', () => {
64
+ it('should work in try-catch block', () => {
65
+ expect(() => {
66
+ throw new AppError('TEST_ERROR');
67
+ }).toThrow(AppError);
68
+ });
69
+
70
+ it('should preserve stack trace', () => {
71
+ const error = new AppError('TEST_ERROR');
72
+ expect(error.stack).toBeDefined();
73
+ expect(error.stack).toContain('AppError.test.ts');
74
+ });
75
+
76
+ it('should handle nested errors', () => {
77
+ const originalError = new Error('Original error');
78
+ const wrappedError = new AppError('WRAPPED_ERROR', originalError);
79
+ expect(wrappedError.source).toBe(originalError);
80
+ expect(wrappedError.message).toBe('Original error');
81
+ });
82
+ });
83
+
84
+ describe('error message formatting', () => {
85
+ it('should use id as message when source is undefined', () => {
86
+ const error = new AppError('TEST_ERROR');
87
+ expect(error.message).toBe('TEST_ERROR');
88
+ });
89
+
90
+ it('should use source message when source is Error', () => {
91
+ const source = new Error('Source error message');
92
+ const error = new AppError('TEST_ERROR', source);
93
+ expect(error.message).toBe('Source error message');
94
+ });
95
+
96
+ it('should use source string when source is string', () => {
97
+ const source = 'Source error message';
98
+ const error = new AppError('TEST_ERROR', source);
99
+ expect(error.message).toBe('Source error message');
100
+ });
101
+ });
102
+ });
@@ -0,0 +1,228 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /**
3
+ * DialogHandler test suite
4
+ *
5
+ * Coverage:
6
+ * 1. constructor - Constructor initialization
7
+ * 2. setters - Message, Modal, Notification setters
8
+ * 3. formatErrorMessage - Error message formatting
9
+ * 4. notification methods - success, error, info, warn
10
+ * 5. confirm method - Modal confirmation
11
+ * 6. edge cases - Null/undefined handling
12
+ */
13
+
14
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
15
+ import { DialogHandler } from '../../../../src/base/cases/DialogHandler';
16
+ import type {
17
+ MessageApi,
18
+ ModalApi,
19
+ NotificationApi
20
+ } from '@brain-toolkit/antd-theme-override/react';
21
+ import type { ConfirmOptions } from '../../../../src/base/port/InteractionHubInterface';
22
+
23
+ describe('DialogHandler', () => {
24
+ let dialogHandler: DialogHandler;
25
+ let mockMessage: MessageApi;
26
+ let mockModal: ModalApi;
27
+ let mockNotification: NotificationApi;
28
+
29
+ beforeEach(() => {
30
+ // Create mock APIs
31
+ mockMessage = {
32
+ success: vi.fn(),
33
+ error: vi.fn(),
34
+ info: vi.fn(),
35
+ warning: vi.fn()
36
+ } as unknown as MessageApi;
37
+
38
+ mockModal = {
39
+ confirm: vi.fn()
40
+ } as unknown as ModalApi;
41
+
42
+ mockNotification = {
43
+ success: vi.fn(),
44
+ error: vi.fn(),
45
+ info: vi.fn(),
46
+ warning: vi.fn()
47
+ } as unknown as NotificationApi;
48
+
49
+ // Initialize DialogHandler
50
+ dialogHandler = new DialogHandler();
51
+ });
52
+
53
+ afterEach(() => {
54
+ vi.clearAllMocks();
55
+ });
56
+
57
+ describe('constructor', () => {
58
+ it('should create instance with empty antds object', () => {
59
+ expect(dialogHandler).toBeInstanceOf(DialogHandler);
60
+ expect((dialogHandler as any).antds).toEqual({});
61
+ });
62
+ });
63
+
64
+ describe('setters', () => {
65
+ it('should set message api', () => {
66
+ dialogHandler.setMessage(mockMessage);
67
+ expect((dialogHandler as any).antds.message).toBe(mockMessage);
68
+ });
69
+
70
+ it('should set modal api', () => {
71
+ dialogHandler.setModal(mockModal);
72
+ expect((dialogHandler as any).antds.modal).toBe(mockModal);
73
+ });
74
+
75
+ it('should set notification api', () => {
76
+ dialogHandler.setNotification(mockNotification);
77
+ expect((dialogHandler as any).antds.notification).toBe(mockNotification);
78
+ });
79
+ });
80
+
81
+ describe('formatErrorMessage', () => {
82
+ it('should format Error object', () => {
83
+ const error = new Error('test error');
84
+ const result = (dialogHandler as any).formatErrorMessage(error);
85
+ expect(result).toBe('test error');
86
+ });
87
+
88
+ it('should format string error', () => {
89
+ const result = (dialogHandler as any).formatErrorMessage('test error');
90
+ expect(result).toBe('test error');
91
+ });
92
+
93
+ it('should handle unknown error type', () => {
94
+ const result = (dialogHandler as any).formatErrorMessage({});
95
+ expect(result).toBe('An unknown error occurred');
96
+ });
97
+ });
98
+
99
+ describe('notification methods', () => {
100
+ beforeEach(() => {
101
+ dialogHandler.setMessage(mockMessage);
102
+ });
103
+
104
+ describe('success', () => {
105
+ it('should call message.success with content', () => {
106
+ dialogHandler.success('test success');
107
+ expect(mockMessage.success).toHaveBeenCalledWith({
108
+ content: 'test success'
109
+ });
110
+ });
111
+
112
+ it('should pass through options', () => {
113
+ const options = { duration: 5000 };
114
+ dialogHandler.success('test success', options);
115
+ expect(mockMessage.success).toHaveBeenCalledWith({
116
+ content: 'test success',
117
+ ...options
118
+ });
119
+ });
120
+ });
121
+
122
+ describe('error', () => {
123
+ it('should call message.error with content', () => {
124
+ dialogHandler.error('test error');
125
+ expect(mockMessage.error).toHaveBeenCalledWith({
126
+ content: 'test error'
127
+ });
128
+ });
129
+
130
+ it('should format error from options', () => {
131
+ const error = new Error('formatted error');
132
+ const options = { error };
133
+ dialogHandler.error('test error', options);
134
+ expect(mockMessage.error).toHaveBeenCalledWith({
135
+ content: 'formatted error',
136
+ error
137
+ });
138
+ });
139
+
140
+ it('should pass through additional options', () => {
141
+ const error = new Error('formatted error');
142
+ const options = { error, duration: 5000 };
143
+ dialogHandler.error('test error', options);
144
+ expect(mockMessage.error).toHaveBeenCalledWith({
145
+ content: 'formatted error',
146
+ error,
147
+ duration: 5000
148
+ });
149
+ });
150
+ });
151
+
152
+ describe('info', () => {
153
+ it('should call message.info with content', () => {
154
+ dialogHandler.info('test info');
155
+ expect(mockMessage.info).toHaveBeenCalledWith({
156
+ content: 'test info'
157
+ });
158
+ });
159
+
160
+ it('should pass through options', () => {
161
+ const options = { duration: 5000 };
162
+ dialogHandler.info('test info', options);
163
+ expect(mockMessage.info).toHaveBeenCalledWith({
164
+ content: 'test info',
165
+ ...options
166
+ });
167
+ });
168
+ });
169
+
170
+ describe('warn', () => {
171
+ it('should call message.warning with content', () => {
172
+ dialogHandler.warn('test warning');
173
+ expect(mockMessage.warning).toHaveBeenCalledWith({
174
+ content: 'test warning'
175
+ });
176
+ });
177
+
178
+ it('should pass through options', () => {
179
+ const options = { duration: 5000 };
180
+ dialogHandler.warn('test warning', options);
181
+ expect(mockMessage.warning).toHaveBeenCalledWith({
182
+ content: 'test warning',
183
+ ...options
184
+ });
185
+ });
186
+ });
187
+ });
188
+
189
+ describe('confirm', () => {
190
+ beforeEach(() => {
191
+ dialogHandler.setModal(mockModal);
192
+ });
193
+
194
+ it('should call modal.confirm with options', () => {
195
+ const options: ConfirmOptions = {
196
+ title: 'Confirm',
197
+ content: 'Are you sure?',
198
+ onOk: vi.fn(),
199
+ onCancel: vi.fn()
200
+ };
201
+ dialogHandler.confirm(options);
202
+ expect(mockModal.confirm).toHaveBeenCalledWith(options);
203
+ });
204
+ });
205
+
206
+ describe('edge cases', () => {
207
+ it('should handle undefined message api', () => {
208
+ expect(() => dialogHandler.success('test')).not.toThrow();
209
+ expect(() => dialogHandler.error('test')).not.toThrow();
210
+ expect(() => dialogHandler.info('test')).not.toThrow();
211
+ expect(() => dialogHandler.warn('test')).not.toThrow();
212
+ });
213
+
214
+ it('should handle undefined modal api', () => {
215
+ const options: ConfirmOptions = {
216
+ title: 'test',
217
+ content: 'test content'
218
+ };
219
+ expect(() => dialogHandler.confirm(options)).not.toThrow();
220
+ });
221
+
222
+ it('should handle undefined notification api', () => {
223
+ expect(() =>
224
+ dialogHandler.setNotification(undefined as any)
225
+ ).not.toThrow();
226
+ });
227
+ });
228
+ });