mirror of
https://gitee.com/wot-design-uni/wot-design-uni.git
synced 2025-12-06 17:18:40 +08:00
chore: 🚀 添加 jest 用于组件库工具方法和hooks的测试 (#971)
This commit is contained in:
parent
4319fa9bad
commit
58157d8014
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
|
coverage/
|
||||||
node_modules/
|
node_modules/
|
||||||
unpackage/
|
unpackage/
|
||||||
dist/
|
dist/
|
||||||
|
|||||||
20
babel.config.js
Normal file
20
babel.config.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
module.exports = {
|
||||||
|
presets: [
|
||||||
|
['@babel/preset-env', {
|
||||||
|
targets: { node: 'current' },
|
||||||
|
modules: 'commonjs'
|
||||||
|
}],
|
||||||
|
'@babel/preset-typescript'
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
function () {
|
||||||
|
return {
|
||||||
|
visitor: {
|
||||||
|
MetaProperty(path) {
|
||||||
|
path.replaceWithSourceString('{ url: "file://test" }')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
48
jest.config.js
Normal file
48
jest.config.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* @Author: weisheng
|
||||||
|
* @Date: 2025-03-24 12:33:15
|
||||||
|
* @LastEditTime: 2025-03-24 22:02:51
|
||||||
|
* @LastEditors: weisheng
|
||||||
|
* @Description:
|
||||||
|
* @FilePath: /wot-design-uni/jest.config.js
|
||||||
|
* 记得注释
|
||||||
|
*/
|
||||||
|
module.exports = {
|
||||||
|
testEnvironment: 'jsdom',
|
||||||
|
moduleFileExtensions: ['ts', 'js', 'json', 'vue'],
|
||||||
|
moduleNameMapper: {
|
||||||
|
'^@/(.*)$': '<rootDir>/src/$1',
|
||||||
|
'\\.(css|less|scss|sass)$': 'identity-obj-proxy'
|
||||||
|
},
|
||||||
|
transform: {
|
||||||
|
'^.+\\.ts$': 'ts-jest',
|
||||||
|
'^.+\\.js$': 'babel-jest',
|
||||||
|
'^.+\\.vue$': '@vue/vue3-jest'
|
||||||
|
},
|
||||||
|
testRegex: '(/tests/.*\\.spec)\\.(jsx?|tsx?)$', // 只匹配 .spec 结尾的文件
|
||||||
|
testPathIgnorePatterns: ['/node_modules/', '/tests/setup.js', '/tests/__mocks__/'],
|
||||||
|
globals: {
|
||||||
|
'vue-jest': {
|
||||||
|
compilerOptions: {
|
||||||
|
isCustomElement: (tag) => tag.startsWith('uni-'),
|
||||||
|
whitespace: 'condense',
|
||||||
|
delimiters: ['{{', '}}']
|
||||||
|
},
|
||||||
|
experimentalCoverage: true, // 添加实验性覆盖率支持
|
||||||
|
templateCompiler: {
|
||||||
|
compiler: require('@vue/compiler-dom'),
|
||||||
|
compilerOptions: {
|
||||||
|
hoistStatic: false,
|
||||||
|
prefixIdentifiers: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'ts-jest': {
|
||||||
|
diagnostics: false,
|
||||||
|
isolatedModules: true,
|
||||||
|
babelConfig: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
transformIgnorePatterns: ['/node_modules/(?!(uni-app|@dcloudio)/)'],
|
||||||
|
setupFiles: ['<rootDir>/tests/setup.js']
|
||||||
|
}
|
||||||
23
package.json
23
package.json
@ -58,7 +58,14 @@
|
|||||||
"upload:mp-dingtalk": "uni build -p mp-dingtalk && minici --platform dd",
|
"upload:mp-dingtalk": "uni build -p mp-dingtalk && minici --platform dd",
|
||||||
"build:qrcode": "esno ./scripts/qrcode.ts",
|
"build:qrcode": "esno ./scripts/qrcode.ts",
|
||||||
"build:changelog": "esno ./scripts/changelog.ts",
|
"build:changelog": "esno ./scripts/changelog.ts",
|
||||||
"build:theme-vars": "esno ./scripts/buildThemeVars.ts"
|
"build:theme-vars": "esno ./scripts/buildThemeVars.ts",
|
||||||
|
"test": "jest",
|
||||||
|
"test:watch": "jest --watch",
|
||||||
|
"test:h5": "cross-env UNI_PLATFORM=h5 jest -i",
|
||||||
|
"test:android": "cross-env UNI_PLATFORM=app UNI_OS_NAME=android jest -i",
|
||||||
|
"test:ios": "cross-env UNI_PLATFORM=app UNI_OS_NAME=ios jest -i",
|
||||||
|
"test:mp-weixin": "cross-env UNI_PLATFORM=mp-weixin jest -i",
|
||||||
|
"test:mp-baidu": "cross-env UNI_PLATFORM=mp-baidu jest -i"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@dcloudio/uni-app": "3.0.0-4020420240722002",
|
"@dcloudio/uni-app": "3.0.0-4020420240722002",
|
||||||
@ -130,7 +137,19 @@
|
|||||||
"vitepress": "^1.5.0",
|
"vitepress": "^1.5.0",
|
||||||
"vitest": "^0.30.1",
|
"vitest": "^0.30.1",
|
||||||
"vue-eslint-parser": "^9.1.0",
|
"vue-eslint-parser": "^9.1.0",
|
||||||
"vue-tsc": "^2.0.29"
|
"vue-tsc": "^2.0.29",
|
||||||
|
"@babel/core": "^7.15.0",
|
||||||
|
"@babel/preset-env": "^7.15.0",
|
||||||
|
"@babel/preset-typescript": "^7.15.0",
|
||||||
|
"@types/jest": "^27.0.0",
|
||||||
|
"@vue/test-utils": "^2.0.0",
|
||||||
|
"babel-jest": "^27.0.4",
|
||||||
|
"jest": "27.0.4",
|
||||||
|
"jest-environment-node": "27.5.1",
|
||||||
|
"ts-jest": "27.0.4",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
|
"puppeteer": "14.0.0",
|
||||||
|
"@vue/vue3-jest": "27.0.0-alpha.1"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"commitizen": {
|
"commitizen": {
|
||||||
|
|||||||
1233
pnpm-lock.yaml
generated
1233
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
46
tests/composables/useTouch.spec.ts
Normal file
46
tests/composables/useTouch.spec.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { useTouch } from '@/uni_modules/wot-design-uni/components/composables/useTouch'
|
||||||
|
|
||||||
|
describe('useTouch', () => {
|
||||||
|
const touch = useTouch()
|
||||||
|
|
||||||
|
it('should initialize with default values', () => {
|
||||||
|
expect(touch.direction.value).toBe('')
|
||||||
|
expect(touch.deltaX.value).toBe(0)
|
||||||
|
expect(touch.deltaY.value).toBe(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle touch start', () => {
|
||||||
|
touch.touchStart({
|
||||||
|
touches: [{ clientX: 100, clientY: 100 }]
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(touch.startX.value).toBe(100)
|
||||||
|
expect(touch.startY.value).toBe(100)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle touch move horizontal', () => {
|
||||||
|
touch.touchStart({
|
||||||
|
touches: [{ clientX: 100, clientY: 100 }]
|
||||||
|
})
|
||||||
|
|
||||||
|
touch.touchMove({
|
||||||
|
touches: [{ clientX: 200, clientY: 120 }]
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(touch.direction.value).toBe('horizontal')
|
||||||
|
expect(touch.deltaX.value).toBe(100)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle touch move vertical', () => {
|
||||||
|
touch.touchStart({
|
||||||
|
touches: [{ clientX: 100, clientY: 100 }]
|
||||||
|
})
|
||||||
|
|
||||||
|
touch.touchMove({
|
||||||
|
touches: [{ clientX: 120, clientY: 200 }]
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(touch.direction.value).toBe('vertical')
|
||||||
|
expect(touch.deltaY.value).toBe(100)
|
||||||
|
})
|
||||||
|
})
|
||||||
105
tests/composables/useTranslate.spec.ts
Normal file
105
tests/composables/useTranslate.spec.ts
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
import { useTranslate } from '@/uni_modules/wot-design-uni/components/composables/useTranslate'
|
||||||
|
import Locale from '@/uni_modules/wot-design-uni/locale'
|
||||||
|
import enUS from '@/uni_modules/wot-design-uni/locale/lang/en-US'
|
||||||
|
|
||||||
|
describe('useTranslate', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
Locale.use('zh-CN')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should translate basic messages in Chinese', () => {
|
||||||
|
const { translate: calendarTranslate } = useTranslate('calendar')
|
||||||
|
const { translate: pickerTranslate } = useTranslate('picker')
|
||||||
|
|
||||||
|
expect(calendarTranslate('placeholder')).toBe('请选择')
|
||||||
|
expect(pickerTranslate('cancel')).toBe('取消')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should switch to English translations', () => {
|
||||||
|
const { translate } = useTranslate('calendar')
|
||||||
|
expect(translate('confirm')).toBe('确定')
|
||||||
|
|
||||||
|
Locale.use('en-US', enUS)
|
||||||
|
expect(translate('confirm')).toBe('OK')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle function messages with parameters', () => {
|
||||||
|
const { translate } = useTranslate('calendarView')
|
||||||
|
expect(translate('rangePrompt', 7)).toBe('选择天数不能超过7天')
|
||||||
|
expect(translate('hour', 10)).toBe('10时')
|
||||||
|
expect(translate('minute', 30)).toBe('30分')
|
||||||
|
expect(translate('second', 45)).toBe('45秒')
|
||||||
|
|
||||||
|
Locale.use('en-US', enUS)
|
||||||
|
expect(translate('rangePrompt', 7)).toBe('The number of selected days cannot exceed 7 days')
|
||||||
|
expect(translate('hour', 10)).toBe('10')
|
||||||
|
expect(translate('minute', 30)).toBe('30')
|
||||||
|
expect(translate('second', 45)).toBe('45')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle nested object translations', () => {
|
||||||
|
const { translate } = useTranslate('calendarView')
|
||||||
|
expect(translate('weeks.mon')).toBe('一')
|
||||||
|
expect(translate('weeks.sun')).toBe('日')
|
||||||
|
|
||||||
|
Locale.use('en-US', enUS)
|
||||||
|
expect(translate('weeks.mon')).toBe('Mon')
|
||||||
|
expect(translate('weeks.sun')).toBe('Sun')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle pagination translations', () => {
|
||||||
|
const { translate } = useTranslate('pagination')
|
||||||
|
expect(translate('prev')).toBe('上一页')
|
||||||
|
expect(translate('next')).toBe('下一页')
|
||||||
|
expect(translate('total', 100)).toBe('当前数据:100条')
|
||||||
|
|
||||||
|
Locale.use('en-US', enUS)
|
||||||
|
expect(translate('prev')).toBe('Previous')
|
||||||
|
expect(translate('next')).toBe('Next')
|
||||||
|
expect(translate('total', 100)).toBe('Total: 100')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle date formats', () => {
|
||||||
|
const { translate } = useTranslate('calendar')
|
||||||
|
expect(translate('timeFormat')).toBe('YY年MM月DD日 HH:mm:ss')
|
||||||
|
expect(translate('dateFormat')).toBe('YYYY年MM月DD日')
|
||||||
|
expect(translate('weekFormat', 2023, 1)).toBe('2023 第 1 周')
|
||||||
|
|
||||||
|
Locale.use('en-US', enUS)
|
||||||
|
expect(translate('timeFormat')).toBe('YY-MM-DD HH:mm:ss')
|
||||||
|
expect(translate('dateFormat')).toBe('YYYY-MM-DD')
|
||||||
|
expect(translate('weekFormat', 2023, 1)).toBe('2023 W1')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle form related translations', () => {
|
||||||
|
const { translate } = useTranslate('messageBox')
|
||||||
|
expect(translate('confirm')).toBe('确定')
|
||||||
|
expect(translate('cancel')).toBe('取消')
|
||||||
|
expect(translate('inputPlaceholder')).toBe('请输入')
|
||||||
|
|
||||||
|
Locale.use('en-US', enUS)
|
||||||
|
expect(translate('confirm')).toBe('OK')
|
||||||
|
expect(translate('cancel')).toBe('Cancel')
|
||||||
|
expect(translate('inputPlaceholder')).toBe('Please input information')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should fallback to key path when translation missing', () => {
|
||||||
|
const { translate } = useTranslate('nonexistent')
|
||||||
|
expect(translate('key')).toBe('nonexistent.key')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle component specific messages', () => {
|
||||||
|
const { translate: uploadTranslate } = useTranslate('upload')
|
||||||
|
const { translate: searchTranslate } = useTranslate('search')
|
||||||
|
const { translate: signatureTranslate } = useTranslate('signature')
|
||||||
|
|
||||||
|
expect(uploadTranslate('error')).toBe('上传失败')
|
||||||
|
expect(searchTranslate('search')).toBe('搜索')
|
||||||
|
expect(signatureTranslate('confirmText')).toBe('确认')
|
||||||
|
|
||||||
|
Locale.use('en-US', enUS)
|
||||||
|
expect(uploadTranslate('error')).toBe('Failed to upload')
|
||||||
|
expect(searchTranslate('search')).toBe('Search')
|
||||||
|
expect(signatureTranslate('confirmText')).toBe('OK')
|
||||||
|
})
|
||||||
|
})
|
||||||
287
tests/composables/useUpload.spec.ts
Normal file
287
tests/composables/useUpload.spec.ts
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
import { useUpload } from '@/uni_modules/wot-design-uni/components/composables/useUpload'
|
||||||
|
import type { UploadFileItem } from '@/uni_modules/wot-design-uni/components/wd-upload/types'
|
||||||
|
|
||||||
|
// Mock uni API
|
||||||
|
const mockUploadTask = {
|
||||||
|
abort: jest.fn(),
|
||||||
|
onProgressUpdate: jest.fn((callback) => {
|
||||||
|
callback({ progress: 50 })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
;(global as any).uni = {
|
||||||
|
uploadFile: jest.fn((options) => {
|
||||||
|
const { success, fail } = options
|
||||||
|
if (options.url.includes('success')) {
|
||||||
|
success?.({ statusCode: 200, data: 'success' })
|
||||||
|
} else {
|
||||||
|
fail?.({ errMsg: 'upload failed' })
|
||||||
|
}
|
||||||
|
return mockUploadTask
|
||||||
|
})
|
||||||
|
} as any
|
||||||
|
|
||||||
|
describe('useUpload', () => {
|
||||||
|
const { startUpload, abort, UPLOAD_STATUS } = useUpload()
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 测试基本上传功能
|
||||||
|
it('should upload file successfully', async () => {
|
||||||
|
const file: UploadFileItem = {
|
||||||
|
url: 'file://temp/image.png',
|
||||||
|
status: UPLOAD_STATUS.PENDING,
|
||||||
|
percent: 0,
|
||||||
|
uid: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
const onSuccess = jest.fn()
|
||||||
|
const onProgress = jest.fn()
|
||||||
|
|
||||||
|
await startUpload(file, {
|
||||||
|
action: 'https://api.example.com/success',
|
||||||
|
name: 'file',
|
||||||
|
onSuccess,
|
||||||
|
onProgress
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(file.status).toBe(UPLOAD_STATUS.SUCCESS)
|
||||||
|
expect(onSuccess).toHaveBeenCalled()
|
||||||
|
expect(onProgress).toHaveBeenCalledWith({ progress: 50 }, file)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 测试上传失败场景
|
||||||
|
it('should handle upload failure', async () => {
|
||||||
|
const file: UploadFileItem = {
|
||||||
|
url: 'file://temp/image.png',
|
||||||
|
status: UPLOAD_STATUS.PENDING,
|
||||||
|
percent: 0,
|
||||||
|
uid: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
const onError = jest.fn()
|
||||||
|
|
||||||
|
await startUpload(file, {
|
||||||
|
action: 'https://api.example.com/fail',
|
||||||
|
name: 'file',
|
||||||
|
onError
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(file.status).toBe(UPLOAD_STATUS.FAIL)
|
||||||
|
expect(file.error).toBe('upload failed')
|
||||||
|
expect(onError).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 测试自定义上传方法
|
||||||
|
it('should use custom upload method', async () => {
|
||||||
|
const file: UploadFileItem = {
|
||||||
|
url: 'file://temp/image.png',
|
||||||
|
status: UPLOAD_STATUS.PENDING,
|
||||||
|
percent: 0,
|
||||||
|
uid: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
const customUpload = jest.fn()
|
||||||
|
|
||||||
|
await startUpload(file, {
|
||||||
|
action: 'https://api.example.com',
|
||||||
|
uploadMethod: customUpload
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(customUpload).toHaveBeenCalledWith(
|
||||||
|
file,
|
||||||
|
{},
|
||||||
|
expect.objectContaining({
|
||||||
|
action: 'https://api.example.com'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 测试中断上传
|
||||||
|
it('should abort upload task', () => {
|
||||||
|
const file: UploadFileItem = {
|
||||||
|
url: 'file://temp/image.png',
|
||||||
|
status: UPLOAD_STATUS.PENDING,
|
||||||
|
percent: 0,
|
||||||
|
uid: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
startUpload(file, {
|
||||||
|
action: 'https://api.example.com/success',
|
||||||
|
abortPrevious: true
|
||||||
|
})
|
||||||
|
|
||||||
|
abort()
|
||||||
|
expect(mockUploadTask.abort).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 测试自动中断之前的上传任务
|
||||||
|
it('should abort previous upload when abortPrevious is true', async () => {
|
||||||
|
const file1: UploadFileItem = {
|
||||||
|
url: 'file://temp/image1.png',
|
||||||
|
status: UPLOAD_STATUS.PENDING,
|
||||||
|
percent: 0,
|
||||||
|
uid: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
const file2: UploadFileItem = {
|
||||||
|
url: 'file://temp/image2.png',
|
||||||
|
status: UPLOAD_STATUS.PENDING,
|
||||||
|
percent: 0,
|
||||||
|
uid: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
await startUpload(file1, {
|
||||||
|
action: 'https://api.example.com/success',
|
||||||
|
abortPrevious: true
|
||||||
|
})
|
||||||
|
|
||||||
|
await startUpload(file2, {
|
||||||
|
action: 'https://api.example.com/success',
|
||||||
|
abortPrevious: true
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(mockUploadTask.abort).toHaveBeenCalledTimes(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 测试请求头和表单数据的传递
|
||||||
|
it('should pass custom headers and formData', () => {
|
||||||
|
const file: UploadFileItem = {
|
||||||
|
url: 'file://temp/image.png',
|
||||||
|
status: UPLOAD_STATUS.PENDING,
|
||||||
|
percent: 0,
|
||||||
|
uid: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
const customHeaders = { 'X-Custom-Header': 'test' }
|
||||||
|
const customFormData = { field: 'value' }
|
||||||
|
|
||||||
|
startUpload(file, {
|
||||||
|
action: 'https://api.example.com/success',
|
||||||
|
header: customHeaders,
|
||||||
|
formData: customFormData
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(uni.uploadFile).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
header: customHeaders,
|
||||||
|
formData: customFormData
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 测试特定文件类型上传
|
||||||
|
it('should handle specific file types', () => {
|
||||||
|
const file: UploadFileItem = {
|
||||||
|
url: 'file://temp/video.mp4',
|
||||||
|
status: UPLOAD_STATUS.PENDING,
|
||||||
|
percent: 0,
|
||||||
|
uid: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
startUpload(file, {
|
||||||
|
action: 'https://api.example.com/success',
|
||||||
|
fileType: 'video'
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(uni.uploadFile).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
fileType: 'video'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 测试自定义状态码
|
||||||
|
it('should handle custom status code', async () => {
|
||||||
|
const file: UploadFileItem = {
|
||||||
|
url: 'file://temp/image.png',
|
||||||
|
status: UPLOAD_STATUS.PENDING,
|
||||||
|
percent: 0,
|
||||||
|
uid: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
const onSuccess = jest.fn()
|
||||||
|
const onError = jest.fn()
|
||||||
|
|
||||||
|
await startUpload(file, {
|
||||||
|
action: 'https://api.example.com/success',
|
||||||
|
statusCode: 201,
|
||||||
|
onSuccess,
|
||||||
|
onError
|
||||||
|
})
|
||||||
|
|
||||||
|
// 由于mock返回200,使用201作为成功状态码应该触发错误回调
|
||||||
|
expect(onError).toHaveBeenCalled()
|
||||||
|
expect(onSuccess).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 测试自定义状态字段
|
||||||
|
it('should use custom status key', async () => {
|
||||||
|
const file: UploadFileItem = {
|
||||||
|
url: 'file://temp/image.png',
|
||||||
|
customStatus: UPLOAD_STATUS.PENDING,
|
||||||
|
percent: 0,
|
||||||
|
uid: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
await startUpload(file, {
|
||||||
|
action: 'https://api.example.com/success',
|
||||||
|
statusKey: 'customStatus'
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(file.customStatus).toBe(UPLOAD_STATUS.SUCCESS)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 测试具体任务的中断
|
||||||
|
it('should abort specific upload task', () => {
|
||||||
|
const file: UploadFileItem = {
|
||||||
|
url: 'file://temp/image.png',
|
||||||
|
status: UPLOAD_STATUS.PENDING,
|
||||||
|
percent: 0,
|
||||||
|
uid: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
const task = startUpload(file, {
|
||||||
|
action: 'https://api.example.com/success'
|
||||||
|
})
|
||||||
|
|
||||||
|
abort(task as UniApp.UploadTask)
|
||||||
|
expect(mockUploadTask.abort).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 测试进度回调的详细信息
|
||||||
|
it('should provide detailed progress information', () => {
|
||||||
|
const file: UploadFileItem = {
|
||||||
|
url: 'file://temp/image.png',
|
||||||
|
status: UPLOAD_STATUS.PENDING,
|
||||||
|
percent: 0,
|
||||||
|
uid: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
const onProgress = jest.fn()
|
||||||
|
|
||||||
|
mockUploadTask.onProgressUpdate = jest.fn((callback) => {
|
||||||
|
callback({
|
||||||
|
progress: 50,
|
||||||
|
totalBytesSent: 5000,
|
||||||
|
totalBytesExpectedToSend: 10000
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
startUpload(file, {
|
||||||
|
action: 'https://api.example.com/success',
|
||||||
|
onProgress
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(onProgress).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
progress: 50,
|
||||||
|
totalBytesSent: 5000,
|
||||||
|
totalBytesExpectedToSend: 10000
|
||||||
|
}),
|
||||||
|
file
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
57
tests/setup.js
Normal file
57
tests/setup.js
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* @Author: weisheng
|
||||||
|
* @Date: 2025-03-24 13:52:28
|
||||||
|
* @LastEditTime: 2025-03-24 14:05:48
|
||||||
|
* @LastEditors: weisheng
|
||||||
|
* @Description:
|
||||||
|
* @FilePath: /wot-design-uni/tests/setup.js
|
||||||
|
* 记得注释
|
||||||
|
*/
|
||||||
|
import { config } from '@vue/test-utils'
|
||||||
|
import { defineComponent } from 'vue'
|
||||||
|
|
||||||
|
// 创建通用的 uni 组件 mock
|
||||||
|
const createUniBehavior = () => {
|
||||||
|
return defineComponent({
|
||||||
|
template: '<div class="uni-mock"><slot /></div>',
|
||||||
|
props: ['modelValue'],
|
||||||
|
emits: ['update:modelValue', 'input', 'change']
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 配置全局组件
|
||||||
|
config.global.components = {
|
||||||
|
'uni-table': createUniBehavior(),
|
||||||
|
'uni-tr': createUniBehavior(),
|
||||||
|
'uni-td': createUniBehavior()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 配置 Vue Test Utils
|
||||||
|
config.global.mocks = {
|
||||||
|
$t: (key) => key
|
||||||
|
// 添加其他全局属性
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mock uni-app global API
|
||||||
|
global.uni = {
|
||||||
|
uploadFile: jest.fn(),
|
||||||
|
showToast: jest.fn(),
|
||||||
|
showModal: jest.fn()
|
||||||
|
// 添加其他需要的 uni API
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加 Vue 编译器配置
|
||||||
|
global.__VUE_OPTIONS_API__ = true
|
||||||
|
global.__VUE_PROD_DEVTOOLS__ = false
|
||||||
|
|
||||||
|
// Mock import.meta
|
||||||
|
global.import = {
|
||||||
|
meta: {
|
||||||
|
glob: () => ({})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mock window
|
||||||
|
global.window = {
|
||||||
|
// Add any window properties needed
|
||||||
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extends": "@vue/tsconfig/tsconfig.json",
|
"extends": "@vue/tsconfig/tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"verbatimModuleSyntax":true,
|
"verbatimModuleSyntax": false,
|
||||||
"ignoreDeprecations": "5.0",
|
"ignoreDeprecations": "5.0",
|
||||||
"lib": [
|
"lib": [
|
||||||
"ESNext",
|
"ESNext",
|
||||||
@ -19,9 +19,11 @@
|
|||||||
"@dcloudio/types",
|
"@dcloudio/types",
|
||||||
"mini-types",
|
"mini-types",
|
||||||
"@uni-helper/uni-types",
|
"@uni-helper/uni-types",
|
||||||
"miniprogram-api-typings"
|
"miniprogram-api-typings",
|
||||||
|
"jest"
|
||||||
],
|
],
|
||||||
"sourceMap": true
|
"sourceMap": true,
|
||||||
|
"module": "ESNext"
|
||||||
},
|
},
|
||||||
"vueCompilerOptions": {
|
"vueCompilerOptions": {
|
||||||
"plugins": [
|
"plugins": [
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user