From 7c84df1405d568ee11e20837c4fa6308210af9f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Sat, 8 Aug 2026 11:12:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=94=BB=E5=B8=83=E7=94=9F?= =?UTF-8?q?=E6=88=90=E8=BE=93=E5=85=A5=E5=9B=9E=E5=BD=92=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 迁移生成集成测试至 Lexical 文本输入契约 补齐基础生成与角色动画输入测试断言 --- ...CanvasBasicGenerationComposerView.test.tsx | 9 +- ...CanvasCharacterAnimationPanelView.test.tsx | 50 ++-- ...CanvasEditorGenerationIntegration.test.tsx | 245 ++++++++++-------- 3 files changed, 161 insertions(+), 143 deletions(-) diff --git a/src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx b/src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx index 88cdbaa80..1b9739b81 100644 --- a/src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx +++ b/src/components/image-editor/ImageCanvasBasicGenerationComposerView.test.tsx @@ -4,6 +4,7 @@ import { fireEvent, render, screen, within } from '@testing-library/react'; import { createRef, useState } from 'react'; import { describe, expect, it, vi } from 'vitest'; +import { setPlainTextEditorValue } from '../common/AutoGrowTextArea.test-utils'; import { ImageCanvasBasicGenerationComposerView } from './ImageCanvasBasicGenerationComposerView'; import type { GenerateDialogState, @@ -83,9 +84,7 @@ describe('ImageCanvasBasicGenerationComposerView', () => { />, ); - fireEvent.change(screen.getByLabelText('生成提示词'), { - target: { value: '新的提示' }, - }); + setPlainTextEditorValue(screen.getByLabelText('生成提示词'), '新的提示'); const panel = screen.getByRole('dialog', { name: '生成图片' }); expect( within(panel).queryByRole('textbox', { name: '资源名称' }), @@ -216,7 +215,9 @@ describe('ImageCanvasBasicGenerationComposerView', () => { name: '快速编辑提示词', }); - expect(prompt.className).toContain('auto-grow-text-area'); + expect(prompt.closest('.auto-grow-text-area')?.className).toContain( + 'auto-grow-text-area', + ); expect(prompt.className).not.toContain('platform-text-field'); fireEvent.keyDown(prompt, { key: 'Enter' }); expect(submitQuickEdit).not.toHaveBeenCalled(); diff --git a/src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx b/src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx index aed7bcf1f..ddc7fd156 100644 --- a/src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx +++ b/src/components/image-editor/ImageCanvasCharacterAnimationPanelView.test.tsx @@ -4,9 +4,12 @@ import { fireEvent, render, screen } from '@testing-library/react'; import { useState } from 'react'; import { describe, expect, it, vi } from 'vitest'; +import { setPlainTextEditorValue } from '../common/AutoGrowTextArea.test-utils'; import { ImageCanvasCharacterAnimationPanelView } from './ImageCanvasCharacterAnimationPanelView'; -import type { CanvasLayer, CharacterAnimationPanelState } from './ImageCanvasEditorTypes'; - +import type { + CanvasLayer, + CharacterAnimationPanelState, +} from './ImageCanvasEditorTypes'; function createSourceLayer(): CanvasLayer { return { @@ -61,14 +64,11 @@ function CharacterAnimationPanelHarness({ currentPanel ? { ...currentPanel, - frameCount: - frameCount === 48 ? 48 : frameCount === 40 ? 40 : 32, + frameCount: frameCount === 48 ? 48 : frameCount === 40 ? 40 : 32, durationSeconds: frameCount === 48 ? 6 : frameCount === 40 ? 5 : 4, status: - currentPanel.status === 'failed' - ? 'idle' - : currentPanel.status, + currentPanel.status === 'failed' ? 'idle' : currentPanel.status, errorMessage: currentPanel.status === 'failed' ? undefined @@ -114,12 +114,12 @@ describe('ImageCanvasCharacterAnimationPanelView', () => { ); const description = screen.getByLabelText('动画描述'); - 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'); - fireEvent.change(description, { - target: { value: `${'a'.repeat(4001)}` }, - }); + setPlainTextEditorValue(description, 'a'.repeat(4001)); fireEvent.click( screen.getByRole('button', { name: '动画参数 同图尺寸 · 4秒 · 480p' }), ); @@ -128,7 +128,9 @@ describe('ImageCanvasCharacterAnimationPanelView', () => { fireEvent.click(screen.getByRole('button', { name: '比例 16:9' })); expect(screen.getByRole('menu', { name: '动画参数选项' })).toBeTruthy(); - expect(screen.getByLabelText('当前动画描述').textContent).toHaveLength(4000); + expect(screen.getByLabelText('当前动画描述').textContent).toHaveLength( + 4000, + ); expect(screen.getByLabelText('当前分辨率').textContent).toBe('720p'); expect(screen.getByLabelText('当前比例').textContent).toBe('16:9'); expect(menu).toBeTruthy(); @@ -142,9 +144,7 @@ describe('ImageCanvasCharacterAnimationPanelView', () => { }); it('clicks the parent animation panel to collapse the parameter menu', () => { - render( - , - ); + render(); fireEvent.click( screen.getByRole('button', { name: '动画参数 同图尺寸 · 4秒 · 480p' }), @@ -211,15 +211,17 @@ describe('ImageCanvasCharacterAnimationPanelView', () => { fireEvent.click(screen.getByRole('button', { name: '生成中' })); - const description = screen.getByLabelText( - '动画描述', - ) as HTMLTextAreaElement; - expect(description.disabled).toBe(true); - expect(description.className).toContain('disabled:cursor-not-allowed'); - expect(description.className).toContain('disabled:opacity-60'); - expect((screen.getByRole('button', { name: '待机' }) as HTMLButtonElement).disabled).toBe( - true, - ); + const description = screen.getByLabelText('动画描述'); + expect(description.getAttribute('aria-disabled')).toBe('true'); + expect( + description + .closest('.auto-grow-text-area') + ?.getAttribute('data-disabled'), + ).toBe('true'); + expect( + (screen.getByRole('button', { name: '待机' }) as HTMLButtonElement) + .disabled, + ).toBe(true); expect(submitCharacterAnimation).not.toHaveBeenCalled(); }); diff --git a/src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx b/src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx index 02a333b7d..f17ab7f24 100644 --- a/src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx +++ b/src/components/image-editor/ImageCanvasEditorGenerationIntegration.test.tsx @@ -12,6 +12,7 @@ import userEvent from '@testing-library/user-event'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import type { ExternalGenerationTaskRecord } from '../../../packages/shared/src/contracts/externalGeneration'; +import { setPlainTextEditorValue } from '../common/AutoGrowTextArea.test-utils'; import { ApiClientError, defaultEditorProjectLayers, @@ -554,9 +555,9 @@ describe('ImageCanvasEditorView generation integration', () => { expect(screen.queryByLabelText('图像生成占位图')).toBeNull(); const generateDialog = screen.getByRole('dialog', { name: '生成图片' }); expect(generateDialog).toBeTruthy(); - expect( - (screen.getByLabelText('生成提示词') as HTMLTextAreaElement).value, - ).toBe('刷新后恢复生成器'); + expect(screen.getByLabelText('生成提示词').textContent).toBe( + '刷新后恢复生成器', + ); }); it('restores generated image composer from layer metadata when the dialog snapshot is missing', async () => { @@ -609,9 +610,9 @@ describe('ImageCanvasEditorView generation integration', () => { expect( await screen.findByRole('dialog', { name: '生成图片' }), ).toBeTruthy(); - expect( - (screen.getByLabelText('生成提示词') as HTMLTextAreaElement).value, - ).toBe('元数据恢复生成器'); + expect(screen.getByLabelText('生成提示词').textContent).toBe( + '元数据恢复生成器', + ); }); it('does not open a generator on direct click for tagged uploaded images', async () => { @@ -781,11 +782,9 @@ describe('ImageCanvasEditorView generation integration', () => { ).value, ).toBe('非对称对抗'); expect( - ( - within(publicationDialog).getByRole('textbox', { - name: '运营海报一句话描述游戏', - }) as HTMLTextAreaElement - ).value, + within(publicationDialog).getByRole('textbox', { + name: '运营海报一句话描述游戏', + }).textContent, ).toBe('找到钥匙,开门逃离马戏团'); expect(within(publicationDialog).getByLabelText('首图参考')).toBeTruthy(); expect(screen.getByLabelText('宣发素材生成占位图')).toBeTruthy(); @@ -838,9 +837,11 @@ describe('ImageCanvasEditorView generation integration', () => { .className, ).toContain('image-canvas-editor__reference-chip'); const generatePrompt = screen.getByLabelText('生成提示词'); - expect(generatePrompt.className).toContain('auto-grow-text-area'); + expect(generatePrompt.closest('.auto-grow-text-area')?.className).toContain( + 'auto-grow-text-area', + ); expect(generatePrompt.className).not.toContain('platform-text-field'); - expect(generatePrompt.className).toContain( + expect(generatePrompt.closest('.auto-grow-text-area')?.className).toContain( 'image-canvas-editor__generation-prompt', ); expect( @@ -865,9 +866,10 @@ describe('ImageCanvasEditorView generation integration', () => { ).toContain('image-canvas-editor__generation-submit'); expect(screen.getByRole('toolbar', { name: 'AI画布工具栏' })).toBeTruthy(); - fireEvent.change(screen.getByLabelText('生成提示词'), { - target: { value: '一张明亮的拼图主视觉' }, - }); + setPlainTextEditorValue( + screen.getByLabelText('生成提示词'), + '一张明亮的拼图主视觉', + ); fireEvent.click(pixelArtToggle); fireEvent.click( within(generateDialog).getByRole('button', { name: '生成' }), @@ -890,9 +892,7 @@ describe('ImageCanvasEditorView generation integration', () => { }); const submittedGenerationInputs = generateEditorImageMock.mock.calls[0]?.[0]?.generationInputs; - expect(JSON.stringify(submittedGenerationInputs)).not.toContain( - 'pixelArt', - ); + expect(JSON.stringify(submittedGenerationInputs)).not.toContain('pixelArt'); await waitFor(() => { expect(screen.getByAltText(/画布图片:生成图片/)).toBeTruthy(); @@ -979,9 +979,10 @@ describe('ImageCanvasEditorView generation integration', () => { const draggedFrameCenterY = Number.parseFloat(draggedFrame.style.top) + Number.parseFloat(draggedFrame.style.height) / 2; - fireEvent.change(screen.getByLabelText('生成提示词'), { - target: { value: '拖拽后的生成图' }, - }); + setPlainTextEditorValue( + screen.getByLabelText('生成提示词'), + '拖拽后的生成图', + ); fireEvent.click(screen.getByRole('button', { name: '生成' })); await waitFor(() => { @@ -1019,9 +1020,10 @@ describe('ImageCanvasEditorView generation integration', () => { fireEvent.click(screen.getByRole('button', { name: '生成图片' })); const generateDialog = screen.getByRole('dialog', { name: '生成图片' }); - fireEvent.change(screen.getByLabelText('生成提示词'), { - target: { value: '生成中继续拖动的图片' }, - }); + setPlainTextEditorValue( + screen.getByLabelText('生成提示词'), + '生成中继续拖动的图片', + ); fireEvent.click( within(generateDialog).getByRole('button', { name: '生成' }), ); @@ -1098,9 +1100,10 @@ describe('ImageCanvasEditorView generation integration', () => { }); fireEvent.click(screen.getByRole('button', { name: '生成图片' })); - fireEvent.change(screen.getByLabelText('生成提示词'), { - target: { value: '准备删除的生成中图片' }, - }); + setPlainTextEditorValue( + screen.getByLabelText('生成提示词'), + '准备删除的生成中图片', + ); fireEvent.click(screen.getByRole('button', { name: '生成' })); const frame = screen.getByLabelText('图像生成占位图'); @@ -1213,9 +1216,10 @@ describe('ImageCanvasEditorView generation integration', () => { render(); fireEvent.click(screen.getByRole('button', { name: '生成图片' })); - fireEvent.change(screen.getByLabelText('生成提示词'), { - target: { value: '一张真实生成失败的图' }, - }); + setPlainTextEditorValue( + screen.getByLabelText('生成提示词'), + '一张真实生成失败的图', + ); fireEvent.click(screen.getByRole('button', { name: '生成' })); expect(screen.getByRole('status').textContent).toContain('生成中'); @@ -1240,9 +1244,10 @@ describe('ImageCanvasEditorView generation integration', () => { render(); fireEvent.click(screen.getByRole('button', { name: '生成图片' })); - fireEvent.change(screen.getByLabelText('生成提示词'), { - target: { value: '一张需要登录生成的图' }, - }); + setPlainTextEditorValue( + screen.getByLabelText('生成提示词'), + '一张需要登录生成的图', + ); fireEvent.click(screen.getByRole('button', { name: '生成' })); await waitFor(() => { @@ -1263,9 +1268,10 @@ describe('ImageCanvasEditorView generation integration', () => { '1:1', '2K', ); - fireEvent.change(screen.getByLabelText('生成提示词'), { - target: { value: '生成中的普通图片' }, - }); + setPlainTextEditorValue( + screen.getByLabelText('生成提示词'), + '生成中的普通图片', + ); fireEvent.click(screen.getByRole('button', { name: '生成' })); }, dialogName: '生成图片', @@ -1284,9 +1290,10 @@ describe('ImageCanvasEditorView generation integration', () => { screen.getByRole('menu', { name: '生成规范类型' }), ).getByRole('menuitem', { name: '自定义规范' }), ); - fireEvent.change(screen.getByLabelText('自定义规范提示词'), { - target: { value: '生成中的自定义规范图' }, - }); + setPlainTextEditorValue( + screen.getByLabelText('自定义规范提示词'), + '生成中的自定义规范图', + ); fireEvent.click( within(screen.getByRole('dialog', { name: '生成规范' })).getByRole( 'button', @@ -1306,9 +1313,10 @@ describe('ImageCanvasEditorView generation integration', () => { '2:3', '2K', ); - fireEvent.change(screen.getByLabelText('角色设定'), { - target: { value: '生成中的角色形象' }, - }); + setPlainTextEditorValue( + screen.getByLabelText('角色设定'), + '生成中的角色形象', + ); fireEvent.click(screen.getByRole('button', { name: '生成' })); }, dialogName: '生成角色形象', @@ -1397,12 +1405,12 @@ describe('ImageCanvasEditorView generation integration', () => { clientY: 120, }, ); - fireEvent.change( + setPlainTextEditorValue( within(screen.getByRole('dialog', { name: '生成图标素材' })).getByRole( 'textbox', { name: '素材描述' }, ), - { target: { value: '返回按钮' } }, + '返回按钮', ); fireEvent.click( within(screen.getByRole('dialog', { name: '生成图标素材' })).getByRole( @@ -1412,9 +1420,7 @@ describe('ImageCanvasEditorView generation integration', () => { ); await waitFor(() => { - expect( - screen.queryByRole('dialog', { name: '生成图标素材' }), - ).toBeNull(); + expect(screen.queryByRole('dialog', { name: '生成图标素材' })).toBeNull(); }); const frame = screen.getByLabelText('图标素材生成占位图'); expect(frame.className).toContain( @@ -1497,7 +1503,9 @@ describe('ImageCanvasEditorView generation integration', () => { fireEvent.change(screen.getByLabelText('角色视角'), { target: { value: '左向三分之二侧身站姿' }, }); - fireEvent.submit(specDialog); + fireEvent.click( + within(specDialog).getByRole('button', { name: '提交生成规范' }), + ); await waitFor(() => { expect(generateEditorImageMock).toHaveBeenCalledWith( @@ -1689,9 +1697,10 @@ describe('ImageCanvasEditorView generation integration', () => { const characterPanel = screen.getByRole('dialog', { name: '生成角色形象', }); - fireEvent.change(within(characterPanel).getByLabelText('角色设定'), { - target: { value: '高个子游侠' }, - }); + setPlainTextEditorValue( + within(characterPanel).getByLabelText('角色设定'), + '高个子游侠', + ); fireEvent.click( within(characterPanel).getByRole('button', { name: '生成' }), ); @@ -1784,9 +1793,10 @@ describe('ImageCanvasEditorView generation integration', () => { }); selectGenerationModel(characterPanel, 'gpt-image-2'); selectGenerationDimensions(characterPanel, '2:3', '2K'); - fireEvent.change(within(characterPanel).getByLabelText('角色设定'), { - target: { value: '蓝衣剑士' }, - }); + setPlainTextEditorValue( + within(characterPanel).getByLabelText('角色设定'), + '蓝衣剑士', + ); fireEvent.click( within(characterPanel).getByRole('button', { name: '生成' }), ); @@ -1829,12 +1839,12 @@ describe('ImageCanvasEditorView generation integration', () => { screen.getByRole('dialog', { name: '生成图标素材' }), '图标规范 2', ); - fireEvent.change( + setPlainTextEditorValue( within(screen.getByRole('dialog', { name: '生成图标素材' })).getByRole( 'textbox', { name: '素材描述' }, ), - { target: { value: '返回按钮' } }, + '返回按钮', ); fireEvent.click( within(screen.getByRole('dialog', { name: '生成图标素材' })).getByRole( @@ -1910,9 +1920,10 @@ describe('ImageCanvasEditorView generation integration', () => { }); fireEvent.click(screen.getByRole('button', { name: '生成图片' })); - fireEvent.change(screen.getByLabelText('生成提示词'), { - target: { value: '生成中切换后仍保留位置' }, - }); + setPlainTextEditorValue( + screen.getByLabelText('生成提示词'), + '生成中切换后仍保留位置', + ); fireEvent.click(screen.getByRole('button', { name: '生成' })); const originalFrame = screen.getByLabelText('图像生成占位图'); @@ -2078,16 +2089,16 @@ describe('ImageCanvasEditorView generation integration', () => { iconPanel.querySelector('.image-canvas-editor__icon-spec-card'), ).toBeTruthy(); - fireEvent.change( + setPlainTextEditorValue( within(iconPanel).getByRole('textbox', { name: '素材描述' }), - { target: { value: '返回按钮\n设置按钮\n提示按钮' } }, + '返回按钮\n设置按钮\n提示按钮', ); const iconPrompt = within(iconPanel).getByRole('textbox', { name: '素材描述', }); - expect(iconPrompt.tagName).toBe('TEXTAREA'); - expect(iconPrompt.className).toContain( + expect(iconPrompt.getAttribute('contenteditable')).toBe('true'); + expect(iconPrompt.closest('.auto-grow-text-area')?.className).toContain( 'image-canvas-editor__generation-prompt', ); expect(iconPrompt.className).not.toContain( @@ -2118,9 +2129,10 @@ describe('ImageCanvasEditorView generation integration', () => { render(); fireEvent.click(screen.getByRole('button', { name: '生成图片' })); - fireEvent.change(screen.getByLabelText('生成提示词'), { - target: { value: '发光蘑菇角色' }, - }); + setPlainTextEditorValue( + screen.getByLabelText('生成提示词'), + '发光蘑菇角色', + ); fireEvent.click(screen.getByRole('button', { name: '生成' })); const generatedImage = await screen.findByAltText(/画布图片:生成图片/u); @@ -2198,7 +2210,12 @@ describe('ImageCanvasEditorView generation integration', () => { fireEvent.change(screen.getByLabelText('美术风格'), { target: { value: '糖果玻璃拟物' }, }); - fireEvent.submit(screen.getByRole('dialog', { name: '生成规范' })); + fireEvent.click( + within(screen.getByRole('dialog', { name: '生成规范' })).getByRole( + 'button', + { name: '提交生成规范' }, + ), + ); await waitFor(() => { expect(generateEditorImageMock).toHaveBeenCalledWith( @@ -2248,10 +2265,16 @@ describe('ImageCanvasEditorView generation integration', () => { ), ); fireEvent.click(screen.getByRole('menuitem', { name: '自定义规范' })); - fireEvent.change(screen.getByLabelText('自定义规范提示词'), { - target: { value: ' 生成一张武器图标规范展板 ' }, - }); - fireEvent.submit(screen.getByRole('dialog', { name: '生成规范' })); + setPlainTextEditorValue( + screen.getByLabelText('自定义规范提示词'), + ' 生成一张武器图标规范展板 ', + ); + fireEvent.click( + within(screen.getByRole('dialog', { name: '生成规范' })).getByRole( + 'button', + { name: '提交生成规范' }, + ), + ); await waitFor(() => { expect(generateEditorImageMock).toHaveBeenCalledWith( @@ -2480,9 +2503,10 @@ describe('ImageCanvasEditorView generation integration', () => { const readyCharacterPanel = screen.getByRole('dialog', { name: '生成角色形象', }); - fireEvent.change(within(readyCharacterPanel).getByLabelText('角色设定'), { - target: { value: '银发游侠,蓝色披风,弓箭手,适合像素风战棋。' }, - }); + setPlainTextEditorValue( + within(readyCharacterPanel).getByLabelText('角色设定'), + '银发游侠,蓝色披风,弓箭手,适合像素风战棋。', + ); fireEvent.click( within(readyCharacterPanel).getByRole('button', { name: '生成' }), ); @@ -2495,10 +2519,7 @@ describe('ImageCanvasEditorView generation integration', () => { model: 'gemini-3.1-flash-image-preview', aspectRatio: '1:1', imageSize: '1K', - referenceImageSrcs: [ - 'resource-character-spec', - 'resource-big-fish', - ], + referenceImageSrcs: ['resource-character-spec', 'resource-big-fish'], projectId: 'editor-project-default', assetFolderId: 'project', assetKind: 'character', @@ -2633,11 +2654,9 @@ describe('ImageCanvasEditorView generation integration', () => { within(iconPanel).getByRole('button', { name: '图标规范' }), ).toBeTruthy(); expect( - ( - within(iconPanel).getByRole('textbox', { - name: '素材描述', - }) as HTMLTextAreaElement - ).value, + within(iconPanel).getByRole('textbox', { + name: '素材描述', + }).textContent, ).toBe(''); fireEvent.click( @@ -2677,11 +2696,9 @@ describe('ImageCanvasEditorView generation integration', () => { screen.queryByText('请选择画布中的图标规范,按 Esc 退出'), ).toBeNull(); - fireEvent.change( + setPlainTextEditorValue( within(iconPanel).getByRole('textbox', { name: '素材描述' }), - { - target: { value: '返回按钮\n设置按钮' }, - }, + '返回按钮\n设置按钮', ); fireEvent.click(within(iconPanel).getByRole('button', { name: '生成' })); @@ -2854,11 +2871,9 @@ describe('ImageCanvasEditorView generation integration', () => { clientY: 100, }, ); - fireEvent.change( + setPlainTextEditorValue( within(iconPanel).getByRole('textbox', { name: '素材描述' }), - { - target: { value: '返回按钮' }, - }, + '返回按钮', ); fireEvent.click(within(iconPanel).getByRole('button', { name: '生成' })); @@ -3139,11 +3154,9 @@ describe('ImageCanvasEditorView generation integration', () => { screen.queryByText('请选择画布中的图标规范,按 Esc 退出'), ).toBeNull(); - fireEvent.change( + setPlainTextEditorValue( within(iconPanel).getByRole('textbox', { name: '素材描述' }), - { - target: { value: '背包按钮' }, - }, + '背包按钮', ); fireEvent.click(within(iconPanel).getByRole('button', { name: '生成' })); @@ -3344,21 +3357,23 @@ describe('ImageCanvasEditorView generation integration', () => { ).toBeTruthy(); } fireEvent.click(within(panel).getByRole('button', { name: '待机' })); - expect( - (within(panel).getByLabelText('动画描述') as HTMLTextAreaElement).value, - ).toContain('待机'); + expect(within(panel).getByLabelText('动画描述').textContent).toContain( + '待机', + ); const longPrompt = '走'.repeat(4100); - fireEvent.change(within(panel).getByLabelText('动画描述'), { - target: { value: longPrompt }, - }); - expect( - (within(panel).getByLabelText('动画描述') as HTMLTextAreaElement).value, - ).toHaveLength(4000); + setPlainTextEditorValue( + within(panel).getByLabelText('动画描述'), + longPrompt, + ); + expect(within(panel).getByLabelText('动画描述').textContent).toHaveLength( + 4000, + ); const precisePrompt = 'The elderly market woman gently shifts weight while the basket sways.'; - fireEvent.change(within(panel).getByLabelText('动画描述'), { - target: { value: precisePrompt }, - }); + setPlainTextEditorValue( + within(panel).getByLabelText('动画描述'), + precisePrompt, + ); expect( within(panel).getByLabelText(`生成文本:${precisePrompt}`), ).toBeTruthy(); @@ -3428,10 +3443,9 @@ describe('ImageCanvasEditorView generation integration', () => { const remodelPanel = screen.getByRole('dialog', { name: '角色动画生成面板', }); - expect( - (within(remodelPanel).getByLabelText('动画描述') as HTMLTextAreaElement) - .value, - ).toBe(precisePrompt); + expect(within(remodelPanel).getByLabelText('动画描述').textContent).toBe( + precisePrompt, + ); }); it('extracts UI design assets from the floating toolbar and keeps the spritesheet on canvas', async () => { @@ -3687,9 +3701,10 @@ describe('ImageCanvasEditorView generation integration', () => { render(); fireEvent.click(screen.getByRole('button', { name: '生成图片' })); - fireEvent.change(screen.getByLabelText('生成提示词'), { - target: { value: '一张可修改的生成图' }, - }); + setPlainTextEditorValue( + screen.getByLabelText('生成提示词'), + '一张可修改的生成图', + ); fireEvent.click(screen.getByRole('button', { name: '生成' })); await waitFor(() => {