mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-20 23:04:06 +00:00
## 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)
135 lines
3.9 KiB
TypeScript
135 lines
3.9 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import { isReactive, isReadonly } from 'vue'
|
|
|
|
import {
|
|
ServerFeatureFlag,
|
|
useFeatureFlags
|
|
} from '@/composables/useFeatureFlags'
|
|
import { api } from '@/scripts/api'
|
|
|
|
// Mock the API module
|
|
vi.mock('@/scripts/api', () => ({
|
|
api: {
|
|
getServerFeature: vi.fn()
|
|
}
|
|
}))
|
|
|
|
describe('useFeatureFlags', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
describe('flags object', () => {
|
|
it('should provide reactive readonly flags', () => {
|
|
const { flags } = useFeatureFlags()
|
|
|
|
expect(isReadonly(flags)).toBe(true)
|
|
expect(isReactive(flags)).toBe(true)
|
|
})
|
|
|
|
it('should access supportsPreviewMetadata', () => {
|
|
vi.mocked(api.getServerFeature).mockImplementation(
|
|
(path, defaultValue) => {
|
|
if (path === ServerFeatureFlag.SUPPORTS_PREVIEW_METADATA) return true
|
|
return defaultValue
|
|
}
|
|
)
|
|
|
|
const { flags } = useFeatureFlags()
|
|
expect(flags.supportsPreviewMetadata).toBe(true)
|
|
expect(api.getServerFeature).toHaveBeenCalledWith(
|
|
ServerFeatureFlag.SUPPORTS_PREVIEW_METADATA
|
|
)
|
|
})
|
|
|
|
it('should access maxUploadSize', () => {
|
|
vi.mocked(api.getServerFeature).mockImplementation(
|
|
(path, defaultValue) => {
|
|
if (path === ServerFeatureFlag.MAX_UPLOAD_SIZE) return 209715200 // 200MB
|
|
return defaultValue
|
|
}
|
|
)
|
|
|
|
const { flags } = useFeatureFlags()
|
|
expect(flags.maxUploadSize).toBe(209715200)
|
|
expect(api.getServerFeature).toHaveBeenCalledWith(
|
|
ServerFeatureFlag.MAX_UPLOAD_SIZE
|
|
)
|
|
})
|
|
|
|
it('should access supportsManagerV4', () => {
|
|
vi.mocked(api.getServerFeature).mockImplementation(
|
|
(path, defaultValue) => {
|
|
if (path === ServerFeatureFlag.MANAGER_SUPPORTS_V4) return true
|
|
return defaultValue
|
|
}
|
|
)
|
|
|
|
const { flags } = useFeatureFlags()
|
|
expect(flags.supportsManagerV4).toBe(true)
|
|
expect(api.getServerFeature).toHaveBeenCalledWith(
|
|
ServerFeatureFlag.MANAGER_SUPPORTS_V4
|
|
)
|
|
})
|
|
|
|
it('should return undefined when features are not available and no default provided', () => {
|
|
vi.mocked(api.getServerFeature).mockImplementation(
|
|
(_path, defaultValue) => defaultValue
|
|
)
|
|
|
|
const { flags } = useFeatureFlags()
|
|
expect(flags.supportsPreviewMetadata).toBeUndefined()
|
|
expect(flags.maxUploadSize).toBeUndefined()
|
|
expect(flags.supportsManagerV4).toBeUndefined()
|
|
})
|
|
})
|
|
|
|
describe('featureFlag', () => {
|
|
it('should create reactive computed for custom feature flags', () => {
|
|
vi.mocked(api.getServerFeature).mockImplementation(
|
|
(path, defaultValue) => {
|
|
if (path === 'custom.feature') return 'custom-value'
|
|
return defaultValue
|
|
}
|
|
)
|
|
|
|
const { featureFlag } = useFeatureFlags()
|
|
const customFlag = featureFlag('custom.feature', 'default')
|
|
|
|
expect(customFlag.value).toBe('custom-value')
|
|
expect(api.getServerFeature).toHaveBeenCalledWith(
|
|
'custom.feature',
|
|
'default'
|
|
)
|
|
})
|
|
|
|
it('should handle nested paths', () => {
|
|
vi.mocked(api.getServerFeature).mockImplementation(
|
|
(path, defaultValue) => {
|
|
if (path === 'extension.custom.nested.feature') return true
|
|
return defaultValue
|
|
}
|
|
)
|
|
|
|
const { featureFlag } = useFeatureFlags()
|
|
const nestedFlag = featureFlag('extension.custom.nested.feature', false)
|
|
|
|
expect(nestedFlag.value).toBe(true)
|
|
})
|
|
|
|
it('should work with ServerFeatureFlag enum', () => {
|
|
vi.mocked(api.getServerFeature).mockImplementation(
|
|
(path, defaultValue) => {
|
|
if (path === ServerFeatureFlag.MAX_UPLOAD_SIZE) return 104857600
|
|
return defaultValue
|
|
}
|
|
)
|
|
|
|
const { featureFlag } = useFeatureFlags()
|
|
const maxUploadSize = featureFlag(ServerFeatureFlag.MAX_UPLOAD_SIZE)
|
|
|
|
expect(maxUploadSize.value).toBe(104857600)
|
|
})
|
|
})
|
|
})
|