/* @vitest-environment jsdom */ import { fireEvent, render, screen } from '@testing-library/react'; import { useRef, useState } from 'react'; import { describe, expect, it, vi } from 'vitest'; import { setPlainTextEditorValue } from '../common/AutoGrowTextArea.test-utils'; import type { CharacterReferenceImage, QuickEditPanelState, UploadTarget, } from './ImageCanvasEditorTypes'; import { ImageCanvasQuickEditPanelView } from './ImageCanvasQuickEditPanelView'; function QuickEditPanelHarness({ initialPanel, onSubmit = vi.fn(), onRequestUpload = vi.fn(), onRememberImageModel = vi.fn(), }: { initialPanel: QuickEditPanelState; onSubmit?: () => void; onRequestUpload?: (target: UploadTarget) => void; onRememberImageModel?: (model: string) => void; }) { const [panel, setPanel] = useState(initialPanel); const [isReferenceMenuOpen, setIsReferenceMenuOpen] = useState(false); const [isPickingReference, setIsPickingReference] = useState(false); const referenceButtonRef = useRef(null); return panel ? (
node} onRequestUpload={onRequestUpload} onRememberImageModel={onRememberImageModel} setQuickEditPanel={setPanel} onSubmit={onSubmit} /> {panel.prompt} {panel.size} {panel.aspectRatio ?? '-'} {panel.imageSize ?? '-'} {panel.model} {panel.status} {panel.errorMessage ?? '-'} {panel.quickEditReferences?.length ?? 0} {isPickingReference ? 'picking' : 'idle'}
) : ( closed ); } describe('ImageCanvasQuickEditPanelView', () => { it('updates prompt and clears failed state while keeping model editable', () => { const rememberImageModel = vi.fn(); render( , ); setPlainTextEditorValue(screen.getByLabelText('快速编辑提示词'), '新提示'); expect(screen.getByLabelText('当前提示词').textContent).toBe('新提示'); expect(screen.getByLabelText('当前尺寸').textContent).toBe('1024x1024'); expect(screen.getByLabelText('当前模型').textContent).toBe( 'gemini-3.1-flash-image-preview', ); expect(screen.getByLabelText('当前状态').textContent).toBe('idle'); expect(screen.getByLabelText('当前错误').textContent).toBe('-'); expect( screen.getByRole('button', { name: '快速编辑尺寸 1:1·1K' }), ).toBeTruthy(); fireEvent.click( screen.getByRole('button', { name: '快速编辑模型 nanobanana2' }), ); expect(screen.getByRole('button', { name: 'nanobanana2' })).toBeTruthy(); fireEvent.click(screen.getByRole('button', { name: 'gpt-image-2' })); expect(screen.getByLabelText('当前模型').textContent).toBe('gpt-image-2'); expect(rememberImageModel).toHaveBeenCalledWith('gpt-image-2'); }); it('renders the failure message inside the quick edit alert', () => { render( , ); expect(screen.getByRole('alert').textContent).toContain('图集快速编辑失败'); }); it('submits without rendering a standalone close button', () => { const submitQuickEdit = vi.fn(); render( , ); fireEvent.click(screen.getByRole('button', { name: '修改' })); expect(submitQuickEdit).toHaveBeenCalledTimes(1); expect( screen.queryByRole('button', { name: '关闭快速编辑图片' }), ).toBeNull(); }); it('hides quick edit references from the simplified panel', () => { render( , ); expect(screen.queryByLabelText('图1')).toBeNull(); expect(screen.queryByLabelText('原图 图2')).toBeNull(); expect( screen.queryByRole('button', { name: '添加快速编辑参考图' }), ).toBeNull(); expect(screen.getByLabelText('参考图数量').textContent).toBe('1'); }); it('does not expose quick edit reference pick actions', () => { const requestUpload = vi.fn(); render( , ); expect( screen.queryByRole('button', { name: '添加快速编辑参考图' }), ).toBeNull(); expect(requestUpload).not.toHaveBeenCalled(); expect(screen.getByLabelText('画布选择参考图').textContent).toBe('idle'); }); it('keeps quick edit reference controls hidden even with many references', () => { render( ({ id: `ref-${index}`, label: `参考${index + 1}`, src: `/ref-${index}.png`, })) satisfies CharacterReferenceImage[], }} />, ); expect( screen.queryByRole('button', { name: '添加快速编辑参考图', }), ).toBeNull(); expect(screen.queryByLabelText('原图 图9')).toBeNull(); }); });