Files
ComfyUI_frontend/src/utils/__tests__/litegraphTestUtils.ts
Johnpaul Chiwetelu 5769f96f55 fix: resolve no-misused-spread lint warnings in test files (#8318)
## Summary

Replace spread operators with Object.assign() to fix 3 no-misused-spread
lint warnings in test utilities and test files.

## Changes

- **What**: Replaced spread operators with Object.assign() in
createMockFileList and mock node creation functions to avoid spreading
arrays into objects and class instances that could lose prototypes.
Simplified BypassButton.test.ts by removing redundant type annotations.
- **Breaking**: None

## Review Focus

Type safety is preserved without using weak TypeScript patterns (no
`any`, `as unknown as`, or unnecessary casts).

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8318-fix-resolve-no-misused-spread-lint-warnings-in-test-files-2f46d73d365081aca3f6cf208556d492)
by [Unito](https://www.unito.io)
2026-01-26 19:26:35 +01:00

206 lines
4.9 KiB
TypeScript

import type {
INodeInputSlot,
INodeOutputSlot,
Positionable
} from '@/lib/litegraph/src/interfaces'
import { Rectangle } from '@/lib/litegraph/src/infrastructure/Rectangle'
import type {
CanvasPointerEvent,
LGraph,
LGraphCanvas,
LGraphGroup,
LinkNetwork
} from '@/lib/litegraph/src/litegraph'
import { LGraphEventMode, LGraphNode } from '@/lib/litegraph/src/litegraph'
import { vi } from 'vitest'
/**
* Creates a mock LGraphNode with minimal required properties
*/
export function createMockLGraphNode(
overrides: Partial<LGraphNode> | Record<string, unknown> = {}
): LGraphNode {
const partial: Partial<LGraphNode> = {
id: 1,
pos: [0, 0],
size: [100, 100],
title: 'Test Node',
mode: LGraphEventMode.ALWAYS,
...(overrides as Partial<LGraphNode>)
}
return partial as Partial<LGraphNode> as LGraphNode
}
/**
* Creates a mock Positionable object
*/
export function createMockPositionable(
overrides: Partial<Positionable> = {}
): Positionable {
const partial: Partial<Positionable> = {
id: 1,
pos: [0, 0],
...overrides
}
return partial as Partial<Positionable> as Positionable
}
/**
* Creates a mock LGraphGroup with minimal required properties
*/
export function createMockLGraphGroup(
overrides: Partial<LGraphGroup> = {}
): LGraphGroup {
const partial: Partial<LGraphGroup> = {
id: 1,
pos: [0, 0],
boundingRect: new Rectangle(0, 0, 100, 100),
...overrides
}
return partial as Partial<LGraphGroup> as LGraphGroup
}
/**
* Creates a mock SubgraphNode with sub-nodes
*/
export function createMockSubgraphNode(
subNodes: LGraphNode[],
overrides: Partial<LGraphNode> | Record<string, unknown> = {}
): LGraphNode {
const baseNode = createMockLGraphNode(overrides)
return Object.assign(baseNode, {
isSubgraphNode: () => true,
subgraph: {
nodes: subNodes
}
})
}
/**
* Creates a mock LGraphCanvas with minimal required properties for testing
*/
export function createMockCanvas(
overrides: Partial<LGraphCanvas> = {}
): LGraphCanvas {
return {
setDirty: vi.fn(),
state: {
selectionChanged: false
},
...overrides
} as LGraphCanvas
}
/**
* Creates a mock LGraph with trigger function
*/
export function createMockLGraph(overrides: Partial<LGraph> = {}): LGraph {
return {
trigger: vi.fn(),
...overrides
} as LGraph
}
/**
* Creates a mock CanvasPointerEvent
*/
export function createMockCanvasPointerEvent(
canvasX: number,
canvasY: number,
overrides: Partial<CanvasPointerEvent> = {}
): CanvasPointerEvent {
return {
canvasX,
canvasY,
...overrides
} as CanvasPointerEvent
}
/**
* Creates a mock CanvasRenderingContext2D
*/
export function createMockCanvasRenderingContext2D(
overrides: Partial<CanvasRenderingContext2D> = {}
): CanvasRenderingContext2D {
const partial: Partial<CanvasRenderingContext2D> = {
measureText: vi.fn(() => ({ width: 10 }) as TextMetrics),
...overrides
}
return partial as CanvasRenderingContext2D
}
/**
* Creates a mock LinkNetwork
*/
export function createMockLinkNetwork(
overrides: Partial<LinkNetwork> = {}
): LinkNetwork {
return {
...overrides
} as LinkNetwork
}
/**
* Creates a mock INodeInputSlot
*/
export function createMockNodeInputSlot(
overrides: Partial<INodeInputSlot> = {}
): INodeInputSlot {
return {
...overrides
} as INodeInputSlot
}
/**
* Creates a mock INodeOutputSlot
*/
export function createMockNodeOutputSlot(
overrides: Partial<INodeOutputSlot> = {}
): INodeOutputSlot {
return {
...overrides
} as INodeOutputSlot
}
/**
* Creates a real LGraphNode instance (not a lightweight mock) with its boundingRect
* property represented as a Float64Array for testing position methods.
*
* Use createMockLGraphNodeWithArrayBoundingRect when:
* - Tests rely on Float64Array boundingRect behavior
* - Tests call position-related methods like updateArea()
* - Tests need actual LGraphNode implementation details
*
* Use createMockLGraphNode when:
* - Tests only need simple/mock-only behavior
* - Tests don't depend on boundingRect being a Float64Array
* - A lightweight mock with minimal properties is sufficient
*
* @param name - The node name/type to pass to the LGraphNode constructor
* @returns A fully constructed LGraphNode instance with Float64Array boundingRect
*/
export function createMockLGraphNodeWithArrayBoundingRect(
name: string
): LGraphNode {
const node = new LGraphNode(name)
// The actual node has a Float64Array boundingRect, we just need to type it correctly
return node
}
/**
* Creates a mock FileList from an array of files
*/
export function createMockFileList(files: File[]): FileList {
const fileList = Object.assign(
{
length: files.length,
item: (index: number) => files[index] ?? null,
[Symbol.iterator]: function* () {
yield* files
}
},
files
)
return fileList as FileList
}