mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-12 00:20:15 +00:00
Road to No explicit any Part 8 (Group 3): Improve type safety in Group 3 test mocks (#8304)
## Summary - Eliminated all `as unknown as` type assertions from Group 3 test files - Created reusable factory functions in `litegraphTestUtils.ts` for better type safety - Improved test mock composition using `Partial` types with single `as` casts - Fixed LGraphNode tests to use proper API methods instead of direct property assignment ## Changes by Category ### New Factory Functions in `litegraphTestUtils.ts` - `createMockLGraphNodeWithArrayBoundingRect()` - Creates LGraphNode with proper boundingRect for position tests - `createMockFileList()` - Creates mock FileList with proper structure including `item()` method ### Test File Improvements **Composables:** - `useLoad3dDrag.test.ts` - Used `createMockFileList` factory - `useLoad3dViewer.test.ts` - Created local `MockSceneManager` interface with proper typing **LiteGraph Tests:** - `LGraphNode.test.ts` - Replaced direct `boundingRect` assignments with `updateArea()` calls - `LinkConnector.test.ts` - Improved mock composition with proper Partial types - `ToOutputRenderLink.test.ts` - Added `MockEvents` interface for type-safe event mocking - Updated integration and core tests to use new factory functions **Extension Tests:** - `contextMenuFilter.test.ts` - Updated menu factories to accept `(IContextMenuValue | null)[]` ## Type Safety Improvements - Zero `as unknown as` instances (was: multiple instances across 17 files) - All mocks use proper `Partial<T>` composition with single `as T` casts - Improved IntelliSense and type checking in test files - Centralized mock creation reduces duplication and improves maintainability ## Test Plan - ✅ All TypeScript type checks pass - ✅ ESLint passes with no new errors - ✅ Pre-commit hooks (format, lint, typecheck) all pass - ✅ Knip unused export check passes - ✅ No behavioral changes to actual tests (only type improvements) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8304-Road-to-No-explicit-any-Improve-type-safety-in-Group-3-test-mocks-2f36d73d365081ab841de96e5f01306d) by [Unito](https://www.unito.io)
This commit is contained in:
committed by
GitHub
parent
ba5380395d
commit
29220f6562
@@ -30,8 +30,7 @@ describe('useFeatureFlags', () => {
|
||||
it('should access supportsPreviewMetadata', () => {
|
||||
vi.mocked(api.getServerFeature).mockImplementation(
|
||||
(path, defaultValue) => {
|
||||
if (path === ServerFeatureFlag.SUPPORTS_PREVIEW_METADATA)
|
||||
return true as any
|
||||
if (path === ServerFeatureFlag.SUPPORTS_PREVIEW_METADATA) return true
|
||||
return defaultValue
|
||||
}
|
||||
)
|
||||
@@ -46,8 +45,7 @@ describe('useFeatureFlags', () => {
|
||||
it('should access maxUploadSize', () => {
|
||||
vi.mocked(api.getServerFeature).mockImplementation(
|
||||
(path, defaultValue) => {
|
||||
if (path === ServerFeatureFlag.MAX_UPLOAD_SIZE)
|
||||
return 209715200 as any // 200MB
|
||||
if (path === ServerFeatureFlag.MAX_UPLOAD_SIZE) return 209715200 // 200MB
|
||||
return defaultValue
|
||||
}
|
||||
)
|
||||
@@ -62,7 +60,7 @@ describe('useFeatureFlags', () => {
|
||||
it('should access supportsManagerV4', () => {
|
||||
vi.mocked(api.getServerFeature).mockImplementation(
|
||||
(path, defaultValue) => {
|
||||
if (path === ServerFeatureFlag.MANAGER_SUPPORTS_V4) return true as any
|
||||
if (path === ServerFeatureFlag.MANAGER_SUPPORTS_V4) return true
|
||||
return defaultValue
|
||||
}
|
||||
)
|
||||
@@ -76,7 +74,7 @@ describe('useFeatureFlags', () => {
|
||||
|
||||
it('should return undefined when features are not available and no default provided', () => {
|
||||
vi.mocked(api.getServerFeature).mockImplementation(
|
||||
(_path, defaultValue) => defaultValue as any
|
||||
(_path, defaultValue) => defaultValue
|
||||
)
|
||||
|
||||
const { flags } = useFeatureFlags()
|
||||
@@ -90,7 +88,7 @@ describe('useFeatureFlags', () => {
|
||||
it('should create reactive computed for custom feature flags', () => {
|
||||
vi.mocked(api.getServerFeature).mockImplementation(
|
||||
(path, defaultValue) => {
|
||||
if (path === 'custom.feature') return 'custom-value' as any
|
||||
if (path === 'custom.feature') return 'custom-value'
|
||||
return defaultValue
|
||||
}
|
||||
)
|
||||
@@ -108,7 +106,7 @@ describe('useFeatureFlags', () => {
|
||||
it('should handle nested paths', () => {
|
||||
vi.mocked(api.getServerFeature).mockImplementation(
|
||||
(path, defaultValue) => {
|
||||
if (path === 'extension.custom.nested.feature') return true as any
|
||||
if (path === 'extension.custom.nested.feature') return true
|
||||
return defaultValue
|
||||
}
|
||||
)
|
||||
@@ -122,8 +120,7 @@ describe('useFeatureFlags', () => {
|
||||
it('should work with ServerFeatureFlag enum', () => {
|
||||
vi.mocked(api.getServerFeature).mockImplementation(
|
||||
(path, defaultValue) => {
|
||||
if (path === ServerFeatureFlag.MAX_UPLOAD_SIZE)
|
||||
return 104857600 as any
|
||||
if (path === ServerFeatureFlag.MAX_UPLOAD_SIZE) return 104857600
|
||||
return defaultValue
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { nextTick, ref } from 'vue'
|
||||
import { nextTick, ref, shallowRef } from 'vue'
|
||||
|
||||
import { nodeToLoad3dMap, useLoad3d } from '@/composables/useLoad3d'
|
||||
import Load3d from '@/extensions/core/load3d/Load3d'
|
||||
import Load3dUtils from '@/extensions/core/load3d/Load3dUtils'
|
||||
import type { Size } from '@/lib/litegraph/src/interfaces'
|
||||
import type { LGraph } from '@/lib/litegraph/src/LGraph'
|
||||
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
|
||||
import type { IWidget } from '@/lib/litegraph/src/types/widgets'
|
||||
import { useToastStore } from '@/platform/updates/common/toastStore'
|
||||
import { api } from '@/scripts/api'
|
||||
import {
|
||||
createMockCanvasPointerEvent,
|
||||
createMockLGraphNode
|
||||
} from '@/utils/__tests__/litegraphTestUtils'
|
||||
|
||||
vi.mock('@/extensions/core/load3d/Load3d', () => ({
|
||||
default: vi.fn()
|
||||
@@ -36,15 +44,15 @@ vi.mock('@/i18n', () => ({
|
||||
}))
|
||||
|
||||
describe('useLoad3d', () => {
|
||||
let mockLoad3d: any
|
||||
let mockNode: any
|
||||
let mockToastStore: any
|
||||
let mockLoad3d: Partial<Load3d>
|
||||
let mockNode: LGraphNode
|
||||
let mockToastStore: ReturnType<typeof useToastStore>
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
nodeToLoad3dMap.clear()
|
||||
|
||||
mockNode = {
|
||||
mockNode = createMockLGraphNode({
|
||||
properties: {
|
||||
'Scene Config': {
|
||||
showGrid: true,
|
||||
@@ -68,18 +76,21 @@ describe('useLoad3d', () => {
|
||||
'Resource Folder': ''
|
||||
},
|
||||
widgets: [
|
||||
{ name: 'width', value: 512 },
|
||||
{ name: 'height', value: 512 }
|
||||
{ name: 'width', value: 512, type: 'number' } as IWidget,
|
||||
{ name: 'height', value: 512, type: 'number' } as IWidget
|
||||
],
|
||||
graph: {
|
||||
setDirtyCanvas: vi.fn()
|
||||
},
|
||||
} as Partial<LGraph> as LGraph,
|
||||
flags: {},
|
||||
onMouseEnter: null,
|
||||
onMouseLeave: null,
|
||||
onResize: null,
|
||||
onDrawBackground: null
|
||||
}
|
||||
onMouseEnter: undefined,
|
||||
onMouseLeave: undefined,
|
||||
onResize: undefined,
|
||||
onDrawBackground: undefined
|
||||
})
|
||||
|
||||
const mockCanvas = document.createElement('canvas')
|
||||
mockCanvas.hidden = false
|
||||
|
||||
mockLoad3d = {
|
||||
toggleGrid: vi.fn(),
|
||||
@@ -114,19 +125,20 @@ describe('useLoad3d', () => {
|
||||
removeEventListener: vi.fn(),
|
||||
remove: vi.fn(),
|
||||
renderer: {
|
||||
domElement: {
|
||||
hidden: false
|
||||
}
|
||||
}
|
||||
domElement: mockCanvas
|
||||
} as Partial<Load3d['renderer']> as Load3d['renderer']
|
||||
}
|
||||
|
||||
vi.mocked(Load3d).mockImplementation(function () {
|
||||
vi.mocked(Load3d).mockImplementation(function (this: Load3d) {
|
||||
Object.assign(this, mockLoad3d)
|
||||
return this
|
||||
})
|
||||
|
||||
mockToastStore = {
|
||||
addAlert: vi.fn()
|
||||
}
|
||||
} as Partial<ReturnType<typeof useToastStore>> as ReturnType<
|
||||
typeof useToastStore
|
||||
>
|
||||
vi.mocked(useToastStore).mockReturnValue(mockToastStore)
|
||||
})
|
||||
|
||||
@@ -208,14 +220,14 @@ describe('useLoad3d', () => {
|
||||
expect(mockNode.onDrawBackground).toBeDefined()
|
||||
|
||||
// Test the handlers
|
||||
mockNode.onMouseEnter()
|
||||
mockNode.onMouseEnter?.(createMockCanvasPointerEvent(0, 0))
|
||||
expect(mockLoad3d.refreshViewport).toHaveBeenCalled()
|
||||
expect(mockLoad3d.updateStatusMouseOnNode).toHaveBeenCalledWith(true)
|
||||
|
||||
mockNode.onMouseLeave()
|
||||
mockNode.onMouseLeave?.(createMockCanvasPointerEvent(0, 0))
|
||||
expect(mockLoad3d.updateStatusMouseOnNode).toHaveBeenCalledWith(false)
|
||||
|
||||
mockNode.onResize()
|
||||
mockNode.onResize?.([512, 512] as Size)
|
||||
expect(mockLoad3d.handleResize).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
@@ -226,13 +238,17 @@ describe('useLoad3d', () => {
|
||||
await composable.initializeLoad3d(containerRef)
|
||||
|
||||
mockNode.flags.collapsed = true
|
||||
mockNode.onDrawBackground()
|
||||
mockNode.onDrawBackground?.({} as CanvasRenderingContext2D)
|
||||
|
||||
expect(mockLoad3d.renderer.domElement.hidden).toBe(true)
|
||||
expect(mockLoad3d.renderer!.domElement.hidden).toBe(true)
|
||||
})
|
||||
|
||||
it('should load model if model_file widget exists', async () => {
|
||||
mockNode.widgets.push({ name: 'model_file', value: 'test.glb' })
|
||||
mockNode.widgets!.push({
|
||||
name: 'model_file',
|
||||
value: 'test.glb',
|
||||
type: 'text'
|
||||
} as IWidget)
|
||||
vi.mocked(Load3dUtils.splitFilePath).mockReturnValue([
|
||||
'subfolder',
|
||||
'test.glb'
|
||||
@@ -255,8 +271,12 @@ describe('useLoad3d', () => {
|
||||
})
|
||||
|
||||
it('should restore camera state after loading model', async () => {
|
||||
mockNode.widgets.push({ name: 'model_file', value: 'test.glb' })
|
||||
mockNode.properties['Camera Config'].state = {
|
||||
mockNode.widgets!.push({
|
||||
name: 'model_file',
|
||||
value: 'test.glb',
|
||||
type: 'text'
|
||||
} as IWidget)
|
||||
;(mockNode.properties!['Camera Config'] as { state: unknown }).state = {
|
||||
position: { x: 1, y: 2, z: 3 },
|
||||
target: { x: 0, y: 0, z: 0 }
|
||||
}
|
||||
@@ -312,13 +332,13 @@ describe('useLoad3d', () => {
|
||||
it('should handle missing container or node', async () => {
|
||||
const composable = useLoad3d(mockNode)
|
||||
|
||||
await composable.initializeLoad3d(null as any)
|
||||
await composable.initializeLoad3d(null!)
|
||||
|
||||
expect(Load3d).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should accept ref as parameter', () => {
|
||||
const nodeRef = ref(mockNode)
|
||||
const nodeRef = shallowRef<LGraphNode | null>(mockNode)
|
||||
const composable = useLoad3d(nodeRef)
|
||||
|
||||
expect(composable.sceneConfig.value.backgroundColor).toBe('#000000')
|
||||
@@ -370,9 +390,9 @@ describe('useLoad3d', () => {
|
||||
|
||||
await composable.initializeLoad3d(containerRef)
|
||||
|
||||
mockLoad3d.toggleGrid.mockClear()
|
||||
mockLoad3d.setBackgroundColor.mockClear()
|
||||
mockLoad3d.setBackgroundImage.mockClear()
|
||||
vi.mocked(mockLoad3d.toggleGrid!).mockClear()
|
||||
vi.mocked(mockLoad3d.setBackgroundColor!).mockClear()
|
||||
vi.mocked(mockLoad3d.setBackgroundImage!).mockClear()
|
||||
|
||||
composable.sceneConfig.value = {
|
||||
showGrid: false,
|
||||
@@ -403,8 +423,8 @@ describe('useLoad3d', () => {
|
||||
await composable.initializeLoad3d(containerRef)
|
||||
await nextTick()
|
||||
|
||||
mockLoad3d.setUpDirection.mockClear()
|
||||
mockLoad3d.setMaterialMode.mockClear()
|
||||
vi.mocked(mockLoad3d.setUpDirection!).mockClear()
|
||||
vi.mocked(mockLoad3d.setMaterialMode!).mockClear()
|
||||
|
||||
composable.modelConfig.value.upDirection = '+y'
|
||||
composable.modelConfig.value.materialMode = 'wireframe'
|
||||
@@ -426,8 +446,8 @@ describe('useLoad3d', () => {
|
||||
await composable.initializeLoad3d(containerRef)
|
||||
await nextTick()
|
||||
|
||||
mockLoad3d.toggleCamera.mockClear()
|
||||
mockLoad3d.setFOV.mockClear()
|
||||
vi.mocked(mockLoad3d.toggleCamera!).mockClear()
|
||||
vi.mocked(mockLoad3d.setFOV!).mockClear()
|
||||
|
||||
composable.cameraConfig.value.cameraType = 'orthographic'
|
||||
composable.cameraConfig.value.fov = 90
|
||||
@@ -449,7 +469,7 @@ describe('useLoad3d', () => {
|
||||
await composable.initializeLoad3d(containerRef)
|
||||
await nextTick()
|
||||
|
||||
mockLoad3d.setLightIntensity.mockClear()
|
||||
vi.mocked(mockLoad3d.setLightIntensity!).mockClear()
|
||||
|
||||
composable.lightConfig.value.intensity = 10
|
||||
await nextTick()
|
||||
@@ -589,7 +609,7 @@ describe('useLoad3d', () => {
|
||||
})
|
||||
|
||||
it('should use resource folder for upload', async () => {
|
||||
mockNode.properties['Resource Folder'] = 'subfolder'
|
||||
mockNode.properties!['Resource Folder'] = 'subfolder'
|
||||
vi.mocked(Load3dUtils.uploadFile).mockResolvedValue('uploaded-image.jpg')
|
||||
|
||||
const composable = useLoad3d(mockNode)
|
||||
@@ -641,7 +661,9 @@ describe('useLoad3d', () => {
|
||||
})
|
||||
|
||||
it('should handle export errors', async () => {
|
||||
mockLoad3d.exportModel.mockRejectedValueOnce(new Error('Export failed'))
|
||||
vi.mocked(mockLoad3d.exportModel!).mockRejectedValueOnce(
|
||||
new Error('Export failed')
|
||||
)
|
||||
|
||||
const composable = useLoad3d(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
@@ -719,12 +741,12 @@ describe('useLoad3d', () => {
|
||||
})
|
||||
|
||||
it('should handle materialModeChange event', async () => {
|
||||
let materialModeHandler: any
|
||||
let materialModeHandler: ((mode: string) => void) | undefined
|
||||
|
||||
mockLoad3d.addEventListener.mockImplementation(
|
||||
(event: string, handler: any) => {
|
||||
vi.mocked(mockLoad3d.addEventListener!).mockImplementation(
|
||||
(event: string, handler: unknown) => {
|
||||
if (event === 'materialModeChange') {
|
||||
materialModeHandler = handler
|
||||
materialModeHandler = handler as (mode: string) => void
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -734,21 +756,21 @@ describe('useLoad3d', () => {
|
||||
|
||||
await composable.initializeLoad3d(containerRef)
|
||||
|
||||
materialModeHandler('wireframe')
|
||||
materialModeHandler?.('wireframe')
|
||||
|
||||
expect(composable.modelConfig.value.materialMode).toBe('wireframe')
|
||||
})
|
||||
|
||||
it('should handle loading events', async () => {
|
||||
let modelLoadingStartHandler: any
|
||||
let modelLoadingEndHandler: any
|
||||
let modelLoadingStartHandler: (() => void) | undefined
|
||||
let modelLoadingEndHandler: (() => void) | undefined
|
||||
|
||||
mockLoad3d.addEventListener.mockImplementation(
|
||||
(event: string, handler: any) => {
|
||||
vi.mocked(mockLoad3d.addEventListener!).mockImplementation(
|
||||
(event: string, handler: unknown) => {
|
||||
if (event === 'modelLoadingStart') {
|
||||
modelLoadingStartHandler = handler
|
||||
modelLoadingStartHandler = handler as () => void
|
||||
} else if (event === 'modelLoadingEnd') {
|
||||
modelLoadingEndHandler = handler
|
||||
modelLoadingEndHandler = handler as () => void
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -758,22 +780,22 @@ describe('useLoad3d', () => {
|
||||
|
||||
await composable.initializeLoad3d(containerRef)
|
||||
|
||||
modelLoadingStartHandler()
|
||||
modelLoadingStartHandler?.()
|
||||
expect(composable.loading.value).toBe(true)
|
||||
expect(composable.loadingMessage.value).toBe('load3d.loadingModel')
|
||||
|
||||
modelLoadingEndHandler()
|
||||
modelLoadingEndHandler?.()
|
||||
expect(composable.loading.value).toBe(false)
|
||||
expect(composable.loadingMessage.value).toBe('')
|
||||
})
|
||||
|
||||
it('should handle recordingStatusChange event', async () => {
|
||||
let recordingStatusHandler: any
|
||||
let recordingStatusHandler: ((status: boolean) => void) | undefined
|
||||
|
||||
mockLoad3d.addEventListener.mockImplementation(
|
||||
(event: string, handler: any) => {
|
||||
vi.mocked(mockLoad3d.addEventListener!).mockImplementation(
|
||||
(event: string, handler: unknown) => {
|
||||
if (event === 'recordingStatusChange') {
|
||||
recordingStatusHandler = handler
|
||||
recordingStatusHandler = handler as (status: boolean) => void
|
||||
}
|
||||
}
|
||||
)
|
||||
@@ -783,7 +805,7 @@ describe('useLoad3d', () => {
|
||||
|
||||
await composable.initializeLoad3d(containerRef)
|
||||
|
||||
recordingStatusHandler(false)
|
||||
recordingStatusHandler?.(false)
|
||||
|
||||
expect(composable.isRecording.value).toBe(false)
|
||||
expect(composable.recordingDuration.value).toBe(10)
|
||||
@@ -814,10 +836,11 @@ describe('useLoad3d', () => {
|
||||
|
||||
describe('getModelUrl', () => {
|
||||
it('should handle http URLs directly', async () => {
|
||||
mockNode.widgets.push({
|
||||
mockNode.widgets!.push({
|
||||
name: 'model_file',
|
||||
value: 'http://example.com/model.glb'
|
||||
})
|
||||
value: 'http://example.com/model.glb',
|
||||
type: 'text'
|
||||
} as IWidget)
|
||||
|
||||
const composable = useLoad3d(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
@@ -830,7 +853,11 @@ describe('useLoad3d', () => {
|
||||
})
|
||||
|
||||
it('should construct URL for local files', async () => {
|
||||
mockNode.widgets.push({ name: 'model_file', value: 'models/test.glb' })
|
||||
mockNode.widgets!.push({
|
||||
name: 'model_file',
|
||||
value: 'models/test.glb',
|
||||
type: 'text'
|
||||
} as IWidget)
|
||||
vi.mocked(Load3dUtils.splitFilePath).mockReturnValue([
|
||||
'models',
|
||||
'test.glb'
|
||||
@@ -860,7 +887,9 @@ describe('useLoad3d', () => {
|
||||
})
|
||||
|
||||
it('should use output type for preview mode', async () => {
|
||||
mockNode.widgets = [{ name: 'model_file', value: 'test.glb' }] // No width/height widgets
|
||||
mockNode.widgets = [
|
||||
{ name: 'model_file', value: 'test.glb', type: 'text' } as IWidget
|
||||
] // No width/height widgets
|
||||
vi.mocked(Load3dUtils.splitFilePath).mockReturnValue(['', 'test.glb'])
|
||||
vi.mocked(Load3dUtils.getResourceURL).mockReturnValue(
|
||||
'/api/view/test.glb'
|
||||
@@ -894,10 +923,10 @@ describe('useLoad3d', () => {
|
||||
})
|
||||
|
||||
it('should handle missing configurations', async () => {
|
||||
delete mockNode.properties['Scene Config']
|
||||
delete mockNode.properties['Model Config']
|
||||
delete mockNode.properties['Camera Config']
|
||||
delete mockNode.properties['Light Config']
|
||||
delete mockNode.properties!['Scene Config']
|
||||
delete mockNode.properties!['Model Config']
|
||||
delete mockNode.properties!['Camera Config']
|
||||
delete mockNode.properties!['Light Config']
|
||||
|
||||
const composable = useLoad3d(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
@@ -909,7 +938,11 @@ describe('useLoad3d', () => {
|
||||
})
|
||||
|
||||
it('should handle background image with existing config', async () => {
|
||||
mockNode.properties['Scene Config'].backgroundImage = 'existing.jpg'
|
||||
;(
|
||||
mockNode.properties!['Scene Config'] as {
|
||||
backgroundImage: string
|
||||
}
|
||||
).backgroundImage = 'existing.jpg'
|
||||
|
||||
const composable = useLoad3d(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ref } from 'vue'
|
||||
|
||||
import { useLoad3dDrag } from '@/composables/useLoad3dDrag'
|
||||
import { useToastStore } from '@/platform/updates/common/toastStore'
|
||||
import { createMockFileList } from '@/utils/__tests__/litegraphTestUtils'
|
||||
|
||||
vi.mock('@/platform/updates/common/toastStore', () => ({
|
||||
useToastStore: vi.fn()
|
||||
@@ -19,22 +20,22 @@ function createMockDragEvent(
|
||||
const files = options.files || []
|
||||
const types = options.hasFiles ? ['Files'] : []
|
||||
|
||||
const dataTransfer = {
|
||||
const dataTransfer: Partial<DataTransfer> = {
|
||||
types,
|
||||
files,
|
||||
files: createMockFileList(files),
|
||||
dropEffect: 'none' as DataTransfer['dropEffect']
|
||||
}
|
||||
|
||||
const event = {
|
||||
const event: Partial<DragEvent> = {
|
||||
type,
|
||||
dataTransfer
|
||||
} as unknown as DragEvent
|
||||
dataTransfer: dataTransfer as DataTransfer
|
||||
}
|
||||
|
||||
return event
|
||||
return event as DragEvent
|
||||
}
|
||||
|
||||
describe('useLoad3dDrag', () => {
|
||||
let mockToastStore: any
|
||||
let mockToastStore: ReturnType<typeof useToastStore>
|
||||
let mockOnModelDrop: (file: File) => void | Promise<void>
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -42,7 +43,9 @@ describe('useLoad3dDrag', () => {
|
||||
|
||||
mockToastStore = {
|
||||
addAlert: vi.fn()
|
||||
}
|
||||
} as Partial<ReturnType<typeof useToastStore>> as ReturnType<
|
||||
typeof useToastStore
|
||||
>
|
||||
vi.mocked(useToastStore).mockReturnValue(mockToastStore)
|
||||
|
||||
mockOnModelDrop = vi.fn()
|
||||
|
||||
@@ -4,8 +4,11 @@ import { nextTick } from 'vue'
|
||||
import { useLoad3dViewer } from '@/composables/useLoad3dViewer'
|
||||
import Load3d from '@/extensions/core/load3d/Load3d'
|
||||
import Load3dUtils from '@/extensions/core/load3d/Load3dUtils'
|
||||
import type { LGraph } from '@/lib/litegraph/src/LGraph'
|
||||
import type { LGraphNode } from '@/lib/litegraph/src/LGraphNode'
|
||||
import { useToastStore } from '@/platform/updates/common/toastStore'
|
||||
import { useLoad3dService } from '@/services/load3dService'
|
||||
import { createMockLGraphNode } from '@/utils/__tests__/litegraphTestUtils'
|
||||
|
||||
vi.mock('@/services/load3dService', () => ({
|
||||
useLoad3dService: vi.fn()
|
||||
@@ -29,17 +32,32 @@ vi.mock('@/extensions/core/load3d/Load3d', () => ({
|
||||
default: vi.fn()
|
||||
}))
|
||||
|
||||
function createMockSceneManager(): Load3d['sceneManager'] {
|
||||
const mock: Partial<Load3d['sceneManager']> = {
|
||||
scene: {} as Load3d['sceneManager']['scene'],
|
||||
backgroundScene: {} as Load3d['sceneManager']['backgroundScene'],
|
||||
backgroundCamera: {} as Load3d['sceneManager']['backgroundCamera'],
|
||||
currentBackgroundColor: '#282828',
|
||||
gridHelper: { visible: true } as Load3d['sceneManager']['gridHelper'],
|
||||
getCurrentBackgroundInfo: vi.fn().mockReturnValue({
|
||||
type: 'color',
|
||||
value: '#282828'
|
||||
})
|
||||
}
|
||||
return mock as Load3d['sceneManager']
|
||||
}
|
||||
|
||||
describe('useLoad3dViewer', () => {
|
||||
let mockLoad3d: any
|
||||
let mockSourceLoad3d: any
|
||||
let mockLoad3dService: any
|
||||
let mockToastStore: any
|
||||
let mockNode: any
|
||||
let mockLoad3d: Partial<Load3d>
|
||||
let mockSourceLoad3d: Partial<Load3d>
|
||||
let mockLoad3dService: ReturnType<typeof useLoad3dService>
|
||||
let mockToastStore: ReturnType<typeof useToastStore>
|
||||
let mockNode: LGraphNode
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks()
|
||||
|
||||
mockNode = {
|
||||
mockNode = createMockLGraphNode({
|
||||
properties: {
|
||||
'Scene Config': {
|
||||
backgroundColor: '#282828',
|
||||
@@ -62,9 +80,9 @@ describe('useLoad3dViewer', () => {
|
||||
},
|
||||
graph: {
|
||||
setDirtyCanvas: vi.fn()
|
||||
},
|
||||
} as Partial<LGraph> as LGraph,
|
||||
widgets: []
|
||||
} as any
|
||||
})
|
||||
|
||||
mockLoad3d = {
|
||||
setBackgroundColor: vi.fn(),
|
||||
@@ -97,24 +115,17 @@ describe('useLoad3dViewer', () => {
|
||||
zoom: 1,
|
||||
cameraType: 'perspective'
|
||||
}),
|
||||
sceneManager: {
|
||||
currentBackgroundColor: '#282828',
|
||||
gridHelper: { visible: true },
|
||||
getCurrentBackgroundInfo: vi.fn().mockReturnValue({
|
||||
type: 'color',
|
||||
value: '#282828'
|
||||
})
|
||||
},
|
||||
sceneManager: createMockSceneManager(),
|
||||
lightingManager: {
|
||||
lights: [null, { intensity: 1 }]
|
||||
},
|
||||
} as Load3d['lightingManager'],
|
||||
cameraManager: {
|
||||
perspectiveCamera: { fov: 75 }
|
||||
},
|
||||
} as Load3d['cameraManager'],
|
||||
modelManager: {
|
||||
currentUpDirection: 'original',
|
||||
materialMode: 'original'
|
||||
},
|
||||
} as Load3d['modelManager'],
|
||||
setBackgroundImage: vi.fn().mockResolvedValue(undefined),
|
||||
setBackgroundRenderMode: vi.fn(),
|
||||
forceRender: vi.fn()
|
||||
@@ -128,12 +139,16 @@ describe('useLoad3dViewer', () => {
|
||||
copyLoad3dState: vi.fn().mockResolvedValue(undefined),
|
||||
handleViewportRefresh: vi.fn(),
|
||||
getLoad3d: vi.fn().mockReturnValue(mockSourceLoad3d)
|
||||
}
|
||||
} as Partial<ReturnType<typeof useLoad3dService>> as ReturnType<
|
||||
typeof useLoad3dService
|
||||
>
|
||||
vi.mocked(useLoad3dService).mockReturnValue(mockLoad3dService)
|
||||
|
||||
mockToastStore = {
|
||||
addAlert: vi.fn()
|
||||
}
|
||||
} as Partial<ReturnType<typeof useToastStore>> as ReturnType<
|
||||
typeof useToastStore
|
||||
>
|
||||
vi.mocked(useToastStore).mockReturnValue(mockToastStore)
|
||||
})
|
||||
|
||||
@@ -160,7 +175,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
expect(Load3d).toHaveBeenCalledWith(containerRef, {
|
||||
width: undefined,
|
||||
@@ -184,16 +199,20 @@ describe('useLoad3dViewer', () => {
|
||||
})
|
||||
|
||||
it('should handle background image during initialization', async () => {
|
||||
mockSourceLoad3d.sceneManager.getCurrentBackgroundInfo.mockReturnValue({
|
||||
vi.mocked(
|
||||
mockSourceLoad3d.sceneManager!.getCurrentBackgroundInfo
|
||||
).mockReturnValue({
|
||||
type: 'image',
|
||||
value: ''
|
||||
})
|
||||
mockNode.properties['Scene Config'].backgroundImage = 'test-image.jpg'
|
||||
;(
|
||||
mockNode.properties!['Scene Config'] as Record<string, unknown>
|
||||
).backgroundImage = 'test-image.jpg'
|
||||
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
expect(viewer.backgroundImage.value).toBe('test-image.jpg')
|
||||
expect(viewer.hasBackgroundImage.value).toBe(true)
|
||||
@@ -207,7 +226,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
expect(mockToastStore.addAlert).toHaveBeenCalledWith(
|
||||
'toastMessages.failedToInitializeLoad3dViewer'
|
||||
@@ -220,7 +239,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
viewer.backgroundColor.value = '#ff0000'
|
||||
await nextTick()
|
||||
@@ -232,7 +251,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
viewer.showGrid.value = false
|
||||
await nextTick()
|
||||
@@ -244,7 +263,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
viewer.cameraType.value = 'orthographic'
|
||||
await nextTick()
|
||||
@@ -256,7 +275,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
viewer.fov.value = 90
|
||||
await nextTick()
|
||||
@@ -268,7 +287,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
viewer.lightIntensity.value = 2
|
||||
await nextTick()
|
||||
@@ -280,7 +299,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
viewer.backgroundImage.value = 'new-bg.jpg'
|
||||
await nextTick()
|
||||
@@ -293,7 +312,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
viewer.upDirection.value = '+y'
|
||||
await nextTick()
|
||||
@@ -305,7 +324,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
viewer.materialMode.value = 'wireframe'
|
||||
await nextTick()
|
||||
@@ -314,14 +333,16 @@ describe('useLoad3dViewer', () => {
|
||||
})
|
||||
|
||||
it('should handle watcher errors gracefully', async () => {
|
||||
mockLoad3d.setBackgroundColor.mockImplementationOnce(function () {
|
||||
throw new Error('Color update failed')
|
||||
})
|
||||
vi.mocked(mockLoad3d.setBackgroundColor!).mockImplementationOnce(
|
||||
function () {
|
||||
throw new Error('Color update failed')
|
||||
}
|
||||
)
|
||||
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
viewer.backgroundColor.value = '#ff0000'
|
||||
await nextTick()
|
||||
@@ -337,7 +358,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
await viewer.exportModel('glb')
|
||||
|
||||
@@ -345,12 +366,14 @@ describe('useLoad3dViewer', () => {
|
||||
})
|
||||
|
||||
it('should handle export errors', async () => {
|
||||
mockLoad3d.exportModel.mockRejectedValueOnce(new Error('Export failed'))
|
||||
vi.mocked(mockLoad3d.exportModel!).mockRejectedValueOnce(
|
||||
new Error('Export failed')
|
||||
)
|
||||
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
await viewer.exportModel('glb')
|
||||
|
||||
@@ -373,7 +396,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
viewer.handleResize()
|
||||
|
||||
@@ -384,7 +407,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
viewer.handleMouseEnter()
|
||||
|
||||
@@ -395,7 +418,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
viewer.handleMouseLeave()
|
||||
|
||||
@@ -408,22 +431,35 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
|
||||
mockNode.properties['Scene Config'].backgroundColor = '#ff0000'
|
||||
mockNode.properties['Scene Config'].showGrid = false
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
;(
|
||||
mockNode.properties!['Scene Config'] as Record<string, unknown>
|
||||
).backgroundColor = '#ff0000'
|
||||
;(
|
||||
mockNode.properties!['Scene Config'] as Record<string, unknown>
|
||||
).showGrid = false
|
||||
|
||||
viewer.restoreInitialState()
|
||||
|
||||
expect(mockNode.properties['Scene Config'].backgroundColor).toBe(
|
||||
'#282828'
|
||||
)
|
||||
expect(mockNode.properties['Scene Config'].showGrid).toBe(true)
|
||||
expect(mockNode.properties['Camera Config'].cameraType).toBe(
|
||||
'perspective'
|
||||
)
|
||||
expect(mockNode.properties['Camera Config'].fov).toBe(75)
|
||||
expect(mockNode.properties['Light Config'].intensity).toBe(1)
|
||||
expect(
|
||||
(mockNode.properties!['Scene Config'] as Record<string, unknown>)
|
||||
.backgroundColor
|
||||
).toBe('#282828')
|
||||
expect(
|
||||
(mockNode.properties!['Scene Config'] as Record<string, unknown>)
|
||||
.showGrid
|
||||
).toBe(true)
|
||||
expect(
|
||||
(mockNode.properties!['Camera Config'] as Record<string, unknown>)
|
||||
.cameraType
|
||||
).toBe('perspective')
|
||||
expect(
|
||||
(mockNode.properties!['Camera Config'] as Record<string, unknown>).fov
|
||||
).toBe(75)
|
||||
expect(
|
||||
(mockNode.properties!['Light Config'] as Record<string, unknown>)
|
||||
.intensity
|
||||
).toBe(1)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -432,7 +468,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
viewer.backgroundColor.value = '#ff0000'
|
||||
viewer.showGrid.value = false
|
||||
@@ -440,23 +476,27 @@ describe('useLoad3dViewer', () => {
|
||||
const result = await viewer.applyChanges()
|
||||
|
||||
expect(result).toBe(true)
|
||||
expect(mockNode.properties['Scene Config'].backgroundColor).toBe(
|
||||
'#ff0000'
|
||||
)
|
||||
expect(mockNode.properties['Scene Config'].showGrid).toBe(false)
|
||||
expect(
|
||||
(mockNode.properties!['Scene Config'] as Record<string, unknown>)
|
||||
.backgroundColor
|
||||
).toBe('#ff0000')
|
||||
expect(
|
||||
(mockNode.properties!['Scene Config'] as Record<string, unknown>)
|
||||
.showGrid
|
||||
).toBe(false)
|
||||
expect(mockLoad3dService.copyLoad3dState).toHaveBeenCalledWith(
|
||||
mockLoad3d,
|
||||
mockSourceLoad3d
|
||||
)
|
||||
expect(mockSourceLoad3d.forceRender).toHaveBeenCalled()
|
||||
expect(mockNode.graph.setDirtyCanvas).toHaveBeenCalledWith(true, true)
|
||||
expect(mockNode.graph!.setDirtyCanvas).toHaveBeenCalledWith(true, true)
|
||||
})
|
||||
|
||||
it('should handle background image during apply', async () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
viewer.backgroundImage.value = 'new-bg.jpg'
|
||||
|
||||
@@ -481,7 +521,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
viewer.refreshViewport()
|
||||
|
||||
@@ -498,7 +538,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
const file = new File([''], 'test.jpg', { type: 'image/jpeg' })
|
||||
await viewer.handleBackgroundImageUpdate(file)
|
||||
@@ -515,7 +555,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
const file = new File([''], 'test.jpg', { type: 'image/jpeg' })
|
||||
await viewer.handleBackgroundImageUpdate(file)
|
||||
@@ -527,7 +567,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
viewer.backgroundImage.value = 'existing.jpg'
|
||||
viewer.hasBackgroundImage.value = true
|
||||
@@ -546,7 +586,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
const file = new File([''], 'test.jpg', { type: 'image/jpeg' })
|
||||
await viewer.handleBackgroundImageUpdate(file)
|
||||
@@ -562,7 +602,7 @@ describe('useLoad3dViewer', () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
viewer.cleanup()
|
||||
|
||||
@@ -580,33 +620,36 @@ describe('useLoad3dViewer', () => {
|
||||
it('should handle missing container ref', async () => {
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
|
||||
await viewer.initializeViewer(null as any, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(null!, mockSourceLoad3d as Load3d)
|
||||
|
||||
expect(Load3d).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('should handle orthographic camera', async () => {
|
||||
mockSourceLoad3d.getCurrentCameraType.mockReturnValue('orthographic')
|
||||
vi.mocked(mockSourceLoad3d.getCurrentCameraType!).mockReturnValue(
|
||||
'orthographic'
|
||||
)
|
||||
mockSourceLoad3d.cameraManager = {
|
||||
perspectiveCamera: { fov: 75 }
|
||||
}
|
||||
delete mockNode.properties['Camera Config'].cameraType
|
||||
} as Partial<Load3d['cameraManager']> as Load3d['cameraManager']
|
||||
delete (mockNode.properties!['Camera Config'] as Record<string, unknown>)
|
||||
.cameraType
|
||||
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
expect(viewer.cameraType.value).toBe('orthographic')
|
||||
})
|
||||
|
||||
it('should handle missing lights', async () => {
|
||||
mockSourceLoad3d.lightingManager.lights = []
|
||||
mockSourceLoad3d.lightingManager!.lights = []
|
||||
|
||||
const viewer = useLoad3dViewer(mockNode)
|
||||
const containerRef = document.createElement('div')
|
||||
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d)
|
||||
await viewer.initializeViewer(containerRef, mockSourceLoad3d as Load3d)
|
||||
|
||||
expect(viewer.lightIntensity.value).toBe(1) // Default value
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user