// @vitest-environment jsdom import { act, fireEvent, render, screen } from '@testing-library/react'; import { afterEach, describe, expect, it, vi } from 'vitest'; import type { Transform } from '../src/features/ui-editor/types/Transform'; import { TransformEditor } from '../src/view/ui-editor/components/Inspector/Transform/TransformEditor'; const transform: Transform = { anchor_min: [0, 0], anchor_max: [1, 1], offset_min: [10, 20], offset_max: [30, 40], }; function firePointerDown(element: HTMLElement, button: number) { const event = new Event('pointerdown', { bubbles: true }); Object.defineProperty(event, 'button', { value: button }); fireEvent(element, event); } function renderEditor(onChange = vi.fn()) { return { onChange, ...render(), }; } describe('TransformEditor corner offset controls', () => { afterEach(() => { vi.useRealTimers(); }); it('uses one X/Y input pair for the selected corner', () => { renderEditor(); expect( screen.getByRole('spinbutton', { name: '位置微调 X' }), ).toHaveProperty('value', '10'); expect( screen.getByRole('spinbutton', { name: '位置微调 Y' }), ).toHaveProperty('value', '20'); expect(screen.getAllByRole('spinbutton')).toHaveLength(2); fireEvent.click(screen.getByRole('button', { name: '右下角' })); expect( screen.getByRole('spinbutton', { name: '位置微调 X' }), ).toHaveProperty('value', '30'); expect( screen.getByRole('spinbutton', { name: '位置微调 Y' }), ).toHaveProperty('value', '40'); }); it('writes the selected corner input back to the matching offset component', () => { const { onChange } = renderEditor(); fireEvent.click(screen.getByRole('button', { name: '右上角' })); const xInput = screen.getByRole('spinbutton', { name: '位置微调 X' }); fireEvent.change(xInput, { target: { value: '55' } }); fireEvent.blur(xInput); expect(onChange).toHaveBeenLastCalledWith({ ...transform, offset_max: [55, 40], }); }); it('moves only the selected corner with direction keys', () => { const { onChange } = renderEditor(); fireEvent.click(screen.getByRole('button', { name: '右下角' })); fireEvent.click(screen.getByRole('button', { name: '右下角向左' })); expect(onChange).toHaveBeenLastCalledWith({ ...transform, offset_max: [29, 40], }); fireEvent.click(screen.getByRole('button', { name: '右下角向上' }), { shiftKey: true, }); expect(onChange).toHaveBeenLastCalledWith({ ...transform, offset_max: [30, 30], }); }); it('allows a click adjustment after a cancelled long press', () => { vi.useFakeTimers(); const { onChange } = renderEditor(); const button = screen.getByRole('button', { name: '左上角向右' }); firePointerDown(button, 0); act(() => { vi.advanceTimersByTime(350); }); fireEvent.pointerCancel(button); fireEvent.click(button); expect(onChange).toHaveBeenCalledTimes(2); }); it('does not start repeating for non-primary pointer buttons', () => { vi.useFakeTimers(); const { onChange } = renderEditor(); const button = screen.getByRole('button', { name: '左上角向右' }); firePointerDown(button, 2); act(() => { vi.advanceTimersByTime(350); }); expect(onChange).not.toHaveBeenCalled(); }); });