|
|
@@ -0,0 +1,432 @@
|
|
|
+import '@testing-library/jest-dom'
|
|
|
+
|
|
|
+/* eslint-disable react/display-name */
|
|
|
+
|
|
|
+// 设置环境变量
|
|
|
+process.env.TARO_ENV = 'h5'
|
|
|
+process.env.TARO_PLATFORM = 'web'
|
|
|
+process.env.SUPPORT_TARO_POLYFILL = 'disabled'
|
|
|
+
|
|
|
+// Mock Taro 组件
|
|
|
+// eslint-disable-next-line react/display-name
|
|
|
+jest.mock('@tarojs/components', () => {
|
|
|
+ const React = require('react')
|
|
|
+ const MockView = React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ })
|
|
|
+ MockView.displayName = 'MockView'
|
|
|
+
|
|
|
+ const MockScrollView = React.forwardRef((props: any, ref: any) => {
|
|
|
+ const {
|
|
|
+ children,
|
|
|
+ onScroll,
|
|
|
+ onTouchStart,
|
|
|
+ onScrollEnd,
|
|
|
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
+ scrollY,
|
|
|
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
+ showScrollbar,
|
|
|
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
+ scrollTop,
|
|
|
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
|
+ scrollWithAnimation,
|
|
|
+ ...restProps
|
|
|
+ } = props
|
|
|
+ return React.createElement('div', {
|
|
|
+ ...restProps,
|
|
|
+ ref,
|
|
|
+ onScroll: (e: any) => {
|
|
|
+ if (onScroll) onScroll(e)
|
|
|
+ },
|
|
|
+ onTouchStart: (e: any) => {
|
|
|
+ if (onTouchStart) onTouchStart(e)
|
|
|
+ },
|
|
|
+ onTouchEnd: () => {
|
|
|
+ if (onScrollEnd) onScrollEnd()
|
|
|
+ },
|
|
|
+ style: {
|
|
|
+ overflow: 'auto',
|
|
|
+ height: '200px',
|
|
|
+ ...restProps.style
|
|
|
+ }
|
|
|
+ }, children)
|
|
|
+ })
|
|
|
+ MockScrollView.displayName = 'MockScrollView'
|
|
|
+
|
|
|
+ return {
|
|
|
+ View: MockView,
|
|
|
+ ScrollView: MockScrollView,
|
|
|
+ Text: (() => {
|
|
|
+ const MockText = React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('span', { ...restProps, ref }, children)
|
|
|
+ })
|
|
|
+ MockText.displayName = 'MockText'
|
|
|
+ return MockText
|
|
|
+ })(),
|
|
|
+ Button: (() => {
|
|
|
+ const MockButton = React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('button', { ...restProps, ref }, children)
|
|
|
+ })
|
|
|
+ MockButton.displayName = 'MockButton'
|
|
|
+ return MockButton
|
|
|
+ })(),
|
|
|
+ Input: (() => {
|
|
|
+ const MockInput = React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { ...restProps } = props
|
|
|
+ return React.createElement('input', { ...restProps, ref })
|
|
|
+ })
|
|
|
+ MockInput.displayName = 'MockInput'
|
|
|
+ return MockInput
|
|
|
+ })(),
|
|
|
+ Textarea: (() => {
|
|
|
+ const MockTextarea = React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('textarea', { ...restProps, ref }, children)
|
|
|
+ })
|
|
|
+ MockTextarea.displayName = 'MockTextarea'
|
|
|
+ return MockTextarea
|
|
|
+ })(),
|
|
|
+ Image: (() => {
|
|
|
+ const MockImage = React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { ...restProps } = props
|
|
|
+ return React.createElement('img', { ...restProps, ref })
|
|
|
+ })
|
|
|
+ MockImage.displayName = 'MockImage'
|
|
|
+ return MockImage
|
|
|
+ })(),
|
|
|
+ Form: (() => {
|
|
|
+ const MockForm = React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('form', { ...restProps, ref }, children)
|
|
|
+ })
|
|
|
+ MockForm.displayName = 'MockForm'
|
|
|
+ return MockForm
|
|
|
+ })(),
|
|
|
+ Label: (() => {
|
|
|
+ const MockLabel = React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('label', { ...restProps, ref }, children)
|
|
|
+ })
|
|
|
+ MockLabel.displayName = 'MockLabel'
|
|
|
+ return MockLabel
|
|
|
+ })(),
|
|
|
+ Picker: (() => {
|
|
|
+ const MockPicker = React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ })
|
|
|
+ MockPicker.displayName = 'MockPicker'
|
|
|
+ return MockPicker
|
|
|
+ })(),
|
|
|
+ Switch: (() => {
|
|
|
+ const MockSwitch = React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { ...restProps } = props
|
|
|
+ return React.createElement('input', { type: 'checkbox', ...restProps, ref })
|
|
|
+ })
|
|
|
+ MockSwitch.displayName = 'MockSwitch'
|
|
|
+ return MockSwitch
|
|
|
+ })(),
|
|
|
+ Slider: (() => {
|
|
|
+ const MockSlider = React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { ...restProps } = props
|
|
|
+ return React.createElement('input', { type: 'range', ...restProps, ref })
|
|
|
+ })
|
|
|
+ MockSlider.displayName = 'MockSlider'
|
|
|
+ return MockSlider
|
|
|
+ })(),
|
|
|
+ Radio: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('input', { type: 'radio', ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ RadioGroup: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ Checkbox: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('input', { type: 'checkbox', ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ CheckboxGroup: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ Progress: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { ...restProps } = props
|
|
|
+ return React.createElement('progress', { ...restProps, ref })
|
|
|
+ }),
|
|
|
+ RichText: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ MovableArea: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ MovableView: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ Swiper: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ SwiperItem: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ Navigator: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('a', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ Audio: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { ...restProps } = props
|
|
|
+ return React.createElement('audio', { ...restProps, ref })
|
|
|
+ }),
|
|
|
+ Video: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('video', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ Camera: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ LivePlayer: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ LivePusher: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ Map: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ Canvas: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('canvas', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ OpenData: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ WebView: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('iframe', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ Ad: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ OfficialAccount: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ CoverView: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ CoverImage: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { ...restProps } = props
|
|
|
+ return React.createElement('img', { ...restProps, ref })
|
|
|
+ }),
|
|
|
+ FunctionalPageNavigator: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ AdContent: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ MatchMedia: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ PageContainer: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ ShareElement: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ KeyboardAccessory: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ RootPortal: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ PageMeta: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ NavigationBar: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ Block: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ Import: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ Include: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ Template: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ Slot: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ NativeSlot: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ CustomWrapper: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ Editor: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ VoipRoom: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ }),
|
|
|
+ AdCustom: React.forwardRef((props: any, ref: any) => {
|
|
|
+ const { children, ...restProps } = props
|
|
|
+ return React.createElement('div', { ...restProps, ref }, children)
|
|
|
+ })
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+// 模拟 MutationObserver
|
|
|
+// @ts-ignore
|
|
|
+global.MutationObserver = class {
|
|
|
+ disconnect() {}
|
|
|
+ observe(_element: any, _initObject: any) {}
|
|
|
+ takeRecords() { return [] }
|
|
|
+}
|
|
|
+
|
|
|
+// 模拟 IntersectionObserver
|
|
|
+// @ts-ignore
|
|
|
+global.IntersectionObserver = class {
|
|
|
+ constructor(fn: (args: any[]) => void) {
|
|
|
+ setTimeout(() => {
|
|
|
+ fn([{ isIntersecting: true }])
|
|
|
+ }, 1000)
|
|
|
+ }
|
|
|
+
|
|
|
+ observe() {}
|
|
|
+ unobserve() {}
|
|
|
+ disconnect() {}
|
|
|
+ takeRecords() { return [] }
|
|
|
+ root: null = null
|
|
|
+ rootMargin: string = ''
|
|
|
+ thresholds: number[] = []
|
|
|
+}
|
|
|
+
|
|
|
+// 模拟 ResizeObserver
|
|
|
+// @ts-ignore
|
|
|
+global.ResizeObserver = class {
|
|
|
+ observe() {}
|
|
|
+ unobserve() {}
|
|
|
+ disconnect() {}
|
|
|
+}
|
|
|
+
|
|
|
+// 模拟 matchMedia
|
|
|
+Object.defineProperty(window, 'matchMedia', {
|
|
|
+ writable: true,
|
|
|
+ value: jest.fn().mockImplementation(query => ({
|
|
|
+ matches: false,
|
|
|
+ media: query,
|
|
|
+ onchange: null,
|
|
|
+ addListener: jest.fn(), // deprecated
|
|
|
+ removeListener: jest.fn(), // deprecated
|
|
|
+ addEventListener: jest.fn(),
|
|
|
+ removeEventListener: jest.fn(),
|
|
|
+ dispatchEvent: jest.fn(),
|
|
|
+ })),
|
|
|
+})
|
|
|
+
|
|
|
+// 模拟 getComputedStyle
|
|
|
+Object.defineProperty(window, 'getComputedStyle', {
|
|
|
+ value: () => ({
|
|
|
+ getPropertyValue: (prop: string) => {
|
|
|
+ return {
|
|
|
+ 'font-size': '16px',
|
|
|
+ 'font-family': 'Arial',
|
|
|
+ color: 'rgb(0, 0, 0)',
|
|
|
+ 'background-color': 'rgb(255, 255, 255)',
|
|
|
+ width: '100px',
|
|
|
+ height: '100px',
|
|
|
+ top: '0px',
|
|
|
+ left: '0px',
|
|
|
+ right: '0px',
|
|
|
+ bottom: '0px',
|
|
|
+ x: '0px',
|
|
|
+ y: '0px'
|
|
|
+ }[prop] || ''
|
|
|
+ }
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+// 模拟 Element.prototype.getBoundingClientRect
|
|
|
+Element.prototype.getBoundingClientRect = jest.fn(() => ({
|
|
|
+ width: 100,
|
|
|
+ height: 100,
|
|
|
+ top: 0,
|
|
|
+ left: 0,
|
|
|
+ bottom: 100,
|
|
|
+ right: 100,
|
|
|
+ x: 0,
|
|
|
+ y: 0,
|
|
|
+ toJSON: () => ({
|
|
|
+ width: 100,
|
|
|
+ height: 100,
|
|
|
+ top: 0,
|
|
|
+ left: 0,
|
|
|
+ bottom: 100,
|
|
|
+ right: 100,
|
|
|
+ x: 0,
|
|
|
+ y: 0
|
|
|
+ })
|
|
|
+}))
|
|
|
+
|
|
|
+// 静默 console.error 在测试中
|
|
|
+const originalConsoleError = console.error
|
|
|
+console.error = (...args: any[]) => {
|
|
|
+ // 检查是否在测试环境中(通过 Jest 环境变量判断)
|
|
|
+ const isTestEnv = process.env.JEST_WORKER_ID !== undefined ||
|
|
|
+ typeof jest !== 'undefined'
|
|
|
+
|
|
|
+ // 在测试环境中静默错误输出,除非是重要错误
|
|
|
+ if (isTestEnv && !args[0]?.includes?.('重要错误')) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ originalConsoleError(...args)
|
|
|
+}
|
|
|
+
|
|
|
+// Mock 常用 UI 组件
|
|
|
+jest.mock('@/components/ui/dialog', () => {
|
|
|
+ const React = require('react')
|
|
|
+ return {
|
|
|
+ Dialog: ({ open, children }: any) => open ? React.createElement('div', { 'data-testid': 'dialog' }, children) : null,
|
|
|
+ DialogContent: ({ children, className }: any) => React.createElement('div', { className }, children),
|
|
|
+ DialogHeader: ({ children, className }: any) => React.createElement('div', { className }, children),
|
|
|
+ DialogTitle: ({ children, className }: any) => React.createElement('div', { className }, children),
|
|
|
+ DialogFooter: ({ children, className }: any) => React.createElement('div', { className }, children)
|
|
|
+ }
|
|
|
+})
|