@zat-design/sisyphus-react 4.0.0-beta.3 → 4.0.0-beta.4

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 (243) hide show
  1. package/babel.config.js +7 -30
  2. package/dist/esm/index.d.ts +5 -0
  3. package/dist/esm/index.js +5 -0
  4. package/dist/esm/regExp/index.d.ts +19 -0
  5. package/dist/esm/regExp/index.js +73 -0
  6. package/dist/esm/tools/calc/index.d.ts +4 -0
  7. package/dist/esm/tools/calc/index.js +67 -0
  8. package/dist/esm/tools/dateUtils.d.ts +7 -0
  9. package/dist/esm/tools/dateUtils.js +23 -0
  10. package/dist/esm/tools/disableDate/index.d.ts +9 -0
  11. package/dist/esm/tools/disableDate/index.js +43 -0
  12. package/dist/esm/tools/disableTimeRange/index.d.ts +9 -0
  13. package/dist/esm/tools/disableTimeRange/index.js +121 -0
  14. package/dist/esm/tools/formatAmount/index.d.ts +7 -0
  15. package/dist/esm/tools/formatAmount/index.js +14 -0
  16. package/dist/esm/tools/formatPerMill/index.d.ts +7 -0
  17. package/dist/esm/tools/formatPerMill/index.js +11 -0
  18. package/dist/esm/tools/formatPercent/index.d.ts +7 -0
  19. package/dist/esm/tools/formatPercent/index.js +11 -0
  20. package/dist/esm/tools/getDataByIdCard/index.d.ts +16 -0
  21. package/dist/esm/tools/getDataByIdCard/index.js +65 -0
  22. package/dist/esm/tools/index.d.ts +12 -0
  23. package/dist/esm/tools/index.js +14 -0
  24. package/dist/esm/tools/sumAmount/index.d.ts +16 -0
  25. package/dist/esm/tools/sumAmount/index.js +40 -0
  26. package/dist/esm/tools/toChineseNum/index.d.ts +7 -0
  27. package/dist/esm/tools/toChineseNum/index.js +103 -0
  28. package/dist/esm/tools/toFixed/index.d.ts +2 -0
  29. package/dist/esm/tools/toFixed/index.js +5 -0
  30. package/dist/esm/tools/transformDataName/index.d.ts +12 -0
  31. package/dist/esm/tools/transformDataName/index.js +37 -0
  32. package/dist/esm/transforms/dateTransformer/index.d.ts +24 -0
  33. package/dist/esm/transforms/dateTransformer/index.js +67 -0
  34. package/dist/esm/transforms/index.d.ts +6 -0
  35. package/dist/esm/transforms/index.js +6 -0
  36. package/dist/esm/transforms/propTypes.d.ts +7 -0
  37. package/dist/esm/transforms/propTypes.js +1 -0
  38. package/dist/esm/transforms/transformDate/index.d.ts +21 -0
  39. package/dist/esm/transforms/transformDate/index.js +141 -0
  40. package/dist/esm/transforms/transformDatePicker/index.d.ts +12 -0
  41. package/dist/esm/transforms/transformDatePicker/index.js +24 -0
  42. package/dist/esm/transforms/transformRangePicker/index.d.ts +29 -0
  43. package/dist/esm/transforms/transformRangePicker/index.js +61 -0
  44. package/dist/esm/transforms/transformSwitch/index.d.ts +13 -0
  45. package/dist/esm/transforms/transformSwitch/index.js +35 -0
  46. package/dist/esm/transforms/utils.d.ts +2 -0
  47. package/dist/esm/transforms/utils.js +8 -0
  48. package/dist/esm/validate/index.d.ts +107 -0
  49. package/dist/esm/validate/index.js +284 -0
  50. package/es/ProAction/index.less +0 -2
  51. package/es/ProConfigProvider/index.d.ts +1 -0
  52. package/es/ProConfigProvider/index.js +4 -5
  53. package/es/ProDownload/style/index.less +0 -2
  54. package/es/ProDrawerForm/index.js +33 -29
  55. package/es/ProDrawerForm/style/index.less +0 -2
  56. package/es/ProEditLabel/style/index.less +0 -2
  57. package/es/ProEditTable/components/RcTable/DraggableTable.js +1 -1
  58. package/es/ProEditTable/components/RenderField/ListChangedWrapper.js +14 -2
  59. package/es/ProEditTable/propsType.d.ts +1 -1
  60. package/es/ProEditTable/style/index.less +2 -4
  61. package/es/ProEditTable/utils/diffOriginal.d.ts +1 -0
  62. package/es/ProEditTable/utils/diffOriginal.js +68 -1
  63. package/es/ProEnum/hooks/useEnum.js +5 -0
  64. package/es/ProEnum/style/index.less +0 -2
  65. package/es/ProForm/components/FormFooter/index.js +6 -6
  66. package/es/ProForm/components/base/DatePicker/index.js +19 -34
  67. package/es/ProForm/components/base/SwitchCheckbox/style/index.less +0 -2
  68. package/es/ProForm/components/base/TextArea/index.less +0 -2
  69. package/es/ProForm/components/base/TimePicker/style/index.less +0 -2
  70. package/es/ProForm/components/combination/Container/style/index.less +0 -2
  71. package/es/ProForm/components/combination/FormList/style/index.less +0 -2
  72. package/es/ProForm/components/combination/Group/component/ComRender.js +9 -8
  73. package/es/ProForm/components/combination/Group/hooks/index.js +17 -4
  74. package/es/ProForm/components/combination/Group/index.d.ts +8 -2
  75. package/es/ProForm/components/combination/Group/index.js +10 -16
  76. package/es/ProForm/components/combination/ProCascader/index.js +106 -52
  77. package/es/ProForm/components/combination/ProCascader/propsType.d.ts +12 -4
  78. package/es/ProForm/components/combination/ProCascader/style/index.less +1 -3
  79. package/es/ProForm/components/combination/ProModalSelect/hooks/useRequestList.js +2 -4
  80. package/es/ProForm/components/combination/ProModalSelect/index.js +38 -64
  81. package/es/ProForm/components/combination/ProModalSelect/propsType.d.ts +7 -3
  82. package/es/ProForm/components/combination/ProModalSelect/style/index.less +1 -4
  83. package/es/ProForm/components/combination/ProNumberRange/style/index.less +4 -3
  84. package/es/ProForm/components/combination/ProTimeLimit/style/index.less +0 -2
  85. package/es/ProForm/components/render/ChangedWrapper.js +2 -2
  86. package/es/ProForm/components/render/Render.js +17 -5
  87. package/es/ProForm/components/render/RenderFields.d.ts +1 -0
  88. package/es/ProForm/components/render/RenderFields.js +4 -2
  89. package/es/ProForm/components/render/propsType.d.ts +1 -0
  90. package/es/ProForm/index.d.ts +2 -2
  91. package/es/ProForm/index.js +5 -2
  92. package/es/ProForm/propsType.d.ts +2 -0
  93. package/es/ProForm/style/index.less +0 -2
  94. package/es/ProForm/utils/diffOriginal.d.ts +1 -0
  95. package/es/ProForm/utils/diffOriginal.js +66 -1
  96. package/es/ProForm/utils/index.js +1 -1
  97. package/es/ProForm/utils/useShouldUpdate.d.ts +1 -0
  98. package/es/ProForm/utils/useShouldUpdate.js +89 -3
  99. package/es/ProIcon/style/index.less +0 -2
  100. package/es/ProLayout/components/Layout/Menu/FoldMenu/index.js +60 -8
  101. package/es/ProLayout/components/Layout/Menu/FoldMenu/style/index.less +0 -2
  102. package/es/ProLayout/components/Layout/Menu/OpenMenu/index.js +25 -3
  103. package/es/ProLayout/components/Layout/Menu/SideMenu/index.js +3 -1
  104. package/es/ProLayout/components/Layout/Menu/SideMenu/style/index.less +0 -2
  105. package/es/ProLayout/components/Layout/Menu/index.js +4 -1
  106. package/es/ProLayout/components/Layout/Menu/style/index.less +0 -2
  107. package/es/ProLayout/components/Layout/Notice/style/index.less +0 -2
  108. package/es/ProLayout/components/ProCollapse/PropTypes.d.ts +8 -3
  109. package/es/ProLayout/components/ProCollapse/index.js +27 -3
  110. package/es/ProLayout/components/ProCollapse/style/index.less +148 -4
  111. package/es/ProLayout/components/ProFooter/style/index.less +0 -2
  112. package/es/ProLayout/components/ProHeader/components/ProBackBtn/style/index.less +0 -2
  113. package/es/ProLayout/components/ProHeader/style/index.less +0 -2
  114. package/es/ProLayout/index.d.ts +0 -11
  115. package/es/ProLayout/index.js +60 -32
  116. package/es/ProLayout/propTypes.d.ts +9 -0
  117. package/es/ProLayout/style/index.less +0 -2
  118. package/es/ProLayout/utils/index.d.ts +7 -0
  119. package/es/ProLayout/utils/index.js +30 -0
  120. package/es/ProSelect/index.less +0 -2
  121. package/es/ProSelect/utils/index.js +62 -1
  122. package/es/ProStep/components/Item/index.js +1 -2
  123. package/es/ProStep/style/index.less +0 -2
  124. package/es/ProTable/components/RcTable/components/DraggableTable/components/DndWrapper/index.js +1 -1
  125. package/es/ProTable/hooks/useAntdTable.d.ts +3 -0
  126. package/es/ProTable/hooks/useAntdTable.js +92 -64
  127. package/es/ProTable/index.d.ts +3 -7
  128. package/es/ProTable/index.js +14 -14
  129. package/es/ProTable/propsType.d.ts +3 -2
  130. package/es/ProTable/style/index.less +4 -6
  131. package/es/ProTabs/style/index.less +0 -2
  132. package/es/ProThemeTools/index.d.ts +0 -7
  133. package/es/ProThemeTools/index.js +10 -12
  134. package/es/ProThemeTools/style/index.less +0 -2
  135. package/es/ProTooltip/style/index.less +0 -2
  136. package/es/ProTree/components/ProTreeSelect/style/index.less +0 -2
  137. package/es/ProTree/style/index.less +0 -2
  138. package/es/ProTreeModal/style/index.less +0 -2
  139. package/es/ProUpload/style/index.less +0 -2
  140. package/es/ProViewer/style/index.less +0 -2
  141. package/es/style/theme/antd.less +0 -2
  142. package/jest.config.js +46 -4
  143. package/lib/ProAction/index.less +0 -2
  144. package/lib/ProConfigProvider/index.d.ts +1 -0
  145. package/lib/ProConfigProvider/index.js +4 -3
  146. package/lib/ProDownload/style/index.less +0 -2
  147. package/lib/ProDrawerForm/index.js +25 -28
  148. package/lib/ProDrawerForm/style/index.less +0 -2
  149. package/lib/ProEditLabel/style/index.less +0 -2
  150. package/lib/ProEditTable/components/RcTable/DraggableTable.js +1 -1
  151. package/lib/ProEditTable/components/RenderField/ListChangedWrapper.js +10 -2
  152. package/lib/ProEditTable/propsType.d.ts +1 -1
  153. package/lib/ProEditTable/style/index.less +2 -4
  154. package/lib/ProEditTable/utils/diffOriginal.d.ts +1 -0
  155. package/lib/ProEditTable/utils/diffOriginal.js +48 -1
  156. package/lib/ProEnum/hooks/useEnum.js +3 -0
  157. package/lib/ProEnum/style/index.less +0 -2
  158. package/lib/ProForm/components/FormFooter/index.js +6 -5
  159. package/lib/ProForm/components/base/DatePicker/index.js +21 -33
  160. package/lib/ProForm/components/base/SwitchCheckbox/style/index.less +0 -2
  161. package/lib/ProForm/components/base/TextArea/index.less +0 -2
  162. package/lib/ProForm/components/base/TimePicker/style/index.less +0 -2
  163. package/lib/ProForm/components/combination/Container/style/index.less +0 -2
  164. package/lib/ProForm/components/combination/FormList/style/index.less +0 -2
  165. package/lib/ProForm/components/combination/Group/component/ComRender.js +8 -7
  166. package/lib/ProForm/components/combination/Group/hooks/index.js +8 -2
  167. package/lib/ProForm/components/combination/Group/index.d.ts +8 -2
  168. package/lib/ProForm/components/combination/Group/index.js +8 -13
  169. package/lib/ProForm/components/combination/ProCascader/index.js +73 -16
  170. package/lib/ProForm/components/combination/ProCascader/propsType.d.ts +12 -4
  171. package/lib/ProForm/components/combination/ProCascader/style/index.less +1 -3
  172. package/lib/ProForm/components/combination/ProModalSelect/hooks/useRequestList.js +2 -2
  173. package/lib/ProForm/components/combination/ProModalSelect/index.js +26 -52
  174. package/lib/ProForm/components/combination/ProModalSelect/propsType.d.ts +7 -3
  175. package/lib/ProForm/components/combination/ProModalSelect/style/index.less +1 -4
  176. package/lib/ProForm/components/combination/ProNumberRange/style/index.less +4 -3
  177. package/lib/ProForm/components/combination/ProTimeLimit/style/index.less +0 -2
  178. package/lib/ProForm/components/render/ChangedWrapper.js +2 -2
  179. package/lib/ProForm/components/render/Render.js +11 -3
  180. package/lib/ProForm/components/render/RenderFields.d.ts +1 -0
  181. package/lib/ProForm/components/render/RenderFields.js +4 -2
  182. package/lib/ProForm/components/render/propsType.d.ts +1 -0
  183. package/lib/ProForm/index.d.ts +2 -2
  184. package/lib/ProForm/index.js +3 -1
  185. package/lib/ProForm/propsType.d.ts +2 -0
  186. package/lib/ProForm/style/index.less +0 -2
  187. package/lib/ProForm/utils/diffOriginal.d.ts +1 -0
  188. package/lib/ProForm/utils/diffOriginal.js +48 -1
  189. package/lib/ProForm/utils/index.js +1 -1
  190. package/lib/ProForm/utils/useShouldUpdate.d.ts +1 -0
  191. package/lib/ProForm/utils/useShouldUpdate.js +50 -1
  192. package/lib/ProIcon/style/index.less +0 -2
  193. package/lib/ProLayout/components/Layout/Menu/FoldMenu/index.js +33 -4
  194. package/lib/ProLayout/components/Layout/Menu/FoldMenu/style/index.less +0 -2
  195. package/lib/ProLayout/components/Layout/Menu/OpenMenu/index.js +7 -2
  196. package/lib/ProLayout/components/Layout/Menu/SideMenu/index.js +2 -1
  197. package/lib/ProLayout/components/Layout/Menu/SideMenu/style/index.less +0 -2
  198. package/lib/ProLayout/components/Layout/Menu/index.js +4 -1
  199. package/lib/ProLayout/components/Layout/Menu/style/index.less +0 -2
  200. package/lib/ProLayout/components/Layout/Notice/style/index.less +0 -2
  201. package/lib/ProLayout/components/ProCollapse/PropTypes.d.ts +8 -3
  202. package/lib/ProLayout/components/ProCollapse/index.js +27 -3
  203. package/lib/ProLayout/components/ProCollapse/style/index.less +148 -4
  204. package/lib/ProLayout/components/ProFooter/style/index.less +0 -2
  205. package/lib/ProLayout/components/ProHeader/components/ProBackBtn/style/index.less +0 -2
  206. package/lib/ProLayout/components/ProHeader/style/index.less +0 -2
  207. package/lib/ProLayout/index.d.ts +0 -11
  208. package/lib/ProLayout/index.js +51 -32
  209. package/lib/ProLayout/propTypes.d.ts +9 -0
  210. package/lib/ProLayout/style/index.less +0 -2
  211. package/lib/ProLayout/utils/index.d.ts +7 -0
  212. package/lib/ProLayout/utils/index.js +15 -0
  213. package/lib/ProSelect/index.less +0 -2
  214. package/lib/ProSelect/utils/index.js +34 -5
  215. package/lib/ProStep/components/Item/index.js +1 -2
  216. package/lib/ProStep/style/index.less +0 -2
  217. package/lib/ProTable/components/RcTable/components/DraggableTable/components/DndWrapper/index.js +1 -1
  218. package/lib/ProTable/hooks/useAntdTable.d.ts +3 -0
  219. package/lib/ProTable/hooks/useAntdTable.js +71 -36
  220. package/lib/ProTable/index.d.ts +3 -7
  221. package/lib/ProTable/index.js +8 -13
  222. package/lib/ProTable/propsType.d.ts +3 -2
  223. package/lib/ProTable/style/index.less +4 -6
  224. package/lib/ProTabs/style/index.less +0 -2
  225. package/lib/ProThemeTools/index.d.ts +0 -7
  226. package/lib/ProThemeTools/index.js +5 -12
  227. package/lib/ProThemeTools/style/index.less +0 -2
  228. package/lib/ProTooltip/style/index.less +0 -2
  229. package/lib/ProTree/components/ProTreeSelect/style/index.less +0 -2
  230. package/lib/ProTree/style/index.less +0 -2
  231. package/lib/ProTreeModal/style/index.less +0 -2
  232. package/lib/ProUpload/style/index.less +0 -2
  233. package/lib/ProViewer/style/index.less +0 -2
  234. package/lib/style/theme/antd.less +0 -2
  235. package/package.json +7 -6
  236. package/tests/__mocks__/fileMock.js +1 -0
  237. package/tests/__mocks__/zatUtils.js +27 -0
  238. package/tests/setup.ts +484 -0
  239. package/tests/test-utils.tsx +81 -0
  240. package/dist/index.esm.css +0 -6445
  241. package/dist/index.esm.js +0 -3
  242. package/dist/less.esm.css +0 -5871
  243. package/dist/less.esm.js +0 -3
