2
0

setup.ts 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. // Taro组件mock配置
  2. // 从mini/tests/setup.ts中复制的完整mock配置
  3. // 这个文件应该在其他包的jest.config.cjs中通过setupFilesAfterEnv引用
  4. import '@testing-library/jest-dom'
  5. // 扩展全局类型以支持 Taro 配置测试
  6. declare var defineAppConfig: (config: any) => any
  7. /* eslint-disable react/display-name */
  8. // 设置环境变量
  9. process.env.TARO_ENV = 'h5'
  10. process.env.TARO_PLATFORM = 'web'
  11. process.env.SUPPORT_TARO_POLYFILL = 'disabled'
  12. // 定义 defineAppConfig 全局函数用于测试 Taro 配置文件
  13. ;(global as any).defineAppConfig = (config: any) => config
  14. // Mock Taro 组件
  15. // eslint-disable-next-line react/display-name
  16. jest.mock('@tarojs/components', () => {
  17. const React = require('react')
  18. const MockView = React.forwardRef((props: any, ref: any) => {
  19. const { children, ...restProps } = props
  20. return React.createElement('div', { ...restProps, ref }, children)
  21. })
  22. MockView.displayName = 'MockView'
  23. const MockScrollView = React.forwardRef((props: any, ref: any) => {
  24. const {
  25. children,
  26. onScroll,
  27. onTouchStart,
  28. onScrollEnd,
  29. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  30. scrollY,
  31. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  32. showScrollbar,
  33. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  34. scrollTop,
  35. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  36. scrollWithAnimation,
  37. ...restProps
  38. } = props
  39. return React.createElement('div', {
  40. ...restProps,
  41. ref,
  42. onScroll: (e: any) => {
  43. if (onScroll) onScroll(e)
  44. },
  45. onTouchStart: (e: any) => {
  46. if (onTouchStart) onTouchStart(e)
  47. },
  48. onTouchEnd: () => {
  49. if (onScrollEnd) onScrollEnd()
  50. },
  51. style: {
  52. overflow: 'auto',
  53. height: '200px',
  54. ...restProps.style
  55. }
  56. }, children)
  57. })
  58. MockScrollView.displayName = 'MockScrollView'
  59. return {
  60. View: MockView,
  61. ScrollView: MockScrollView,
  62. Text: (() => {
  63. const MockText = React.forwardRef((props: any, ref: any) => {
  64. const { children, ...restProps } = props
  65. return React.createElement('span', { ...restProps, ref }, children)
  66. })
  67. MockText.displayName = 'MockText'
  68. return MockText
  69. })(),
  70. Button: (() => {
  71. const MockButton = React.forwardRef((props: any, ref: any) => {
  72. const { children, ...restProps } = props
  73. return React.createElement('button', { ...restProps, ref }, children)
  74. })
  75. MockButton.displayName = 'MockButton'
  76. return MockButton
  77. })(),
  78. Input: (() => {
  79. const MockInput = React.forwardRef((props: any, ref: any) => {
  80. const { ...restProps } = props
  81. return React.createElement('input', { ...restProps, ref })
  82. })
  83. MockInput.displayName = 'MockInput'
  84. return MockInput
  85. })(),
  86. Textarea: (() => {
  87. const MockTextarea = React.forwardRef((props: any, ref: any) => {
  88. const { children, ...restProps } = props
  89. return React.createElement('textarea', { ...restProps, ref }, children)
  90. })
  91. MockTextarea.displayName = 'MockTextarea'
  92. return MockTextarea
  93. })(),
  94. Image: (() => {
  95. const MockImage = React.forwardRef((props: any, ref: any) => {
  96. const { ...restProps } = props
  97. return React.createElement('img', { ...restProps, ref })
  98. })
  99. MockImage.displayName = 'MockImage'
  100. return MockImage
  101. })(),
  102. Form: (() => {
  103. const MockForm = React.forwardRef((props: any, ref: any) => {
  104. const { children, ...restProps } = props
  105. return React.createElement('form', { ...restProps, ref }, children)
  106. })
  107. MockForm.displayName = 'MockForm'
  108. return MockForm
  109. })(),
  110. Label: (() => {
  111. const MockLabel = React.forwardRef((props: any, ref: any) => {
  112. const { children, ...restProps } = props
  113. return React.createElement('label', { ...restProps, ref }, children)
  114. })
  115. MockLabel.displayName = 'MockLabel'
  116. return MockLabel
  117. })(),
  118. Picker: (() => {
  119. const MockPicker = React.forwardRef((props: any, ref: any) => {
  120. const { children, ...restProps } = props
  121. return React.createElement('div', { ...restProps, ref }, children)
  122. })
  123. MockPicker.displayName = 'MockPicker'
  124. return MockPicker
  125. })(),
  126. Switch: (() => {
  127. const MockSwitch = React.forwardRef((props: any, ref: any) => {
  128. const { ...restProps } = props
  129. return React.createElement('input', { type: 'checkbox', ...restProps, ref })
  130. })
  131. MockSwitch.displayName = 'MockSwitch'
  132. return MockSwitch
  133. })(),
  134. Slider: (() => {
  135. const MockSlider = React.forwardRef((props: any, ref: any) => {
  136. const { ...restProps } = props
  137. return React.createElement('input', { type: 'range', ...restProps, ref })
  138. })
  139. MockSlider.displayName = 'MockSlider'
  140. return MockSlider
  141. })(),
  142. Radio: React.forwardRef((props: any, ref: any) => {
  143. const { children, ...restProps } = props
  144. return React.createElement('input', { type: 'radio', ...restProps, ref }, children)
  145. }),
  146. RadioGroup: React.forwardRef((props: any, ref: any) => {
  147. const { children, ...restProps } = props
  148. return React.createElement('div', { ...restProps, ref }, children)
  149. }),
  150. Checkbox: React.forwardRef((props: any, ref: any) => {
  151. const { children, ...restProps } = props
  152. return React.createElement('input', { type: 'checkbox', ...restProps, ref }, children)
  153. }),
  154. CheckboxGroup: React.forwardRef((props: any, ref: any) => {
  155. const { children, ...restProps } = props
  156. return React.createElement('div', { ...restProps, ref }, children)
  157. }),
  158. Progress: React.forwardRef((props: any, ref: any) => {
  159. const { ...restProps } = props
  160. return React.createElement('progress', { ...restProps, ref })
  161. }),
  162. RichText: React.forwardRef((props: any, ref: any) => {
  163. const { children, ...restProps } = props
  164. return React.createElement('div', { ...restProps, ref }, children)
  165. }),
  166. MovableArea: React.forwardRef((props: any, ref: any) => {
  167. const { children, ...restProps } = props
  168. return React.createElement('div', { ...restProps, ref }, children)
  169. }),
  170. MovableView: React.forwardRef((props: any, ref: any) => {
  171. const { children, ...restProps } = props
  172. return React.createElement('div', { ...restProps, ref }, children)
  173. }),
  174. Swiper: React.forwardRef((props: any, ref: any) => {
  175. const { children, ...restProps } = props
  176. return React.createElement('div', { ...restProps, ref }, children)
  177. }),
  178. SwiperItem: React.forwardRef((props:any, ref: any) => {
  179. const { children, ...restProps } = props
  180. return React.createElement('div', { ...restProps, ref }, children)
  181. }),
  182. Navigator: React.forwardRef((props: any, ref: any) => {
  183. const { children, ...restProps } = props
  184. return React.createElement('a', { ...restProps, ref }, children)
  185. }),
  186. Audio: React.forwardRef((props: any, ref: any) => {
  187. const { ...restProps } = props
  188. return React.createElement('audio', { ...restProps, ref })
  189. }),
  190. Video: React.forwardRef((props: any, ref: any) => {
  191. const { children, ...restProps } = props
  192. return React.createElement('video', { ...restProps, ref }, children)
  193. }),
  194. Camera: React.forwardRef((props: any, ref: any) => {
  195. const { children, ...restProps } = props
  196. return React.createElement('div', { ...restProps, ref }, children)
  197. }),
  198. LivePlayer: React.forwardRef((props: any, ref: any) => {
  199. const { children, ...restProps } = props
  200. return React.createElement('div', { ...restProps, ref }, children)
  201. }),
  202. LivePusher: React.forwardRef((props: any, ref: any) => {
  203. const { children, ...restProps } = props
  204. return React.createElement('div', { ...restProps, ref }, children)
  205. }),
  206. Map: React.forwardRef((props: any, ref: any) => {
  207. const { children, ...restProps } = props
  208. return React.createElement('div', { ...restProps, ref }, children)
  209. }),
  210. Canvas: React.forwardRef((props: any, ref: any) => {
  211. const { children, ...restProps } = props
  212. return React.createElement('canvas', { ...restProps, ref }, children)
  213. }),
  214. OpenData: React.forwardRef((props: any, ref: any) => {
  215. const { children, ...restProps } = props
  216. return React.createElement('div', { ...restProps, ref }, children)
  217. }),
  218. WebView: React.forwardRef((props: any, ref: any) => {
  219. const { children, ...restProps } = props
  220. return React.createElement('iframe', { ...restProps, ref }, children)
  221. }),
  222. Ad: React.forwardRef((props: any, ref: any) => {
  223. const { children, ...restProps } = props
  224. return React.createElement('div', { ...restProps, ref }, children)
  225. }),
  226. OfficialAccount: React.forwardRef((props: any, ref: any) => {
  227. const { children, ...restProps } = props
  228. return React.createElement('div', { ...restProps, ref }, children)
  229. }),
  230. CoverView: React.forwardRef((props: any, ref: any) => {
  231. const { children, ...restProps } = props
  232. return React.createElement('div', { ...restProps, ref }, children)
  233. }),
  234. CoverImage: React.forwardRef((props: any, ref: any) => {
  235. const { ...restProps } = props
  236. return React.createElement('img', { ...restProps, ref })
  237. }),
  238. FunctionalPageNavigator: React.forwardRef((props: any, ref: any) => {
  239. const { children, ...restProps } = props
  240. return React.createElement('div', { ...restProps, ref }, children)
  241. }),
  242. AdContent: React.forwardRef((props: any, ref: any) => {
  243. const { children, ...restProps } = props
  244. return React.createElement('div', { ...restProps, ref }, children)
  245. }),
  246. MatchMedia: React.forwardRef((props: any, ref: any) => {
  247. const { children, ...restProps } = props
  248. return React.createElement('div', { ...restProps, ref }, children)
  249. }),
  250. PageContainer: React.forwardRef((props: any, ref:any) => {
  251. const { children, ...restProps } = props
  252. return React.createElement('div', { ...restProps, ref }, children)
  253. }),
  254. ShareElement: React.forwardRef((props: any, ref: any) => {
  255. const { children, ...restProps } = props
  256. return React.createElement('div', { ...restProps, ref }, children)
  257. }),
  258. KeyboardAccessory: React.forwardRef((props: any, ref: any) => {
  259. const { children, ...restProps } = props
  260. return React.createElement('div', { ...restProps, ref }, children)
  261. }),
  262. RootPortal: React.forwardRef((props: any, ref: any) => {
  263. const { children, ...restProps } = props
  264. return React.createElement('div', { ...restProps, ref }, children)
  265. }),
  266. PageMeta: React.forwardRef((props: any, ref: any) => {
  267. const { children, ...restProps } = props
  268. return React.createElement('div', { ...restProps, ref }, children)
  269. }),
  270. NavigationBar: React.forwardRef((props: any, ref: any) => {
  271. const { children, ...restProps } = props
  272. return React.createElement('div', { ...restProps, ref }, children)
  273. }),
  274. Block: React.forwardRef((props: any, ref: any) => {
  275. const { children, ...restProps } = props
  276. return React.createElement('div', { ...restProps, ref }, children)
  277. }),
  278. Import: React.forwardRef((props: any, ref: any) => {
  279. const { children, ...restProps } = props
  280. return React.createElement('div', { ...restProps, ref }, children)
  281. }),
  282. Include: React.forwardRef((props: any, ref: any) => {
  283. const { children, ...restProps } = props
  284. return React.createElement('div', { ...restProps, ref }, children)
  285. }),
  286. Template: React.forwardRef((props: any, ref: any) => {
  287. const { children, ...restProps } = props
  288. return React.createElement('div', { ...restProps, ref }, children)
  289. }),
  290. Slot: React.forwardRef((props: any, ref: any) => {
  291. const { children, ...restProps } = props
  292. return React.createElement('div', { ...restProps, ref }, children)
  293. }),
  294. NativeSlot: React.forwardRef((props: any, ref: any) => {
  295. const { children, ...restProps } = props
  296. return React.createElement('div', { ...restProps, ref }, children)
  297. }),
  298. CustomWrapper: React.forwardRef((props: any, ref: any) => {
  299. const { children, ...restProps } = props
  300. return React.createElement('div', { ...restProps, ref }, children)
  301. }),
  302. Editor: React.forwardRef((props: any, ref: any) => {
  303. const { children, ...restProps } = props
  304. return React.createElement('div', { ...restProps, ref }, children)
  305. }),
  306. VoipRoom: React.forwardRef((props: any, ref: any) => {
  307. const { children, ...restProps } = props
  308. return React.createElement('div', { ...restProps, ref }, children)
  309. }),
  310. AdCustom: React.forwardRef((props: any, ref: any) => {
  311. const { children, ...restProps } = props
  312. return React.createElement('div', { ...restProps, ref }, children)
  313. })
  314. }
  315. })
  316. // Mock 常用 UI 组件(可选)
  317. // 注意:这个mock需要在实际使用这些组件的包中配置
  318. // 这里注释掉是因为mini-testing-utils包本身不包含这些组件
  319. /*
  320. jest.mock('@/components/ui/dialog', () => {
  321. const React = require('react')
  322. return {
  323. Dialog: ({ open, children }: any) => open ? React.createElement('div', { 'data-testid': 'dialog' }, children) : null,
  324. DialogContent: ({ children, className }: any) => React.createElement('div', { className }, children),
  325. DialogHeader: ({ children, className }: any) => React.createElement('div', { className }, children),
  326. DialogTitle: ({ children, className }: any) => React.createElement('div', { className }, children),
  327. DialogFooter: ({ children, className }: any) => React.createElement('div', { className }, children)
  328. }
  329. })
  330. */
  331. // 模拟 MutationObserver
  332. // @ts-ignore
  333. global.MutationObserver = class {
  334. disconnect() {}
  335. observe(_element: any, _initObject: any) {}
  336. takeRecords() { return [] }
  337. }
  338. // 模拟 IntersectionObserver
  339. // @ts-ignore
  340. global.IntersectionObserver = class {
  341. constructor(fn: (args: any[]) => void) {
  342. setTimeout(() => {
  343. fn([{ isIntersecting: true }])
  344. }, 1000)
  345. }
  346. observe() {}
  347. unobserve() {}
  348. disconnect() {}
  349. takeRecords() { return [] }
  350. root: null = null
  351. rootMargin: string = ''
  352. thresholds: number[] = []
  353. }
  354. // 模拟 ResizeObserver
  355. // @ts-ignore
  356. global.ResizeObserver = class {
  357. observe() {}
  358. unobserve() {}
  359. disconnect() {}
  360. }
  361. // 模拟 matchMedia
  362. Object.defineProperty(window, 'matchMedia', {
  363. writable: true,
  364. value: jest.fn().mockImplementation(query => ({
  365. matches: false,
  366. media: query,
  367. onchange: null,
  368. addListener: jest.fn(), // deprecated
  369. removeListener: jest.fn(), // deprecated
  370. addEventListener: jest.fn(),
  371. removeEventListener: jest.fn(),
  372. dispatchEvent: jest.fn(),
  373. })),
  374. })
  375. // 模拟 getComputedStyle
  376. Object.defineProperty(window, 'getComputedStyle', {
  377. value: () => ({
  378. getPropertyValue: (prop: string) => {
  379. return {
  380. 'font-size': '16px',
  381. 'font-family': 'Arial',
  382. color: 'rgb(0, 0, 0)',
  383. 'background-color': 'rgb(255, 255, 255)',
  384. width: '100px',
  385. height: '100px',
  386. top: '0px',
  387. left: '0px',
  388. right: '0px',
  389. bottom: '0px',
  390. x: '0px',
  391. y: '0px'
  392. }[prop] || ''
  393. }
  394. })
  395. })
  396. // 模拟 Element.prototype.getBoundingClientRect
  397. Element.prototype.getBoundingClientRect = jest.fn(() => ({
  398. width: 100,
  399. height: 100,
  400. top: 0,
  401. left: 0,
  402. bottom: 100,
  403. right: 100,
  404. x: 0,
  405. y: 0,
  406. toJSON: () => ({
  407. width: 100,
  408. height: 100,
  409. top: 0,
  410. left: 0,
  411. bottom: 100,
  412. right: 100,
  413. x: 0,
  414. y: 0
  415. })
  416. }))
  417. // 静默 console.error 在测试中
  418. const originalConsoleError = console.error
  419. console.error = (...args: any[]) => {
  420. // 检查是否在测试环境中(通过 Jest 环境变量判断)
  421. const isTestEnv = process.env.JEST_WORKER_ID !== undefined ||
  422. typeof jest !== 'undefined'
  423. // 在测试环境中静默错误输出,除非是重要错误
  424. if (isTestEnv && !args[0]?.includes?.('重要错误')) {
  425. return
  426. }
  427. originalConsoleError(...args)
  428. }
  429. // 默认导出
  430. export default {}