import { flushPromises, mount, type VueWrapper } from '@vue/test-utils' import { afterEach, describe, expect, it, vi } from 'vitest' import { NInput, NDropdown } from 'naive-ui' import ActionMenu from '@/components/ui/ActionMenu.vue' import DetailDisclosure from '@/components/ui/DetailDisclosure.vue' import StyleEditor from '@/features/visual-style/components/StyleEditor.vue' import SubjectList from '@/features/breakdown/components/SubjectList.vue' import { selectMenu } from '@/testing/naive' import type { SubjectCandidate } from '@/features/breakdown/types' let wrapper: VueWrapper | undefined afterEach(() => { wrapper?.unmount() wrapper = undefined document.body.innerHTML = '' vi.unstubAllGlobals() }) describe('精简入口保留功能', () => { it('菜单按点击展开,禁用项不能绕过,触发器有可访问名称', async () => { wrapper = mount(ActionMenu, { attachTo: document.body, props: { label: '测试更多操作', items: [ { key: 'history', label: '执行记录' }, { key: 'export', label: '导出', disabled: true } ] } }) expect(wrapper.get('button').attributes('aria-haspopup')).toBe('menu') expect(wrapper.get('button').attributes('aria-expanded')).toBe('false') expect(document.querySelector('.n-dropdown-option-body')).toBeNull() await selectMenu('测试更多操作', '执行记录') expect(wrapper.emitted('select')).toEqual([['history']]) wrapper.getComponent(NDropdown).vm.$emit('select', 'export') expect(wrapper.emitted('select')).toHaveLength(1) }) it('补充说明默认不展开,键盘可聚焦的标题可查看原文', async () => { wrapper = mount(DetailDisclosure, { props: { title: '规则说明' }, slots: { default: '完整规则仍然保留' } }) expect(wrapper.text()).not.toContain('完整规则仍然保留') await wrapper.get('.n-collapse-item__header-main').trigger('click') await flushPromises() expect(wrapper.text()).toContain('完整规则仍然保留') }) it('风格高级字段收起不丢失保存值,展开后仍可修改', async () => { wrapper = mount(StyleEditor, { props: { visualStyle: null, disabled: false } }) expect(wrapper.find('#style-constraints').exists()).toBe(false) await wrapper.get('.n-collapse-item__header-main').trigger('click') await flushPromises() await wrapper.get('#style-constraints').setValue('["保留硬约束"]') const fields = wrapper.findAllComponents(NInput) fields.find(item => item.props('placeholder')?.includes('人物质感'))!.vm.$emit('update:value', '人物风格') await flushPromises() await wrapper.get('.n-collapse-item__header-main').trigger('click') await wrapper.get('form').trigger('submit') expect(wrapper.emitted('save')).toMatchObject([ [{ characterPrompt: '人物风格', hardConstraints: ['保留硬约束'] }] ]) }) it('主体长文收起仅影响显示,完整内容与图片入口不丢失', async () => { const description = '主体完整经历。'.repeat(30) wrapper = mount(SubjectList, { props: { projectId: 'p', subjects: [ { profileId: 'p1', ref: '@CH0001', name: '人物', module: 'character', description, appearance_prompt: '外观', aliases: [] } as SubjectCandidate ], forms: [] }, global: { stubs: { RouterLink: true } } }) const text = wrapper.get('.line-clamp-3') expect(text.text()).toBe(description) await wrapper.get('button').trigger('click') expect(wrapper.find('.line-clamp-3').exists()).toBe(false) expect(wrapper.findAll('router-link-stub')).toHaveLength(2) }) })