import { act, fireEvent, screen } from "@testing-library/react"; import { describe, expect, it, vi } from "vitest"; import { DEFAULT_TOOLCRAFT_ORIENTATION_POSE, getToolcraftOrientationPoseFromPointerDelta, readToolcraftOrientationPose, } from "./orientation-gizmo-math"; import { expectOrientationPoseClose, mockModelSurfaceBounds, renderOrientationGizmoRuntime, } from "./orientation-gizmo-test-harness"; describe("Toolcraft direct model orbit integration", () => { it("ends direct orbit ownership when pointer capture is lost", () => { vi.useFakeTimers(); const store = renderOrientationGizmoRuntime(); const surface = screen.getByTestId("model-surface"); mockModelSurfaceBounds(surface); fireEvent.pointerDown(surface, { button: 0, clientX: 100, clientY: 100, pointerId: 10, }); fireEvent.lostPointerCapture(surface, { pointerId: 10 }); fireEvent.pointerMove(surface, { clientX: 130, clientY: 120, pointerId: 10, }); act(() => { vi.advanceTimersByTime(20); }); expect(store.getState().values["view.orbit"]).toEqual( DEFAULT_TOOLCRAFT_ORIENTATION_POSE, ); }); it("orbits on a model hit and leaves canvas pan untouched", () => { vi.useFakeTimers(); const store = renderOrientationGizmoRuntime(); const surface = screen.getByTestId("model-surface"); mockModelSurfaceBounds(surface); fireEvent.pointerDown(surface, { button: 0, clientX: 100, clientY: 100, pointerId: 2, }); fireEvent.pointerMove(surface, { clientX: 130, clientY: 112, pointerId: 2, }); act(() => { vi.advanceTimersByTime(20); }); fireEvent.pointerUp(surface, { pointerId: 2 }); expect(store.getState().canvas.offset).toEqual({ x: 0, y: 0 }); expectOrientationPoseClose( readToolcraftOrientationPose(store.getState().values["view.orbit"]), getToolcraftOrientationPoseFromPointerDelta( DEFAULT_TOOLCRAFT_ORIENTATION_POSE, 30, 12, ), ); act(() => { store.dispatch({ type: "history.undo" }); }); expect(store.getState().values["view.orbit"]).toEqual( DEFAULT_TOOLCRAFT_ORIENTATION_POSE, ); }); it("passes a model miss to canvas pan", () => { const store = renderOrientationGizmoRuntime({ hit: false }); const surface = screen.getByTestId("model-surface"); fireEvent.pointerDown(surface, { button: 0, clientX: 10, clientY: 20, pointerId: 3, }); fireEvent.pointerMove(surface, { clientX: 30, clientY: 45, pointerId: 3, }); fireEvent.pointerUp(surface, { pointerId: 3 }); expect(store.getState().canvas.offset).toEqual({ x: 20, y: 25 }); expect(store.getState().values["view.orbit"]).toEqual( DEFAULT_TOOLCRAFT_ORIENTATION_POSE, ); }); it("passes a modified primary press to canvas pan even on a model hit", () => { const store = renderOrientationGizmoRuntime({ hit: true }); const surface = screen.getByTestId("model-surface"); fireEvent.pointerDown(surface, { button: 0, clientX: 10, clientY: 20, pointerId: 4, shiftKey: true, }); fireEvent.pointerMove(surface, { clientX: 25, clientY: 30, pointerId: 4, shiftKey: true, }); fireEvent.pointerUp(surface, { pointerId: 4, shiftKey: true }); expect(store.getState().canvas.offset).toEqual({ x: 15, y: 10 }); expect(store.getState().values["view.orbit"]).toEqual( DEFAULT_TOOLCRAFT_ORIENTATION_POSE, ); }); });