useCheckin.test.js 5.23 KB
import { describe, expect, it, vi, beforeEach } from 'vitest'

vi.mock('vue-router', () => {
    const router = {
        push: vi.fn(),
        back: vi.fn()
    }
    return {
        useRoute: () => ({
            query: {}
        }),
        useRouter: () => router
    }
})

vi.mock('vant', () => {
    return {
        showToast: vi.fn(),
        showLoadingToast: vi.fn(() => ({ close: vi.fn() }))
    }
})

vi.mock('@/api/common', () => {
    return {
        qiniuTokenAPI: vi.fn(),
        qiniuUploadAPI: vi.fn(),
        saveFileAPI: vi.fn()
    }
})

vi.mock('@/api/checkin', () => {
    return {
        addUploadTaskAPI: vi.fn(),
        getUploadTaskInfoAPI: vi.fn(),
        editUploadTaskInfoAPI: vi.fn()
    }
})

vi.mock('@/utils/qiniuFileHash', () => {
    return {
        qiniuFileHash: vi.fn(async () => 'hash')
    }
})

vi.mock('@/contexts/auth', async () => {
    const { ref } = await import('vue')
    return {
        useAuth: () => ({
            currentUser: ref({ mobile: '18800001111' })
        })
    }
})

import { useCheckin } from '../useCheckin'
import { showToast } from 'vant'
import { addUploadTaskAPI } from '@/api/checkin'

describe('useCheckin 上传大小限制', () => {
    beforeEach(() => {
        vi.clearAllMocks()
        if (!globalThis.sessionStorage) {
            let store = {}
            globalThis.sessionStorage = {
                getItem: (key) => store[key] ?? null,
                setItem: (key, value) => { store[key] = String(value) },
                removeItem: (key) => { delete store[key] },
                clear: () => { store = {} },
            }
        } else {
            sessionStorage.clear()
        }
    })

    it('setMaxFileSizeMbMap 能更新并保留其他类型默认值', () => {
        const { activeType, maxFileSizeMb, setMaxFileSizeMbMap } = useCheckin()

        activeType.value = 'image'
        expect(maxFileSizeMb.value).toBe(20)

        setMaxFileSizeMbMap({ image: 500 })
        expect(maxFileSizeMb.value).toBe(500)

        activeType.value = 'video'
        expect(maxFileSizeMb.value).toBe(20)
    })

    it('setMaxFileSizeMbMap 会忽略非法值', () => {
        const { activeType, maxFileSizeMb, setMaxFileSizeMbMap } = useCheckin()

        activeType.value = 'audio'
        setMaxFileSizeMbMap({ audio: 0 })
        expect(maxFileSizeMb.value).toBe(20)

        setMaxFileSizeMbMap({ audio: -10 })
        expect(maxFileSizeMb.value).toBe(20)

        setMaxFileSizeMbMap({ audio: 'not_a_number' })
        expect(maxFileSizeMb.value).toBe(20)

        setMaxFileSizeMbMap({ audio: 300 })
        expect(maxFileSizeMb.value).toBe(300)
    })

    it('beforeRead 超过动态大小会拦截并提示', () => {
        const { activeType, beforeRead, setMaxFileSizeMbMap } = useCheckin()

        activeType.value = 'image'
        setMaxFileSizeMbMap({ image: 1 })

        const ok = beforeRead({
            type: 'image/jpeg',
            size: 2 * 1024 * 1024
        })

        expect(ok).toBe(false)
        expect(showToast).toHaveBeenCalled()
        expect(String(showToast.mock.calls[0][0])).toContain('最大文件体积为1MB')
    })

    it('beforeRead 图片类型校验失败会拦截', () => {
        const { activeType, beforeRead, setMaxFileSizeMbMap } = useCheckin()

        activeType.value = 'image'
        setMaxFileSizeMbMap({ image: 10 })

        const ok = beforeRead({
            type: 'application/pdf',
            size: 1 * 1024 * 1024
        })

        expect(ok).toBe(false)
        expect(showToast).toHaveBeenCalled()
    })
})

describe('useCheckin 提交兼容', () => {
    beforeEach(() => {
        vi.clearAllMocks()
        if (globalThis.sessionStorage?.clear) sessionStorage.clear()
    })

    it('新结构失败会回退旧结构提交', async () => {
        addUploadTaskAPI
            .mockResolvedValueOnce({ code: 0, msg: '参数错误' })
            .mockResolvedValueOnce({ code: 1, data: { id: 1 } })

        const { activeType, fileList, message, onSubmit } = useCheckin()

        activeType.value = 'audio'
        message.value = '随便写点内容'
        fileList.value = [
            { status: 'done', meta_id: 11, file_type: 'audio' }
        ]

        await onSubmit({ subtask_id: 's1' })

        expect(addUploadTaskAPI).toHaveBeenCalledTimes(2)
        expect(addUploadTaskAPI.mock.calls[0][0]).toHaveProperty('files')
        expect(addUploadTaskAPI.mock.calls[1][0]).toHaveProperty('meta_id')
        expect(addUploadTaskAPI.mock.calls[1][0]).not.toHaveProperty('files')
        expect(showToast).toHaveBeenCalledWith('提交成功')
    })

    it('混合附件且新结构失败时会提示分别提交', async () => {
        addUploadTaskAPI.mockResolvedValueOnce({ code: 0, msg: '参数错误' })

        const { activeType, fileList, message, onSubmit } = useCheckin()

        activeType.value = 'image'
        message.value = '随便写点内容'
        fileList.value = [
            { status: 'done', meta_id: 11, file_type: 'image' },
            { status: 'done', meta_id: 12, file_type: 'audio' },
        ]

        await onSubmit({ subtask_id: 's1' })

        expect(addUploadTaskAPI).toHaveBeenCalledTimes(1)
        expect(showToast).toHaveBeenCalledWith('当前接口暂不支持多类型附件,请分别提交')
    })
})