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');
+ });
});