From 46db6055fa8fbf41ffe0cbb87e91f56e76f65718 Mon Sep 17 00:00:00 2001 From: Yunine Date: Sun, 19 Jul 2026 18:56:31 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A1=A5=E5=85=85=E7=94=BB=E5=B8=83=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E4=BA=A4=E4=BA=92=E4=BA=8B=E4=BB=B6=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../useImageCanvasStageInteractions.test.tsx | 242 ++++++++++++++++-- 1 file changed, 223 insertions(+), 19 deletions(-) diff --git a/src/components/image-editor/useImageCanvasStageInteractions.test.tsx b/src/components/image-editor/useImageCanvasStageInteractions.test.tsx index 9c1ccdde9..acb03151a 100644 --- a/src/components/image-editor/useImageCanvasStageInteractions.test.tsx +++ b/src/components/image-editor/useImageCanvasStageInteractions.test.tsx @@ -1,6 +1,6 @@ /* @vitest-environment jsdom */ -import { act, render, screen } from '@testing-library/react'; +import { act, fireEvent, render, screen } from '@testing-library/react'; import { type PointerEvent as ReactPointerEvent, useRef, @@ -309,7 +309,10 @@ function StageInteractionsHarness({ {layers - .map((layer) => `${layer.id}:${layer.x.toFixed(1)},${layer.y.toFixed(1)}`) + .map( + (layer) => + `${layer.id}:${layer.x.toFixed(1)},${layer.y.toFixed(1)}`, + ) .join('|')} @@ -323,7 +326,9 @@ function StageInteractionsHarness({ {String(interaction.isPanning)} {interaction.effectiveTool} - {interaction.snapGuide?.vertical ?? interaction.snapGuide?.horizontal ?? '-'} + {interaction.snapGuide?.vertical ?? + interaction.snapGuide?.horizontal ?? + '-'} {generateDialog?.placeholder @@ -337,9 +342,7 @@ function StageInteractionsHarness({ {String(generateDialog?.composerOpen ?? false)} {clearCount} - - {imageMenuCloseCount} - + {imageMenuCloseCount} + + + + ); } @@ -778,7 +861,9 @@ describe('useImageCanvasStageInteractions', () => { act(() => { screen.getByRole('button', { name: '直接移动平移' }).click(); }); - expect(screen.getByTestId('viewport-state').textContent).toBe('30.0,25.0,1'); + expect(screen.getByTestId('viewport-state').textContent).toBe( + '30.0,25.0,1', + ); act(() => { screen.getByRole('button', { name: '清理交互' }).click(); }); @@ -800,9 +885,7 @@ describe('useImageCanvasStageInteractions', () => { render(); act(() => { - screen - .getByRole('button', { name: '直接贴近图层拖生成占位' }) - .click(); + screen.getByRole('button', { name: '直接贴近图层拖生成占位' }).click(); }); expect(screen.getByTestId('dialog-position').textContent).toBe( @@ -844,8 +927,9 @@ describe('useImageCanvasStageInteractions', () => { act(() => { screen.getByRole('button', { name: '直接追加生成器' }).click(); }); - const generationSelectionId = - screen.getByTestId('dialog-selection-id').textContent; + const generationSelectionId = screen.getByTestId( + 'dialog-selection-id', + ).textContent; expect(screen.getByTestId('selection').textContent).toBe( `first:first,${generationSelectionId}`, ); @@ -921,15 +1005,15 @@ describe('useImageCanvasStageInteractions', () => { expect(onViewportInteractionEnd).toHaveBeenCalledTimes(2); }); - it('allows middle-button dragging and rejects right-button dragging', () => { + it('allows middle-button dragging and rejects right-button dragging in select, hand, and Space modes', () => { render(); const viewport = screen.getByTestId('viewport'); act(() => { fireEvent( - viewport, - new MouseEvent('pointerdown',{ + viewport, + new MouseEvent('pointerdown', { bubbles: true, clientX: 100, clientY: 100, @@ -942,8 +1026,8 @@ describe('useImageCanvasStageInteractions', () => { act(() => { fireEvent( - viewport, - new MouseEvent('pointerup',{ + viewport, + new MouseEvent('pointerup', { bubbles: true, clientX: 100, clientY: 100, @@ -956,8 +1040,49 @@ describe('useImageCanvasStageInteractions', () => { act(() => { fireEvent( - viewport, - new MouseEvent('pointerdown',{ + viewport, + new MouseEvent('pointerdown', { + bubbles: true, + clientX: 100, + clientY: 100, + button: 2, + buttons: 2, + }), + ); + }); + expect(screen.getByTestId('panning').textContent).toBe('false'); + + act(() => { + screen.getByRole('button', { name: '切抓手' }).click(); + }); + expect(screen.getByTestId('tool').textContent).toBe('hand'); + + act(() => { + fireEvent( + viewport, + new MouseEvent('pointerdown', { + bubbles: true, + clientX: 100, + clientY: 100, + button: 2, + buttons: 2, + }), + ); + }); + expect(screen.getByTestId('panning').textContent).toBe('false'); + + act(() => { + screen.getByRole('button', { name: '松开空格' }).click(); + }); + act(() => { + screen.getByRole('button', { name: '按住空格' }).click(); + }); + expect(screen.getByTestId('tool').textContent).toBe('hand'); + + act(() => { + fireEvent( + viewport, + new MouseEvent('pointerdown', { bubbles: true, clientX: 100, clientY: 100, @@ -968,4 +1093,83 @@ describe('useImageCanvasStageInteractions', () => { }); expect(screen.getByTestId('panning').textContent).toBe('false'); }); + + it('rejects right-click panning on layers in select, hand, and Space modes', () => { + render(); + + act(() => { + screen.getByRole('button', { name: '右键选第一层' }).click(); + }); + expect(screen.getByTestId('panning').textContent).toBe('false'); + expect(screen.getByTestId('selection').textContent).toBe('-:'); + + act(() => { + screen.getByRole('button', { name: '右键抓手模式选第一层' }).click(); + }); + expect(screen.getByTestId('panning').textContent).toBe('false'); + expect(screen.getByTestId('tool').textContent).toBe('hand'); + expect(screen.getByTestId('selection').textContent).toBe('-:'); + + act(() => { + screen.getByRole('button', { name: '松开空格' }).click(); + }); + act(() => { + screen.getByRole('button', { name: '按住空格' }).click(); + }); + expect(screen.getByTestId('tool').textContent).toBe('hand'); + + act(() => { + const layer = screen.getByTestId('layer-first'); + fireEvent( + layer, + new MouseEvent('pointerdown', { + bubbles: true, + clientX: 40, + clientY: 40, + button: 2, + buttons: 2, + }), + ); + }); + expect(screen.getByTestId('panning').textContent).toBe('false'); + expect(screen.getByTestId('selection').textContent).toBe('-:'); + }); + + it('rejects right-click panning on generation frames in select, hand, and Space modes', () => { + render(); + + act(() => { + screen.getByRole('button', { name: '右键拖生成占位' }).click(); + }); + expect(screen.getByTestId('panning').textContent).toBe('false'); + + act(() => { + screen.getByRole('button', { name: '右键抓手模式拖生成占位' }).click(); + }); + expect(screen.getByTestId('panning').textContent).toBe('false'); + expect(screen.getByTestId('tool').textContent).toBe('hand'); + + act(() => { + screen.getByRole('button', { name: '松开空格' }).click(); + }); + act(() => { + screen.getByRole('button', { name: '按住空格' }).click(); + }); + expect(screen.getByTestId('tool').textContent).toBe('hand'); + + act(() => { + const frame = screen.getByTestId('generation-frame'); + fireEvent( + frame, + new MouseEvent('pointerdown', { + bubbles: true, + clientX: 300, + clientY: 200, + button: 2, + buttons: 2, + }), + ); + }); + expect(screen.getByTestId('panning').textContent).toBe('false'); + }); });