mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-20 14:30:41 +00:00
## Summary Improved type safety in test files by eliminating unsafe type assertions and adopting official testing patterns. Reduced unsafe `as unknown as` type assertions and eliminated all `null!` assertions. ## Changes - **Adopted @pinia/testing patterns** - Replaced manual Pinia store mocking with `createTestingPinia()` in `useSelectionState.test.ts` - Eliminated ~120 lines of mock boilerplate - Created `createMockSettingStore()` helper to replace duplicated store mocks in `useCoreCommands.test.ts` - **Eliminated unsafe null assertions** - Created explicit `MockMaskEditorStore` interface with proper nullable types in `useCanvasTools.test.ts` - Replaced `null!` initializations with `null` and used `!` at point of use or `?.` for optional chaining - **Made partial mock intent explicit** - Updated test utilities in `litegraphTestUtils.ts` to use explicit `Partial<T>` typing - Changed cast pattern from `as T` to `as Partial<T> as T` to show incomplete mock intent - Applied to `createMockLGraphNode()`, `createMockPositionable()`, and `createMockLGraphGroup()` - **Created centralized mock utilities** in `src/utils/__tests__/litegraphTestUtils.ts` - `createMockLGraphNode()`, `createMockPositionable()`, `createMockLGraphGroup()`, `createMockSubgraphNode()` - Updated 8+ test files to use centralized utilities - Used union types `Partial<T> | Record<string, unknown>` for flexible mock creation ## Results - ✅ 0 typecheck errors - ✅ 0 lint errors - ✅ All tests passing in modified files - ✅ Eliminated all `null!` assertions - ✅ Reduced unsafe double-cast patterns significantly ## Files Modified (18) - `src/components/graph/SelectionToolbox.test.ts` - `src/components/graph/selectionToolbox/{BypassButton,ColorPickerButton,ExecuteButton}.test.ts` - `src/components/sidebar/tabs/queue/ResultGallery.test.ts` - `src/composables/canvas/useSelectedLiteGraphItems.test.ts` - `src/composables/graph/{useGraphHierarchy,useSelectionState}.test.ts` - `src/composables/maskeditor/{useCanvasHistory,useCanvasManager,useCanvasTools,useCanvasTransform}.test.ts` - `src/composables/node/{useNodePricing,useWatchWidget}.test.ts` - `src/composables/{useBrowserTabTitle,useCoreCommands}.test.ts` - `src/utils/__tests__/litegraphTestUtils.ts` ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-8258-refactor-eliminate-unsafe-type-assertions-from-Group-2-test-files-2f16d73d365081549c65fd546cc7c765) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <action@github.com> Co-authored-by: Alexander Brown <drjkl@comfy.org> Co-authored-by: Amp <amp@ampcode.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: AustinMroz <austin@comfy.org> Co-authored-by: Christian Byrne <cbyrne@comfy.org> Co-authored-by: Benjamin Lu <benjaminlu1107@gmail.com>
185 lines
5.2 KiB
TypeScript
185 lines
5.2 KiB
TypeScript
import { mount } from '@vue/test-utils'
|
|
import PrimeVue from 'primevue/config'
|
|
import Galleria from 'primevue/galleria'
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
import { createApp, nextTick } from 'vue'
|
|
|
|
import type { NodeId } from '@/platform/workflow/validation/schemas/workflowSchema'
|
|
import type { ResultItemImpl } from '@/stores/queueStore'
|
|
|
|
import ResultGallery from './ResultGallery.vue'
|
|
|
|
type MockResultItem = Partial<ResultItemImpl> & {
|
|
filename: string
|
|
subfolder: string
|
|
type: string
|
|
nodeId: NodeId
|
|
mediaType: string
|
|
id?: string
|
|
url?: string
|
|
isImage?: boolean
|
|
isVideo?: boolean
|
|
}
|
|
|
|
describe('ResultGallery', () => {
|
|
// Mock ComfyImage and ResultVideo components
|
|
const mockComfyImage = {
|
|
name: 'ComfyImage',
|
|
template: '<div class="mock-comfy-image" data-testid="comfy-image"></div>',
|
|
props: ['src', 'contain', 'alt']
|
|
}
|
|
|
|
const mockResultVideo = {
|
|
name: 'ResultVideo',
|
|
template:
|
|
'<div class="mock-result-video" data-testid="result-video"></div>',
|
|
props: ['result']
|
|
}
|
|
|
|
// Sample gallery items - using mock instances with only required properties
|
|
const mockGalleryItems: MockResultItem[] = [
|
|
{
|
|
filename: 'image1.jpg',
|
|
subfolder: 'outputs',
|
|
type: 'output',
|
|
nodeId: '123' as NodeId,
|
|
mediaType: 'images',
|
|
isImage: true,
|
|
isVideo: false,
|
|
url: 'image1.jpg',
|
|
id: '1'
|
|
},
|
|
{
|
|
filename: 'image2.jpg',
|
|
subfolder: 'outputs',
|
|
type: 'output',
|
|
nodeId: '456' as NodeId,
|
|
mediaType: 'images',
|
|
isImage: true,
|
|
isVideo: false,
|
|
url: 'image2.jpg',
|
|
id: '2'
|
|
}
|
|
]
|
|
|
|
beforeEach(() => {
|
|
const app = createApp({})
|
|
app.use(PrimeVue)
|
|
|
|
// Create mock elements for Galleria to find
|
|
document.body.innerHTML = `
|
|
<div id="app"></div>
|
|
`
|
|
})
|
|
|
|
afterEach(() => {
|
|
// Clean up any elements added to body
|
|
document.body.innerHTML = ''
|
|
vi.restoreAllMocks()
|
|
})
|
|
|
|
const mountGallery = (props = {}) => {
|
|
return mount(ResultGallery, {
|
|
global: {
|
|
plugins: [PrimeVue],
|
|
components: {
|
|
Galleria,
|
|
ComfyImage: mockComfyImage,
|
|
ResultVideo: mockResultVideo
|
|
},
|
|
stubs: {
|
|
teleport: true
|
|
}
|
|
},
|
|
props: {
|
|
allGalleryItems: mockGalleryItems as ResultItemImpl[],
|
|
activeIndex: 0,
|
|
...props
|
|
},
|
|
attachTo: document.getElementById('app') || undefined
|
|
})
|
|
}
|
|
|
|
it('renders Galleria component with correct props', async () => {
|
|
const wrapper = mountGallery()
|
|
|
|
await nextTick() // Wait for component to mount
|
|
|
|
const galleria = wrapper.findComponent(Galleria)
|
|
expect(galleria.exists()).toBe(true)
|
|
expect(galleria.props('value')).toEqual(mockGalleryItems)
|
|
expect(galleria.props('showIndicators')).toBe(false)
|
|
expect(galleria.props('showItemNavigators')).toBe(true)
|
|
expect(galleria.props('fullScreen')).toBe(true)
|
|
})
|
|
|
|
it('shows gallery when activeIndex changes from -1', async () => {
|
|
const wrapper = mountGallery({ activeIndex: -1 })
|
|
|
|
// Initially galleryVisible should be false
|
|
type GalleryVM = typeof wrapper.vm & {
|
|
galleryVisible: boolean
|
|
}
|
|
const vm = wrapper.vm as GalleryVM
|
|
expect(vm.galleryVisible).toBe(false)
|
|
|
|
// Change activeIndex
|
|
await wrapper.setProps({ activeIndex: 0 })
|
|
await nextTick()
|
|
|
|
// galleryVisible should become true
|
|
expect(vm.galleryVisible).toBe(true)
|
|
})
|
|
|
|
it('should render the component properly', () => {
|
|
// This is a meta-test to confirm the component mounts properly
|
|
const wrapper = mountGallery()
|
|
|
|
// We can't directly test the compiled CSS, but we can verify the component renders
|
|
expect(wrapper.exists()).toBe(true)
|
|
|
|
// Verify that the Galleria component exists and is properly mounted
|
|
const galleria = wrapper.findComponent(Galleria)
|
|
expect(galleria.exists()).toBe(true)
|
|
})
|
|
|
|
it('ensures correct configuration for mobile viewport', async () => {
|
|
// Mock window.matchMedia to simulate mobile viewport
|
|
Object.defineProperty(window, 'matchMedia', {
|
|
writable: true,
|
|
value: vi.fn().mockImplementation((query) => ({
|
|
matches: query.includes('max-width: 768px'),
|
|
media: query,
|
|
onchange: null,
|
|
addListener: vi.fn(),
|
|
removeListener: vi.fn(),
|
|
addEventListener: vi.fn(),
|
|
removeEventListener: vi.fn(),
|
|
dispatchEvent: vi.fn()
|
|
}))
|
|
})
|
|
|
|
const wrapper = mountGallery()
|
|
await nextTick()
|
|
|
|
// Verify mobile media query is working
|
|
expect(window.matchMedia('(max-width: 768px)').matches).toBe(true)
|
|
|
|
// Check if the component renders with Galleria
|
|
const galleria = wrapper.findComponent(Galleria)
|
|
expect(galleria.exists()).toBe(true)
|
|
|
|
// Check that our PT props for positioning work correctly
|
|
interface GalleriaPT {
|
|
prevButton?: { style?: string }
|
|
nextButton?: { style?: string }
|
|
}
|
|
const pt = galleria.props('pt') as GalleriaPT
|
|
expect(pt?.prevButton?.style).toContain('position: fixed')
|
|
expect(pt?.nextButton?.style).toContain('position: fixed')
|
|
})
|
|
|
|
// Additional tests for interaction could be added once we can reliably
|
|
// test Galleria component in fullscreen mode
|
|
})
|