-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test(react-components): added test for few hooks (#4767)
* added useCameraNavigation and use3dModels test files * type error fix
- Loading branch information
Showing
8 changed files
with
310 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,21 @@ | ||
import { type CogniteCadModel } from '@cognite/reveal'; | ||
import { Mock } from 'moq.ts'; | ||
import { Matrix4 } from 'three'; | ||
import { It, Mock } from 'moq.ts'; | ||
import { Box3, Matrix4, Vector3 } from 'three'; | ||
|
||
export const cadModelOptions = { | ||
modelId: 123, | ||
revisionId: 456 | ||
}; | ||
|
||
export const nodeBoundingBox = new Box3(new Vector3(1, 1, 1), new Vector3(2, 2, 2)); | ||
|
||
export const cadMock = new Mock<CogniteCadModel>() | ||
.setup((p) => p.modelId) | ||
.returns(cadModelOptions.modelId) | ||
.setup((p) => p.revisionId) | ||
.returns(cadModelOptions.revisionId) | ||
.setup((p) => p.getModelTransformation()) | ||
.returns(new Matrix4()) | ||
.setup(async (p) => await p.getBoundingBoxesByNodeIds(It.IsAny())) | ||
.returns(Promise.resolve([nodeBoundingBox])) | ||
.object(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
react-components/tests/unit-tests/fixtures/fdmNodeCache.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { Mock } from 'moq.ts'; | ||
import { type FdmNodeCache } from '../../../src/components/CacheProvider/FdmNodeCache'; | ||
import { type FdmNodeCacheContent } from '../../../src/components/CacheProvider/NodeCacheProvider'; | ||
import { type DmsUniqueIdentifier } from '../../../src/data-providers/FdmSDK'; | ||
import { type TypedReveal3DModel } from '../../../src/components/Reveal3DResources/types'; | ||
import { type Node3D } from '@cognite/sdk'; | ||
import { | ||
type FdmCadConnection, | ||
type FdmConnectionWithNode | ||
} from '../../../src/components/CacheProvider/types'; | ||
|
||
const fdmNodeCacheMock = new Mock<FdmNodeCache>() | ||
.setup((instance) => instance.getAllMappingExternalIds) | ||
.returns( | ||
async ( | ||
modelRevisionIds: Array<{ modelId: number; revisionId: number }>, | ||
_fetchViews: boolean | ||
) => { | ||
return new Map( | ||
modelRevisionIds.map(({ modelId, revisionId }) => [ | ||
`${modelId}/${revisionId}`, | ||
[ | ||
{ | ||
connection: { | ||
instance: { space: 'space', externalId: 'id' }, | ||
modelId, | ||
revisionId, | ||
treeIndex: 1 | ||
} satisfies FdmCadConnection, | ||
cadNode: { | ||
id: 1, | ||
treeIndex: 1, | ||
parentId: 0, | ||
depth: 0, | ||
name: 'node-name', | ||
subtreeSize: 1 | ||
} satisfies Node3D | ||
} satisfies FdmConnectionWithNode | ||
] | ||
]) | ||
); | ||
} | ||
) | ||
.setup((instance) => instance.getClosestParentDataPromises) | ||
.returns((modelId: number, revisionId: number, treeIndex: number) => { | ||
return { | ||
modelId, | ||
revisionId, | ||
treeIndex, | ||
data: `data-for-${modelId}-${revisionId}-${treeIndex}`, | ||
cadAndFdmNodesPromise: Promise.resolve(undefined), | ||
viewsPromise: Promise.resolve([]) | ||
}; | ||
}) | ||
.setup((instance) => instance.getMappingsForFdmInstances) | ||
.returns(async (fdmAssetExternalIds: DmsUniqueIdentifier[], models: TypedReveal3DModel[]) => { | ||
return models.map((model) => ({ | ||
modelId: model.modelId, | ||
revisionId: model.revisionId, | ||
mappings: new Map(fdmAssetExternalIds.map((id) => [JSON.stringify(id), [] as Node3D[]])) | ||
})); | ||
}); | ||
|
||
const fdmNodeCacheContentMock: FdmNodeCacheContent = { | ||
cache: fdmNodeCacheMock.object() | ||
}; | ||
|
||
export { fdmNodeCacheContentMock }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 75 additions & 0 deletions
75
react-components/tests/unit-tests/hooks/use3dModels.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import { describe, expect, test, vi, beforeEach, beforeAll, afterAll } from 'vitest'; | ||
import { use3dModels } from '../../../src/hooks/use3dModels'; | ||
import { CogniteCadModel, type CogniteModel } from '@cognite/reveal'; | ||
import { renderHook } from '@testing-library/react'; | ||
|
||
import { viewerMock, viewerModelsMock } from '../fixtures/viewer'; | ||
import { cadMock, cadModelOptions } from '../fixtures/cadModel'; | ||
import { Mock } from 'moq.ts'; | ||
import { Matrix4 } from 'three'; | ||
|
||
const mockResourceCount = { reveal3DResourcesCount: 2 }; | ||
|
||
vi.mock('../../../src/components/RevealCanvas/ViewerContext', () => ({ | ||
useReveal: () => viewerMock | ||
})); | ||
|
||
vi.mock('../../../src/components/Reveal3DResources/Reveal3DResourcesInfoContext', () => ({ | ||
useReveal3DResourcesCount: () => mockResourceCount | ||
})); | ||
|
||
describe('use3dModels', () => { | ||
beforeEach(() => { | ||
vi.resetAllMocks(); | ||
}); | ||
|
||
beforeAll(() => { | ||
vi.useFakeTimers(); | ||
}); | ||
|
||
afterAll(() => { | ||
vi.useRealTimers(); | ||
}); | ||
|
||
test('returns models from viewer', () => { | ||
const mockModels: CogniteModel[] = [cadMock, cadMock]; | ||
viewerModelsMock.mockReturnValue(mockModels); | ||
|
||
const { result } = renderHook(() => use3dModels()); | ||
|
||
expect(result.current).toEqual(mockModels); | ||
}); | ||
|
||
test('updates models when viewer or resourceCount changes', () => { | ||
const mockModels: CogniteModel[] = [cadMock, cadMock]; | ||
viewerModelsMock.mockReturnValue(mockModels); | ||
|
||
const { result, rerender } = renderHook(() => use3dModels()); | ||
|
||
expect(result.current).toEqual(mockModels); | ||
|
||
const newCadModelOptions = { | ||
modelId: 987, | ||
revisionId: 654 | ||
}; | ||
|
||
const newCadMock = new Mock<CogniteCadModel>() | ||
.setup((p) => p.modelId) | ||
.returns(newCadModelOptions.modelId) | ||
.setup((p) => p.revisionId) | ||
.returns(newCadModelOptions.revisionId) | ||
.setup((p) => p.getModelTransformation()) | ||
.returns(new Matrix4()) | ||
.object(); | ||
|
||
const newMockModels: CogniteModel[] = [newCadMock, newCadMock]; | ||
const newMockResourceCount = { reveal3DResourcesCount: 3 }; | ||
|
||
viewerModelsMock.mockReturnValue(newMockModels); | ||
mockResourceCount.reveal3DResourcesCount = newMockResourceCount.reveal3DResourcesCount; | ||
|
||
rerender(); | ||
|
||
expect(result.current).toEqual(newMockModels); | ||
}); | ||
}); |
141 changes: 141 additions & 0 deletions
141
react-components/tests/unit-tests/hooks/useCameraNavigation.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
import { describe, expect, test, vi, beforeEach, beforeAll, afterAll } from 'vitest'; | ||
import { useCameraNavigation } from '../../../src/hooks/useCameraNavigation'; | ||
import { viewerMock, viewerModelsMock } from '../fixtures/viewer'; | ||
import { cadMock, nodeBoundingBox } from '../fixtures/cadModel'; | ||
import { act, renderHook } from '@testing-library/react'; | ||
import { fdmNodeCacheContentMock } from '../fixtures/fdmNodeCache'; | ||
import { Vector3 } from 'three'; | ||
|
||
vi.mock('../../../src/components/RevealCanvas/ViewerContext', () => ({ | ||
useReveal: () => viewerMock | ||
})); | ||
|
||
vi.mock('../../../src/components/CacheProvider/NodeCacheProvider', () => ({ | ||
useFdmNodeCache: () => fdmNodeCacheContentMock | ||
})); | ||
|
||
describe('useCameraNavigation', () => { | ||
beforeEach(() => { | ||
vi.resetAllMocks(); | ||
viewerMock.cameraManager.setCameraState = vi.fn(); | ||
viewerMock.cameraManager.fitCameraToBoundingBox = vi.fn(); | ||
}); | ||
|
||
beforeAll(() => { | ||
vi.useFakeTimers(); | ||
}); | ||
|
||
afterAll(() => { | ||
vi.useRealTimers(); | ||
}); | ||
|
||
test('fitCameraToVisualSceneBoundingBox calls viewer method', () => { | ||
const { result } = renderHook(() => useCameraNavigation()); | ||
|
||
act(() => { | ||
result.current.fitCameraToVisualSceneBoundingBox(1000); | ||
}); | ||
|
||
expect(viewerMock.fitCameraToVisualSceneBoundingBox).toHaveBeenCalledWith(1000); | ||
}); | ||
|
||
test('fitCameraToAllModels calls viewer method with models', () => { | ||
const mockModels = [cadMock, cadMock]; | ||
viewerModelsMock.mockReturnValue(mockModels); | ||
|
||
const { result } = renderHook(() => useCameraNavigation()); | ||
|
||
act(() => { | ||
result.current.fitCameraToAllModels(1000); | ||
}); | ||
|
||
expect(viewerMock.fitCameraToModels).toHaveBeenCalledWith(mockModels, 1000, true); | ||
}); | ||
|
||
test('fitCameraToModelNodes calls viewer method with bounding box', async () => { | ||
const mockModels = [cadMock, cadMock]; | ||
viewerModelsMock.mockReturnValue(mockModels); | ||
|
||
const { result } = renderHook(() => useCameraNavigation()); | ||
const fitCameraToModelNodesSpy = vi.spyOn(result.current, 'fitCameraToModelNodes'); | ||
|
||
await act(async () => { | ||
await result.current.fitCameraToModelNodes(456, [1, 2]); | ||
}); | ||
|
||
expect(fitCameraToModelNodesSpy).toHaveBeenCalledWith(456, [1, 2]); | ||
|
||
expect(viewerMock.cameraManager.fitCameraToBoundingBox).toHaveBeenCalledWith(nodeBoundingBox); | ||
}); | ||
|
||
test('fitCameraToModelNode calls fitCameraToModelNodes with single node', async () => { | ||
const mockModels = [cadMock, cadMock]; | ||
viewerModelsMock.mockReturnValue(mockModels); | ||
|
||
const { result } = renderHook(() => useCameraNavigation()); | ||
const fitCameraToModelNodeSpy = vi.spyOn(result.current, 'fitCameraToModelNode'); | ||
|
||
await act(async () => { | ||
await result.current.fitCameraToModelNode(456, 1); | ||
}); | ||
|
||
expect(fitCameraToModelNodeSpy).toHaveBeenCalledWith(456, 1); | ||
}); | ||
|
||
test('fitCameraToInstances calls fitCameraToModelNodes with node ids', async () => { | ||
const mockModels = [cadMock, cadMock]; | ||
viewerModelsMock.mockReturnValue(mockModels); | ||
const mockMappings = { | ||
revisionId: 456, | ||
mappings: new Map([['model1', [{ id: 1 }, { id: 2 }]]]) | ||
}; | ||
|
||
fdmNodeCacheContentMock.cache.getMappingsForFdmInstances = vi | ||
.fn() | ||
.mockResolvedValue([mockMappings]); | ||
|
||
const { result } = renderHook(() => useCameraNavigation()); | ||
|
||
await act(async () => { | ||
await result.current.fitCameraToInstances([{ externalId: 'ext1', space: 'space1' }]); | ||
}); | ||
|
||
expect(viewerMock.cameraManager.fitCameraToBoundingBox).toHaveBeenCalled(); | ||
}); | ||
|
||
test('fitCameraToInstance calls fitCameraToInstances with single instance', async () => { | ||
const mockModels = [cadMock, cadMock]; | ||
const mockMappings = { | ||
revisionId: 456, | ||
mappings: new Map([['model1', [{ id: 1 }]]]) | ||
}; | ||
viewerModelsMock.mockReturnValue(mockModels); | ||
|
||
fdmNodeCacheContentMock.cache.getMappingsForFdmInstances = vi | ||
.fn() | ||
.mockResolvedValue([mockMappings]); | ||
|
||
const { result } = renderHook(() => useCameraNavigation()); | ||
|
||
await act(async () => { | ||
await result.current.fitCameraToInstance('ext1', 'space1'); | ||
}); | ||
|
||
expect(viewerMock.cameraManager.fitCameraToBoundingBox).toHaveBeenCalled(); | ||
}); | ||
|
||
test('fitCameraToState calls viewer method with camera state', () => { | ||
const mockCameraState = { | ||
position: new Vector3(0, 0, 0), | ||
target: new Vector3(1, 1, 1) | ||
}; | ||
|
||
const { result } = renderHook(() => useCameraNavigation()); | ||
|
||
act(() => { | ||
result.current.fitCameraToState(mockCameraState); | ||
}); | ||
|
||
expect(viewerMock.cameraManager.setCameraState).toHaveBeenCalledWith(mockCameraState); | ||
}); | ||
}); |