fix: replace as-unknown-as casts with safer patterns (#9107)

## Summary

- Replace 83 `as unknown as` double casts with safer alternatives across
33 files
- Use `as Partial<X> as X` pattern where TypeScript allows it
- Create/reuse factory functions from `litegraphTestUtils.ts` for mock
objects
- Widen `getWorkflowDataFromFile` return type to include `ComfyMetadata`
directly
- Reduce total `as unknown as` count from ~153 to 71

The remaining 71 occurrences are genuinely necessary due to cross-schema
casts, generic variance, missing index signatures, Float64Array-to-tuple
conversions, and DOM type incompatibilities.

## Test plan

- [x] `pnpm typecheck` passes
- [x] `pnpm lint` passes
- [x] All affected unit tests pass

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-9107-fix-replace-as-unknown-as-casts-with-safer-patterns-3106d73d3650815cb5bcd613ad635bd7)
by [Unito](https://www.unito.io)
This commit is contained in:
Johnpaul Chiwetelu
2026-02-23 05:46:12 +01:00
committed by GitHub
parent 8998d92e1b
commit 02e926471f
33 changed files with 282 additions and 346 deletions

View File

@@ -77,7 +77,7 @@ const createMockElectronAPI = () => {
}
const ensureElectronAPI = () => {
const globalWindow = window as unknown as { electronAPI?: unknown }
const globalWindow = window as { electronAPI?: unknown }
if (!globalWindow.electronAPI) {
globalWindow.electronAPI = createMockElectronAPI()
}

View File

@@ -88,7 +88,7 @@ export class SubgraphHelper {
if (node.onPointerDown) {
node.onPointerDown(
event as unknown as CanvasPointerEvent,
event as Partial<CanvasPointerEvent> as CanvasPointerEvent,
app.canvas.pointer,
app.canvas.linkConnector
)
@@ -121,7 +121,7 @@ export class SubgraphHelper {
if (node.onPointerDown) {
node.onPointerDown(
event as unknown as CanvasPointerEvent,
event as Partial<CanvasPointerEvent> as CanvasPointerEvent,
app.canvas.pointer,
app.canvas.linkConnector
)
@@ -129,7 +129,7 @@ export class SubgraphHelper {
// Trigger double-click
if (app.canvas.pointer.onDoubleClick) {
app.canvas.pointer.onDoubleClick(
event as unknown as CanvasPointerEvent
event as Partial<CanvasPointerEvent> as CanvasPointerEvent
)
}
}

View File

@@ -57,7 +57,7 @@ settings: testData as any
// Don't add test settings to src/schemas/apiSchema.ts
// ❌ Don't chain through unknown to bypass types
data as unknown as SomeType // Avoid; prefer explicit typings or helpers
data as unknown as SomeType // Avoid; prefer `as Partial<SomeType> as SomeType` or explicit typings
```
### Accessing Internal State

View File

@@ -11,7 +11,7 @@ import {
} from '../packages/shared-frontend-utils/src/formatUtil'
import { CORE_MENU_COMMANDS } from '../src/constants/coreMenuCommands'
import { SERVER_CONFIG_ITEMS } from '../src/constants/serverConfig'
import type { FormItem, SettingParams } from '../src/platform/settings/types'
import type { SettingParams } from '../src/platform/settings/types'
import type { ComfyCommandImpl } from '../src/stores/commandStore'
const localePath = './src/locales/en/main.json'
@@ -123,8 +123,8 @@ test('collect-i18n-general', async ({ comfyPage }) => {
SERVER_CONFIG_ITEMS.map((config) => [
normalizeI18nKey(config.id),
{
name: (config as unknown as FormItem).name,
tooltip: (config as unknown as FormItem).tooltip
name: config.name,
tooltip: config.tooltip
}
])
)

View File

@@ -190,7 +190,7 @@ describe('downloadUtil', () => {
ok: false,
status: 404,
blob: vi.fn()
} as unknown as Response)
} as Partial<Response> as Response)
downloadFile(testUrl)

View File

@@ -6,8 +6,8 @@ import type { Ref } from 'vue'
import QueueInlineProgress from '@/components/queue/QueueInlineProgress.vue'
const mockProgress = vi.hoisted(() => ({
totalPercent: null as unknown as Ref<number>,
currentNodePercent: null as unknown as Ref<number>
totalPercent: null! as Ref<number>,
currentNodePercent: null! as Ref<number>
}))
vi.mock('@/composables/queue/useQueueProgress', () => ({

View File

@@ -39,7 +39,7 @@ describe('useJobErrorReporting', () => {
dialog = {
showErrorDialog,
showExecutionErrorDialog
} as unknown as JobErrorDialogService
} as Partial<JobErrorDialogService> as JobErrorDialogService
composable = useJobErrorReporting({
taskForJob,
copyToClipboard: copyToClipboard as (

View File

@@ -31,7 +31,10 @@ function createFilter(
filterDef: {
id,
matches: vi.fn(() => true)
} as unknown as FuseFilter<ComfyNodeDefImpl, string>,
} as Partial<FuseFilter<ComfyNodeDefImpl, string>> as FuseFilter<
ComfyNodeDefImpl,
string
>,
value
}
}
@@ -43,7 +46,10 @@ function createActiveFilter(label: string): FilterChip {
filter: {
id: label.toLowerCase(),
matches: vi.fn(() => true)
} as unknown as FuseFilter<ComfyNodeDefImpl, string>
} as Partial<FuseFilter<ComfyNodeDefImpl, string>> as FuseFilter<
ComfyNodeDefImpl,
string
>
}
}

View File

@@ -72,7 +72,9 @@ describe('useNodePreviewAndDrag', () => {
toJSON: () => ({})
})
const mockEvent = { currentTarget: mockElement } as unknown as MouseEvent
const mockEvent = {
currentTarget: mockElement
} as Partial<MouseEvent> as MouseEvent
result.handleMouseEnter(mockEvent)
expect(result.isHovered.value).toBe(true)
@@ -83,7 +85,9 @@ describe('useNodePreviewAndDrag', () => {
const result = useNodePreviewAndDrag(nodeDef)
const mockElement = document.createElement('div')
const mockEvent = { currentTarget: mockElement } as unknown as MouseEvent
const mockEvent = {
currentTarget: mockElement
} as Partial<MouseEvent> as MouseEvent
result.handleMouseEnter(mockEvent)
expect(result.isHovered.value).toBe(false)
@@ -150,7 +154,7 @@ describe('useNodePreviewAndDrag', () => {
const mockEvent = {
clientX: 100,
clientY: 200
} as unknown as DragEvent
} as Partial<DragEvent> as DragEvent
result.handleDragEnd(mockEvent)
@@ -168,7 +172,7 @@ describe('useNodePreviewAndDrag', () => {
dataTransfer: { dropEffect: 'none' },
clientX: 300,
clientY: 400
} as unknown as DragEvent
} as Partial<DragEvent> as DragEvent
result.handleDragEnd(mockEvent)

View File

@@ -3,7 +3,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { nextTick, reactive } from 'vue'
import { useQueueNotificationBanners } from '@/composables/queue/useQueueNotificationBanners'
import { api } from '@/scripts/api'
import { useExecutionStore } from '@/stores/executionStore'
import { useQueueStore } from '@/stores/queueStore'
@@ -135,7 +134,7 @@ describe(useQueueNotificationBanners, () => {
const { wrapper, composable } = mountComposable()
try {
;(api as unknown as EventTarget).dispatchEvent(
mockApi.dispatchEvent(
new CustomEvent('promptQueued', { detail: { batchCount: 4 } })
)
await nextTick()
@@ -157,7 +156,7 @@ describe(useQueueNotificationBanners, () => {
const { wrapper, composable } = mountComposable()
try {
;(api as unknown as EventTarget).dispatchEvent(
mockApi.dispatchEvent(
new CustomEvent('promptQueueing', {
detail: { requestId: 1, batchCount: 2 }
})
@@ -170,7 +169,7 @@ describe(useQueueNotificationBanners, () => {
requestId: 1
})
;(api as unknown as EventTarget).dispatchEvent(
mockApi.dispatchEvent(
new CustomEvent('promptQueued', {
detail: { requestId: 1, batchCount: 2 }
})
@@ -191,7 +190,7 @@ describe(useQueueNotificationBanners, () => {
const { wrapper, composable } = mountComposable()
try {
;(api as unknown as EventTarget).dispatchEvent(
mockApi.dispatchEvent(
new CustomEvent('promptQueued', { detail: { batchCount: 0 } })
)
await nextTick()

View File

@@ -7,6 +7,7 @@ import type {
} from '@/lib/litegraph/src/litegraph'
import { LiteGraph } from '@/lib/litegraph/src/litegraph'
import { app } from '@/scripts/app'
import { createMockLGraphNode } from '@/utils/__tests__/litegraphTestUtils'
import { createNode, isImageNode } from '@/utils/litegraphUtil'
import {
cloneDataTransfer,
@@ -15,12 +16,12 @@ import {
usePaste
} from './usePaste'
function createMockNode() {
return {
function createMockNode(): LGraphNode {
return createMockLGraphNode({
pos: [0, 0],
pasteFile: vi.fn(),
pasteFiles: vi.fn()
}
})
}
function createImageFile(
@@ -84,7 +85,8 @@ vi.mock('@/scripts/app', () => ({
}
}))
vi.mock('@/lib/litegraph/src/litegraph', () => ({
vi.mock('@/lib/litegraph/src/litegraph', async (importOriginal) => ({
...(await importOriginal()),
LiteGraph: {
createNode: vi.fn()
}
@@ -111,15 +113,12 @@ describe('pasteImageNode', () => {
it('should create new LoadImage node when no image node provided', async () => {
const mockNode = createMockNode()
vi.mocked(createNode).mockResolvedValue(mockNode as unknown as LGraphNode)
vi.mocked(createNode).mockResolvedValue(mockNode)
const file = createImageFile()
const dataTransfer = createDataTransfer([file])
await pasteImageNode(
mockCanvas as unknown as LGraphCanvas,
dataTransfer.items
)
await pasteImageNode(mockCanvas, dataTransfer.items)
expect(createNode).toHaveBeenCalledWith(mockCanvas, 'LoadImage')
expect(mockNode.pasteFile).toHaveBeenCalledWith(file)
@@ -130,11 +129,7 @@ describe('pasteImageNode', () => {
const file = createImageFile()
const dataTransfer = createDataTransfer([file])
await pasteImageNode(
mockCanvas as unknown as LGraphCanvas,
dataTransfer.items,
mockNode as unknown as LGraphNode
)
await pasteImageNode(mockCanvas, dataTransfer.items, mockNode)
expect(mockNode.pasteFile).toHaveBeenCalledWith(file)
expect(mockNode.pasteFiles).toHaveBeenCalledWith([file])
@@ -146,11 +141,7 @@ describe('pasteImageNode', () => {
const file2 = createImageFile('test2.jpg', 'image/jpeg')
const dataTransfer = createDataTransfer([file1, file2])
await pasteImageNode(
mockCanvas as unknown as LGraphCanvas,
dataTransfer.items,
mockNode as unknown as LGraphNode
)
await pasteImageNode(mockCanvas, dataTransfer.items, mockNode)
expect(mockNode.pasteFile).toHaveBeenCalledWith(file1)
expect(mockNode.pasteFiles).toHaveBeenCalledWith([file1, file2])
@@ -160,11 +151,7 @@ describe('pasteImageNode', () => {
const mockNode = createMockNode()
const dataTransfer = createDataTransfer()
await pasteImageNode(
mockCanvas as unknown as LGraphCanvas,
dataTransfer.items,
mockNode as unknown as LGraphNode
)
await pasteImageNode(mockCanvas, dataTransfer.items, mockNode)
expect(mockNode.pasteFile).not.toHaveBeenCalled()
expect(mockNode.pasteFiles).not.toHaveBeenCalled()
@@ -176,11 +163,7 @@ describe('pasteImageNode', () => {
const textFile = new File([''], 'test.txt', { type: 'text/plain' })
const dataTransfer = createDataTransfer([textFile, imageFile])
await pasteImageNode(
mockCanvas as unknown as LGraphCanvas,
dataTransfer.items,
mockNode as unknown as LGraphNode
)
await pasteImageNode(mockCanvas, dataTransfer.items, mockNode)
expect(mockNode.pasteFile).toHaveBeenCalledWith(imageFile)
expect(mockNode.pasteFiles).toHaveBeenCalledWith([imageFile])
@@ -196,16 +179,13 @@ describe('pasteImageNodes', () => {
const mockNode1 = createMockNode()
const mockNode2 = createMockNode()
vi.mocked(createNode)
.mockResolvedValueOnce(mockNode1 as unknown as LGraphNode)
.mockResolvedValueOnce(mockNode2 as unknown as LGraphNode)
.mockResolvedValueOnce(mockNode1)
.mockResolvedValueOnce(mockNode2)
const file1 = createImageFile('test1.png')
const file2 = createImageFile('test2.jpg', 'image/jpeg')
const result = await pasteImageNodes(
mockCanvas as unknown as LGraphCanvas,
[file1, file2]
)
const result = await pasteImageNodes(mockCanvas, [file1, file2])
expect(createNode).toHaveBeenCalledTimes(2)
expect(createNode).toHaveBeenNthCalledWith(1, mockCanvas, 'LoadImage')
@@ -216,10 +196,7 @@ describe('pasteImageNodes', () => {
})
it('should handle empty file list', async () => {
const result = await pasteImageNodes(
mockCanvas as unknown as LGraphCanvas,
[]
)
const result = await pasteImageNodes(mockCanvas, [])
expect(createNode).not.toHaveBeenCalled()
expect(result).toEqual([])
@@ -238,7 +215,7 @@ describe('usePaste', () => {
it('should handle image paste', async () => {
const mockNode = createMockNode()
vi.mocked(createNode).mockResolvedValue(mockNode as unknown as LGraphNode)
vi.mocked(createNode).mockResolvedValue(mockNode)
usePaste()
@@ -255,9 +232,7 @@ describe('usePaste', () => {
it('should handle audio paste', async () => {
const mockNode = createMockNode()
vi.mocked(LiteGraph.createNode).mockReturnValue(
mockNode as unknown as LGraphNode
)
vi.mocked(LiteGraph.createNode).mockReturnValue(mockNode)
usePaste()
@@ -302,11 +277,11 @@ describe('usePaste', () => {
})
it('should use existing image node when selected', () => {
const mockNode = {
const mockNode = createMockLGraphNode({
is_selected: true,
pasteFile: vi.fn(),
pasteFiles: vi.fn()
} as unknown as Partial<LGraphNode> as LGraphNode
})
mockCanvas.current_node = mockNode
vi.mocked(isImageNode).mockReturnValue(true)

View File

@@ -36,7 +36,7 @@ describe('LGraphButton', () => {
const button = new LGraphButton({ text: '' }) // Empty text makes it invisible
const ctx = {
measureText: vi.fn().mockReturnValue({ width: 100 })
} as unknown as CanvasRenderingContext2D
} as Partial<CanvasRenderingContext2D> as CanvasRenderingContext2D
const superDrawSpy = vi.spyOn(
Object.getPrototypeOf(Object.getPrototypeOf(button)),
@@ -66,7 +66,7 @@ describe('LGraphButton', () => {
font: '',
fillStyle: '',
globalAlpha: 1
} as unknown as CanvasRenderingContext2D
} as Partial<CanvasRenderingContext2D> as CanvasRenderingContext2D
const mockGetWidth = vi.fn().mockReturnValue(80)
button.getWidth = mockGetWidth
@@ -98,7 +98,7 @@ describe('LGraphButton', () => {
font: '',
fillStyle: '',
globalAlpha: 1
} as unknown as CanvasRenderingContext2D
} as Partial<CanvasRenderingContext2D> as CanvasRenderingContext2D
const mockGetWidth = vi.fn().mockReturnValue(50)
button.getWidth = mockGetWidth
@@ -172,7 +172,7 @@ describe('LGraphButton', () => {
font: '',
fillStyle: '',
globalAlpha: 1
} as unknown as CanvasRenderingContext2D
} as Partial<CanvasRenderingContext2D> as CanvasRenderingContext2D
// Draw the button
button.draw(ctx, 100, 50)

View File

@@ -63,7 +63,7 @@ describe('LGraphCanvas slot hit detection', () => {
globalAlpha: 1,
textAlign: 'left' as CanvasTextAlign,
textBaseline: 'alphabetic' as CanvasTextBaseline
} as unknown as CanvasRenderingContext2D
} as Partial<CanvasRenderingContext2D> as CanvasRenderingContext2D
canvasElement.getContext = vi.fn().mockReturnValue(ctx)
canvasElement.getBoundingClientRect = vi.fn().mockReturnValue({

View File

@@ -43,7 +43,7 @@ describe('LGraphCanvas Title Button Rendering', () => {
globalAlpha: 1,
textAlign: 'left' as CanvasTextAlign,
textBaseline: 'alphabetic' as CanvasTextBaseline
} as unknown as CanvasRenderingContext2D
} as Partial<CanvasRenderingContext2D> as CanvasRenderingContext2D
canvasElement.getContext = vi.fn().mockReturnValue(ctx)

View File

@@ -863,7 +863,7 @@ export class LGraphCanvas implements CustomEventDispatcher<LGraphCanvasEventMap>
if ('shiftKey' in e && e.shiftKey) {
if (this.allow_searchbox) {
this.showSearchBox(
e as unknown as MouseEvent,
e as MouseEvent,
linkReleaseContext as IShowSearchOptions
)
}

View File

@@ -65,7 +65,7 @@ describe('LGraphNode Title Buttons', () => {
const canvas = {
ctx: {} as CanvasRenderingContext2D,
dispatch: vi.fn()
} as unknown as LGraphCanvas
} as Partial<LGraphCanvas> as LGraphCanvas
// Mock the node's onTitleButtonClick method to verify it gets called
const onTitleButtonClickSpy = vi.spyOn(node, 'onTitleButtonClick')
@@ -119,7 +119,7 @@ describe('LGraphNode Title Buttons', () => {
const canvas = {
ctx: {} as CanvasRenderingContext2D,
dispatch: vi.fn()
} as unknown as LGraphCanvas
} as Partial<LGraphCanvas> as LGraphCanvas
// Calculate node-relative position
const clickPosRelativeToNode: [number, number] = [
@@ -177,7 +177,7 @@ describe('LGraphNode Title Buttons', () => {
const canvas = {
ctx: {} as CanvasRenderingContext2D,
dispatch: vi.fn()
} as unknown as LGraphCanvas
} as Partial<LGraphCanvas> as LGraphCanvas
// Mock the node's onTitleButtonClick method
const onTitleButtonClickSpy = vi.spyOn(node, 'onTitleButtonClick')
@@ -242,7 +242,7 @@ describe('LGraphNode Title Buttons', () => {
const canvas = {
ctx: {} as CanvasRenderingContext2D,
dispatch: vi.fn()
} as unknown as LGraphCanvas
} as Partial<LGraphCanvas> as LGraphCanvas
// Mock the node's onTitleButtonClick method
const onTitleButtonClickSpy = vi.spyOn(node, 'onTitleButtonClick')
@@ -292,7 +292,7 @@ describe('LGraphNode Title Buttons', () => {
const canvas = {
dispatch: vi.fn()
} as unknown as LGraphCanvas
} as Partial<LGraphCanvas> as LGraphCanvas
node.onTitleButtonClick(button, canvas)

View File

@@ -510,7 +510,7 @@ describe('Rectangle', () => {
lineWidth: 1,
beginPath: vi.fn(),
strokeRect: vi.fn()
} as unknown as CanvasRenderingContext2D
} as Partial<CanvasRenderingContext2D> as CanvasRenderingContext2D
rect._drawDebug(mockCtx, 'blue')
@@ -533,7 +533,7 @@ describe('Rectangle', () => {
lineWidth: 1,
beginPath: vi.fn(),
strokeRect: vi.fn()
} as unknown as CanvasRenderingContext2D
} as Partial<CanvasRenderingContext2D> as CanvasRenderingContext2D
rect._drawDebug(mockCtx)
// Check if strokeStyle was "red" at the time of strokeRect
// This requires a more complex mock or observing calls.

View File

@@ -38,7 +38,7 @@ describe('getCheckoutAttribution', () => {
callback(valueByField[fieldName])
}
)
window.gtag = gtagSpy as unknown as Window['gtag']
window.gtag = gtagSpy as Partial<Window['gtag']> as Window['gtag']
window.history.pushState(
{},
@@ -108,7 +108,7 @@ describe('getCheckoutAttribution', () => {
callback(valueByField[fieldName])
}
)
window.gtag = gtagSpy as unknown as Window['gtag']
window.gtag = gtagSpy as Partial<Window['gtag']> as Window['gtag']
const attribution = await getCheckoutAttribution()

View File

@@ -91,7 +91,7 @@ function createWorkflow(
activeState: { nodes: [], links: [] },
changeTracker: { reset: vi.fn(), restore: vi.fn() }
})
} as unknown as ComfyWorkflow
} as Partial<ComfyWorkflow> as ComfyWorkflow
}
function enableWarningSettings() {
@@ -181,7 +181,10 @@ describe('useWorkflowService', () => {
vi.mocked(app.loadGraphData).mockImplementation(
async (_data, _clean, _restore, wf) => {
;(
workflowStore as unknown as Record<string, unknown>
workflowStore as Partial<Record<string, unknown>> as Record<
string,
unknown
>
).activeWorkflow = wf
}
)

View File

@@ -104,7 +104,7 @@ describe('useCanvasInteractions', () => {
it('should return early when canvas is null', () => {
const { getCanvas } = useCanvasStore()
vi.mocked(getCanvas).mockReturnValue(null as unknown as LGraphCanvas) // TODO: Fix misaligned types
vi.mocked(getCanvas).mockReturnValue(null!)
const { handlePointer } = useCanvasInteractions()
const mockEvent = createMockPointerEvent(1)

View File

@@ -2,8 +2,8 @@ import { mount } from '@vue/test-utils'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { computed, nextTick } from 'vue'
import type { LGraphCanvas } from '@/lib/litegraph/src/LGraphCanvas'
import { useTransformState } from '@/renderer/core/layout/transform/useTransformState'
import { createMockCanvas } from '@/utils/__tests__/litegraphTestUtils'
import TransformPane from '../transform/TransformPane.vue'
@@ -29,8 +29,8 @@ vi.mock('@/renderer/core/layout/transform/useTransformState', () => {
}
})
function createMockCanvas(): LGraphCanvas {
return {
function createMockLGraphCanvas() {
return createMockCanvas({
canvas: {
addEventListener: vi.fn(),
removeEventListener: vi.fn()
@@ -39,7 +39,7 @@ function createMockCanvas(): LGraphCanvas {
offset: [0, 0],
scale: 1
}
} as unknown as LGraphCanvas
})
}
describe('TransformPane', () => {
@@ -52,7 +52,7 @@ describe('TransformPane', () => {
describe('component mounting', () => {
it('should mount successfully with minimal props', () => {
const mockCanvas = createMockCanvas()
const mockCanvas = createMockLGraphCanvas()
const wrapper = mount(TransformPane, {
props: {
canvas: mockCanvas
@@ -69,7 +69,7 @@ describe('TransformPane', () => {
transformOrigin: '0 0'
}
const mockCanvas = createMockCanvas()
const mockCanvas = createMockLGraphCanvas()
const wrapper = mount(TransformPane, {
props: {
canvas: mockCanvas
@@ -83,7 +83,7 @@ describe('TransformPane', () => {
})
it('should render slot content', () => {
const mockCanvas = createMockCanvas()
const mockCanvas = createMockLGraphCanvas()
const wrapper = mount(TransformPane, {
props: {
canvas: mockCanvas
@@ -100,7 +100,7 @@ describe('TransformPane', () => {
describe('RAF synchronization', () => {
it('should call syncWithCanvas during RAF updates', async () => {
const mockCanvas = createMockCanvas()
const mockCanvas = createMockLGraphCanvas()
mount(TransformPane, {
props: {
canvas: mockCanvas
@@ -119,7 +119,7 @@ describe('TransformPane', () => {
describe('canvas event listeners', () => {
it('should add event listeners to canvas on mount', async () => {
const mockCanvas = createMockCanvas()
const mockCanvas = createMockLGraphCanvas()
mount(TransformPane, {
props: {
canvas: mockCanvas
@@ -151,7 +151,7 @@ describe('TransformPane', () => {
})
it('should remove event listeners on unmount', async () => {
const mockCanvas = createMockCanvas()
const mockCanvas = createMockLGraphCanvas()
const wrapper = mount(TransformPane, {
props: {
canvas: mockCanvas
@@ -186,7 +186,7 @@ describe('TransformPane', () => {
describe('interaction state management', () => {
it('should apply interacting class during interactions', async () => {
const mockCanvas = createMockCanvas()
const mockCanvas = createMockLGraphCanvas()
const wrapper = mount(TransformPane, {
props: {
canvas: mockCanvas
@@ -204,7 +204,7 @@ describe('TransformPane', () => {
})
it('should handle pointer events for node delegation', async () => {
const mockCanvas = createMockCanvas()
const mockCanvas = createMockLGraphCanvas()
const wrapper = mount(TransformPane, {
props: {
canvas: mockCanvas
@@ -225,7 +225,7 @@ describe('TransformPane', () => {
describe('transform state integration', () => {
it('should provide transform utilities to child components', () => {
const mockCanvas = createMockCanvas()
const mockCanvas = createMockLGraphCanvas()
mount(TransformPane, {
props: {
canvas: mockCanvas

View File

@@ -4,11 +4,7 @@ import { computed, shallowRef } from 'vue'
import { useGraphNodeManager } from '@/composables/graph/useGraphNodeManager'
import type { GraphNodeManager } from '@/composables/graph/useGraphNodeManager'
import { useVueNodeLifecycle } from '@/composables/graph/useVueNodeLifecycle'
import type {
LGraph,
LGraphCanvas,
LGraphNode
} from '@/lib/litegraph/src/litegraph'
import type { LGraphCanvas, LGraphNode } from '@/lib/litegraph/src/litegraph'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import { useLayoutMutations } from '@/renderer/core/layout/operations/layoutMutations'
import { useNodeEventHandlers } from '@/renderer/extensions/vueNodes/composables/useNodeEventHandlers'
@@ -64,7 +60,7 @@ vi.mock('@/composables/graph/useGraphNodeManager', () => {
})
vi.mock('@/composables/graph/useVueNodeLifecycle', () => {
const nodeManager = useGraphNodeManager(undefined as unknown as LGraph)
const nodeManager = useGraphNodeManager(null!)
return {
useVueNodeLifecycle: vi.fn(() => ({
nodeManager

View File

@@ -108,7 +108,7 @@ function createPointerEvent(
preventDefault: vi.fn(),
stopPropagation: vi.fn(),
...overrides
} as unknown as PointerEvent
} as Partial<PointerEvent> as PointerEvent
}
function startResizeAt(

View File

@@ -5,6 +5,7 @@ import { getDataFromJSON } from '@/scripts/metadata/json'
import { getMp3Metadata } from '@/scripts/metadata/mp3'
import { getOggMetadata } from '@/scripts/metadata/ogg'
import { getSvgMetadata } from '@/scripts/metadata/svg'
import type { ComfyMetadata } from '@/types/metadataTypes'
import {
getAvifMetadata,
getWebpMetadata,
@@ -15,7 +16,7 @@ import {
export async function getWorkflowDataFromFile(
file: File
): Promise<Record<string, string | object> | undefined> {
): Promise<ComfyMetadata | Record<string, string | object> | undefined> {
if (file.type === 'image/png') {
return await getPngMetadata(file)
}
@@ -43,7 +44,7 @@ export async function getWorkflowDataFromFile(
return { workflow, prompt }
}
if (file.type === 'video/webm') {
return (await getFromWebmFile(file)) as unknown as Record<string, object>
return await getFromWebmFile(file)
}
if (
file.name?.endsWith('.mp4') ||
@@ -53,16 +54,13 @@ export async function getWorkflowDataFromFile(
file.type === 'video/quicktime' ||
file.type === 'video/x-m4v'
) {
return (await getFromIsobmffFile(file)) as unknown as Record<string, object>
return await getFromIsobmffFile(file)
}
if (file.type === 'image/svg+xml' || file.name?.endsWith('.svg')) {
return (await getSvgMetadata(file)) as unknown as Record<string, object>
return await getSvgMetadata(file)
}
if (file.type === 'model/gltf-binary' || file.name?.endsWith('.glb')) {
return (await getGltfBinaryMetadata(file)) as unknown as Record<
string,
object
>
return await getGltfBinaryMetadata(file)
}
if (file.name?.endsWith('.latent') || file.name?.endsWith('.safetensors')) {
return await getLatentMetadata(file)

View File

@@ -104,7 +104,7 @@ describe('useAudioService', () => {
const mockTrack2 = { stop: vi.fn() }
const mockStream = {
getTracks: vi.fn().mockReturnValue([mockTrack1, mockTrack2])
} as unknown as MediaStream
} as Partial<MediaStream> as MediaStream
service.stopAllTracks(mockStream)
@@ -120,7 +120,7 @@ describe('useAudioService', () => {
it('should handle stream with no tracks', () => {
const mockStream = {
getTracks: vi.fn().mockReturnValue([])
} as unknown as MediaStream
} as Partial<MediaStream> as MediaStream
expect(() => service.stopAllTracks(mockStream)).not.toThrow()
expect(mockStream.getTracks).toHaveBeenCalledTimes(1)
@@ -135,7 +135,7 @@ describe('useAudioService', () => {
}
const mockStream = {
getTracks: vi.fn().mockReturnValue([mockTrack1, mockTrack2])
} as unknown as MediaStream
} as Partial<MediaStream> as MediaStream
expect(() => service.stopAllTracks(mockStream)).toThrow()
expect(mockTrack1.stop).toHaveBeenCalledTimes(1)

View File

@@ -107,8 +107,7 @@ export const useColorPaletteService = () => {
for (const dataType of nodeDefStore.nodeDataTypes) {
const cssVar = `color-datatype-${dataType}`
const valueMaybe =
linkColorPalette[dataType as unknown as keyof Colors['node_slot']]
const valueMaybe = linkColorPalette[dataType as keyof Colors['node_slot']]
if (valueMaybe) {
rootStyle.setProperty(`--${cssVar}`, valueMaybe)
} else {

View File

@@ -32,7 +32,7 @@ const createMockNode = (overrides: Record<string, unknown> = {}): LGraphNode =>
id: 1,
type: 'TestNode',
...overrides
}) as unknown as LGraphNode
}) as Partial<LGraphNode> as LGraphNode
const createMockOutputs = (
images?: ExecutedWsMessage['output']['images']

View File

@@ -20,17 +20,17 @@ vi.mock('@/platform/settings/settingStore', () => ({
}))
function createMockPopover(): InstanceType<typeof NodeSearchBoxPopover> {
return { showSearchBox: vi.fn() } satisfies Partial<
return { showSearchBox: vi.fn() } as Partial<
InstanceType<typeof NodeSearchBoxPopover>
> as unknown as InstanceType<typeof NodeSearchBoxPopover>
> as InstanceType<typeof NodeSearchBoxPopover>
}
function createMockSettingStore(): ReturnType<typeof useSettingStore> {
return {
get: vi.fn()
} satisfies Partial<
ReturnType<typeof useSettingStore>
> as unknown as ReturnType<typeof useSettingStore>
} as Partial<ReturnType<typeof useSettingStore>> as ReturnType<
typeof useSettingStore
>
}
describe('useSearchBoxStore', () => {

View File

@@ -82,14 +82,14 @@ export function createMockSubgraphNode(
* Creates a mock LGraphCanvas with minimal required properties for testing
*/
export function createMockCanvas(
overrides: Partial<LGraphCanvas> = {}
overrides: Partial<LGraphCanvas> | Record<string, unknown> = {}
): LGraphCanvas {
return {
setDirty: vi.fn(),
state: {
selectionChanged: false
},
...overrides
...(overrides as Partial<LGraphCanvas>)
} as LGraphCanvas
}

View File

@@ -40,7 +40,7 @@ function createMockCanvas(overrides: Partial<LGraphCanvas> = {}): LGraphCanvas {
const mockGraph = {
add: vi.fn((node) => node),
change: vi.fn()
} satisfies Partial<LGraph> as unknown as LGraph
} as Partial<LGraph> as LGraph
const mockCanvas: Partial<LGraphCanvas> = {
graph_mouse: [100, 200],
graph: mockGraph,

View File

@@ -271,7 +271,8 @@ describe('useMissingNodes', () => {
// Update workflow packs
workflowPacksRef.value = mockWorkflowPacks as unknown as WorkflowPack[]
workflowPacksRef.value =
mockWorkflowPacks as Partial<WorkflowPack>[] as WorkflowPack[]
await nextTick()
// Should update missing packs (2 missing since pack-3 is installed)

View File

@@ -39,6 +39,32 @@ const mockUseComfyManagerStore = vi.mocked(useComfyManagerStore)
const mockSemverCompare = vi.mocked(compare)
const mockSemverValid = vi.mocked(valid)
type InstalledPacksReturn = ReturnType<typeof useInstalledPacks>
type ManagerStoreReturn = ReturnType<typeof useComfyManagerStore>
function createMockInstalledPacksReturn(
overrides: Partial<InstalledPacksReturn> = {}
): InstalledPacksReturn {
return {
installedPacks: ref([]),
isLoading: ref(false),
isReady: ref(false),
error: ref(null),
startFetchInstalled: vi.fn(),
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn(),
...overrides
} as Partial<InstalledPacksReturn> as InstalledPacksReturn
}
function createMockManagerStoreReturn(
overrides: Partial<ManagerStoreReturn> = {}
): ManagerStoreReturn {
return {
...overrides
} as Partial<ManagerStoreReturn> as ManagerStoreReturn
}
describe('useUpdateAvailableNodes', () => {
const mockInstalledPacks = [
{
@@ -103,34 +129,29 @@ describe('useUpdateAvailableNodes', () => {
return 0
})
mockUseComfyManagerStore.mockReturnValue({
isPackInstalled: mockIsPackInstalled,
getInstalledPackVersion: mockGetInstalledPackVersion,
isPackEnabled: mockIsPackEnabled
} as unknown as ReturnType<typeof useComfyManagerStore>)
mockUseComfyManagerStore.mockReturnValue(
createMockManagerStoreReturn({
isPackInstalled: mockIsPackInstalled,
getInstalledPackVersion: mockGetInstalledPackVersion,
isPackEnabled: mockIsPackEnabled
})
)
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref([]),
isLoading: ref(false),
isReady: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
startFetchInstalled: mockStartFetchInstalled
})
)
})
describe('core filtering logic', () => {
it('identifies outdated packs correctly', () => {
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref(mockInstalledPacks),
isLoading: ref(false),
isReady: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: ref(mockInstalledPacks),
startFetchInstalled: mockStartFetchInstalled
})
)
const { updateAvailableNodePacks } = useUpdateAvailableNodes()
@@ -140,15 +161,12 @@ describe('useUpdateAvailableNodes', () => {
})
it('excludes up-to-date packs', () => {
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref([mockInstalledPacks[1]]), // pack-2: up to date
isLoading: ref(false),
isReady: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: ref([mockInstalledPacks[1]]), // pack-2: up to date
startFetchInstalled: mockStartFetchInstalled
})
)
const { updateAvailableNodePacks } = useUpdateAvailableNodes()
@@ -156,15 +174,12 @@ describe('useUpdateAvailableNodes', () => {
})
it('excludes nightly packs from updates', () => {
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref([mockInstalledPacks[2]]), // pack-3: nightly
isLoading: ref(false),
isReady: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: ref([mockInstalledPacks[2]]), // pack-3: nightly
startFetchInstalled: mockStartFetchInstalled
})
)
const { updateAvailableNodePacks } = useUpdateAvailableNodes()
@@ -172,15 +187,12 @@ describe('useUpdateAvailableNodes', () => {
})
it('excludes packs with no latest version', () => {
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref([mockInstalledPacks[3]]), // pack-4: no latest version
isLoading: ref(false),
isReady: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: ref([mockInstalledPacks[3]]), // pack-4: no latest version
startFetchInstalled: mockStartFetchInstalled
})
)
const { updateAvailableNodePacks } = useUpdateAvailableNodes()
@@ -189,15 +201,12 @@ describe('useUpdateAvailableNodes', () => {
it('excludes uninstalled packs', () => {
mockIsPackInstalled.mockReturnValue(false)
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref(mockInstalledPacks),
isLoading: ref(false),
isReady: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: ref(mockInstalledPacks),
startFetchInstalled: mockStartFetchInstalled
})
)
const { updateAvailableNodePacks } = useUpdateAvailableNodes()
@@ -213,15 +222,12 @@ describe('useUpdateAvailableNodes', () => {
describe('hasUpdateAvailable computed', () => {
it('returns true when updates are available', () => {
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref([mockInstalledPacks[0]]), // pack-1: outdated
isLoading: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
isReady: ref(false),
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: ref([mockInstalledPacks[0]]), // pack-1: outdated
startFetchInstalled: mockStartFetchInstalled
})
)
const { hasUpdateAvailable } = useUpdateAvailableNodes()
@@ -229,15 +235,12 @@ describe('useUpdateAvailableNodes', () => {
})
it('returns false when no updates are available', () => {
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref([mockInstalledPacks[1]]), // pack-2: up to date
isLoading: ref(false),
isReady: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: ref([mockInstalledPacks[1]]), // pack-2: up to date
startFetchInstalled: mockStartFetchInstalled
})
)
const { hasUpdateAvailable } = useUpdateAvailableNodes()
@@ -253,15 +256,12 @@ describe('useUpdateAvailableNodes', () => {
})
it('does not fetch when packs already exist', () => {
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref(mockInstalledPacks),
isLoading: ref(false),
isReady: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: ref(mockInstalledPacks),
startFetchInstalled: mockStartFetchInstalled
})
)
useUpdateAvailableNodes()
@@ -269,15 +269,12 @@ describe('useUpdateAvailableNodes', () => {
})
it('does not fetch when already loading', () => {
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref([]),
isLoading: ref(true),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
isReady: ref(false),
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
isLoading: ref(true),
startFetchInstalled: mockStartFetchInstalled
})
)
useUpdateAvailableNodes()
@@ -287,15 +284,12 @@ describe('useUpdateAvailableNodes', () => {
describe('state management', () => {
it('exposes loading state from useInstalledPacks', () => {
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref([]),
isLoading: ref(true),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
isReady: ref(false),
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
isLoading: ref(true),
startFetchInstalled: mockStartFetchInstalled
})
)
const { isLoading } = useUpdateAvailableNodes()
@@ -304,15 +298,12 @@ describe('useUpdateAvailableNodes', () => {
it('exposes error state from useInstalledPacks', () => {
const testError = 'Failed to fetch installed packs'
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref([]),
isLoading: ref(false),
error: ref(testError),
startFetchInstalled: mockStartFetchInstalled,
isReady: ref(false),
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
error: ref(testError),
startFetchInstalled: mockStartFetchInstalled
})
)
const { error } = useUpdateAvailableNodes()
@@ -323,15 +314,12 @@ describe('useUpdateAvailableNodes', () => {
describe('reactivity', () => {
it('updates when installed packs change', async () => {
const installedPacksRef = ref<components['schemas']['Node'][]>([])
mockUseInstalledPacks.mockReturnValue({
installedPacks: installedPacksRef,
isLoading: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
isReady: ref(false),
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: installedPacksRef,
startFetchInstalled: mockStartFetchInstalled
})
)
const { updateAvailableNodePacks, hasUpdateAvailable } =
useUpdateAvailableNodes()
@@ -352,15 +340,12 @@ describe('useUpdateAvailableNodes', () => {
describe('version comparison logic', () => {
it('calls compareVersions with correct parameters', () => {
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref([mockInstalledPacks[0]]), // pack-1
isLoading: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
isReady: ref(false),
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: ref([mockInstalledPacks[0]]), // pack-1
startFetchInstalled: mockStartFetchInstalled
})
)
const { updateAvailableNodePacks } = useUpdateAvailableNodes()
@@ -371,15 +356,12 @@ describe('useUpdateAvailableNodes', () => {
})
it('calls semver.valid to check nightly versions', () => {
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref([mockInstalledPacks[2]]), // pack-3: nightly
isLoading: ref(false),
isReady: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: ref([mockInstalledPacks[2]]), // pack-3: nightly
startFetchInstalled: mockStartFetchInstalled
})
)
const { updateAvailableNodePacks } = useUpdateAvailableNodes()
@@ -390,15 +372,12 @@ describe('useUpdateAvailableNodes', () => {
})
it('calls isPackInstalled for each pack', () => {
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref(mockInstalledPacks),
isLoading: ref(false),
isReady: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: ref(mockInstalledPacks),
startFetchInstalled: mockStartFetchInstalled
})
)
const { updateAvailableNodePacks } = useUpdateAvailableNodes()
@@ -419,15 +398,12 @@ describe('useUpdateAvailableNodes', () => {
return id !== 'pack-1'
})
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref([mockInstalledPacks[0], mockInstalledPacks[1]]),
isLoading: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
isReady: ref(false),
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: ref([mockInstalledPacks[0], mockInstalledPacks[1]]),
startFetchInstalled: mockStartFetchInstalled
})
)
const { updateAvailableNodePacks, enabledUpdateAvailableNodePacks } =
useUpdateAvailableNodes()
@@ -441,15 +417,12 @@ describe('useUpdateAvailableNodes', () => {
})
it('returns all packs when all are enabled', () => {
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref([mockInstalledPacks[0]]), // pack-1: outdated
isLoading: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
isReady: ref(false),
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: ref([mockInstalledPacks[0]]), // pack-1: outdated
startFetchInstalled: mockStartFetchInstalled
})
)
const { updateAvailableNodePacks, enabledUpdateAvailableNodePacks } =
useUpdateAvailableNodes()
@@ -467,15 +440,12 @@ describe('useUpdateAvailableNodes', () => {
return id !== 'pack-1'
})
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref([mockInstalledPacks[0]]), // pack-1: outdated
isLoading: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
isReady: ref(false),
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: ref([mockInstalledPacks[0]]), // pack-1: outdated
startFetchInstalled: mockStartFetchInstalled
})
)
const { hasDisabledUpdatePacks } = useUpdateAvailableNodes()
@@ -483,15 +453,12 @@ describe('useUpdateAvailableNodes', () => {
})
it('returns false when all packs with updates are enabled', () => {
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref([mockInstalledPacks[0]]), // pack-1: outdated
isLoading: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
isReady: ref(false),
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: ref([mockInstalledPacks[0]]), // pack-1: outdated
startFetchInstalled: mockStartFetchInstalled
})
)
const { hasDisabledUpdatePacks } = useUpdateAvailableNodes()
@@ -499,15 +466,12 @@ describe('useUpdateAvailableNodes', () => {
})
it('returns false when no packs have updates', () => {
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref([mockInstalledPacks[1]]), // pack-2: up to date
isLoading: ref(false),
isReady: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: ref([mockInstalledPacks[1]]), // pack-2: up to date
startFetchInstalled: mockStartFetchInstalled
})
)
const { hasDisabledUpdatePacks } = useUpdateAvailableNodes()
@@ -519,15 +483,12 @@ describe('useUpdateAvailableNodes', () => {
it('returns false when only disabled packs have updates', () => {
mockIsPackEnabled.mockReturnValue(false) // All packs disabled
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref([mockInstalledPacks[0]]), // pack-1: outdated
isLoading: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
isReady: ref(false),
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: ref([mockInstalledPacks[0]]), // pack-1: outdated
startFetchInstalled: mockStartFetchInstalled
})
)
const { hasUpdateAvailable } = useUpdateAvailableNodes()
@@ -540,15 +501,12 @@ describe('useUpdateAvailableNodes', () => {
return id === 'pack-1'
})
mockUseInstalledPacks.mockReturnValue({
installedPacks: ref([mockInstalledPacks[0]]), // pack-1: outdated
isLoading: ref(false),
error: ref(null),
startFetchInstalled: mockStartFetchInstalled,
isReady: ref(false),
installedPacksWithVersions: ref([]),
filterInstalledPack: vi.fn()
} as unknown as ReturnType<typeof useInstalledPacks>)
mockUseInstalledPacks.mockReturnValue(
createMockInstalledPacksReturn({
installedPacks: ref([mockInstalledPacks[0]]), // pack-1: outdated
startFetchInstalled: mockStartFetchInstalled
})
)
const { hasUpdateAvailable } = useUpdateAvailableNodes()

View File

@@ -86,10 +86,7 @@ describe('graphHasMissingNodes', () => {
})
it('ignores nodes without a type', () => {
const graph = createGraph([
createNode(undefined),
createNode(null as unknown as string)
])
const graph = createGraph([createNode(undefined), createNode(null!)])
expect(graphHasMissingNodes(graph, {})).toBe(false)
})