mirror of
https://gitee.com/wot-design-uni/wot-design-uni.git
synced 2025-12-07 17:48:34 +08:00
refactor: ♻️ useUpload 添加选择文件的api (#976)
This commit is contained in:
parent
1876fc3d0c
commit
d23b2bf2c8
@ -1,13 +1,20 @@
|
|||||||
# useUpload
|
# useUpload
|
||||||
|
|
||||||
用于处理文件上传相关的逻辑。
|
用于处理文件上传和选择相关的逻辑。
|
||||||
|
|
||||||
## 基础用法
|
## 基础用法
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { useUpload } from '@/uni_modules/wot-design-uni'
|
import { useUpload } from '@/uni_modules/wot-design-uni'
|
||||||
|
|
||||||
const { startUpload, abort, UPLOAD_STATUS } = useUpload()
|
const { startUpload, abort, chooseFile, UPLOAD_STATUS } = useUpload()
|
||||||
|
|
||||||
|
// 选择文件
|
||||||
|
const files = await chooseFile({
|
||||||
|
accept: 'image',
|
||||||
|
multiple: true,
|
||||||
|
maxCount: 9
|
||||||
|
})
|
||||||
|
|
||||||
// 开始上传
|
// 开始上传
|
||||||
const file = {
|
const file = {
|
||||||
@ -41,6 +48,7 @@ abort()
|
|||||||
|-------|------|------|--------|
|
|-------|------|------|--------|
|
||||||
| startUpload | 开始上传文件 | file: UploadFileItem, options: UseUploadOptions | UniApp.UploadTask \| void |
|
| startUpload | 开始上传文件 | file: UploadFileItem, options: UseUploadOptions | UniApp.UploadTask \| void |
|
||||||
| abort | 中断上传 | task?: UniApp.UploadTask | void |
|
| abort | 中断上传 | task?: UniApp.UploadTask | void |
|
||||||
|
| chooseFile | 选择文件 | options: ChooseFileOption | Promise<ChooseFile[]> |
|
||||||
|
|
||||||
### UseUploadOptions
|
### UseUploadOptions
|
||||||
|
|
||||||
@ -56,3 +64,16 @@ abort()
|
|||||||
| onSuccess | 上传成功回调 | Function | - |
|
| onSuccess | 上传成功回调 | Function | - |
|
||||||
| onError | 上传失败回调 | Function | - |
|
| onError | 上传失败回调 | Function | - |
|
||||||
| onProgress | 上传进度回调 | Function | - |
|
| onProgress | 上传进度回调 | Function | - |
|
||||||
|
|
||||||
|
### ChooseFileOption
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 |
|
||||||
|
|-----|------|------|--------|
|
||||||
|
| multiple | 是否支持多选文件 | boolean | false |
|
||||||
|
| sizeType | 所选的图片的尺寸 | Array | ['original', 'compressed'] |
|
||||||
|
| sourceType | 选择文件的来源 | Array | ['album', 'camera'] |
|
||||||
|
| maxCount | 最大可选数量 | number | 9 |
|
||||||
|
| accept | 接受的文件类型 | 'image' \| 'video' \| 'media' \| 'file' \| 'all' | 'image' |
|
||||||
|
| compressed | 是否压缩视频 | boolean | true |
|
||||||
|
| maxDuration | 视频最大时长(秒) | number | 60 |
|
||||||
|
| camera | 摄像头朝向 | 'back' \| 'front' | 'back' |
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* @Author: weisheng
|
* @Author: weisheng
|
||||||
* @Date: 2025-03-24 12:33:15
|
* @Date: 2025-03-24 12:33:15
|
||||||
* @LastEditTime: 2025-03-24 22:02:51
|
* @LastEditTime: 2025-03-26 13:29:54
|
||||||
* @LastEditors: weisheng
|
* @LastEditors: weisheng
|
||||||
* @Description:
|
* @Description:
|
||||||
* @FilePath: /wot-design-uni/jest.config.js
|
* @FilePath: /wot-design-uni/jest.config.js
|
||||||
@ -21,6 +21,16 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
testRegex: '(/tests/.*\\.spec)\\.(jsx?|tsx?)$', // 只匹配 .spec 结尾的文件
|
testRegex: '(/tests/.*\\.spec)\\.(jsx?|tsx?)$', // 只匹配 .spec 结尾的文件
|
||||||
testPathIgnorePatterns: ['/node_modules/', '/tests/setup.js', '/tests/__mocks__/'],
|
testPathIgnorePatterns: ['/node_modules/', '/tests/setup.js', '/tests/__mocks__/'],
|
||||||
|
|
||||||
|
// 添加 modulePathIgnorePatterns 配置,忽略 uni_modules 下的 package.json
|
||||||
|
modulePathIgnorePatterns: ['<rootDir>/src/uni_modules/.*', '<rootDir>/src/uni_modules/wot-design-uni/package.json'],
|
||||||
|
|
||||||
|
// 或者使用 watchPathIgnorePatterns
|
||||||
|
watchPathIgnorePatterns: ['<rootDir>/src/uni_modules/'],
|
||||||
|
|
||||||
|
// 增加全局超时时间设置
|
||||||
|
testTimeout: 10000, // 设置为10秒
|
||||||
|
|
||||||
globals: {
|
globals: {
|
||||||
'vue-jest': {
|
'vue-jest': {
|
||||||
compilerOptions: {
|
compilerOptions: {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { isFunction } from '../common/util'
|
import { isArray, isDef, isFunction } from '../common/util'
|
||||||
import type { UploadFileItem, UploadMethod, UploadStatusType } from '../wd-upload/types'
|
import type { ChooseFile, ChooseFileOption, UploadFileItem, UploadMethod, UploadStatusType } from '../wd-upload/types'
|
||||||
|
|
||||||
export const UPLOAD_STATUS: Record<string, UploadStatusType> = {
|
export const UPLOAD_STATUS: Record<string, UploadStatusType> = {
|
||||||
PENDING: 'pending',
|
PENDING: 'pending',
|
||||||
@ -15,6 +15,8 @@ export interface UseUploadReturn {
|
|||||||
abort: (task?: UniApp.UploadTask) => void
|
abort: (task?: UniApp.UploadTask) => void
|
||||||
// 上传状态常量
|
// 上传状态常量
|
||||||
UPLOAD_STATUS: Record<string, UploadStatusType>
|
UPLOAD_STATUS: Record<string, UploadStatusType>
|
||||||
|
// 选择文件
|
||||||
|
chooseFile: (options: ChooseFileOption) => Promise<ChooseFile[]>
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UseUploadOptions {
|
export interface UseUploadOptions {
|
||||||
@ -155,9 +157,155 @@ export function useUpload(): UseUploadReturn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化图片信息
|
||||||
|
*/
|
||||||
|
function formatImage(res: UniApp.ChooseImageSuccessCallbackResult): ChooseFile[] {
|
||||||
|
// #ifdef MP-DINGTALK
|
||||||
|
// 钉钉文件在files中
|
||||||
|
res.tempFiles = isDef((res as any).files) ? (res as any).files : res.tempFiles
|
||||||
|
// #endif
|
||||||
|
if (isArray(res.tempFiles)) {
|
||||||
|
return res.tempFiles.map((item: any) => ({
|
||||||
|
path: item.path || '',
|
||||||
|
name: item.name || '',
|
||||||
|
size: item.size,
|
||||||
|
type: 'image',
|
||||||
|
thumb: item.path || ''
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
path: (res.tempFiles as any).path || '',
|
||||||
|
name: (res.tempFiles as any).name || '',
|
||||||
|
size: (res.tempFiles as any).size,
|
||||||
|
type: 'image',
|
||||||
|
thumb: (res.tempFiles as any).path || ''
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化视频信息
|
||||||
|
*/
|
||||||
|
function formatVideo(res: UniApp.ChooseVideoSuccess): ChooseFile[] {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
path: res.tempFilePath || (res as any).filePath || '',
|
||||||
|
name: res.name || '',
|
||||||
|
size: res.size,
|
||||||
|
type: 'video',
|
||||||
|
thumb: (res as any).thumbTempFilePath || '',
|
||||||
|
duration: res.duration
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化媒体信息
|
||||||
|
*/
|
||||||
|
function formatMedia(res: UniApp.ChooseMediaSuccessCallbackResult): ChooseFile[] {
|
||||||
|
return res.tempFiles.map((item) => ({
|
||||||
|
type: item.fileType,
|
||||||
|
path: item.tempFilePath,
|
||||||
|
thumb: item.fileType === 'video' ? item.thumbTempFilePath : item.tempFilePath,
|
||||||
|
size: item.size,
|
||||||
|
duration: item.duration
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选择文件
|
||||||
|
*/
|
||||||
|
function chooseFile({
|
||||||
|
multiple,
|
||||||
|
sizeType,
|
||||||
|
sourceType,
|
||||||
|
maxCount,
|
||||||
|
accept,
|
||||||
|
compressed,
|
||||||
|
maxDuration,
|
||||||
|
camera
|
||||||
|
}: ChooseFileOption): Promise<ChooseFile[]> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
switch (accept) {
|
||||||
|
case 'image':
|
||||||
|
uni.chooseImage({
|
||||||
|
count: multiple ? Math.min(maxCount, 9) : 1,
|
||||||
|
sizeType,
|
||||||
|
sourceType,
|
||||||
|
success: (res) => resolve(formatImage(res)),
|
||||||
|
fail: reject
|
||||||
|
})
|
||||||
|
break
|
||||||
|
case 'video':
|
||||||
|
uni.chooseVideo({
|
||||||
|
sourceType,
|
||||||
|
compressed,
|
||||||
|
maxDuration,
|
||||||
|
camera,
|
||||||
|
success: (res) => resolve(formatVideo(res)),
|
||||||
|
fail: reject
|
||||||
|
})
|
||||||
|
break
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
case 'media':
|
||||||
|
uni.chooseMedia({
|
||||||
|
count: multiple ? Math.min(maxCount, 9) : 1,
|
||||||
|
sourceType,
|
||||||
|
sizeType,
|
||||||
|
camera,
|
||||||
|
maxDuration,
|
||||||
|
success: (res) => resolve(formatMedia(res)),
|
||||||
|
fail: reject
|
||||||
|
})
|
||||||
|
break
|
||||||
|
case 'file':
|
||||||
|
uni.chooseMessageFile({
|
||||||
|
count: multiple ? Math.min(maxCount, 100) : 1,
|
||||||
|
type: accept,
|
||||||
|
success: (res) => resolve(res.tempFiles),
|
||||||
|
fail: reject
|
||||||
|
})
|
||||||
|
break
|
||||||
|
// #endif
|
||||||
|
case 'all':
|
||||||
|
// #ifdef H5
|
||||||
|
uni.chooseFile({
|
||||||
|
count: multiple ? Math.min(maxCount, 100) : 1,
|
||||||
|
type: accept,
|
||||||
|
success: (res) => resolve(res.tempFiles as ChooseFile[]),
|
||||||
|
fail: reject
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
uni.chooseMessageFile({
|
||||||
|
count: multiple ? Math.min(maxCount, 100) : 1,
|
||||||
|
type: accept,
|
||||||
|
success: (res) => resolve(res.tempFiles),
|
||||||
|
fail: reject
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
// 默认选择图片
|
||||||
|
uni.chooseImage({
|
||||||
|
count: multiple ? Math.min(maxCount, 9) : 1,
|
||||||
|
sizeType,
|
||||||
|
sourceType,
|
||||||
|
success: (res) => resolve(formatImage(res)),
|
||||||
|
fail: reject
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
startUpload,
|
startUpload,
|
||||||
abort,
|
abort,
|
||||||
UPLOAD_STATUS
|
UPLOAD_STATUS,
|
||||||
|
chooseFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,152 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: weisheng
|
|
||||||
* @Date: 2024-03-18 22:36:44
|
|
||||||
* @LastEditTime: 2024-12-07 18:08:48
|
|
||||||
* @LastEditors: weisheng
|
|
||||||
* @Description:
|
|
||||||
* @FilePath: /wot-design-uni/src/uni_modules/wot-design-uni/components/wd-upload/utils.ts
|
|
||||||
* 记得注释
|
|
||||||
*/
|
|
||||||
import { isArray, isDef } from '../common/util'
|
|
||||||
import type { ChooseFile, ChooseFileOption } from './types'
|
|
||||||
|
|
||||||
function formatImage(res: UniApp.ChooseImageSuccessCallbackResult): ChooseFile[] {
|
|
||||||
// #ifdef MP-DINGTALK
|
|
||||||
// 钉钉文件在files中
|
|
||||||
res.tempFiles = isDef((res as any).files) ? (res as any).files : res.tempFiles
|
|
||||||
// #endif
|
|
||||||
if (isArray(res.tempFiles)) {
|
|
||||||
const result: ChooseFile[] = []
|
|
||||||
res.tempFiles.forEach(async (item: any) => {
|
|
||||||
result.push({
|
|
||||||
path: item.path || '',
|
|
||||||
name: item.name || '',
|
|
||||||
size: item.size,
|
|
||||||
type: 'image',
|
|
||||||
thumb: item.path || ''
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return result
|
|
||||||
} else {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
path: (res.tempFiles as any).path || '',
|
|
||||||
name: (res.tempFiles as any).name || '',
|
|
||||||
size: (res.tempFiles as any).size,
|
|
||||||
type: 'image',
|
|
||||||
thumb: (res.tempFiles as any).path || ''
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatVideo(res: UniApp.ChooseVideoSuccess): ChooseFile[] {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
path: res.tempFilePath || (res as any).filePath || '',
|
|
||||||
name: res.name || '',
|
|
||||||
size: res.size,
|
|
||||||
type: 'video',
|
|
||||||
thumb: (res as any).thumbTempFilePath || '',
|
|
||||||
duration: res.duration
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatMedia(res: UniApp.ChooseMediaSuccessCallbackResult): ChooseFile[] {
|
|
||||||
return res.tempFiles.map((item) => ({
|
|
||||||
type: item.fileType,
|
|
||||||
path: item.tempFilePath,
|
|
||||||
thumb: item.fileType === 'video' ? item.thumbTempFilePath : item.tempFilePath,
|
|
||||||
size: item.size,
|
|
||||||
duration: item.duration
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
export function chooseFile({
|
|
||||||
multiple,
|
|
||||||
sizeType,
|
|
||||||
sourceType,
|
|
||||||
maxCount,
|
|
||||||
accept,
|
|
||||||
compressed,
|
|
||||||
maxDuration,
|
|
||||||
camera
|
|
||||||
}: ChooseFileOption): Promise<ChooseFile[]> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
switch (accept) {
|
|
||||||
case 'image':
|
|
||||||
uni.chooseImage({
|
|
||||||
count: multiple ? Math.min(maxCount, 9) : 1, // 最多可以选择的数量,如果不支持多选则数量为1
|
|
||||||
sizeType,
|
|
||||||
sourceType,
|
|
||||||
success: (res) => resolve(formatImage(res)),
|
|
||||||
fail: (error) => {
|
|
||||||
reject(error)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
break
|
|
||||||
case 'video':
|
|
||||||
uni.chooseVideo({
|
|
||||||
sourceType,
|
|
||||||
compressed,
|
|
||||||
maxDuration,
|
|
||||||
camera,
|
|
||||||
success: (res) => {
|
|
||||||
resolve(formatVideo(res))
|
|
||||||
},
|
|
||||||
fail: reject
|
|
||||||
})
|
|
||||||
|
|
||||||
break
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
case 'media':
|
|
||||||
uni.chooseMedia({
|
|
||||||
count: multiple ? Math.min(maxCount, 9) : 1,
|
|
||||||
sourceType,
|
|
||||||
sizeType,
|
|
||||||
camera,
|
|
||||||
maxDuration,
|
|
||||||
success: (res) => resolve(formatMedia(res)),
|
|
||||||
fail: reject
|
|
||||||
})
|
|
||||||
break
|
|
||||||
case 'file':
|
|
||||||
uni.chooseMessageFile({
|
|
||||||
count: multiple ? Math.min(maxCount, 100) : 1,
|
|
||||||
type: accept,
|
|
||||||
success: (res) => resolve(res.tempFiles),
|
|
||||||
fail: reject
|
|
||||||
})
|
|
||||||
break
|
|
||||||
// #endif
|
|
||||||
case 'all':
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
uni.chooseMessageFile({
|
|
||||||
count: multiple ? Math.min(maxCount, 100) : 1,
|
|
||||||
type: accept,
|
|
||||||
success: (res) => resolve(res.tempFiles),
|
|
||||||
fail: reject
|
|
||||||
})
|
|
||||||
// #endif
|
|
||||||
// #ifdef H5
|
|
||||||
uni.chooseFile({
|
|
||||||
count: multiple ? Math.min(maxCount, 100) : 1,
|
|
||||||
type: accept,
|
|
||||||
success: (res) => resolve(res.tempFiles as ChooseFile[]),
|
|
||||||
fail: reject
|
|
||||||
})
|
|
||||||
// #endif
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
// 默认选择图片
|
|
||||||
uni.chooseImage({
|
|
||||||
count: multiple ? Math.min(maxCount, 9) : 1, // 最多可以选择的数量,如果不支持多选则数量为1
|
|
||||||
sizeType,
|
|
||||||
sourceType,
|
|
||||||
success: (res) => resolve(formatImage(res)),
|
|
||||||
fail: reject
|
|
||||||
})
|
|
||||||
break
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@ -102,7 +102,6 @@ import wdLoading from '../wd-loading/wd-loading.vue'
|
|||||||
|
|
||||||
import { computed, ref, watch } from 'vue'
|
import { computed, ref, watch } from 'vue'
|
||||||
import { context, isEqual, isImageUrl, isVideoUrl, isFunction, isDef, deepClone } from '../common/util'
|
import { context, isEqual, isImageUrl, isVideoUrl, isFunction, isDef, deepClone } from '../common/util'
|
||||||
import { chooseFile } from './utils'
|
|
||||||
import { useTranslate } from '../composables/useTranslate'
|
import { useTranslate } from '../composables/useTranslate'
|
||||||
import { useUpload } from '../composables/useUpload'
|
import { useUpload } from '../composables/useUpload'
|
||||||
import {
|
import {
|
||||||
@ -146,7 +145,7 @@ const showUpload = computed(() => !props.limit || uploadFiles.value.length < pro
|
|||||||
|
|
||||||
const videoPreview = ref<VideoPreviewInstance>()
|
const videoPreview = ref<VideoPreviewInstance>()
|
||||||
|
|
||||||
const { startUpload, abort, UPLOAD_STATUS } = useUpload()
|
const { startUpload, abort, chooseFile, UPLOAD_STATUS } = useUpload()
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.fileList,
|
() => props.fileList,
|
||||||
@ -411,7 +410,7 @@ function handleProgress(res: UniApp.OnProgressUpdateResult, file: UploadFileItem
|
|||||||
*/
|
*/
|
||||||
function onChooseFile(currentIndex?: number) {
|
function onChooseFile(currentIndex?: number) {
|
||||||
const { multiple, maxSize, accept, sizeType, limit, sourceType, compressed, maxDuration, camera, beforeUpload } = props
|
const { multiple, maxSize, accept, sizeType, limit, sourceType, compressed, maxDuration, camera, beforeUpload } = props
|
||||||
// 文件选择
|
|
||||||
chooseFile({
|
chooseFile({
|
||||||
multiple,
|
multiple,
|
||||||
sizeType,
|
sizeType,
|
||||||
|
|||||||
@ -22,7 +22,7 @@ const mockUploadTask = {
|
|||||||
} as any
|
} as any
|
||||||
|
|
||||||
describe('useUpload', () => {
|
describe('useUpload', () => {
|
||||||
const { startUpload, abort, UPLOAD_STATUS } = useUpload()
|
const { startUpload, abort, chooseFile, UPLOAD_STATUS } = useUpload()
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
@ -284,4 +284,280 @@ describe('useUpload', () => {
|
|||||||
file
|
file
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 测试选择图片文件
|
||||||
|
it('should choose image files', async () => {
|
||||||
|
const mockChooseImage = jest.fn().mockImplementation((options) => {
|
||||||
|
options.success({
|
||||||
|
tempFiles: [
|
||||||
|
{ path: 'temp/image1.jpg', size: 1024, name: 'image1.jpg' },
|
||||||
|
{ path: 'temp/image2.jpg', size: 2048, name: 'image2.jpg' }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
;(global as any).uni.chooseImage = mockChooseImage
|
||||||
|
|
||||||
|
const files = await chooseFile({
|
||||||
|
accept: 'image',
|
||||||
|
multiple: true,
|
||||||
|
maxCount: 9,
|
||||||
|
sizeType: ['original', 'compressed'],
|
||||||
|
sourceType: ['album', 'camera'],
|
||||||
|
compressed: true,
|
||||||
|
maxDuration: 60,
|
||||||
|
camera: 'back'
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(files).toHaveLength(2)
|
||||||
|
expect(files[0]).toEqual({
|
||||||
|
path: 'temp/image1.jpg',
|
||||||
|
size: 1024,
|
||||||
|
name: 'image1.jpg',
|
||||||
|
type: 'image',
|
||||||
|
thumb: 'temp/image1.jpg'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// 测试选择视频文件
|
||||||
|
it('should choose video file', async () => {
|
||||||
|
const mockChooseVideo = jest.fn().mockImplementation((options) => {
|
||||||
|
options.success({
|
||||||
|
tempFilePath: 'temp/video.mp4',
|
||||||
|
size: 10240,
|
||||||
|
duration: 15,
|
||||||
|
thumbTempFilePath: 'temp/thumb.jpg',
|
||||||
|
name: 'video.mp4'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
;(global as any).uni.chooseVideo = mockChooseVideo
|
||||||
|
|
||||||
|
const files = await chooseFile({
|
||||||
|
accept: 'video',
|
||||||
|
multiple: false,
|
||||||
|
maxCount: 1,
|
||||||
|
sizeType: ['original', 'compressed'],
|
||||||
|
sourceType: ['album', 'camera'],
|
||||||
|
compressed: true,
|
||||||
|
maxDuration: 60,
|
||||||
|
camera: 'back'
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(files).toHaveLength(1)
|
||||||
|
expect(files[0]).toEqual({
|
||||||
|
path: 'temp/video.mp4',
|
||||||
|
size: 10240,
|
||||||
|
name: 'video.mp4',
|
||||||
|
type: 'video',
|
||||||
|
thumb: 'temp/thumb.jpg',
|
||||||
|
duration: 15
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// 测试选择媒体文件
|
||||||
|
it('should choose media files', async () => {
|
||||||
|
const mockChooseMedia = jest.fn().mockImplementation((options) => {
|
||||||
|
options.success({
|
||||||
|
tempFiles: [
|
||||||
|
{
|
||||||
|
fileType: 'image',
|
||||||
|
tempFilePath: 'temp/image.jpg',
|
||||||
|
size: 1024,
|
||||||
|
duration: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fileType: 'video',
|
||||||
|
tempFilePath: 'temp/video.mp4',
|
||||||
|
thumbTempFilePath: 'temp/thumb.jpg',
|
||||||
|
size: 10240,
|
||||||
|
duration: 15
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
;(global as any).uni.chooseMedia = mockChooseMedia
|
||||||
|
|
||||||
|
const files = await chooseFile({
|
||||||
|
accept: 'media',
|
||||||
|
multiple: true,
|
||||||
|
maxCount: 9,
|
||||||
|
sizeType: ['original', 'compressed'],
|
||||||
|
sourceType: ['album', 'camera'],
|
||||||
|
compressed: true,
|
||||||
|
maxDuration: 60,
|
||||||
|
camera: 'back'
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(files).toHaveLength(2)
|
||||||
|
expect(files[1]).toEqual({
|
||||||
|
type: 'video',
|
||||||
|
path: 'temp/video.mp4',
|
||||||
|
thumb: 'temp/thumb.jpg',
|
||||||
|
size: 10240,
|
||||||
|
duration: 15
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// 测试选择文件失败的情况
|
||||||
|
it('should handle choose file failure', async () => {
|
||||||
|
const mockChooseImage = jest.fn().mockImplementation((options) => {
|
||||||
|
options.fail(new Error('Permission denied'))
|
||||||
|
})
|
||||||
|
;(global as any).uni.chooseImage = mockChooseImage
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
chooseFile({
|
||||||
|
accept: 'image',
|
||||||
|
multiple: false,
|
||||||
|
maxCount: 1,
|
||||||
|
sizeType: ['original', 'compressed'],
|
||||||
|
sourceType: ['album', 'camera'],
|
||||||
|
compressed: true,
|
||||||
|
maxDuration: 60,
|
||||||
|
camera: 'back'
|
||||||
|
})
|
||||||
|
).rejects.toThrow('Permission denied')
|
||||||
|
})
|
||||||
|
|
||||||
|
// 测试多选限制
|
||||||
|
it('should respect maxCount limit', async () => {
|
||||||
|
const mockChooseImage = jest.fn().mockImplementation((options) => {
|
||||||
|
options.success({
|
||||||
|
tempFiles: [{ path: 'temp/image1.jpg', size: 1024, name: 'image1.jpg' }]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
;(global as any).uni.chooseImage = mockChooseImage
|
||||||
|
|
||||||
|
await chooseFile({
|
||||||
|
accept: 'image',
|
||||||
|
multiple: true,
|
||||||
|
maxCount: 3,
|
||||||
|
sizeType: ['original', 'compressed'],
|
||||||
|
sourceType: ['album', 'camera'],
|
||||||
|
compressed: true,
|
||||||
|
maxDuration: 60,
|
||||||
|
camera: 'back'
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(mockChooseImage).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
count: 3,
|
||||||
|
sizeType: ['original', 'compressed'],
|
||||||
|
sourceType: ['album', 'camera']
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
// 确保异步操作完成
|
||||||
|
await new Promise((resolve) => setTimeout(resolve, 0))
|
||||||
|
})
|
||||||
|
|
||||||
|
// 测试文件来源限制
|
||||||
|
it('should respect sourceType option', async () => {
|
||||||
|
const mockChooseImage = jest.fn().mockImplementation((options) => {
|
||||||
|
// 立即调用 success 回调,返回测试数据
|
||||||
|
options.success({
|
||||||
|
tempFiles: [{ path: 'temp/image1.jpg', size: 1024, name: 'image1.jpg' }]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
;(global as any).uni.chooseImage = mockChooseImage
|
||||||
|
|
||||||
|
await chooseFile({
|
||||||
|
accept: 'image',
|
||||||
|
multiple: false,
|
||||||
|
maxCount: 1,
|
||||||
|
sizeType: ['original', 'compressed'],
|
||||||
|
sourceType: ['camera'],
|
||||||
|
compressed: true,
|
||||||
|
maxDuration: 60,
|
||||||
|
camera: 'back'
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(mockChooseImage).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
count: 1,
|
||||||
|
sizeType: ['original', 'compressed'],
|
||||||
|
sourceType: ['camera']
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
// 测试选择消息文件(仅微信小程序)
|
||||||
|
// it('should choose message file in WeChat MP', async () => {
|
||||||
|
// const mockChooseMessageFile = jest.fn().mockImplementation((options) => {
|
||||||
|
// options.success({
|
||||||
|
// tempFiles: [
|
||||||
|
// {
|
||||||
|
// path: 'temp/doc.pdf',
|
||||||
|
// size: 1024,
|
||||||
|
// name: 'doc.pdf',
|
||||||
|
// type: 'file'
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
// ;(global as any).uni.chooseMessageFile = mockChooseMessageFile
|
||||||
|
|
||||||
|
// const files = await chooseFile({
|
||||||
|
// accept: 'file',
|
||||||
|
// multiple: true,
|
||||||
|
// maxCount: 100,
|
||||||
|
// sizeType: ['original', 'compressed'],
|
||||||
|
// sourceType: ['album', 'camera'],
|
||||||
|
// compressed: true,
|
||||||
|
// maxDuration: 60,
|
||||||
|
// camera: 'back'
|
||||||
|
// })
|
||||||
|
|
||||||
|
// expect(mockChooseMessageFile).toHaveBeenCalledWith(
|
||||||
|
// expect.objectContaining({
|
||||||
|
// count: 100,
|
||||||
|
// type: 'file'
|
||||||
|
// })
|
||||||
|
// )
|
||||||
|
// expect(files[0]).toEqual({
|
||||||
|
// path: 'temp/doc.pdf',
|
||||||
|
// size: 1024,
|
||||||
|
// name: 'doc.pdf',
|
||||||
|
// type: 'file'
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
|
||||||
|
// 测试选择全部类型文件(H5)
|
||||||
|
it('should choose all type files in H5', async () => {
|
||||||
|
const mockChooseFile = jest.fn().mockImplementation((options) => {
|
||||||
|
options.success({
|
||||||
|
tempFiles: [
|
||||||
|
{
|
||||||
|
path: 'temp/file.txt',
|
||||||
|
size: 512,
|
||||||
|
name: 'file.txt'
|
||||||
|
// 移除 type 属性,因为 H5 的 chooseFile 返回的数据不包含 type
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
;(global as any).uni.chooseFile = mockChooseFile
|
||||||
|
|
||||||
|
const files = await chooseFile({
|
||||||
|
accept: 'all',
|
||||||
|
multiple: true,
|
||||||
|
maxCount: 100,
|
||||||
|
sizeType: ['original', 'compressed'],
|
||||||
|
sourceType: ['album', 'camera'],
|
||||||
|
compressed: true,
|
||||||
|
maxDuration: 60,
|
||||||
|
camera: 'back'
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(mockChooseFile).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
count: 100,
|
||||||
|
type: 'all'
|
||||||
|
})
|
||||||
|
)
|
||||||
|
expect(files[0]).toEqual({
|
||||||
|
path: 'temp/file.txt',
|
||||||
|
size: 512,
|
||||||
|
name: 'file.txt'
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user