import { afterEach, describe, expect, it, vi } from 'vitest' import { flushPromises, mount, type VueWrapper } from '@vue/test-utils' import { createMemoryHistory, createRouter } from 'vue-router' import ProjectAssetsPage from '@/features/project-assets/ProjectAssetsPage.vue' import { projectContextKey } from '@/features/projects/context' import { testProjectContext } from '@/testing/project-context' let wrapper: VueWrapper | undefined afterEach(() => { wrapper?.unmount() wrapper = undefined document.body.innerHTML = '' vi.unstubAllGlobals() }) describe('项目资产库页面', () => { it('读取当前项目素材并支持名称、分类和原文件名筛选', async () => { const fetcher = vi.fn().mockResolvedValue( new Response( JSON.stringify({ data: [ { id: 'asset-scene', projectId: 'capability-test', name: '雨夜街道', type: 'image', category: 'scene', mimeType: 'image/png', extension: 'png', size: 4096, publicUrl: '/storage/scene.png', metadata: { originalName: 'street-original.png' }, createdAt: '2026-09-21T00:00:00Z', updatedAt: '2026-09-21T00:00:00Z' }, { id: 'asset-character', projectId: 'capability-test', name: '林默正面照', type: 'image', category: 'character', mimeType: 'image/jpeg', extension: 'jpg', size: 8192, publicUrl: '/storage/character.jpg', metadata: null, createdAt: '2026-09-21T01:00:00Z', updatedAt: '2026-09-21T01:00:00Z' } ] }) ) ) vi.stubGlobal('fetch', fetcher) const router = createRouter({ history: createMemoryHistory(), routes: [{ path: '/projects/:projectId/assets', component: ProjectAssetsPage }] }) await router.push('/projects/capability-test/assets') wrapper = mount(ProjectAssetsPage, { attachTo: document.body, global: { plugins: [router], provide: { [projectContextKey as symbol]: testProjectContext() } } }) await flushPromises() expect(fetcher).toHaveBeenCalledWith( '/api/projects/capability-test/assets', expect.objectContaining({ method: 'GET' }) ) expect(wrapper.findAll('.project-asset-card')).toHaveLength(2) expect(wrapper.text()).toContain('雨夜街道') expect(wrapper.text()).toContain('林默正面照') await wrapper.get('input[aria-label="搜索项目素材"]').setValue('street-original') expect(wrapper.findAll('.project-asset-card')).toHaveLength(1) expect(wrapper.text()).toContain('雨夜街道') expect(wrapper.text()).not.toContain('林默正面照') await wrapper.get('input[aria-label="搜索项目素材"]').setValue('没有结果') expect(wrapper.findAll('.project-asset-card')).toHaveLength(0) expect(wrapper.text()).toContain('没有匹配的素材') }) })