import { flushPromises, mount, type VueWrapper } from '@vue/test-utils' import { afterEach, expect, it, vi } from 'vitest' import ProviderInputInspector from '@/features/production/components/ProviderInputInspector.vue' let wrapper: VueWrapper | undefined afterEach(() => { wrapper?.unmount() vi.unstubAllGlobals() }) /** 仅提供公开输入规格,不连接生成服务。 */ function inputSpec(shotId = 'shot-1') { return { shotId, targetProvider: 'seedance', businessKeyframe: { id: 'keyframe-1', imageUrl: '/key.png' }, providerInputKeyframe: { id: 'variant-1', imageUrl: '/variant.png', source: 'provider_variant', variantReason: '模型输入适配' }, references: [ { subjectId: 'subject-1', subjectFormId: 'form-1', subjectRef: 'C1', subjectName: '角色', subjectFormName: '基础形态', module: 'character', providerAsset: { provider: 'seedance', assetId: 'asset-1' } } ] } } it('按显式模型发出只读查询并展示授权素材,切换镜头清除旧结果', async () => { const fetcher = vi.fn().mockResolvedValue(new Response(JSON.stringify({ data: inputSpec() }))) vi.stubGlobal('fetch', fetcher) wrapper = mount(ProviderInputInspector, { props: { shotId: 'shot-1' } }) expect(fetcher).not.toHaveBeenCalled() await wrapper.get('input').setValue(' Seedance ') await wrapper.get('button').trigger('click') await flushPromises() expect(fetcher.mock.calls[0]?.[0]).toBe('/api/storyboard-shots/shot-1/provider-input-spec?provider=seedance') expect(fetcher.mock.calls[0]?.[1]?.method).toBe('GET') expect(wrapper.text()).toContain('asset-1') expect(wrapper.text()).toContain('variant-1') await wrapper.setProps({ shotId: 'shot-2' }) expect(wrapper.text()).not.toContain('asset-1') }) it('模型切换使晚到的旧响应失效,错误归属不发布结果', async () => { let finish!: (response: Response) => void const fetcher = vi.fn().mockImplementation( () => new Promise(resolve => { finish = resolve }) ) vi.stubGlobal('fetch', fetcher) wrapper = mount(ProviderInputInspector, { props: { shotId: 'shot-1' } }) await wrapper.get('input').setValue('seedance') await wrapper.get('button').trigger('click') await wrapper.get('input').setValue('other') finish(new Response(JSON.stringify({ data: inputSpec() }))) await flushPromises() expect(wrapper.text()).not.toContain('asset-1') await wrapper.get('input').setValue('seedance') fetcher.mockResolvedValue(new Response(JSON.stringify({ data: inputSpec('wrong-shot') }))) await wrapper.get('button').trigger('click') await flushPromises() expect(wrapper.text()).toContain('不匹配') expect(wrapper.text()).not.toContain('asset-1') })