diff --git a/browser_tests/tests/subgraph/subgraphPromotion.spec.ts b/browser_tests/tests/subgraph/subgraphPromotion.spec.ts index f4f271f17a..1e9c8ba21f 100644 --- a/browser_tests/tests/subgraph/subgraphPromotion.spec.ts +++ b/browser_tests/tests/subgraph/subgraphPromotion.spec.ts @@ -667,11 +667,12 @@ test('Properties panel operations @vue-nodes', async ({ comfyPage }) => { ) }) - await editor.togglePromotion(subgraphNode, { - nodeName: 'KSampler', - widgetName: 'steps', - toState: false - }) + // Link-promoted widgets render `icon-link` (disabled toggle) in the editor; + // demotion happens via the source-node context menu inside the subgraph. + await comfyPage.vueNodes.enterSubgraph('2') + const ksampler = await comfyPage.vueNodes.getFixtureByTitle('KSampler') + await comfyPage.subgraph.unpromoteWidget(ksampler.root, 'steps') + await comfyPage.subgraph.exitViaBreadcrumb() await expect(steps, 'Un-promote widget').toBeHidden() }) diff --git a/src/components/rightSidePanel/subgraph/SubgraphEditor.vue b/src/components/rightSidePanel/subgraph/SubgraphEditor.vue index f7f0211e40..197ccbba7d 100644 --- a/src/components/rightSidePanel/subgraph/SubgraphEditor.vue +++ b/src/components/rightSidePanel/subgraph/SubgraphEditor.vue @@ -127,9 +127,16 @@ const interiorWidgets = computed(() => { const candidateWidgets = computed(() => { const node = activeNode.value if (!node) return [] + // An interior widget is "already promoted" iff some active row's source + // identity matches it. PromotedWidgetView carries `sourceNodeId`; preview + // exposures are stored as the interior `[node, widget]` tuple directly. + const promotedSourceKeys = new Set( + activeWidgets.value.map( + ([n, w]) => `${getSourceNodeId(w) ?? String(n.id)}:${getWidgetName(w)}` + ) + ) return interiorWidgets.value.filter( - (item: WidgetItem) => - !activeWidgets.value.some((active) => toKey(active) === toKey(item)) + ([n, w]) => !promotedSourceKeys.has(`${n.id}:${w.name}`) ) }) const filteredCandidates = computed(() => {