UNPKG

@shopware-ag/dive

Version:

Shopware Spatial Framework

628 lines (572 loc) 19.3 kB
import { DIVEBaseTool } from '../BaseTool'; import type DIVEOrbitControls from '../../controls/OrbitControls'; import type { DIVEScene } from '../../scene/Scene'; import { Vector3, type Intersection, type Object3D } from 'three'; import { type DIVEHoverable } from '../../interface/Hoverable'; import { type DIVEDraggable } from '../../interface/Draggable'; import { RaycasterIntersectObjectMock } from '../../../__mocks__/three'; /** * @jest-environment jsdom */ const mock_Canvas = { width: 0, height: 0, getContext: jest.fn(), clientWidth: 1000, clientHeight: 1000, offsetLeft: 0, offsetTop: 0, }; const mockController = { domElement: mock_Canvas, object: { isPerspectiveCamera: true, type: 'cameraP', }, } as unknown as DIVEOrbitControls; const mockScene = { children: [], } as unknown as DIVEScene; const abstractWrapper = class Wrapper extends DIVEBaseTool { constructor(scene: DIVEScene, controller: DIVEOrbitControls) { super(scene, controller); this.name = 'DIVEBaseTool'; } }; describe('dive/toolbox/DIVEBaseTool', () => { afterEach(() => { jest.clearAllMocks(); }); it('should instantiate', () => { const baseTool = new abstractWrapper(mockScene, mockController); expect(baseTool).toBeDefined(); }); it('should Activate', () => { const baseTool = new abstractWrapper(mockScene, mockController); expect(() => baseTool.Activate()).not.toThrow(); }); it('should Deactivate', () => { const baseTool = new abstractWrapper(mockScene, mockController); expect(() => baseTool.Deactivate()).not.toThrow(); }); it('should raycast', () => { const toolBox = new abstractWrapper(mockScene, mockController); RaycasterIntersectObjectMock.mockImplementationOnce(() => { return [ { object: { visible: true, }, } as unknown as Intersection, ]; }); expect(() => toolBox['raycast']()).not.toThrow(); expect(RaycasterIntersectObjectMock).toHaveBeenCalled(); }); it('should raycast with selection of objects', () => { const toolBox = new abstractWrapper(mockScene, mockController); const spy = jest .spyOn(toolBox['_raycaster'], 'intersectObjects') .mockImplementationOnce(() => { return [ { object: { visible: true, }, } as unknown as Intersection, ]; }); expect(() => toolBox['raycast']([])).not.toThrow(); expect(spy).toHaveBeenCalled(); }); it('should return correct pointerAnyDown', () => { const toolBox = new abstractWrapper(mockScene, mockController); expect(toolBox).toBeDefined(); expect(toolBox['_pointerAnyDown']).toBeDefined(); expect(toolBox['_pointerAnyDown']).toBe(false); toolBox['_pointerPrimaryDown'] = false; toolBox['_pointerMiddleDown'] = false; toolBox['_pointerSecondaryDown'] = false; expect(toolBox['_pointerAnyDown']).toBe(false); toolBox['_pointerPrimaryDown'] = true; toolBox['_pointerMiddleDown'] = false; toolBox['_pointerSecondaryDown'] = false; expect(toolBox['_pointerAnyDown']).toBe(true); toolBox['_pointerPrimaryDown'] = false; toolBox['_pointerMiddleDown'] = true; toolBox['_pointerSecondaryDown'] = false; expect(toolBox['_pointerAnyDown']).toBe(true); toolBox['_pointerPrimaryDown'] = false; toolBox['_pointerMiddleDown'] = false; toolBox['_pointerSecondaryDown'] = true; expect(toolBox['_pointerAnyDown']).toBe(true); }); it('should execute onPointerDown correctly', () => { const toolBox = new abstractWrapper(mockScene, mockController); expect(() => toolBox.onPointerDown({ button: 0 } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerDown({ button: 1 } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerDown({ button: 2 } as PointerEvent), ).not.toThrow(); const spy = jest.spyOn(console, 'warn').mockImplementation(); expect(() => toolBox.onPointerDown({ button: 666 } as PointerEvent), ).not.toThrow(); expect(spy).toHaveBeenCalled(); toolBox['_intersects'] = [ { distance: 1, point: { clone() { return { x: 1, y: 1, z: 1, } as unknown as Vector3; }, x: 1, y: 1, z: 1, } as unknown as Vector3, object: { uuid: 'uuid2', isHoverable: true, onPointerEnter() { return; }, } as unknown as Object3D & DIVEHoverable, }, ]; expect(() => toolBox.onPointerDown({ button: 0 } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerDown({ button: 1 } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerDown({ button: 2 } as PointerEvent), ).not.toThrow(); }); it('should execute onPointerMove correctly', () => { const toolBox = new abstractWrapper(mockScene, mockController); jest.spyOn(toolBox['_raycaster'], 'setFromCamera').mockImplementation(); const spy = jest.spyOn(toolBox['_raycaster'], 'intersectObjects'); // test with no hit with hovered object before spy.mockReturnValue([]); toolBox['_hovered'] = { uuid: 'uuid', onPointerLeave() { return; }, } as Object3D & DIVEHoverable; expect(() => toolBox.onPointerMove({ button: 0, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerMove({ button: 1, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerMove({ button: 2, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); // test with no hovered object spy.mockReturnValue([ { distance: 1, point: { x: 1, y: 1, z: 1, } as unknown as Vector3, object: { uuid: 'uuid', isHoverable: true, visible: true, } as Object3D & DIVEHoverable, }, ]); toolBox['_hovered'] = null; expect(() => toolBox.onPointerMove({ button: 0, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerMove({ button: 1, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerMove({ button: 2, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); // test with no hovered object with onPointerEnter spy.mockReturnValue([ { distance: 1, point: { x: 1, y: 1, z: 1, } as unknown as Vector3, object: { uuid: 'uuid', isHoverable: true, visible: true, onPointerEnter() { return; }, } as unknown as Object3D & DIVEHoverable, }, ]); expect(() => toolBox.onPointerMove({ button: 0, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerMove({ button: 1, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerMove({ button: 2, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); // test with same hovered object spy.mockReturnValue([ { distance: 1, point: { x: 1, y: 1, z: 1, } as unknown as Vector3, object: { uuid: 'uuid', isHoverable: true, visible: true, onPointerOver() { return; }, } as unknown as Object3D & DIVEHoverable, }, ]); toolBox['_hovered'] = { uuid: 'uuid', visible: true, onPointerLeave() { return; }, } as Object3D & DIVEHoverable; expect(() => toolBox.onPointerMove({ button: 0, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerMove({ button: 1, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerMove({ button: 2, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); // test with different hovered object spy.mockReturnValue([ { distance: 1, point: new Vector3(1, 1, 1), object: { uuid: 'uuid2', isHoverable: true, visible: true, onPointerEnter() { return; }, } as unknown as Object3D & DIVEHoverable, }, ]); toolBox['_hovered'] = { uuid: 'uuid', visible: true, onPointerLeave() { return; }, } as Object3D & DIVEHoverable; expect(() => toolBox.onPointerMove({ button: 0, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerMove({ button: 1, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerMove({ button: 2, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); // test with pointer down toolBox['_pointerPrimaryDown'] = true; expect(() => toolBox.onPointerMove({ button: 0, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerMove({ button: 1, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerMove({ button: 2, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); // test with pointer down while already dragging toolBox['_pointerPrimaryDown'] = true; toolBox['_dragging'] = true; expect(() => toolBox.onPointerMove({ button: 0, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerMove({ button: 1, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerMove({ button: 2, offsetX: 100, offsetY: 100, } as PointerEvent), ).not.toThrow(); spy.mockRestore(); }); it('should execute onPointerUp correctly', () => { const toolBox = new abstractWrapper(mockScene, mockController); expect(() => toolBox.onPointerUp({ button: 0 } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerUp({ button: 1 } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerUp({ button: 2 } as PointerEvent), ).not.toThrow(); toolBox['pointerWasDragged'] = () => { return true; }; toolBox['_dragging'] = true; toolBox['_intersects'] = [ { distance: 1, point: { clone() { return { x: 1, y: 1, z: 1, } as unknown as Vector3; }, x: 1, y: 1, z: 1, } as unknown as Vector3, object: { uuid: 'uuid2', isHoverable: true, onPointerEnter() { return; }, } as unknown as Object3D & DIVEHoverable, }, ]; toolBox['_draggable'] = { onDragEnd() { return; }, } as unknown as Object3D & DIVEDraggable; expect(() => toolBox.onPointerUp({ button: 0 } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerUp({ button: 1 } as PointerEvent), ).not.toThrow(); expect(() => toolBox.onPointerUp({ button: 2 } as PointerEvent), ).not.toThrow(); }); it('should execute onDragStart correctly', () => { const toolBox = new abstractWrapper(mockScene, mockController); expect(() => toolBox.onDragStart({} as PointerEvent)).not.toThrow(); toolBox['_draggable'] = { onDragStart() { return; }, } as unknown as Object3D & DIVEDraggable; expect(() => toolBox.onDragStart({} as PointerEvent)).not.toThrow(); toolBox['_dragRaycastOnObjects'] = []; jest.spyOn( toolBox['_raycaster'], 'intersectObjects', ).mockReturnValueOnce([]); expect(() => toolBox.onDragStart({} as PointerEvent)).not.toThrow(); jest.spyOn( toolBox['_raycaster'], 'intersectObjects', ).mockReturnValueOnce([]); expect(() => toolBox.onDragStart({} as PointerEvent)).not.toThrow(); jest.spyOn( toolBox['_raycaster'], 'intersectObjects', ).mockReturnValueOnce([ { distance: 1, point: { clone() { return { x: 1, y: 1, z: 1, } as unknown as Vector3; }, x: 1, y: 1, z: 1, } as unknown as Vector3, object: { uuid: 'uuid2', isHoverable: true, onPointerEnter() { return; }, } as unknown as Object3D & DIVEHoverable, }, ]); expect(() => toolBox.onDragStart({} as PointerEvent)).not.toThrow(); toolBox['_draggable'] = { onDragStart() { return; }, } as unknown as Object3D & DIVEDraggable; jest.spyOn( toolBox['_raycaster'], 'intersectObjects', ).mockReturnValueOnce([]); expect(() => toolBox.onDragStart({} as PointerEvent)).not.toThrow(); }); it('should execute onDrag correctly', () => { const toolBox = new abstractWrapper(mockScene, mockController); expect(() => toolBox.onDrag({} as PointerEvent)).not.toThrow(); toolBox['_dragRaycastOnObjects'] = []; jest.spyOn( toolBox['_raycaster'], 'intersectObjects', ).mockReturnValueOnce([]); expect(() => toolBox.onDrag({} as PointerEvent)).not.toThrow(); toolBox['_draggable'] = { onDrag() { return; }, } as unknown as Object3D & DIVEDraggable; jest.spyOn( toolBox['_raycaster'], 'intersectObjects', ).mockReturnValueOnce([ { distance: 1, point: { clone() { return { x: 1, y: 1, z: 1, } as unknown as Vector3; }, x: 1, y: 1, z: 1, } as unknown as Vector3, object: { uuid: 'uuid2', isHoverable: true, onPointerEnter() { return; }, } as unknown as Object3D & DIVEHoverable, }, ]); expect(() => toolBox.onDrag({} as PointerEvent)).not.toThrow(); }); it('should execute onCLick correctly', () => { const toolBox = new abstractWrapper(mockScene, mockController); expect(() => toolBox.onClick({} as PointerEvent)).not.toThrow(); }); it('should execute onDragEnd correctly', () => { const toolBox = new abstractWrapper(mockScene, mockController); expect(() => toolBox.onDragEnd({} as PointerEvent)).not.toThrow(); }); it('should execute onWheel correctly', () => { const toolBox = new abstractWrapper(mockScene, mockController); expect(() => toolBox.onWheel({} as WheelEvent)).not.toThrow(); }); });