fix: browser_tests Phase 2 - null assertions

Amp-Thread-ID: https://ampcode.com/threads/T-019c1797-ff0a-7418-840b-8c76fb81eeec
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Alexander Brown
2026-01-31 21:17:24 -08:00
parent b56045c462
commit 302e9d5be7
11 changed files with 115 additions and 109 deletions

View File

@@ -52,10 +52,11 @@ test.describe('Actionbar', { tag: '@ui' }, () => {
const node = window.app!.graph!._nodes.find(
(n) => n.type === 'EmptyLatentImage'
)
node.widgets[0].value = value
window[
'app'
].extensionManager.workflow.activeWorkflow.changeTracker.checkState()
node!.widgets![0].value = value
;(
window.app!.extensionManager as any
).workflow.activeWorkflow.changeTracker.checkState()
}, value)
}

View File

@@ -2,6 +2,7 @@ import { expect } from '@playwright/test'
import type { ComfyPage } from '../fixtures/ComfyPage'
import { comfyPageFixture as test } from '../fixtures/ComfyPage'
import type { NodeLibrarySidebarTab } from '../fixtures/components/SidebarTab'
import { DefaultGraphPositions } from '../fixtures/constants/defaultGraphPositions'
import type { NodeReference } from '../fixtures/utils/litegraphUtils'
@@ -14,7 +15,7 @@ test.describe('Group Node', { tag: '@node' }, () => {
const groupNodeName = 'DefautWorkflowGroupNode'
const groupNodeCategory = 'group nodes>workflow'
const groupNodeBookmarkName = `workflow>${groupNodeName}`
let libraryTab
let libraryTab: NodeLibrarySidebarTab
test.beforeEach(async ({ comfyPage }) => {
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Top')
@@ -119,7 +120,7 @@ test.describe('Group Node', { tag: '@node' }, () => {
test('Manage group opens with the correct group selected', async ({
comfyPage
}) => {
const makeGroup = async (name, type1, type2) => {
const makeGroup = async (name: string, type1: string, type2: string) => {
const node1 = (await comfyPage.nodeOps.getNodeRefsByType(type1))[0]
const node2 = (await comfyPage.nodeOps.getNodeRefsByType(type2))[0]
await node1.click('title')
@@ -161,15 +162,13 @@ test.describe('Group Node', { tag: '@node' }, () => {
const {
extra: { groupNodes }
} = window.app!.graph!
const { nodes } = groupNodes[nodeName]
return nodes.reduce((acc: number, node) => {
return acc + node.inputs.length
}, 0)
const { nodes } = groupNodes![nodeName]
return nodes.reduce((acc, node) => acc + (node.inputs?.length ?? 0), 0)
}, groupNodeName)
const visibleInputCount = await comfyPage.page.evaluate((id) => {
const node = window.app!.graph!.getNodeById(id)
return node.inputs.length
return node!.inputs.length
}, groupNodeId)
// Verify there are 4 total inputs (2 VAE decode nodes with 2 inputs each)
@@ -314,7 +313,7 @@ test.describe('Group Node', { tag: '@node' }, () => {
await test.step('Load workflow containing a group node pasted from a different workflow', async () => {
await comfyPage.page.evaluate(
(workflow) => window.app!.loadGraphData(workflow),
(workflow) => window.app!.loadGraphData(workflow as any),
currentGraphState
)
await comfyPage.nextFrame()

View File

@@ -27,22 +27,22 @@ test.describe('Remote COMBO Widget', { tag: '@widget' }, () => {
): Promise<string[] | undefined> => {
return await comfyPage.page.evaluate((name) => {
const node = window.app!.graph!.nodes.find((node) => node.title === name)
return node.widgets[0].options.values
return node!.widgets![0].options.values as string[] | undefined
}, nodeName)
}
const getWidgetValue = async (comfyPage: ComfyPage, nodeName: string) => {
return await comfyPage.page.evaluate((name) => {
const node = window.app!.graph!.nodes.find((node) => node.title === name)
return node.widgets[0].value
return node!.widgets![0].value
}, nodeName)
}
const clickRefreshButton = (comfyPage: ComfyPage, nodeName: string) => {
return comfyPage.page.evaluate((name) => {
const node = window.app!.graph!.nodes.find((node) => node.title === name)
const buttonWidget = node.widgets.find((w) => w.name === 'refresh')
return buttonWidget?.callback()
const buttonWidget = node!.widgets!.find((w) => w.name === 'refresh')
return buttonWidget?.callback?.(buttonWidget.value)
}, nodeName)
}

View File

@@ -28,7 +28,7 @@ test.describe(
// Drag the KSampler to the center of the screen
const nodePos = await ksamplerNodes[0].getPosition()
const viewportSize = comfyPage.page.viewportSize()
const viewportSize = comfyPage.page.viewportSize()!
const centerX = viewportSize.width / 3
const centerY = viewportSize.height / 2
await comfyPage.canvasOps.dragAndDrop(

View File

@@ -26,8 +26,8 @@ test.describe('Subgraph Slot Rename Dialog', { tag: '@subgraph' }, () => {
// Get initial slot label
const initialInputLabel = await comfyPage.page.evaluate(() => {
const graph = window.app!.canvas.graph
return graph.inputs?.[0]?.label || graph.inputs?.[0]?.name || null
const graph = window.app!.canvas.graph as any
return graph?.inputs?.[0]?.label || graph?.inputs?.[0]?.name || null
})
// First rename
@@ -55,8 +55,8 @@ test.describe('Subgraph Slot Rename Dialog', { tag: '@subgraph' }, () => {
// Verify the rename worked
const afterFirstRename = await comfyPage.page.evaluate(() => {
const graph = window.app!.canvas.graph
const slot = graph.inputs?.[0]
const graph = window.app!.canvas.graph as any
const slot = graph?.inputs?.[0]
return {
label: slot?.label || null,
name: slot?.name || null,
@@ -98,8 +98,8 @@ test.describe('Subgraph Slot Rename Dialog', { tag: '@subgraph' }, () => {
// Verify the second rename worked
const afterSecondRename = await comfyPage.page.evaluate(() => {
const graph = window.app!.canvas.graph
return graph.inputs?.[0]?.label || null
const graph = window.app!.canvas.graph as any
return graph?.inputs?.[0]?.label || null
})
expect(afterSecondRename).toBe(SECOND_RENAMED_NAME)
})
@@ -114,8 +114,8 @@ test.describe('Subgraph Slot Rename Dialog', { tag: '@subgraph' }, () => {
// Get initial output slot label
const initialOutputLabel = await comfyPage.page.evaluate(() => {
const graph = window.app!.canvas.graph
return graph.outputs?.[0]?.label || graph.outputs?.[0]?.name || null
const graph = window.app!.canvas.graph as any
return graph?.outputs?.[0]?.label || graph?.outputs?.[0]?.name || null
})
// First rename

View File

@@ -26,8 +26,8 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
comfyPage: typeof test.prototype.comfyPage,
type: 'inputs' | 'outputs'
): Promise<number> {
return await comfyPage.page.evaluate((slotType) => {
return window.app!.canvas.graph[slotType]?.length || 0
return await comfyPage.page.evaluate((slotType: 'inputs' | 'outputs') => {
return (window.app!.canvas.graph as any)?.[slotType]?.length || 0
}, type)
}
@@ -36,7 +36,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
comfyPage: typeof test.prototype.comfyPage
): Promise<number> {
return await comfyPage.page.evaluate(() => {
return window.app!.canvas.graph.nodes?.length || 0
return window.app!.canvas.graph!.nodes?.length || 0
})
}
@@ -132,8 +132,8 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
await subgraphNode.navigateIntoSubgraph()
const initialInputLabel = await comfyPage.page.evaluate(() => {
const graph = window.app!.canvas.graph
return graph.inputs?.[0]?.label || null
const graph = window.app!.canvas.graph as any
return graph?.inputs?.[0]?.label || null
})
await comfyPage.subgraph.rightClickInputSlot(initialInputLabel)
@@ -151,8 +151,8 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
await comfyPage.nextFrame()
const newInputName = await comfyPage.page.evaluate(() => {
const graph = window.app!.canvas.graph
return graph.inputs?.[0]?.label || null
const graph = window.app!.canvas.graph as any
return graph?.inputs?.[0]?.label || null
})
expect(newInputName).toBe(RENAMED_INPUT_NAME)
@@ -166,8 +166,8 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
await subgraphNode.navigateIntoSubgraph()
const initialInputLabel = await comfyPage.page.evaluate(() => {
const graph = window.app!.canvas.graph
return graph.inputs?.[0]?.label || null
const graph = window.app!.canvas.graph as any
return graph?.inputs?.[0]?.label || null
})
await comfyPage.subgraph.doubleClickInputSlot(initialInputLabel)
@@ -183,8 +183,8 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
await comfyPage.nextFrame()
const newInputName = await comfyPage.page.evaluate(() => {
const graph = window.app!.canvas.graph
return graph.inputs?.[0]?.label || null
const graph = window.app!.canvas.graph as any
return graph?.inputs?.[0]?.label || null
})
expect(newInputName).toBe(RENAMED_INPUT_NAME)
@@ -198,8 +198,8 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
await subgraphNode.navigateIntoSubgraph()
const initialOutputLabel = await comfyPage.page.evaluate(() => {
const graph = window.app!.canvas.graph
return graph.outputs?.[0]?.label || null
const graph = window.app!.canvas.graph as any
return graph?.outputs?.[0]?.label || null
})
await comfyPage.subgraph.doubleClickOutputSlot(initialOutputLabel)
@@ -216,8 +216,8 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
await comfyPage.nextFrame()
const newOutputName = await comfyPage.page.evaluate(() => {
const graph = window.app!.canvas.graph
return graph.outputs?.[0]?.label || null
const graph = window.app!.canvas.graph as any
return graph?.outputs?.[0]?.label || null
})
expect(newOutputName).toBe(renamedOutputName)
@@ -233,8 +233,8 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
await subgraphNode.navigateIntoSubgraph()
const initialInputLabel = await comfyPage.page.evaluate(() => {
const graph = window.app!.canvas.graph
return graph.inputs?.[0]?.label || null
const graph = window.app!.canvas.graph as any
return graph?.inputs?.[0]?.label || null
})
// Test that right-click still works for renaming
@@ -254,8 +254,8 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
await comfyPage.nextFrame()
const newInputName = await comfyPage.page.evaluate(() => {
const graph = window.app!.canvas.graph
return graph.inputs?.[0]?.label || null
const graph = window.app!.canvas.graph as any
return graph?.inputs?.[0]?.label || null
})
expect(newInputName).toBe(rightClickRenamedName)
@@ -271,15 +271,16 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
await subgraphNode.navigateIntoSubgraph()
const initialInputLabel = await comfyPage.page.evaluate(() => {
const graph = window.app!.canvas.graph
return graph.inputs?.[0]?.label || null
const graph = window.app!.canvas.graph as any
return graph?.inputs?.[0]?.label || null
})
// Use direct pointer event approach to double-click on label
await comfyPage.page.evaluate(() => {
const app = window.app
const graph = app.canvas.graph
const input = graph.inputs?.[0]
const app = window.app!
const graph = app.canvas.graph as any
const input = graph?.inputs?.[0]
if (!input?.labelPos) {
throw new Error('Could not get label position for testing')
@@ -297,17 +298,17 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
stopPropagation: () => {}
}
const inputNode = graph.inputNode
const inputNode = graph?.inputNode
if (inputNode?.onPointerDown) {
inputNode.onPointerDown(
leftClickEvent,
leftClickEvent as any,
app.canvas.pointer,
app.canvas.linkConnector
)
// Trigger double-click if pointer has the handler
if (app.canvas.pointer.onDoubleClick) {
app.canvas.pointer.onDoubleClick(leftClickEvent)
app.canvas.pointer.onDoubleClick(leftClickEvent as any)
}
}
})
@@ -326,8 +327,8 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
await comfyPage.nextFrame()
const newInputName = await comfyPage.page.evaluate(() => {
const graph = window.app!.canvas.graph
return graph.inputs?.[0]?.label || null
const graph = window.app!.canvas.graph as any
return graph?.inputs?.[0]?.label || null
})
expect(newInputName).toBe(labelClickRenamedName)
@@ -340,7 +341,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
'subgraphs/subgraph-compressed-target-slot'
)
const step = await comfyPage.page.evaluate(() => {
return window.app.graph.nodes[0].widgets[0].options.step
return window.app!.graph!.nodes[0].widgets![0].options.step
})
expect(step).toBe(10)
})
@@ -350,7 +351,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
test('Can create subgraph from selected nodes', async ({ comfyPage }) => {
await comfyPage.workflow.loadWorkflow('default')
const _initialNodeCount = await getGraphNodeCount(comfyPage)
await getGraphNodeCount(comfyPage)
await comfyPage.keyboard.selectAll()
await comfyPage.nextFrame()
@@ -459,7 +460,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
const initialNodeCount = await getGraphNodeCount(comfyPage)
const nodesInSubgraph = await comfyPage.page.evaluate(() => {
const nodes = window.app!.canvas.graph.nodes
const nodes = window.app!.canvas.graph!.nodes
return nodes?.[0]?.id || null
})
@@ -689,7 +690,7 @@ test.describe('Subgraph Operations', { tag: ['@slow', '@subgraph'] }, () => {
// Check that the subgraph node has no widgets after removing the text slot
const widgetCount = await comfyPage.page.evaluate(() => {
return window.app!.canvas.graph.nodes[0].widgets?.length || 0
return window.app!.canvas.graph!.nodes[0].widgets?.length || 0
})
expect(widgetCount).toBe(0)

View File

@@ -61,8 +61,8 @@ test.describe('Combo text widget', { tag: ['@screenshot', '@widget'] }, () => {
return window
.app!.graph!.nodes.find(
(node) => node.title === 'Node With Optional Combo Input'
)
.widgets.find((widget) => widget.name === 'optional_combo_input')
)!
.widgets!.find((widget) => widget.name === 'optional_combo_input')!
.options.values
})
@@ -98,8 +98,9 @@ test.describe('Combo text widget', { tag: ['@screenshot', '@widget'] }, () => {
return window
.app!.graph!.nodes.find(
(node) => node.title === 'Node With V2 Combo Input'
)
.widgets.find((widget) => widget.name === 'combo_input').options.values
)!
.widgets!.find((widget) => widget.name === 'combo_input')!.options
.values
})
expect(comboValues).toEqual(['A', 'B'])
})
@@ -125,7 +126,7 @@ test.describe('Slider widget', { tag: ['@screenshot', '@widget'] }, () => {
const widget = await node.getWidget(0)
await comfyPage.page.evaluate(() => {
const widget = window.app!.graph!.nodes[0].widgets[0]
const widget = window.app!.graph!.nodes[0].widgets![0]
widget.callback = (value: number) => {
window.widgetValue = value
}
@@ -146,7 +147,7 @@ test.describe('Number widget', { tag: ['@screenshot', '@widget'] }, () => {
const node = (await comfyPage.nodeOps.getFirstNodeRef())!
const widget = await node.getWidget(0)
await comfyPage.page.evaluate(() => {
const widget = window.app!.graph!.nodes[0].widgets[0]
const widget = window.app!.graph!.nodes[0].widgets![0]
widget.callback = (value: number) => {
window.widgetValue = value
}
@@ -170,8 +171,8 @@ test.describe(
await comfyPage.workflow.loadWorkflow('nodes/single_ksampler')
await comfyPage.page.evaluate(() => {
window.graph!.nodes[0].addWidget('number', 'new_widget', 10)
window.graph!.setDirtyCanvas(true, true)
window.app!.graph!.nodes[0].addWidget('number', 'new_widget', 10, null)
window.app!.graph!.setDirtyCanvas(true, true)
})
await expect(comfyPage.canvas).toHaveScreenshot(
@@ -253,11 +254,11 @@ test.describe('Image widget', { tag: ['@screenshot', '@widget'] }, () => {
const targetNode = graph.nodes[6]
targetNode.imgs = [image1, image2]
targetNode.imageIndex = 1
app.canvas.setDirty(true)
app!.canvas.setDirty(true)
const x = targetNode.pos[0] + targetNode.size[0] - 41
const y = targetNode.pos[1] + targetNode.widgets.at(-1).last_y + 30
return app.canvasPosToClientPos([x, y])
const y = targetNode.pos[1] + targetNode.widgets!.at(-1)!.last_y! + 30
return app!.canvasPosToClientPos([x, y])
})
const clip = { x, y, width: 35, height: 35 }
@@ -354,7 +355,7 @@ test.describe(
([loadId, saveId]) => {
// Set the output of the SaveAnimatedWEBP node to equal the loader node's image
window.app!.nodeOutputs[saveId] = window.app!.nodeOutputs[loadId]
app.canvas.setDirty(true)
app!.canvas.setDirty(true)
},
[loadAnimatedWebpNode.id, saveAnimatedWebpNode.id]
)