Files
short-drama-agent-front/tests/features/project-assets/library.test.ts
T

107 lines
4.8 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from 'vitest'
import { flushPromises, mount, type VueWrapper } from '@vue/test-utils'
import { createMemoryHistory, createRouter } from 'vue-router'
import { NTooltip } from 'naive-ui'
import AssetLibraryPage from '@/features/project-assets/AssetLibraryPage.vue'
let wrapper: VueWrapper | undefined
afterEach(() => {
wrapper?.unmount()
wrapper = undefined
document.body.innerHTML = ''
vi.unstubAllGlobals()
})
describe('全局资产库', () => {
it('单次读取并直接显示全部剧本图片,支持按图片与剧本搜索', async () => {
const assets = [
{
id: 'asset-scene',
projectId: 'project-one',
name: '雨夜街道',
type: 'image',
category: 'scene',
mimeType: 'image/png',
extension: 'png',
size: 4096,
publicUrl: '/storage/scene.png',
metadata: { originalName: 'rain-street-original.png' },
createdAt: '2026-09-22T00:00:00Z',
updatedAt: '2026-09-22T00:00:00Z',
project: { id: 'project-one', title: '记忆当铺', topic: '记忆交易', status: 'completed' }
},
{
id: 'asset-character',
projectId: 'project-two',
name: '林默正面照',
type: 'image',
category: 'character',
mimeType: 'image/jpeg',
extension: 'jpg',
size: 8192,
publicUrl: '/storage/character.jpg',
metadata: null,
createdAt: '2026-09-22T01:00:00Z',
updatedAt: '2026-09-22T01:00:00Z',
project: { id: 'project-two', title: '天降甘霖', topic: '乡村故事', status: 'completed' }
}
]
const projects = assets.map(asset => ({
...asset.project,
style: null,
createdAt: '',
updatedAt: ''
}))
const fetcher = vi.fn<typeof fetch>().mockImplementation(async input => {
const url = String(input)
return new Response(JSON.stringify({ data: url.endsWith('/projects') ? projects : assets }))
})
vi.stubGlobal('fetch', fetcher)
const router = createRouter({
history: createMemoryHistory(),
routes: [
{ path: '/assets', component: AssetLibraryPage },
{ path: '/projects/:projectId/assets', component: { template: '<div />' } }
]
})
await router.push('/assets')
wrapper = mount(AssetLibraryPage, { attachTo: document.body, global: { plugins: [router] } })
await flushPromises()
expect(fetcher).toHaveBeenCalledTimes(2)
expect(fetcher).toHaveBeenCalledWith('/api/assets', expect.objectContaining({ method: 'GET' }))
expect(wrapper.findAll('.asset-library-card')).toHaveLength(2)
expect(wrapper.text()).toContain('雨夜街道')
expect(wrapper.text()).toContain('林默正面照')
expect(wrapper.text()).toContain('记忆当铺')
expect(wrapper.findAllComponents(NTooltip)).toHaveLength(2)
const title = wrapper.get('.asset-library-title')
expect(title.classes()).toContain('asset-library-title')
expect(wrapper.findComponent(NTooltip).props('disabled')).toBe(true)
Object.defineProperties(title.element, {
scrollWidth: { configurable: true, value: 240 },
clientWidth: { configurable: true, value: 120 }
})
await title.trigger('mouseenter')
expect(wrapper.findComponent(NTooltip).props('disabled')).toBe(false)
expect(wrapper.get('.asset-library-card').text()).not.toContain('rain-street-original.png')
expect(wrapper.get('.asset-library-card').text()).not.toContain('4.0 KB')
expect(wrapper.find('[aria-label="预览图片"]').exists()).toBe(false)
expect(wrapper.find('[aria-label="查看素材详情"]').exists()).toBe(false)
await wrapper.get('.asset-library-card').trigger('click')
await flushPromises()
const dialog = document.querySelector('[role="dialog"][aria-label="素材详情与管理"]')!
expect(dialog).not.toBeNull()
expect(dialog.textContent).toContain('rain-street-original.png')
expect(dialog.textContent).toContain('image/png')
expect(dialog.textContent).toContain('4.0 KB')
expect(router.currentRoute.value.path).toBe('/assets')
await wrapper.get('input[aria-label="搜索资产图片"]').setValue('天降甘霖')
expect(wrapper.findAll('.asset-library-card')).toHaveLength(1)
expect(wrapper.text()).toContain('林默正面照')
expect(wrapper.text()).not.toContain('雨夜街道')
})
})