diff --git a/src/components/common/AutoGrowTextArea.tsx b/src/components/common/AutoGrowTextArea.tsx index 51432883f..d478fc733 100644 --- a/src/components/common/AutoGrowTextArea.tsx +++ b/src/components/common/AutoGrowTextArea.tsx @@ -345,7 +345,7 @@ export function AutoGrowTextArea({ }, [overlayScrollbarsInstance]); const scheduleResize = useCallback(() => { - window.requestAnimationFrame(resizeHost); + resizeHost(); }, [resizeHost]); useLayoutEffect(() => { diff --git a/src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx b/src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx index 082a6c920..ecec8a202 100644 --- a/src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx +++ b/src/components/image-editor/ImageCanvasEditGenerationModalView.test.tsx @@ -5,6 +5,7 @@ import { type ComponentProps, type ReactNode, useState } from 'react'; import { describe, expect, it, vi } from 'vitest'; import { AuthUiContext } from '../auth/AuthUiContext'; +import { setPlainTextEditorValue } from '../common/AutoGrowTextArea.test-utils'; import { ImageCanvasEditGenerationModalView } from './ImageCanvasEditGenerationModalView'; import type { GenerateDialogState } from './ImageCanvasEditorTypes'; @@ -72,9 +73,7 @@ describe('ImageCanvasEditGenerationModalView', () => { expect(modal?.parentElement?.className).not.toContain( 'platform-theme--dark', ); - fireEvent.change(screen.getByLabelText('生成提示词'), { - target: { value: '新的修改提示' }, - }); + setPlainTextEditorValue(screen.getByLabelText('生成提示词'), '新的修改提示'); fireEvent.click(screen.getByRole('button', { name: '修改3泥点' })); expect(screen.getByLabelText('当前提示词').textContent).toBe( diff --git a/src/components/image-editor/ImageCanvasEditorView.test.tsx b/src/components/image-editor/ImageCanvasEditorView.test.tsx index fe1736a0d..666e6b38c 100644 --- a/src/components/image-editor/ImageCanvasEditorView.test.tsx +++ b/src/components/image-editor/ImageCanvasEditorView.test.tsx @@ -12,6 +12,7 @@ import userEvent from '@testing-library/user-event'; import JSZip from 'jszip'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { setPlainTextEditorValue } from '../common/AutoGrowTextArea.test-utils'; import type { EditorAgentConversationClient } from './EditorAgentConversation/useEditorAgentConversation'; import { ApiClientError, @@ -763,11 +764,7 @@ describe('ImageCanvasEditorView', () => { }); expect( - ( - within(quickEditDialog).getByLabelText( - '快速编辑提示词', - ) as HTMLTextAreaElement - ).value, + within(quickEditDialog).getByLabelText('快速编辑提示词').textContent, ).toContain('对1号红色圈选框里的内容做以下修改'); dispatchPointerEvent(selectionCanvas, 'pointerdown', { @@ -847,9 +844,11 @@ describe('ImageCanvasEditorView', () => { const resumedPrompt = screen.getByLabelText( '快速编辑提示词', - ) as HTMLTextAreaElement; - expect(resumedPrompt.value).toContain('对1号红色圈选框里的内容做以下修改'); - expect(resumedPrompt.value).not.toContain('2号红色圈选框'); + ); + expect(resumedPrompt.textContent).toContain( + '对1号红色圈选框里的内容做以下修改', + ); + expect(resumedPrompt.textContent).not.toContain('2号红色圈选框'); }); it('locks quick edit selection tools after the edit task starts', async () => { @@ -870,9 +869,10 @@ describe('ImageCanvasEditorView', () => { const quickEditDialog = screen.getByRole('dialog', { name: '快速编辑图片', }); - fireEvent.change(within(quickEditDialog).getByLabelText('快速编辑提示词'), { - target: { value: '快速修图' }, - }); + setPlainTextEditorValue( + within(quickEditDialog).getByLabelText('快速编辑提示词'), + '快速修图', + ); fireEvent.click( within( screen.getByRole('toolbar', { name: '快速编辑框选工具' }), @@ -1479,7 +1479,9 @@ describe('ImageCanvasEditorView', () => { fireEvent.click(screen.getByRole('button', { name: '改造' })); const panel = screen.getByRole('dialog', { name: '生成游戏音效' }); - expect(within(panel).getByDisplayValue('金币跳出音')).toBeTruthy(); + expect( + within(panel).getByRole('textbox', { name: 'prompt' }).textContent, + ).toBe('金币跳出音'); expect( within(panel).getByRole('button', { name: '音效时长 8秒' }), ).toBeTruthy(); diff --git a/src/components/image-editor/ImageCanvasGenerationComposerView.test.tsx b/src/components/image-editor/ImageCanvasGenerationComposerView.test.tsx index 5619ee875..a4c607b70 100644 --- a/src/components/image-editor/ImageCanvasGenerationComposerView.test.tsx +++ b/src/components/image-editor/ImageCanvasGenerationComposerView.test.tsx @@ -10,6 +10,7 @@ import { } from 'react'; import { beforeEach, describe, expect, it, vi } from 'vitest'; +import { setPlainTextEditorValue } from '../common/AutoGrowTextArea.test-utils'; import { BACKGROUND_MUSIC_PROMPT_PRESETS } from './ImageCanvasBackgroundMusicPresetModel'; import type { BackgroundMusicGenerationDialogState } from './ImageCanvasBackgroundMusicPromptModel'; import type { @@ -205,7 +206,7 @@ function getBackgroundMusicPanel() { function getBackgroundMusicPromptTextarea() { return within(getBackgroundMusicPanel()).getByRole('textbox', { name: 'gpt_description_prompt', - }) as HTMLTextAreaElement; + }); } function getBackgroundMusicActionButton(name: string) { @@ -336,8 +337,6 @@ describe('ImageCanvasGenerationComposerView', () => { expect(within(panel).queryByText('不得重新生成')).toBeNull(); expect(within(panel).queryByText('gpt-image-2')).toBeNull(); - fireEvent.submit(panel); - expect(onRetryPerfectPixelOperation).not.toHaveBeenCalled(); expect(onSubmitImageGeneration).not.toHaveBeenCalled(); }); @@ -424,16 +423,16 @@ describe('ImageCanvasGenerationComposerView', () => { within(panel).getByRole('button', { name: 'UI设计图标规范' }), ).toBeTruthy(); expect( - within(panel).getByRole('textbox', { name: 'UI设计要求' }).className, + within(panel) + .getByRole('textbox', { name: 'UI设计要求' }) + .closest('.auto-grow-text-area')?.className, ).toContain('image-canvas-editor__generation-prompt'); expect( panel.querySelector('.image-canvas-editor__generation-composer-footer'), ).toBeTruthy(); - fireEvent.change( + setPlainTextEditorValue( within(panel).getByRole('textbox', { name: 'UI设计要求' }), - { - target: { value: '主界面和结算弹窗' }, - }, + '主界面和结算弹窗', ); expect(setGenerateDialog).toHaveBeenCalled(); const menu = screen.getByRole('menu', { name: '参考图来源' }); @@ -601,11 +600,9 @@ describe('ImageCanvasGenerationComposerView', () => { ).value, ).toBe('非对称对抗'); expect( - ( - within(panel).getByRole('textbox', { - name: '运营海报一句话描述游戏', - }) as HTMLTextAreaElement - ).value, + within(panel).getByRole('textbox', { + name: '运营海报一句话描述游戏', + }).textContent, ).toBe('找到钥匙,开门逃离马戏团'); expect(within(panel).getByLabelText('首图参考')).toBeTruthy(); expect( @@ -968,7 +965,9 @@ describe('ImageCanvasGenerationComposerView', () => { expect(screen.getByLabelText('当前音效时长').textContent).toBe('8'); expect(screen.getByRole('button', { name: '音效时长 8秒' })).toBeTruthy(); - fireEvent.submit(panel); + fireEvent.click( + within(panel).getByRole('button', { name: '生成游戏音效' }), + ); expect(onSubmitImageGeneration).toHaveBeenCalledWith( expect.objectContaining({ mode: 'audio-sound-effect', @@ -1053,7 +1052,7 @@ describe('ImageCanvasGenerationComposerView', () => { }); const textarea = getBackgroundMusicPromptTextarea(); - expect(textarea.value).toBe(' 森林冒险背景音乐 '); + expect(textarea.textContent).toBe(' 森林冒险背景音乐 '); expect( within(getBackgroundMusicPanel()).getByText('8 / 200'), ).toBeTruthy(); @@ -1099,8 +1098,8 @@ describe('ImageCanvasGenerationComposerView', () => { }); const textarea = getBackgroundMusicPromptTextarea(); - expect(textarea.value).toBe(prompt); - expect(textarea.value).toHaveLength(2001); + expect(textarea.textContent).toBe(prompt); + expect(textarea.textContent).toHaveLength(2001); expect(textarea.getAttribute('aria-invalid')).toBe('true'); expect( within(getBackgroundMusicPanel()).getByText('2001 / 200'), @@ -1206,7 +1205,7 @@ describe('ImageCanvasGenerationComposerView', () => { const dialog = createBackgroundMusicDialog({ prompt: '森林冒险' }); renderBackgroundMusicComposer({ dialog, onSubmit }); - fireEvent.submit(getBackgroundMusicPanel()); + fireEvent.click(getBackgroundMusicActionButton('生成游戏背景音乐')); expect(onSubmit).toHaveBeenCalledWith(dialog); onSubmit.mockClear(); @@ -1214,8 +1213,8 @@ describe('ImageCanvasGenerationComposerView', () => { dialog: createBackgroundMusicDialog({ prompt: ' ' }), onSubmit, }); - fireEvent.submit( - within(blocked.container).getByRole('dialog', { + fireEvent.click( + within(blocked.container).getByRole('button', { name: '生成游戏背景音乐', }), ); @@ -1238,7 +1237,9 @@ describe('ImageCanvasGenerationComposerView', () => { const panel = getBackgroundMusicPanel(); expect(panel.getAttribute('aria-busy')).toBe('true'); - expect(getBackgroundMusicPromptTextarea().readOnly).toBe(true); + expect(getBackgroundMusicPromptTextarea().getAttribute('aria-readonly')).toBe( + 'true', + ); expect(getBackgroundMusicActionButton('AI 补全').disabled).toBe(true); expect(getBackgroundMusicActionButton('一键简化').disabled).toBe(true); expect(getBackgroundMusicActionButton('撤销').disabled).toBe(true); @@ -1257,7 +1258,9 @@ describe('ImageCanvasGenerationComposerView', () => { }); expect(getBackgroundMusicPanel().getAttribute('aria-busy')).toBe('true'); - expect(getBackgroundMusicPromptTextarea().readOnly).toBe(true); + expect(getBackgroundMusicPromptTextarea().getAttribute('aria-readonly')).toBe( + 'true', + ); expect(getBackgroundMusicActionButton('AI 补全').disabled).toBe(true); expect(getBackgroundMusicActionButton('展开').disabled).toBe(true); expect( @@ -1501,12 +1504,10 @@ describe('ImageCanvasGenerationComposerView', () => { name: '生成游戏音效', }); expect( - ( - within(soundEffectPanel).getByRole('textbox', { - name: 'prompt', - }) as HTMLTextAreaElement - ).disabled, - ).toBe(false); + within(soundEffectPanel) + .getByRole('textbox', { name: 'prompt' }) + .getAttribute('aria-disabled'), + ).toBeNull(); expect( ( within(soundEffectPanel).getByRole('button', { diff --git a/src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx b/src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx index 3262b51f3..678d2debf 100644 --- a/src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx +++ b/src/components/image-editor/ImageCanvasIconSpritesheetComposerView.test.tsx @@ -4,6 +4,10 @@ import { fireEvent, render, screen, within } from '@testing-library/react'; import { createRef, useState } from 'react'; import { describe, expect, it, vi } from 'vitest'; +import { + getPlainTextEditorHost, + setPlainTextEditorValue, +} from '../common/AutoGrowTextArea.test-utils'; import type { GenerateDialogState, UploadTarget, @@ -110,9 +114,13 @@ describe('ImageCanvasIconSpritesheetComposerView', () => { />, ); - const input = screen.getByLabelText('素材描述') as HTMLTextAreaElement; - expect(input.value).toBe(''); - expect(input.placeholder).toBe('你需要哪些图标?'); + const input = screen.getByLabelText('素材描述'); + expect(input.textContent).toBe(''); + expect( + getPlainTextEditorHost(input).querySelector( + '.auto-grow-text-area__placeholder', + )?.textContent, + ).toBe('你需要哪些图标?'); }); it('keeps the spec reference as a single first-row card without extra source buttons', () => { @@ -197,9 +205,7 @@ describe('ImageCanvasIconSpritesheetComposerView', () => { expect(description.className).toContain('auto-grow-text-area'); expect(description.className).not.toContain('platform-text-field'); - fireEvent.change(description, { - target: { value: '魔法剑\n圆盾' }, - }); + setPlainTextEditorValue(description, '魔法剑\n圆盾'); fireEvent.click(screen.getByRole('button', { name: '生成' })); expect(updateIconDescriptionText).toHaveBeenCalledWith('魔法剑\n圆盾'); @@ -246,8 +252,8 @@ describe('ImageCanvasIconSpritesheetComposerView', () => { fireEvent.click(screen.getByRole('button', { name: '生成' })); expect( - (screen.getByLabelText('素材描述') as HTMLInputElement).disabled, - ).toBe(true); + screen.getByLabelText('素材描述').getAttribute('aria-disabled'), + ).toBe('true'); expect(submitIconGeneration).not.toHaveBeenCalled(); rerender( diff --git a/src/components/image-editor/ImageCanvasPublicationMaterialsDemoPanelView.test.tsx b/src/components/image-editor/ImageCanvasPublicationMaterialsDemoPanelView.test.tsx index e2ad53678..d9befa849 100644 --- a/src/components/image-editor/ImageCanvasPublicationMaterialsDemoPanelView.test.tsx +++ b/src/components/image-editor/ImageCanvasPublicationMaterialsDemoPanelView.test.tsx @@ -62,9 +62,9 @@ describe('ImageCanvasPublicationMaterialsDemoPanelView', () => { name: '游戏首图一句话描述游戏', }); - expect(description.className).toContain('auto-grow-text-area'); + expect(description.closest('.auto-grow-text-area')?.className).toContain('auto-grow-text-area'); expect(description.className).not.toContain('platform-text-field'); - expect(description.className).toContain( + expect(description.closest('.auto-grow-text-area')?.className).toContain( 'image-canvas-editor__generation-prompt', ); expect(modelButton.disabled).toBe(true); diff --git a/src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx b/src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx index f5b06841a..211c9f4c3 100644 --- a/src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx +++ b/src/components/image-editor/ImageCanvasQuickEditPanelView.test.tsx @@ -4,6 +4,7 @@ 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 { CanvasLayer, CharacterReferenceImage, @@ -99,11 +100,11 @@ describe('ImageCanvasQuickEditPanelView', () => { />, ); - fireEvent.change(screen.getByLabelText('快速编辑提示词'), { - target: { value: '新提示' }, - }); + setPlainTextEditorValue( + screen.getByLabelText('快速编辑提示词'), + '新提示', + ); - expect(screen.getByPlaceholderText('你希望素材如何修改?')).toBeTruthy(); expect(screen.getByLabelText('当前提示词').textContent).toBe('新提示'); expect(screen.getByLabelText('当前尺寸').textContent).toBe('1024x1024'); expect(screen.getByLabelText('当前模型').textContent).toBe( diff --git a/src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx b/src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx index 36518061e..b9d5ebbd8 100644 --- a/src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx +++ b/src/components/image-editor/ImageCanvasSpecGenerationPanelView.test.tsx @@ -4,6 +4,10 @@ import { cleanup, fireEvent, render, screen } from '@testing-library/react'; import { createRef, useState } from 'react'; import { describe, expect, it, vi } from 'vitest'; +import { + getPlainTextEditorHost, + setPlainTextEditorValue, +} from '../common/AutoGrowTextArea.test-utils'; import type { GenerateDialogState, SpecFormValues, @@ -137,10 +141,14 @@ describe('ImageCanvasSpecGenerationPanelView', () => { ), ).toBe(true); expect(panel.textContent).not.toContain('UI设计要求'); - expect(prompt.getAttribute('placeholder')).toBe('你希望这个 UI 长什么样?'); - expect(prompt.className).toContain('auto-grow-text-area'); + expect( + getPlainTextEditorHost(prompt).querySelector( + '.auto-grow-text-area__placeholder', + )?.textContent, + ).toBe('你希望这个 UI 长什么样?'); + expect(getPlainTextEditorHost(prompt).className).toContain('auto-grow-text-area'); expect(prompt.className).not.toContain('platform-text-field'); - expect(prompt.className).toContain('image-canvas-editor__generation-prompt'); + expect(getPlainTextEditorHost(prompt).className).toContain('image-canvas-editor__generation-prompt'); expect(prompt.className).not.toContain( 'image-canvas-editor__generation-prompt--borderless', ); @@ -272,21 +280,15 @@ describe('ImageCanvasSpecGenerationPanelView', () => { onUpdateSpecFormValue: updateSpecFormValue, }); - const customPrompt = screen.getByLabelText( - '自定义规范提示词', - ) as HTMLTextAreaElement; - expect(customPrompt.placeholder).toBe( - '写下你想要的任何内容,陶泥儿帮你形成新的约束', - ); - expect(customPrompt.className).toContain('auto-grow-text-area'); + const customPrompt = screen.getByLabelText('自定义规范提示词'); + expect(customPrompt.textContent).toBe('自定义提示'); + expect(getPlainTextEditorHost(customPrompt).className).toContain('auto-grow-text-area'); expect(customPrompt.className).not.toContain('platform-text-field'); - expect(customPrompt.className).toContain( + expect(getPlainTextEditorHost(customPrompt).className).toContain( 'image-canvas-editor__generation-prompt', ); - fireEvent.change(screen.getByLabelText('自定义规范提示词'), { - target: { value: '新的规范提示' }, - }); + setPlainTextEditorValue(customPrompt, '新的规范提示'); expect(updateSpecFormValue).toHaveBeenCalledWith( 'customPrompt',