Files
ComfyUI_frontend/browser_tests/fixtures/components/SubgraphEditor.ts
DrJKL ba2a7423c6 fix(subgraph): unify preview projection and editor visibility on SubgraphNode
- Skip LivePreview render on SubgraphNode hosts; previews flow through
  promotedPreviews / previewExposureStore as the single source of truth
- Treat exposures as authoritative in SubgraphEditor.getActivePreviewWidgets
  so $$canvas-image-preview rows always surface, even when the interior
  source node lacks a matching promotable widget
- Hydrate canonical/legacy preview exposures at configure time in
  SubgraphNode._hydratePreviewExposures; usePromotedPreviews is now a
  pure read with path-style nested host fallback
- Add KSampler/KSamplerAdvanced to virtual canvas-image-preview node types
  so live samplers expose preview rows pre-execution
- SubgraphEditor.open() returns early when panel is already visible to
  avoid flaky context-menu opens
- Remove obsolete proxy-widget test; convert inline @vue-nodes name
  prefix to tag annotation across subgraphPromotion.spec.ts
- Drop stale "migrates legacy host exposure keys while reading previews"
  unit tests now that migration runs at configure time

Review feedback fixes:
- useResolvedSelectedInputs: clone graphNodes array to avoid shared
  reference with app.rootGraph.nodes
- previewExposureSchema: avoid mutating the property parameter
- nodeOutputStore: case-insensitive `.svg` check

Amp-Thread-ID: https://ampcode.com/threads/T-019e23c9-3dc1-7381-ae59-c0372b3325e2
Co-authored-by: Amp <amp@ampcode.com>
2026-05-13 20:11:06 -07:00

83 lines
2.6 KiB
TypeScript

import type { Locator } from '@playwright/test'
import { comfyExpect as expect } from '@e2e/fixtures/ComfyPage'
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
import { TestIds } from '@e2e/fixtures/selectors'
import { dragByIndex } from '@e2e/fixtures/utils/dragAndDrop'
import { VueNodeFixture } from '@e2e/fixtures/utils/vueNodeFixtures'
export class SubgraphEditor {
public readonly root: Locator
public readonly promotionItems: Locator
constructor(protected readonly comfyPage: ComfyPage) {
this.root = this.comfyPage.menu.propertiesPanel.root
this.promotionItems = this.root.getByTestId(
TestIds.subgraphEditor.widgetItem
)
}
async open(subgraphNode: Locator) {
await new VueNodeFixture(subgraphNode).select()
if (await this.root.isVisible()) return
const menu = await this.comfyPage.contextMenu.openFor(subgraphNode)
await menu.clickMenuItemExact('Edit Subgraph Widgets')
await expect(this.root, 'Open Properties Panel').toBeVisible()
}
resolveItem(options: {
nodeName?: string
nodeId?: string
widgetName: string
}): Locator {
const nodeItems =
options.nodeId !== undefined
? this.comfyPage.page.locator(`[data-nodeid="${options.nodeId}"]`)
: options.nodeName !== undefined
? this.promotionItems.filter({
has: this.comfyPage.page
.getByTestId(TestIds.subgraphEditor.nodeName)
.filter({ hasText: options.nodeName })
})
: this.promotionItems
return nodeItems.filter({
has: this.comfyPage.page
.getByTestId(TestIds.subgraphEditor.widgetLabel)
.filter({ hasText: options.widgetName })
})
}
getToggleButton(item: Locator) {
return item.getByTestId(TestIds.subgraphEditor.widgetToggle)
}
async togglePromotionOnItem(item: Locator, toState?: boolean) {
const toggleIcon = item.getByTestId(TestIds.subgraphEditor.iconEye)
if (toState !== undefined) {
const expectedIcon = `icon-[lucide--eye${toState ? '-off' : ''}]`
await expect(toggleIcon).toContainClass(expectedIcon)
}
await toggleIcon.click()
}
async togglePromotion(
subgraphNode: Locator,
options: {
nodeName?: string
nodeId?: string
widgetName: string
toState?: boolean
}
) {
await this.open(subgraphNode)
const item = this.resolveItem(options)
await this.togglePromotionOnItem(item, options.toState)
}
async dragItem(fromIndex: number, toIndex: number) {
await dragByIndex(this.promotionItems, fromIndex, toIndex)
await this.comfyPage.nextFrame()
}
}