78 lines
3.3 KiB
TypeScript
78 lines
3.3 KiB
TypeScript
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
import { projectAssetsApi } from '@/features/project-assets/api'
|
|
import type { ProjectAsset } from '@/features/project-assets/types'
|
|
|
|
const asset: ProjectAsset = {
|
|
id: 'asset-db-1',
|
|
projectId: 'project-db-1',
|
|
name: '雨夜街道',
|
|
type: 'image',
|
|
category: 'scene',
|
|
mimeType: 'image/png',
|
|
extension: 'png',
|
|
size: 2048,
|
|
publicUrl: '/storage/project/scene.png',
|
|
metadata: { originalName: 'scene.png' },
|
|
createdAt: '2026-09-21T00:00:00Z',
|
|
updatedAt: '2026-09-21T00:00:00Z'
|
|
}
|
|
|
|
afterEach(() => vi.unstubAllGlobals())
|
|
|
|
describe('项目资产 API', () => {
|
|
it('通过单个全局接口读取全部项目素材', async () => {
|
|
const globalAsset = {
|
|
...asset,
|
|
project: { id: 'project-db-1', title: '记忆当铺', topic: '记忆交易', status: 'completed' }
|
|
}
|
|
const fetcher = vi.fn<typeof fetch>().mockResolvedValue(new Response(JSON.stringify({ data: [globalAsset] })))
|
|
vi.stubGlobal('fetch', fetcher)
|
|
|
|
await expect(projectAssetsApi.listAll()).resolves.toEqual([globalAsset])
|
|
expect(fetcher).toHaveBeenCalledOnce()
|
|
expect(fetcher).toHaveBeenCalledWith('/api/assets', expect.objectContaining({ method: 'GET' }))
|
|
})
|
|
|
|
it('使用 multipart 上传文件,不手工设置 Content-Type', async () => {
|
|
const fetcher = vi
|
|
.fn<typeof fetch>()
|
|
.mockResolvedValue(new Response(JSON.stringify({ data: asset }), { status: 201 }))
|
|
vi.stubGlobal('fetch', fetcher)
|
|
const file = new File(['image'], 'scene.png', { type: 'image/png' })
|
|
|
|
await expect(
|
|
projectAssetsApi.upload('project-db-1', { file, name: '雨夜街道', category: 'scene' })
|
|
).resolves.toEqual(asset)
|
|
|
|
const [url, init] = fetcher.mock.calls[0]!
|
|
expect(url).toBe('/api/projects/project-db-1/assets')
|
|
expect(init?.method).toBe('POST')
|
|
expect(init?.headers).toEqual({ Accept: 'application/json' })
|
|
expect(init?.body).toBeInstanceOf(FormData)
|
|
const body = init?.body as FormData
|
|
expect(body.get('file')).toBe(file)
|
|
expect(body.get('name')).toBe('雨夜街道')
|
|
expect(body.get('category')).toBe('scene')
|
|
})
|
|
|
|
it('按正式项目和素材 ID 读取、编辑及删除', async () => {
|
|
const fetcher = vi
|
|
.fn<typeof fetch>()
|
|
.mockImplementation(async () => new Response(JSON.stringify({ data: asset })))
|
|
vi.stubGlobal('fetch', fetcher)
|
|
|
|
await projectAssetsApi.list('project/db')
|
|
await projectAssetsApi.get('project/db', 'asset/db')
|
|
await projectAssetsApi.update('project/db', 'asset/db', { name: '新名称', category: 'reference' })
|
|
await projectAssetsApi.remove('project/db', 'asset/db')
|
|
|
|
expect(fetcher.mock.calls.map(([url, init]) => [url, init?.method ?? 'GET'])).toEqual([
|
|
['/api/projects/project%2Fdb/assets', 'GET'],
|
|
['/api/projects/project%2Fdb/assets/asset%2Fdb', 'GET'],
|
|
['/api/projects/project%2Fdb/assets/asset%2Fdb', 'PUT'],
|
|
['/api/projects/project%2Fdb/assets/asset%2Fdb', 'DELETE']
|
|
])
|
|
expect(fetcher.mock.calls[2]?.[1]?.body).toBe(JSON.stringify({ name: '新名称', category: 'reference' }))
|
|
})
|
|
})
|