UNPKG

@shopware-ag/dive

Version:

Shopware Spatial Framework

223 lines (190 loc) 6.77 kB
import { RaycasterIntersectObjectMock } from '../../../__mocks__/three'; import { DIVEModel } from '../Model'; import { DIVECommunication } from '../../com/Communication'; import { GLTF } from 'three/examples/jsm/loaders/GLTFLoader'; import { DIVEScene } from '../../scene/Scene'; import { Vector3, Box3, Mesh, MeshStandardMaterial, type Texture, Object3D, } from 'three'; import { type COMMaterial } from '../../com/types'; jest.mock('../../com/Communication.ts', () => { return { DIVECommunication: { get: jest.fn(() => { return { PerformAction: jest.fn(), }; }), }, }; }); const object = new Object3D(); object.children.push(new Mesh()); const gltf = { scene: { ...object, }, } as unknown as GLTF; jest.spyOn(DIVECommunication, 'get').mockReturnValue({ PerformAction: jest.fn(), } as unknown as DIVECommunication); let model: DIVEModel; describe('dive/model/DIVEModel', () => { beforeEach(() => { jest.clearAllMocks(); RaycasterIntersectObjectMock.mockClear(); model = new DIVEModel(); }); afterEach(() => { jest.clearAllMocks(); }); it('should instantiate', () => { expect(model).toBeDefined(); }); it('should set model', () => { expect(() => model.SetModel(gltf)).not.toThrow(); }); it('should place on floor', () => { model.SetModel(gltf); const com = DIVECommunication.get('id')!; const spyPerformAction = jest.spyOn(com, 'PerformAction'); model.userData.id = 'something'; model.position.set(0, 4, 0); jest.spyOn(model['_mesh']!, 'localToWorld').mockReturnValueOnce( new Vector3(0, 2, 0), ); const scene = { parent: null, Root: { children: [ model, ], }, } as unknown as DIVEScene; scene.Root.parent = scene; model.parent = scene.Root; expect(() => model.PlaceOnFloor()).not.toThrow(); expect(spyPerformAction).toHaveBeenCalledWith( 'UPDATE_OBJECT', expect.objectContaining({ position: expect.objectContaining({ y: 2, }), }), ); }); it('should drop it', () => { const comMock = { PerformAction: jest.fn(), } as unknown as DIVECommunication; jest.spyOn(DIVECommunication, 'get').mockReturnValue(comMock); const spy = jest.spyOn(model, 'onMove').mockImplementation(() => {}); const size = { x: 1, y: 1, z: 1, }; model.userData.id = 'something'; model.position.set(0, 4, 0); model['_boundingBox'] = { min: new Vector3(-size.x / 2, -size.y / 2, -size.z / 2), max: new Vector3(size.x / 2, size.y / 2, size.z / 2), getCenter: jest.fn(() => { return new Vector3(0, 0, 0); }), } as unknown as Box3; const hitObject = new Mesh(); hitObject.geometry.boundingBox = new Box3(); hitObject.geometry.boundingBox.max = new Vector3(0, 2, 0); RaycasterIntersectObjectMock.mockReturnValue([ { object: hitObject, }, ]); const scene = { parent: null, Root: { children: [ model, ], }, } as unknown as DIVEScene; scene.Root.parent = scene; // test when parent is not set console.warn = jest.fn(); expect(() => model.DropIt()).not.toThrow(); expect(console.warn).toHaveBeenCalledTimes(1); model.parent = scene.Root; expect(() => model.DropIt()).not.toThrow(); expect(model.position.y).toBe(2.5); expect(spy).toHaveBeenCalledTimes(1); expect(() => model.DropIt()).not.toThrow(); expect(spy).toHaveBeenCalledTimes(1); // alter position so onMove will be called again model.position.y = 2; jest.spyOn(DIVECommunication, 'get').mockReturnValueOnce(undefined); expect(() => model.DropIt()).not.toThrow(); expect(spy).toHaveBeenCalledTimes(2); }); it('should set material', () => { // apply invalid material should not crash expect(() => model.SetMaterial({} as COMMaterial)).not.toThrow(); expect(model['_material']).not.toBeNull(); expect(() => model.SetMaterial({ color: 0xffffff, roughness: 0, metalness: 1, } as COMMaterial), ).not.toThrow(); expect((model['_material'] as MeshStandardMaterial).roughness).toBe(0); expect( (model['_material'] as MeshStandardMaterial).roughnessMap, ).toBeUndefined(); expect((model['_material'] as MeshStandardMaterial).metalness).toBe(1); expect( (model['_material'] as MeshStandardMaterial).metalnessMap, ).toBeUndefined(); expect(() => model.SetMaterial({ color: 0xff00ff, vertexColors: true, map: 'This_Is_A_Texture' as unknown as Texture, normalMap: 'This_Is_A_Texture' as unknown as Texture, roughness: 0, roughnessMap: 'This_Is_A_Texture' as unknown as Texture, metalness: 1, metalnessMap: 'This_Is_A_Texture' as unknown as Texture, } as COMMaterial), ).not.toThrow(); expect((model['_material'] as MeshStandardMaterial).roughness).toBe(1); expect( (model['_material'] as MeshStandardMaterial).roughnessMap, ).toBeDefined(); expect((model['_material'] as MeshStandardMaterial).metalness).toBe(1); expect( (model['_material'] as MeshStandardMaterial).metalnessMap, ).toBeDefined(); }); it('should set model material when material already set before', () => { model.SetMaterial({ roughness: 0.5 } as COMMaterial); expect(() => model.SetModel(gltf)).not.toThrow(); expect( (model['_mesh']?.material as MeshStandardMaterial).roughness, ).toBe(0.5); }); it('should set material to model when model already set before', () => { model.SetModel(gltf); expect(() => model.SetMaterial({ roughness: 0.5 } as COMMaterial), ).not.toThrow(); expect( (model['_mesh']?.material as MeshStandardMaterial).roughness, ).toBe(0.5); }); });