mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-04 15:10:06 +00:00
fix(types): remove @ts-expect-error in components and composables
Amp-Thread-ID: https://ampcode.com/threads/T-019bafc7-9674-769c-bfea-dd60aa6c47a7 Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -44,12 +44,13 @@ const {
|
||||
|
||||
const emit = defineEmits(['edit', 'cancel'])
|
||||
const inputValue = ref<string>(modelValue)
|
||||
const inputRef = ref<InstanceType<typeof InputText> | undefined>()
|
||||
const inputRef = ref<
|
||||
(InstanceType<typeof InputText> & { $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)
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -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 () => {
|
||||
|
||||
@@ -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<typeof useSystemStatsStore>
|
||||
)
|
||||
})
|
||||
|
||||
const mountComponent = (props = {}) => {
|
||||
|
||||
@@ -39,11 +39,13 @@ const onConfirm = () => {
|
||||
useDialogStore().closeDialog()
|
||||
}
|
||||
|
||||
const inputRef = ref<InstanceType<typeof InputText> | undefined>()
|
||||
const inputRef = ref<
|
||||
(InstanceType<typeof InputText> & { $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)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -194,7 +194,9 @@ const selectedCommandData = ref<ICommandData | null>(null)
|
||||
const editDialogVisible = ref(false)
|
||||
const newBindingKeyCombo = ref<KeyComboImpl | null>(null)
|
||||
const currentEditingCommand = ref<ICommandData | null>(null)
|
||||
const keybindingInput = ref<InstanceType<typeof InputText> | null>(null)
|
||||
const keybindingInput = ref<
|
||||
(InstanceType<typeof InputText> & { $el?: HTMLElement }) | null
|
||||
>(null)
|
||||
|
||||
const existingKeybindingOnCombo = computed<KeybindingImpl | null>(() => {
|
||||
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)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -161,15 +161,14 @@ const selectCategory = (category: string) => {
|
||||
}
|
||||
|
||||
const getCategoryIcon = (category: string) => {
|
||||
const icons = {
|
||||
const icons: Record<string, string> = {
|
||||
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<{
|
||||
|
||||
@@ -145,17 +145,16 @@ const renderedRoot = computed<TreeExplorerNode<ModelOrFolder>>(() => {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,8 +278,7 @@ const renderedRoot = computed<TreeExplorerNode<ComfyNodeDefImpl>>(() => {
|
||||
}
|
||||
},
|
||||
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)
|
||||
|
||||
@@ -162,20 +162,17 @@ const renderedBookmarkedRoot = computed<TreeExplorerNode<ComfyNodeDefImpl>>(
|
||||
droppable: !node.leaf,
|
||||
async handleDrop(data: TreeExplorerDragAndDropData<ComfyNodeDefImpl>) {
|
||||
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<TreeExplorerNode<ComfyNodeDefImpl>>(
|
||||
}
|
||||
},
|
||||
async handleDelete() {
|
||||
// @ts-expect-error fixme ts strict error
|
||||
await nodeBookmarkStore.deleteBookmarkFolder(this.data)
|
||||
if (this.data) {
|
||||
await nodeBookmarkStore.deleteBookmarkFolder(this.data)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -94,27 +94,32 @@ describe('CurrentUserButton', () => {
|
||||
})
|
||||
|
||||
it('toggles popover on button click', async () => {
|
||||
const wrapper = mountComponent()
|
||||
const wrapper = mountComponent() as VueWrapper<
|
||||
InstanceType<typeof CurrentUserButton>
|
||||
>
|
||||
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<typeof CurrentUserButton>
|
||||
>
|
||||
|
||||
// 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
|
||||
|
||||
@@ -62,4 +62,6 @@ const photoURL = computed<string | undefined>(
|
||||
const closePopover = () => {
|
||||
popover.value?.hide()
|
||||
}
|
||||
|
||||
defineExpose({ popover, closePopover })
|
||||
</script>
|
||||
|
||||
@@ -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<Positionable>([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)
|
||||
|
||||
Reference in New Issue
Block a user