Fix prop confirmation bug, add Wan 2.7 model, refine multiple UI details, improve prop generation quality and aspect ratio, remove text overlays from Asset Center created images, and optimize prop filtering logic
This commit is contained in:
155
tests/unit/components/asset-edit-modal-ai-layout.test.ts
Normal file
155
tests/unit/components/asset-edit-modal-ai-layout.test.ts
Normal file
@@ -0,0 +1,155 @@
|
||||
import * as React from 'react'
|
||||
import { createElement } from 'react'
|
||||
import { renderToStaticMarkup } from 'react-dom/server'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
import { NextIntlClientProvider } from 'next-intl'
|
||||
import type { AbstractIntlMessages } from 'next-intl'
|
||||
|
||||
vi.mock('@/components/ui/icons', () => ({
|
||||
AppIcon: (props: { className?: string }) => createElement('span', { className: props.className }),
|
||||
}))
|
||||
|
||||
vi.mock('@/components/task/TaskStatusInline', () => ({
|
||||
default: () => createElement('span', null, 'loading'),
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/task/presentation', () => ({
|
||||
resolveTaskPresentationState: () => null,
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/query/hooks', () => ({
|
||||
useUpdateCharacterName: () => ({ isPending: false, mutateAsync: vi.fn() }),
|
||||
useUpdateProjectCharacterName: () => ({ isPending: false, mutateAsync: vi.fn() }),
|
||||
useUpdateCharacterAppearanceDescription: () => ({ mutateAsync: vi.fn() }),
|
||||
useUpdateProjectAppearanceDescription: () => ({ mutateAsync: vi.fn() }),
|
||||
useUpdateProjectCharacterIntroduction: () => ({ mutateAsync: vi.fn() }),
|
||||
useAiModifyCharacterDescription: () => ({ mutateAsync: vi.fn() }),
|
||||
useAiModifyProjectAppearanceDescription: () => ({ mutateAsync: vi.fn() }),
|
||||
useUpdateLocationName: () => ({ isPending: false, mutateAsync: vi.fn() }),
|
||||
useUpdateProjectLocationName: () => ({ isPending: false, mutateAsync: vi.fn() }),
|
||||
useUpdateLocationSummary: () => ({ mutateAsync: vi.fn() }),
|
||||
useUpdateProjectLocationDescription: () => ({ mutateAsync: vi.fn() }),
|
||||
useAiModifyLocationDescription: () => ({ mutateAsync: vi.fn() }),
|
||||
useAiModifyProjectLocationDescription: () => ({ mutateAsync: vi.fn() }),
|
||||
useAiModifyPropDescription: () => ({ mutateAsync: vi.fn() }),
|
||||
useAiModifyProjectPropDescription: () => ({ mutateAsync: vi.fn() }),
|
||||
useAssetActions: () => ({
|
||||
update: vi.fn(),
|
||||
updateVariant: vi.fn(),
|
||||
generate: vi.fn(),
|
||||
}),
|
||||
}))
|
||||
|
||||
const messages = {
|
||||
assets: {
|
||||
common: {
|
||||
cancel: '取消',
|
||||
},
|
||||
character: {
|
||||
name: '角色名',
|
||||
appearance: '形象',
|
||||
},
|
||||
location: {
|
||||
name: '场景名',
|
||||
description: '场景描述',
|
||||
},
|
||||
prop: {
|
||||
name: '道具名',
|
||||
summary: '简要说明',
|
||||
summaryPlaceholder: '一句话说明这是什么道具,不写剧情用途',
|
||||
description: '图片描述',
|
||||
descriptionPlaceholder: '只写道具本体的材质、颜色、结构和装饰细节',
|
||||
},
|
||||
modal: {
|
||||
editCharacter: '编辑角色',
|
||||
editLocation: '编辑场景',
|
||||
editProp: '编辑道具',
|
||||
namePlaceholder: '输入名称',
|
||||
appearancePrompt: '形象描述提示词',
|
||||
descPlaceholder: '输入描述',
|
||||
modifyDescription: 'AI修改描述',
|
||||
modifyPlaceholder: '改成夜晚',
|
||||
modifyPlaceholderCharacter: '改成黑色西装',
|
||||
modifyPlaceholderProp: '改成磨砂银质',
|
||||
saveName: '保存名字',
|
||||
saveOnly: '仅保存',
|
||||
saveAndGenerate: '保存并生成',
|
||||
introduction: '角色介绍',
|
||||
introductionPlaceholder: '输入角色介绍',
|
||||
introductionTip: '介绍角色在故事中的身份',
|
||||
},
|
||||
smartImport: {
|
||||
preview: {
|
||||
saving: '保存中',
|
||||
},
|
||||
},
|
||||
errors: {
|
||||
saveFailed: '保存失败',
|
||||
failed: '失败',
|
||||
},
|
||||
},
|
||||
} as const
|
||||
|
||||
const TestIntlProvider = NextIntlClientProvider as React.ComponentType<{
|
||||
locale: string
|
||||
messages: AbstractIntlMessages
|
||||
timeZone: string
|
||||
children?: React.ReactNode
|
||||
}>
|
||||
|
||||
function renderWithMessages(node: React.ReactElement) {
|
||||
return renderToStaticMarkup(
|
||||
createElement(
|
||||
TestIntlProvider,
|
||||
{
|
||||
locale: 'zh',
|
||||
messages: messages as unknown as AbstractIntlMessages,
|
||||
timeZone: 'Asia/Shanghai',
|
||||
},
|
||||
node,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
describe('asset edit modal AI layout', () => {
|
||||
it('renders character AI modify action inside the description composer instead of a standalone smart-modify card', async () => {
|
||||
Reflect.set(globalThis, 'React', React)
|
||||
const { CharacterEditModal } = await import('@/components/shared/assets/CharacterEditModal')
|
||||
const html = renderWithMessages(
|
||||
createElement(CharacterEditModal, {
|
||||
mode: 'project',
|
||||
characterId: 'character-1',
|
||||
characterName: '沈烬',
|
||||
description: '冷峻禁欲的男性角色形象描述',
|
||||
appearanceId: 'appearance-1',
|
||||
onClose: () => undefined,
|
||||
onSave: () => undefined,
|
||||
}),
|
||||
)
|
||||
|
||||
expect(html).toContain('AI修改描述')
|
||||
expect(html).not.toContain('改成黑色西装')
|
||||
expect(html).not.toContain('智能修改')
|
||||
})
|
||||
|
||||
it('renders prop AI modify action with the prop-specific placeholder', async () => {
|
||||
Reflect.set(globalThis, 'React', React)
|
||||
const { PropEditModal } = await import('@/components/shared/assets/PropEditModal')
|
||||
const html = renderWithMessages(
|
||||
createElement(PropEditModal, {
|
||||
mode: 'project',
|
||||
propId: 'prop-1',
|
||||
propName: '遗物匕首',
|
||||
summary: '旧时代留下的金属短刃',
|
||||
description: '青铜短刃,刃面斑驳,手柄有细密雕纹',
|
||||
variantId: 'prop-variant-1',
|
||||
projectId: 'project-1',
|
||||
onClose: () => undefined,
|
||||
}),
|
||||
)
|
||||
|
||||
expect(html).toContain('AI修改描述')
|
||||
expect(html).not.toContain('改成磨砂银质')
|
||||
expect(html).not.toContain('智能修改')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user