package/tests/setup.ts ADDED
@@ -0,0 +1,484 @@
1
+ import '@testing-library/jest-dom';
2
+ import 'jest-canvas-mock';
3
+ import React from 'react';
4
+
5
+ // Ensure JSDOM document.body exists and setup proper DOM environment
6
+ if (typeof document !== 'undefined') {
7
+ // Ensure documentElement exists
8
+ if (!document.documentElement) {
9
+ const html = document.createElement('html');
10
+ document.appendChild(html);
11
+ }
12
+
13
+ // Ensure head exists
14
+ if (!document.head) {
15
+ const head = document.createElement('head');
16
+ document.documentElement.appendChild(head);
17
+ }
18
+
19
+ // Ensure body exists
20
+ if (!document.body) {
21
+ const body = document.createElement('body');
22
+ document.documentElement.appendChild(body);
23
+ }
24
+ }
25
+
26
+ // Mock testing library environment setup
27
+ Object.defineProperty(global, 'MutationObserver', {
28
+ writable: true,
29
+ value: jest.fn().mockImplementation(() => ({
30
+ observe: jest.fn(),
31
+ disconnect: jest.fn(),
32
+ takeRecords: jest.fn(),
33
+ })),
34
+ });
35
+
36
+ // Setup test container div
37
+ beforeEach(() => {
38
+ if (typeof document !== 'undefined' && document.body) {
39
+ try {
40
+ // Clean up any existing test containers
41
+ const existingContainers = document.querySelectorAll('[data-testid="test-container"]');
42
+ existingContainers.forEach(container => {
43
+ if (container.parentNode) {
44
+ try {
45
+ container.parentNode.removeChild(container);
46
+ } catch (e) {
47
+ // Ignore cleanup errors
48
+ }
49
+ }
50
+ });
51
+
52
+ // Create a fresh test container
53
+ const testContainer = document.createElement('div');
54
+ testContainer.setAttribute('data-testid', 'test-container');
55
+ testContainer.id = 'test-container';
56
+ document.body.appendChild(testContainer);
57
+ } catch (e) {
58
+ // Ignore setup errors - React Testing Library will handle this
59
+ }
60
+ }
61
+ });
62
+
63
+ // 抑制控制台错误 - 更新以支持 React 18 警告
64
+ const originalError = console.error;
65
+ beforeAll(() => {
66
+ console.error = (...args: any[]) => {
67
+ if (
68
+ args.find(
69
+ arg =>
70
+ typeof arg === 'string' &&
71
+ (
72
+ arg.includes('Warning: ReactDOM.render is no longer supported in React 18') ||
73
+ arg.includes('Warning: ReactDOM.render is deprecated') ||
74
+ arg.includes('Warning: componentWillReceiveProps') ||
75
+ arg.includes('validateDOMNesting') ||
76
+ arg.includes('Warning: componentWillMount') ||
77
+ arg.includes('Warning: React.createFactory() is deprecated') ||
78
+ arg.includes('Warning: findDOMNode is deprecated') ||
79
+ arg.includes('act(...)') ||
80
+ arg.includes('useLayoutEffect does nothing on the server') ||
81
+ arg.includes('Invalid hook call') ||
82
+ arg.includes('Hooks can only be called inside') ||
83
+ arg.includes('Warning: Each child in a list should have a unique') ||
84
+ arg.includes('Warning: validateDOMNesting') ||
85
+ arg.includes('Warning: unmountComponentAtNode is deprecated') ||
86
+ arg.includes('Warning: `ReactDOMTestUtils.act` is deprecated') ||
87
+ arg.includes('Warning: React does not recognize the') ||
88
+ arg.includes('Warning: Invalid DOM property') ||
89
+ arg.includes('Warning: Received `true` for a non-boolean attribute') ||
90
+ arg.includes('Warning: Received `false` for a non-boolean attribute')
91
+ )
92
+ )
93
+ ) {
94
+ return;
95
+ }
96
+ originalError.call(console, ...args);
97
+ };
98
+ });
99
+
100
+ afterAll(() => {
101
+ console.error = originalError;
102
+ });
103
+
104
+ // Mock window APIs
105
+ Object.defineProperty(window, 'matchMedia', {
106
+ writable: true,
107
+ value: jest.fn().mockImplementation(query => ({
108
+ matches: false,
109
+ media: query,
110
+ onchange: null,
111
+ addListener: jest.fn(),
112
+ removeListener: jest.fn(),
113
+ addEventListener: jest.fn(),
114
+ removeEventListener: jest.fn(),
115
+ dispatchEvent: jest.fn(),
116
+ })),
117
+ });
118
+
119
+ // Mock ahooks hooks - 基于ahooks官方测试实践改进
120
+ jest.mock('ahooks', () => ({
121
+ useSetState: jest.fn((initialState) => {
122
+ const mockState = { current: initialState || {} };
123
+ const mockSetState = jest.fn((patch) => {
124
+ if (typeof patch === 'function') {
125
+ mockState.current = patch(mockState.current);
126
+ } else {
127
+ mockState.current = { ...mockState.current, ...patch };
128
+ }
129
+ return mockState.current;
130
+ });
131
+ return [mockState.current, mockSetState];
132
+ }),
133
+
134
+ useRequest: jest.fn((service, options = {}) => {
135
+ const mockState = {
136
+ loading: false,
137
+ data: null,
138
+ error: null,
139
+ params: [],
140
+ };
141
+
142
+ const mockActions = {
143
+ run: jest.fn((...params) => {
144
+ mockState.loading = true;
145
+ mockState.params = params;
146
+ // 模拟异步操作
147
+ setTimeout(() => {
148
+ mockState.loading = false;
149
+ mockState.data = 'mock-data';
150
+ }, 100);
151
+ return Promise.resolve('mock-data');
152
+ }),
153
+ refresh: jest.fn(() => {
154
+ mockState.loading = true;
155
+ setTimeout(() => {
156
+ mockState.loading = false;
157
+ }, 100);
158
+ return Promise.resolve('mock-data');
159
+ }),
160
+ cancel: jest.fn(() => {
161
+ mockState.loading = false;
162
+ }),
163
+ mutate: jest.fn((data) => {
164
+ mockState.data = data;
165
+ }),
166
+ };
167
+
168
+ const result = {
169
+ ...mockState,
170
+ ...mockActions,
171
+ };
172
+
173
+ // 如果提供了service函数,模拟调用
174
+ if (service && typeof service === 'function') {
175
+ result.run = jest.fn((...params) => {
176
+ mockState.loading = true;
177
+ mockState.params = params;
178
+
179
+ return new Promise((resolve, reject) => {
180
+ setTimeout(() => {
181
+ try {
182
+ const serviceResult = service(...params);
183
+ if (serviceResult instanceof Promise) {
184
+ serviceResult.then(resolve).catch(reject);
185
+ } else {
186
+ resolve(serviceResult);
187
+ }
188
+ } catch (error) {
189
+ reject(error);
190
+ } finally {
191
+ mockState.loading = false;
192
+ }
193
+ }, 100);
194
+ });
195
+ });
196
+ }
197
+
198
+ // 处理options
199
+ if (options.manual !== true) {
200
+ // 自动执行
201
+ setTimeout(() => {
202
+ result.run();
203
+ }, 0);
204
+ }
205
+
206
+ return result;
207
+ }),
208
+
209
+ useDebounce: jest.fn((value, delay) => value),
210
+
211
+ useThrottle: jest.fn((value, delay) => value),
212
+
213
+ useLocalStorageState: jest.fn((key, defaultValue) => {
214
+ const [state, setState] = [defaultValue, jest.fn()];
215
+ return [state, setState];
216
+ }),
217
+
218
+ useSessionStorageState: jest.fn((key, defaultValue) => {
219
+ const [state, setState] = [defaultValue, jest.fn()];
220
+ return [state, setState];
221
+ }),
222
+
223
+ useDeepCompareEffect: jest.fn((effect, deps) => {
224
+ if (effect && typeof effect === 'function') {
225
+ effect();
226
+ }
227
+ }),
228
+
229
+ useUpdateEffect: jest.fn((effect, deps) => {
230
+ if (effect && typeof effect === 'function') {
231
+ effect();
232
+ }
233
+ }),
234
+
235
+ useSize: jest.fn(() => ({ width: 100, height: 100 })),
236
+
237
+ useInViewport: jest.fn(() => [true, jest.fn()]),
238
+
239
+ useMemoizedFn: jest.fn((fn) => fn),
240
+
241
+ useMount: jest.fn((fn) => {
242
+ if (fn && typeof fn === 'function') {
243
+ fn();
244
+ }
245
+ }),
246
+
247
+ useUnmount: jest.fn((fn) => {
248
+ if (fn && typeof fn === 'function') {
249
+ fn();
250
+ }
251
+ }),
252
+
253
+ useDebounceEffect: jest.fn((effect, deps, wait) => {
254
+ if (effect && typeof effect === 'function') {
255
+ effect();
256
+ }
257
+ }),
258
+
259
+ useThrottleEffect: jest.fn((effect, deps, wait) => {
260
+ if (effect && typeof effect === 'function') {
261
+ effect();
262
+ }
263
+ }),
264
+ }));
265
+
266
+ Object.defineProperty(window, 'ResizeObserver', {
267
+ writable: true,
268
+ value: jest.fn().mockImplementation(() => ({
269
+ observe: jest.fn(),
270
+ unobserve: jest.fn(),
271
+ disconnect: jest.fn(),
272
+ })),
273
+ });
274
+
275
+ Object.defineProperty(window, 'IntersectionObserver', {
276
+ writable: true,
277
+ value: jest.fn().mockImplementation(() => ({
278
+ observe: jest.fn(),
279
+ unobserve: jest.fn(),
280
+ disconnect: jest.fn(),
281
+ })),
282
+ });
283
+
284
+ // Mock getBoundingClientRect
285
+ Element.prototype.getBoundingClientRect = jest.fn(() => ({
286
+ width: 120,
287
+ height: 120,
288
+ top: 0,
289
+ left: 0,
290
+ bottom: 0,
291
+ right: 0,
292
+ x: 0,
293
+ y: 0,
294
+ toJSON: jest.fn(),
295
+ }));
296
+
297
+ // Mock scrollIntoView
298
+ Element.prototype.scrollIntoView = jest.fn();
299
+
300
+ // Mock getComputedStyle
301
+ window.getComputedStyle = jest.fn(() => ({
302
+ getPropertyValue: jest.fn(() => ''),
303
+ setProperty: jest.fn(),
304
+ removeProperty: jest.fn(),
305
+ } as any));
306
+
307
+ // Mock URL methods
308
+ global.URL.createObjectURL = jest.fn(() => 'mock-url');
309
+ global.URL.revokeObjectURL = jest.fn();
310
+
311
+ // Mock fetch
312
+ global.fetch = jest.fn(() =>
313
+ Promise.resolve({
314
+ ok: true,
315
+ json: () => Promise.resolve({}),
316
+ blob: () => Promise.resolve(new Blob()),
317
+ text: () => Promise.resolve(''),
318
+ } as Response)
319
+ );
320
+
321
+ // Mock String methods to prevent format.match and format.replace errors
322
+ String.prototype.match = String.prototype.match || jest.fn(() => []);
323
+ String.prototype.replace = String.prototype.replace || jest.fn((pattern, replacement) => {
324
+ if (typeof pattern === 'string') {
325
+ return this.split(pattern).join(replacement);
326
+ }
327
+ return this;
328
+ });
329
+
330
+ // Mock FileReader
331
+ class MockFileReader {
332
+ result: any = null;
333
+ error: any = null;
334
+ readyState: number = 0;
335
+ onload: ((this: FileReader, ev: ProgressEvent<FileReader>) => any) | null = null;
336
+ onerror: ((this: FileReader, ev: ProgressEvent<FileReader>) => any) | null = null;
337
+ onloadend: ((this: FileReader, ev: ProgressEvent<FileReader>) => any) | null = null;
338
+
339
+ readAsDataURL = jest.fn(() => {
340
+ this.readyState = 2;
341
+ this.result = 'data:image/png;base64,test';
342
+ setTimeout(() => {
343
+ if (this.onload) this.onload({} as ProgressEvent<FileReader>);
344
+ if (this.onloadend) this.onloadend({} as ProgressEvent<FileReader>);
345
+ }, 0);
346
+ });
347
+
348
+ readAsText = jest.fn(() => {
349
+ this.readyState = 2;
350
+ this.result = 'test content';
351
+ setTimeout(() => {
352
+ if (this.onload) this.onload({} as ProgressEvent<FileReader>);
353
+ if (this.onloadend) this.onloadend({} as ProgressEvent<FileReader>);
354
+ }, 0);
355
+ });
356
+
357
+ abort = jest.fn();
358
+ addEventListener = jest.fn();
359
+ removeEventListener = jest.fn();
360
+ dispatchEvent = jest.fn();
361
+ }
362
+
363
+ global.FileReader = MockFileReader as any;
364
+
365
+ // Mock Blob
366
+ global.Blob = jest.fn().mockImplementation(() => ({
367
+ size: 1024,
368
+ type: 'image/png',
369
+ slice: jest.fn(),
370
+ stream: jest.fn(),
371
+ text: jest.fn(() => Promise.resolve('mock text')),
372
+ arrayBuffer: jest.fn(() => Promise.resolve(new ArrayBuffer(8))),
373
+ }));
374
+
375
+ // Store original createElement
376
+ const originalCreateElement = document.createElement;
377
+
378
+ // Simple mock for specific elements only when needed
379
+ document.createElement = jest.fn((tagName: string) => {
380
+ try {
381
+ return originalCreateElement.call(document, tagName);
382
+ } catch (e) {
383
+ // Fallback for special cases
384
+ const mockElement = {
385
+ tagName: tagName.toUpperCase(),
386
+ style: {},
387
+ className: '',
388
+ textContent: '',
389
+ innerHTML: '',
390
+ addEventListener: jest.fn(),
391
+ removeEventListener: jest.fn(),
392
+ dispatchEvent: jest.fn(),
393
+ setAttribute: jest.fn(),
394
+ getAttribute: jest.fn(),
395
+ removeAttribute: jest.fn(),
396
+ appendChild: jest.fn(),
397
+ removeChild: jest.fn(),
398
+ insertBefore: jest.fn(),
399
+ querySelector: jest.fn(),
400
+ querySelectorAll: jest.fn(() => []),
401
+ parentNode: null,
402
+ childNodes: [],
403
+ children: [],
404
+ };
405
+
406
+ // Add specific properties for different elements
407
+ if (tagName === 'canvas') {
408
+ Object.assign(mockElement, {
409
+ getContext: jest.fn(() => ({
410
+ drawImage: jest.fn(),
411
+ getImageData: jest.fn(),
412
+ putImageData: jest.fn(),
413
+ toDataURL: jest.fn(() => 'data:image/png;base64,test'),
414
+ })),
415
+ toDataURL: jest.fn(() => 'data:image/png;base64,test'),
416
+ width: 100,
417
+ height: 100,
418
+ });
419
+ } else if (tagName === 'a') {
420
+ Object.assign(mockElement, {
421
+ click: jest.fn(),
422
+ download: '',
423
+ href: '',
424
+ });
425
+ }
426
+
427
+ return mockElement as any;
428
+ }
429
+ });
430
+
431
+ // Store original methods
432
+ const originalAppendChild = document.body.appendChild;
433
+ const originalRemoveChild = document.body.removeChild;
434
+
435
+ // Mock but still allow actual functionality for testing
436
+ document.body.appendChild = jest.fn((node) => {
437
+ try {
438
+ // Check if node is a valid DOM element
439
+ if (node && typeof node === 'object' && node.nodeType !== undefined) {
440
+ return originalAppendChild.call(document.body, node);
441
+ }
442
+ // For non-DOM elements, just return the node
443
+ return node;
444
+ } catch (e) {
445
+ // If original fails, just return the node
446
+ return node;
447
+ }
448
+ });
449
+
450
+ document.body.removeChild = jest.fn((node) => {
451
+ try {
452
+ // Check if node is a valid DOM element
453
+ if (node && typeof node === 'object' && node.nodeType !== undefined) {
454
+ return originalRemoveChild.call(document.body, node);
455
+ }
456
+ // For non-DOM elements, just return the node
457
+ return node;
458
+ } catch (e) {
459
+ // If original fails, just return the node
460
+ return node;
461
+ }
462
+ });
463
+
464
+ // Mock getElementsByTagName to prevent ProIcon DOM access issues
465
+ const originalGetElementsByTagName = document.getElementsByTagName;
466
+ document.getElementsByTagName = jest.fn((tagName: string) => {
467
+ if (tagName === 'script') {
468
+ // Return empty collection for script tags to prevent ProIcon issues
469
+ return [];
470
+ }
471
+ try {
472
+ return originalGetElementsByTagName.call(document, tagName);
473
+ } catch (e) {
474
+ // Fallback for testing
475
+ return [];
476
+ }
477
+ });
478
+
479
+ // Mock ProIcon to prevent DOM manipulation
480
+ jest.mock('../src/ProIcon', () => ({
481
+ __esModule: true,
482
+ default: jest.fn(() => null),
483
+ ProIcon: jest.fn(() => null),
484
+ }));
@@ -0,0 +1,81 @@
1
+ import React from 'react';
2
+ import { render, RenderOptions } from '@testing-library/react';
3
+ import { ConfigProvider } from 'antd';
4
+ import zhCN from 'antd/locale/zh_CN';
5
+
6
+ // 确保document.body存在
7
+ const ensureDocumentSetup = () => {
8
+ if (typeof document !== 'undefined') {
9
+ if (!document.body) {
10
+ document.body = document.createElement('body');
11
+ document.documentElement.appendChild(document.body);
12
+ }
13
+
14
+ // 创建一个测试容器
15
+ let testContainer = document.getElementById('test-container');
16
+ if (!testContainer) {
17
+ testContainer = document.createElement('div');
18
+ testContainer.id = 'test-container';
19
+ document.body.appendChild(testContainer);
20
+ }
21
+ }
22
+ };
23
+
24
+ // Mock ProConfigProvider
25
+ const MockProConfigProvider = ({ children }: { children: React.ReactNode }) => {
26
+ const mockValue = {
27
+ state: {
28
+ ProTable: {},
29
+ ProForm: {},
30
+ ProEnum: {},
31
+ ProSelect: {},
32
+ storage: {},
33
+ theme: {},
34
+ locale: {},
35
+ },
36
+ setState: jest.fn(),
37
+ };
38
+
39
+ const MockContext = React.createContext(mockValue);
40
+ return React.createElement(MockContext.Provider, { value: mockValue }, children);
41
+ };
42
+
43
+ // Mock FieldProvider
44
+ const MockFieldProvider = ({ children }: { children: React.ReactNode }) => {
45
+ const mockValue = {
46
+ readonly: false,
47
+ disabled: false,
48
+ };
49
+
50
+ const MockFieldContext = React.createContext(mockValue);
51
+ return React.createElement(MockFieldContext.Provider, { value: mockValue }, children);
52
+ };
53
+
54
+ // All providers wrapper
55
+ const AllTheProviders = ({ children }: { children: React.ReactNode }) => {
56
+ ensureDocumentSetup();
57
+
58
+ return (
59
+ <ConfigProvider locale={zhCN}>
60
+ <MockProConfigProvider>
61
+ <MockFieldProvider>
62
+ {children}
63
+ </MockFieldProvider>
64
+ </MockProConfigProvider>
65
+ </ConfigProvider>
66
+ );
67
+ };
68
+
69
+ const customRender = (ui: React.ReactElement, options?: Omit<RenderOptions, 'wrapper'>) => {
70
+ ensureDocumentSetup();
71
+
72
+ return render(ui, {
73
+ wrapper: AllTheProviders,
74
+ container: document.getElementById('test-container') || document.body,
75
+ ...options
76
+ });
77
+ };
78
+
79
+ export * from '@testing-library/react';
80
+ export { customRender as render };
81
+ export { AllTheProviders, ensureDocumentSetup };