diff --git a/src/components/common/CustomizationDialog.vue b/src/components/common/CustomizationDialog.vue index f5df6d84d..b4e9bcad0 100644 --- a/src/components/common/CustomizationDialog.vue +++ b/src/components/common/CustomizationDialog.vue @@ -92,18 +92,16 @@ const colorOptions = [ const defaultIcon = iconOptions.find( (option) => option.value === nodeBookmarkStore.defaultBookmarkIcon -) +) ?? { name: '', value: '' } -// @ts-expect-error fixme ts strict error const selectedIcon = ref<{ name: string; value: string }>(defaultIcon) const finalColor = ref( props.initialColor || nodeBookmarkStore.defaultBookmarkColor ) const resetCustomization = () => { - // @ts-expect-error fixme ts strict error selectedIcon.value = - iconOptions.find((option) => option.value === props.initialIcon) || + iconOptions.find((option) => option.value === props.initialIcon) ?? defaultIcon finalColor.value = props.initialColor || nodeBookmarkStore.defaultBookmarkColor diff --git a/src/components/common/EditableText.test.ts b/src/components/common/EditableText.test.ts index 2d31123b9..0c1c234cf 100644 --- a/src/components/common/EditableText.test.ts +++ b/src/components/common/EditableText.test.ts @@ -13,8 +13,10 @@ describe('EditableText', () => { app.use(PrimeVue) }) - // @ts-expect-error fixme ts strict error - const mountComponent = (props, options = {}) => { + const mountComponent = ( + props: { modelValue: string; isEditing: boolean }, + options = {} + ) => { return mount(EditableText, { global: { plugins: [PrimeVue], @@ -65,8 +67,7 @@ describe('EditableText', () => { }) await wrapper.findComponent(InputText).trigger('blur') expect(wrapper.emitted('edit')).toBeTruthy() - // @ts-expect-error fixme ts strict error - expect(wrapper.emitted('edit')[0]).toEqual(['Test Text']) + expect(wrapper.emitted('edit')?.[0]).toEqual(['Test Text']) }) it('cancels editing on escape key', async () => { @@ -124,8 +125,7 @@ describe('EditableText', () => { // Trigger blur that happens after enter await enterWrapper.findComponent(InputText).trigger('blur') expect(enterWrapper.emitted('edit')).toBeTruthy() - // @ts-expect-error fixme ts strict error - expect(enterWrapper.emitted('edit')[0]).toEqual(['Saved Text']) + expect(enterWrapper.emitted('edit')?.[0]).toEqual(['Saved Text']) // Test Escape key cancels changes with a fresh wrapper const escapeWrapper = mountComponent({ diff --git a/src/components/common/EditableText.vue b/src/components/common/EditableText.vue index 322d332a4..16b52e7a1 100644 --- a/src/components/common/EditableText.vue +++ b/src/components/common/EditableText.vue @@ -44,12 +44,13 @@ const { const emit = defineEmits(['edit', 'cancel']) const inputValue = ref(modelValue) -const inputRef = ref | undefined>() +const inputRef = ref< + (InstanceType & { $el?: HTMLElement }) | undefined +>() const isCanceling = ref(false) const blurInputElement = () => { - // @ts-expect-error - $el is an internal property of the InputText component - inputRef.value?.$el.blur() + inputRef.value?.$el?.blur() } const finishEditing = () => { // Don't save if we're canceling @@ -74,15 +75,14 @@ watch( if (newVal) { inputValue.value = modelValue await nextTick(() => { - if (!inputRef.value) return + const el = inputRef.value?.$el + if (!el || !(el instanceof HTMLInputElement)) return const fileName = inputValue.value.includes('.') ? inputValue.value.split('.').slice(0, -1).join('.') : inputValue.value const start = 0 const end = fileName.length - // @ts-expect-error - $el is an internal property of the InputText component - const inputElement = inputRef.value.$el - inputElement.setSelectionRange?.(start, end) + el.setSelectionRange?.(start, end) }) } }, diff --git a/src/components/common/ElectronFileDownload.vue b/src/components/common/ElectronFileDownload.vue index 0a85a197b..34916d243 100644 --- a/src/components/common/ElectronFileDownload.vue +++ b/src/components/common/ElectronFileDownload.vue @@ -116,17 +116,16 @@ const fileSize = computed(() => ) const { copyToClipboard } = useCopyToClipboard() const electronDownloadStore = useElectronDownloadStore() -// @ts-expect-error fixme ts strict error -const [savePath, filename] = props.label.split('/') +const [savePath = '', filename = ''] = props.label?.split('/') ?? [] electronDownloadStore.$subscribe((_, { downloads }) => { - const download = downloads.find((download) => props.url === download.url) + const foundDownload = downloads.find((download) => props.url === download.url) - if (download) { - // @ts-expect-error fixme ts strict error - downloadProgress.value = Number((download.progress * 100).toFixed(1)) - // @ts-expect-error fixme ts strict error - status.value = download.status + if (foundDownload) { + downloadProgress.value = Number( + ((foundDownload.progress ?? 0) * 100).toFixed(1) + ) + status.value = foundDownload.status ?? null } }) diff --git a/src/components/common/TreeExplorerTreeNode.test.ts b/src/components/common/TreeExplorerTreeNode.test.ts index d00d3e401..f09626cb9 100644 --- a/src/components/common/TreeExplorerTreeNode.test.ts +++ b/src/components/common/TreeExplorerTreeNode.test.ts @@ -61,8 +61,8 @@ describe('TreeExplorerTreeNode', () => { expect(wrapper.findComponent(EditableText).props('modelValue')).toBe( 'Test Node' ) - // @ts-expect-error fixme ts strict error - expect(wrapper.findComponent(Badge).props()['value'].toString()).toBe('3') + const badgeValue = wrapper.findComponent(Badge).props()['value'] + expect(String(badgeValue)).toBe('3') }) it('makes node label editable when renamingEditingNode matches', async () => { diff --git a/src/components/dialog/content/MissingCoreNodesMessage.test.ts b/src/components/dialog/content/MissingCoreNodesMessage.test.ts index afcb90996..81c28045c 100644 --- a/src/components/dialog/content/MissingCoreNodesMessage.test.ts +++ b/src/components/dialog/content/MissingCoreNodesMessage.test.ts @@ -14,8 +14,6 @@ vi.mock('@/stores/systemStatsStore', () => ({ })) const createMockNode = (type: string, version?: string): LGraphNode => - // @ts-expect-error - Creating a partial mock of LGraphNode for testing purposes. - // We only need specific properties for our tests, not the full LGraphNode interface. ({ type, properties: { cnr_id: 'comfy-core', ver: version }, @@ -28,7 +26,7 @@ const createMockNode = (type: string, version?: string): LGraphNode => mode: 0, inputs: [], outputs: [] - }) + }) as unknown as LGraphNode describe('MissingCoreNodesMessage', () => { const mockSystemStatsStore = { @@ -41,9 +39,9 @@ describe('MissingCoreNodesMessage', () => { // Reset the mock store state mockSystemStatsStore.systemStats = null mockSystemStatsStore.refetchSystemStats = vi.fn() - // @ts-expect-error - Mocking the return value of useSystemStatsStore for testing. - // The actual store has more properties, but we only need these for our tests. - useSystemStatsStore.mockReturnValue(mockSystemStatsStore) + vi.mocked(useSystemStatsStore).mockReturnValue( + mockSystemStatsStore as unknown as ReturnType + ) }) const mountComponent = (props = {}) => { diff --git a/src/components/dialog/content/PromptDialogContent.vue b/src/components/dialog/content/PromptDialogContent.vue index 92c721a24..e96275cf4 100644 --- a/src/components/dialog/content/PromptDialogContent.vue +++ b/src/components/dialog/content/PromptDialogContent.vue @@ -39,11 +39,13 @@ const onConfirm = () => { useDialogStore().closeDialog() } -const inputRef = ref | undefined>() +const inputRef = ref< + (InstanceType & { $el?: HTMLElement }) | undefined +>() const selectAllText = () => { - if (!inputRef.value) return - // @ts-expect-error - $el is an internal property of the InputText component - const inputElement = inputRef.value.$el - inputElement.setSelectionRange(0, inputElement.value.length) + const el = inputRef.value?.$el + if (el instanceof HTMLInputElement) { + el.setSelectionRange(0, el.value.length) + } } diff --git a/src/components/dialog/content/setting/KeybindingPanel.vue b/src/components/dialog/content/setting/KeybindingPanel.vue index 03ca3df47..c97eb8864 100644 --- a/src/components/dialog/content/setting/KeybindingPanel.vue +++ b/src/components/dialog/content/setting/KeybindingPanel.vue @@ -194,7 +194,9 @@ const selectedCommandData = ref(null) const editDialogVisible = ref(false) const newBindingKeyCombo = ref(null) const currentEditingCommand = ref(null) -const keybindingInput = ref | null>(null) +const keybindingInput = ref< + (InstanceType & { $el?: HTMLElement }) | null +>(null) const existingKeybindingOnCombo = computed(() => { if (!currentEditingCommand.value) { @@ -229,8 +231,8 @@ watchEffect(() => { if (editDialogVisible.value) { // nextTick doesn't work here, so we use a timeout instead setTimeout(() => { - // @ts-expect-error - $el is an internal property of the InputText component - keybindingInput.value?.$el?.focus() + const el = keybindingInput.value?.$el + if (el instanceof HTMLElement) el.focus() }, 300) } }) diff --git a/src/components/graph/GraphCanvas.vue b/src/components/graph/GraphCanvas.vue index 48d82e44b..41ecfec97 100644 --- a/src/components/graph/GraphCanvas.vue +++ b/src/components/graph/GraphCanvas.vue @@ -428,7 +428,7 @@ onMounted(async () => { await newUserService().initializeIfNewUser(settingStore) - // @ts-expect-error fixme ts strict error + if (!canvasRef.value) return await comfyApp.setup(canvasRef.value) canvasStore.canvas = comfyApp.canvas canvasStore.canvas.render_canvas_border = false diff --git a/src/components/load3d/Load3DControls.vue b/src/components/load3d/Load3DControls.vue index 68251c741..1c13d5e9c 100644 --- a/src/components/load3d/Load3DControls.vue +++ b/src/components/load3d/Load3DControls.vue @@ -161,15 +161,14 @@ const selectCategory = (category: string) => { } const getCategoryIcon = (category: string) => { - const icons = { + const icons: Record = { scene: 'pi pi-image', model: 'pi pi-box', camera: 'pi pi-camera', light: 'pi pi-sun', export: 'pi pi-download' } - // @ts-expect-error fixme ts strict error - return `${icons[category]} text-base-foreground text-lg` + return `${icons[category] ?? ''} text-base-foreground text-lg` } const emit = defineEmits<{ diff --git a/src/components/sidebar/tabs/ModelLibrarySidebarTab.vue b/src/components/sidebar/tabs/ModelLibrarySidebarTab.vue index 218655231..c7bebb191 100644 --- a/src/components/sidebar/tabs/ModelLibrarySidebarTab.vue +++ b/src/components/sidebar/tabs/ModelLibrarySidebarTab.vue @@ -145,17 +145,16 @@ const renderedRoot = computed>(() => { children, draggable: node.leaf, handleClick(e: MouseEvent) { - if (this.leaf) { - // @ts-expect-error fixme ts strict error + if (this.leaf && model) { const provider = modelToNodeStore.getNodeProvider(model.directory) if (provider) { - const node = useLitegraphService().addNodeOnGraph(provider.nodeDef) - // @ts-expect-error fixme ts strict error - const widget = node.widgets.find( + const addedNode = useLitegraphService().addNodeOnGraph( + provider.nodeDef + ) + const widget = addedNode?.widgets?.find( (widget) => widget.name === provider.key ) if (widget) { - // @ts-expect-error fixme ts strict error widget.value = model.file_name } } diff --git a/src/components/sidebar/tabs/NodeLibrarySidebarTab.vue b/src/components/sidebar/tabs/NodeLibrarySidebarTab.vue index 2240a60b1..1b74d3e93 100644 --- a/src/components/sidebar/tabs/NodeLibrarySidebarTab.vue +++ b/src/components/sidebar/tabs/NodeLibrarySidebarTab.vue @@ -278,8 +278,7 @@ const renderedRoot = computed>(() => { } }, handleClick(e: MouseEvent) { - if (this.leaf) { - // @ts-expect-error fixme ts strict error + if (this.leaf && this.data) { useLitegraphService().addNodeOnGraph(this.data) } else { toggleNodeOnEvent(e, this) @@ -336,8 +335,7 @@ const onAddFilter = async ( await handleSearch(searchQuery.value) } -// @ts-expect-error fixme ts strict error -const onRemoveFilter = async (filterAndValue) => { +const onRemoveFilter = async (filterAndValue: SearchFilter) => { const index = filters.value.findIndex((f) => f === filterAndValue) if (index !== -1) { filters.value.splice(index, 1) diff --git a/src/components/sidebar/tabs/nodeLibrary/NodeBookmarkTreeExplorer.vue b/src/components/sidebar/tabs/nodeLibrary/NodeBookmarkTreeExplorer.vue index 646f841bb..3e5e31387 100644 --- a/src/components/sidebar/tabs/nodeLibrary/NodeBookmarkTreeExplorer.vue +++ b/src/components/sidebar/tabs/nodeLibrary/NodeBookmarkTreeExplorer.vue @@ -162,20 +162,17 @@ const renderedBookmarkedRoot = computed>( droppable: !node.leaf, async handleDrop(data: TreeExplorerDragAndDropData) { const nodeDefToAdd = data.data.data + if (!nodeDefToAdd) return // Remove bookmark if the source is the top level bookmarked node. - // @ts-expect-error fixme ts strict error if (nodeBookmarkStore.isBookmarked(nodeDefToAdd)) { - // @ts-expect-error fixme ts strict error await nodeBookmarkStore.toggleBookmark(nodeDefToAdd) } const folderNodeDef = node.data as ComfyNodeDefImpl - // @ts-expect-error fixme ts strict error const nodePath = folderNodeDef.category + '/' + nodeDefToAdd.name await nodeBookmarkStore.addBookmark(nodePath) }, handleClick(e: MouseEvent) { - if (this.leaf) { - // @ts-expect-error fixme ts strict error + if (this.leaf && this.data) { useLitegraphService().addNodeOnGraph(this.data) } else { toggleNodeOnEvent(e, node) @@ -194,8 +191,9 @@ const renderedBookmarkedRoot = computed>( } }, async handleDelete() { - // @ts-expect-error fixme ts strict error - await nodeBookmarkStore.deleteBookmarkFolder(this.data) + if (this.data) { + await nodeBookmarkStore.deleteBookmarkFolder(this.data) + } } }) } diff --git a/src/components/topbar/CurrentUserButton.test.ts b/src/components/topbar/CurrentUserButton.test.ts index db5349b49..f1a1c2194 100644 --- a/src/components/topbar/CurrentUserButton.test.ts +++ b/src/components/topbar/CurrentUserButton.test.ts @@ -94,27 +94,32 @@ describe('CurrentUserButton', () => { }) it('toggles popover on button click', async () => { - const wrapper = mountComponent() + const wrapper = mountComponent() as VueWrapper< + InstanceType + > const popoverToggleSpy = vi.fn() // Override the ref with a mock implementation - // @ts-expect-error - accessing internal Vue component vm - wrapper.vm.popover = { toggle: popoverToggleSpy } + wrapper.vm.popover = { + toggle: popoverToggleSpy + } as unknown as typeof wrapper.vm.popover await wrapper.findComponent(Button).trigger('click') expect(popoverToggleSpy).toHaveBeenCalled() }) it('hides popover when closePopover is called', async () => { - const wrapper = mountComponent() + const wrapper = mountComponent() as VueWrapper< + InstanceType + > // Replace the popover.hide method with a spy const popoverHideSpy = vi.fn() - // @ts-expect-error - accessing internal Vue component vm - wrapper.vm.popover = { hide: popoverHideSpy } + wrapper.vm.popover = { + hide: popoverHideSpy + } as unknown as typeof wrapper.vm.popover // Directly call the closePopover method through the component instance - // @ts-expect-error - accessing internal Vue component vm wrapper.vm.closePopover() // Verify that popover.hide was called diff --git a/src/components/topbar/CurrentUserButton.vue b/src/components/topbar/CurrentUserButton.vue index 44233aac5..5dfa79223 100644 --- a/src/components/topbar/CurrentUserButton.vue +++ b/src/components/topbar/CurrentUserButton.vue @@ -62,4 +62,6 @@ const photoURL = computed( const closePopover = () => { popover.value?.hide() } + +defineExpose({ popover, closePopover }) diff --git a/src/composables/canvas/useSelectedLiteGraphItems.test.ts b/src/composables/canvas/useSelectedLiteGraphItems.test.ts index 23e1e8dd3..0b936cf3b 100644 --- a/src/composables/canvas/useSelectedLiteGraphItems.test.ts +++ b/src/composables/canvas/useSelectedLiteGraphItems.test.ts @@ -28,11 +28,12 @@ vi.mock('@/lib/litegraph/src/litegraph', () => ({ } })) -// Mock Positionable objects -// @ts-expect-error - Mock implementation for testing +// Mock Positionable objects - full implementation for testing class MockNode implements Positionable { + readonly id = 1 pos: [number, number] size: [number, number] + readonly boundingRect: [number, number, number, number] constructor( pos: [number, number] = [0, 0], @@ -40,22 +41,35 @@ class MockNode implements Positionable { ) { this.pos = pos this.size = size + this.boundingRect = [pos[0], pos[1], size[0], size[1]] + } + + move(): void {} + snapToGrid(): boolean { + return false } } -class MockReroute extends Reroute implements Positionable { - // @ts-expect-error - Override for testing - override pos: [number, number] +// MockReroute - passes instanceof Reroute check +class MockReroute implements Positionable { + readonly id = 1 + pos: [number, number] size: [number, number] + readonly boundingRect: [number, number, number, number] constructor( pos: [number, number] = [0, 0], size: [number, number] = [20, 20] ) { - // @ts-expect-error - Mock constructor - super() + Object.setPrototypeOf(this, Reroute.prototype) this.pos = pos this.size = size + this.boundingRect = [pos[0], pos[1], size[0], size[1]] + } + + move(): void {} + snapToGrid(): boolean { + return false } } @@ -86,7 +100,6 @@ describe('useSelectedLiteGraphItems', () => { it('should return false for non-Reroute items', () => { const { isIgnoredItem } = useSelectedLiteGraphItems() const node = new MockNode() - // @ts-expect-error - Test mock expect(isIgnoredItem(node)).toBe(false) }) }) @@ -98,14 +111,11 @@ describe('useSelectedLiteGraphItems', () => { const node2 = new MockNode([100, 100]) const reroute = new MockReroute([50, 50]) - // @ts-expect-error - Test mocks const items = new Set([node1, node2, reroute]) const filtered = filterSelectableItems(items) expect(filtered.size).toBe(2) - // @ts-expect-error - Test mocks expect(filtered.has(node1)).toBe(true) - // @ts-expect-error - Test mocks expect(filtered.has(node2)).toBe(true) expect(filtered.has(reroute)).toBe(false) }) @@ -143,9 +153,7 @@ describe('useSelectedLiteGraphItems', () => { const selectableItems = getSelectableItems() expect(selectableItems.size).toBe(2) - // @ts-expect-error - Test mock expect(selectableItems.has(node1)).toBe(true) - // @ts-expect-error - Test mock expect(selectableItems.has(node2)).toBe(true) expect(selectableItems.has(reroute)).toBe(false) }) @@ -215,8 +223,7 @@ describe('useSelectedLiteGraphItems', () => { it('getSelectedNodes should return empty array when no nodes selected', () => { const { getSelectedNodes } = useSelectedLiteGraphItems() - // @ts-expect-error - Testing null case - app.canvas.selected_nodes = null + Object.assign(app.canvas, { selected_nodes: null }) const selectedNodes = getSelectedNodes() expect(selectedNodes).toHaveLength(0)