mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-20 14:30:41 +00:00
## Summary Reorganize the subgraph test suite so browser tests are thin representative user journeys while lower-level Vitest suites own combinatorics, migration edge cases, and data-shape semantics. ## Changes - **What**: Migrate 17 flat subgraph browser specs into 10 domain-organized specs under `browser_tests/tests/subgraph/`, move redundant semantic coverage down to 8 Vitest owner suites, delete all legacy flat files - **Browser specs** (54 tests): `subgraphSlots`, `subgraphPromotion`, `subgraphPromotionDom`, `subgraphSerialization`, `subgraphNavigation`, `subgraphNested`, `subgraphLifecycle`, `subgraphCrud`, `subgraphSearch`, `subgraphOperations` - **Vitest owners** (230 tests): `SubgraphNode.test.ts` (rename/label propagation), `subgraphNodePromotion.test.ts`, `promotedWidgetView.test.ts`, `SubgraphSerialization.test.ts` (duplicate-ID remap), `SubgraphWidgetPromotion.test.ts` (legacy hydration), `subgraphNavigationStore*.test.ts` (viewport cache, workflow-switch), `subgraphStore.test.ts` (search aliases, description) - **Net effect**: browser suite shrinks from ~96 scattered tests to 54 focused journeys ## Review Focus - Coverage ownership split: each browser test has a unique UI-only failure mode; semantic coverage lives in Vitest - `subgraphPromotionDom.spec.ts` forces LiteGraph mode and uses `canvas.openSubgraph()` instead of `navigateIntoSubgraph()` to avoid a wrapper-specific DOM overlay duplication issue — entry-affordance coverage lives in `subgraphNavigation.spec.ts` - No product code changes — test-only migration ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-10759-test-reorganize-subgraph-test-suite-into-composable-domain-specs-3336d73d365081b0a56bcbf809b1f584) by [Unito](https://www.unito.io) --------- Co-authored-by: Amp <amp@ampcode.com>
566 lines
19 KiB
TypeScript
566 lines
19 KiB
TypeScript
import { expect } from '@playwright/test'
|
|
|
|
import type { ComfyPage } from '@e2e/fixtures/ComfyPage'
|
|
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
|
|
import { TestIds } from '@e2e/fixtures/selectors'
|
|
import { fitToViewInstant } from '@e2e/helpers/fitToView'
|
|
import {
|
|
getPromotedWidgetNames,
|
|
getPromotedWidgetCount
|
|
} from '@e2e/helpers/promotedWidgets'
|
|
|
|
async function expectPromotedWidgetNamesToContain(
|
|
comfyPage: ComfyPage,
|
|
nodeId: string,
|
|
widgetName: string
|
|
) {
|
|
await expect
|
|
.poll(() => getPromotedWidgetNames(comfyPage, nodeId), {
|
|
timeout: 5000
|
|
})
|
|
.toContain(widgetName)
|
|
}
|
|
|
|
async function expectPromotedWidgetCountToBeGreaterThan(
|
|
comfyPage: ComfyPage,
|
|
nodeId: string,
|
|
count: number
|
|
) {
|
|
await expect
|
|
.poll(() => getPromotedWidgetCount(comfyPage, nodeId), {
|
|
timeout: 5000
|
|
})
|
|
.toBeGreaterThan(count)
|
|
}
|
|
|
|
test.describe(
|
|
'Subgraph Widget Promotion',
|
|
{ tag: ['@subgraph', '@widget'] },
|
|
() => {
|
|
test.beforeEach(async ({ comfyPage }) => {
|
|
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Disabled')
|
|
})
|
|
|
|
test.describe('Auto-promotion on Convert to Subgraph', () => {
|
|
test('Recommended widgets are auto-promoted when creating a subgraph', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.workflow.loadWorkflow('default')
|
|
|
|
const ksampler = await comfyPage.nodeOps.getNodeRefById('3')
|
|
await ksampler.click('title')
|
|
const subgraphNode = await ksampler.convertToSubgraph()
|
|
await comfyPage.nextFrame()
|
|
|
|
expect(await subgraphNode.exists()).toBe(true)
|
|
|
|
const nodeId = String(subgraphNode.id)
|
|
await expectPromotedWidgetNamesToContain(comfyPage, nodeId, 'seed')
|
|
|
|
await expectPromotedWidgetCountToBeGreaterThan(comfyPage, nodeId, 0)
|
|
})
|
|
|
|
test('Preview-capable nodes keep regular and pseudo-widget promotions when converted', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.workflow.loadWorkflow('default')
|
|
|
|
// Select the positive CLIPTextEncode node (id 6)
|
|
const clipNode = await comfyPage.nodeOps.getNodeRefById('6')
|
|
await clipNode.click('title')
|
|
const subgraphNode = await clipNode.convertToSubgraph()
|
|
await comfyPage.nextFrame()
|
|
|
|
const nodeId = String(subgraphNode.id)
|
|
// CLIPTextEncode is in the recommendedNodes list, so its text widget
|
|
// should be promoted
|
|
await expectPromotedWidgetNamesToContain(comfyPage, nodeId, 'text')
|
|
})
|
|
|
|
test('SaveImage/PreviewImage nodes get pseudo-widget promoted', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.workflow.loadWorkflow('default')
|
|
|
|
// Pan to SaveImage node (rightmost, may be off-screen in CI)
|
|
const saveNode = await comfyPage.nodeOps.getNodeRefById('9')
|
|
await saveNode.centerOnNode()
|
|
|
|
await saveNode.click('title')
|
|
const subgraphNode = await saveNode.convertToSubgraph()
|
|
await comfyPage.nextFrame()
|
|
|
|
// SaveImage is in the recommendedNodes list, so filename_prefix is promoted
|
|
await expectPromotedWidgetNamesToContain(
|
|
comfyPage,
|
|
String(subgraphNode.id),
|
|
'filename_prefix'
|
|
)
|
|
})
|
|
})
|
|
|
|
test.describe('Promoted Widget Visibility in LiteGraph Mode', () => {
|
|
test('Promoted text widget is visible on SubgraphNode', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.workflow.loadWorkflow(
|
|
'subgraphs/subgraph-with-promoted-text-widget'
|
|
)
|
|
await comfyPage.nextFrame()
|
|
|
|
const textarea = comfyPage.page.getByTestId(
|
|
TestIds.widgets.domWidgetTextarea
|
|
)
|
|
await expect(textarea).toBeVisible()
|
|
await expect(textarea).toHaveCount(1)
|
|
})
|
|
})
|
|
|
|
test.describe('Promoted Widget Visibility in Vue Mode', () => {
|
|
test.beforeEach(async ({ comfyPage }) => {
|
|
await comfyPage.settings.setSetting('Comfy.VueNodes.Enabled', true)
|
|
})
|
|
|
|
test('Promoted text widget renders and enters the subgraph in Vue mode', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.workflow.loadWorkflow(
|
|
'subgraphs/subgraph-with-promoted-text-widget'
|
|
)
|
|
await comfyPage.vueNodes.waitForNodes()
|
|
|
|
const subgraphVueNode = comfyPage.vueNodes.getNodeLocator('11')
|
|
await expect(subgraphVueNode).toBeVisible()
|
|
|
|
const enterButton = subgraphVueNode.getByTestId('subgraph-enter-button')
|
|
await expect(enterButton).toBeVisible()
|
|
|
|
const nodeBody = subgraphVueNode.locator('[data-testid="node-body-11"]')
|
|
await expect(nodeBody).toBeVisible()
|
|
|
|
const widgets = nodeBody.locator('.lg-node-widgets > div')
|
|
await expect(widgets.first()).toBeVisible()
|
|
await comfyPage.vueNodes.enterSubgraph('11')
|
|
await comfyPage.nextFrame()
|
|
|
|
await expect.poll(() => comfyPage.subgraph.isInSubgraph()).toBe(true)
|
|
})
|
|
})
|
|
|
|
test.describe('Promoted Widget Reactivity', () => {
|
|
test('Promoted and interior widgets stay in sync across navigation', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.workflow.loadWorkflow(
|
|
'subgraphs/subgraph-with-promoted-text-widget'
|
|
)
|
|
await comfyPage.nextFrame()
|
|
|
|
const testContent = 'promoted-value-sync-test'
|
|
|
|
const textarea = comfyPage.page.getByTestId(
|
|
TestIds.widgets.domWidgetTextarea
|
|
)
|
|
await textarea.fill(testContent)
|
|
await comfyPage.nextFrame()
|
|
|
|
const subgraphNode = await comfyPage.nodeOps.getNodeRefById('11')
|
|
await subgraphNode.navigateIntoSubgraph()
|
|
|
|
const interiorTextarea = comfyPage.page.getByTestId(
|
|
TestIds.widgets.domWidgetTextarea
|
|
)
|
|
await expect(interiorTextarea).toHaveValue(testContent)
|
|
|
|
const updatedInteriorContent = 'interior-value-sync-test'
|
|
await interiorTextarea.fill(updatedInteriorContent)
|
|
await comfyPage.nextFrame()
|
|
|
|
await comfyPage.subgraph.exitViaBreadcrumb()
|
|
|
|
const promotedTextarea = comfyPage.page.getByTestId(
|
|
TestIds.widgets.domWidgetTextarea
|
|
)
|
|
await expect(promotedTextarea).toHaveValue(updatedInteriorContent)
|
|
})
|
|
})
|
|
|
|
test.describe('Manual Promote/Demote via Context Menu', () => {
|
|
test.beforeEach(async ({ comfyPage }) => {
|
|
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Top')
|
|
})
|
|
|
|
test('Can promote and un-promote a widget from inside a subgraph', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.workflow.loadWorkflow('subgraphs/basic-subgraph')
|
|
|
|
const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
|
|
await subgraphNode.navigateIntoSubgraph()
|
|
|
|
const ksampler = await comfyPage.nodeOps.getNodeRefById('1')
|
|
await ksampler.click('title')
|
|
|
|
const stepsWidget = await ksampler.getWidget(2)
|
|
const widgetPos = await stepsWidget.getPosition()
|
|
await comfyPage.canvas.click({
|
|
position: widgetPos,
|
|
button: 'right',
|
|
force: true
|
|
})
|
|
await comfyPage.nextFrame()
|
|
|
|
// Look for the Promote Widget menu entry
|
|
const promoteEntry = comfyPage.page
|
|
.locator('.litemenu-entry')
|
|
.filter({ hasText: /Promote Widget/ })
|
|
|
|
await expect(promoteEntry).toBeVisible()
|
|
await promoteEntry.click()
|
|
await comfyPage.nextFrame()
|
|
|
|
// Navigate back to parent
|
|
await comfyPage.subgraph.exitViaBreadcrumb()
|
|
|
|
// SubgraphNode should now have the promoted widget
|
|
await expectPromotedWidgetCountToBeGreaterThan(comfyPage, '2', 0)
|
|
})
|
|
|
|
test('Can un-promote a widget from inside a subgraph', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.workflow.loadWorkflow('subgraphs/basic-subgraph')
|
|
|
|
// First promote a canvas-rendered widget (KSampler "steps")
|
|
const subgraphNode = await comfyPage.nodeOps.getNodeRefById('2')
|
|
await subgraphNode.navigateIntoSubgraph()
|
|
|
|
const ksampler = await comfyPage.nodeOps.getNodeRefById('1')
|
|
const stepsWidget = await ksampler.getWidget(2)
|
|
const widgetPos = await stepsWidget.getPosition()
|
|
|
|
await comfyPage.canvas.click({
|
|
position: widgetPos,
|
|
button: 'right',
|
|
force: true
|
|
})
|
|
await comfyPage.nextFrame()
|
|
|
|
const promoteEntry = comfyPage.page
|
|
.locator('.litemenu-entry')
|
|
.filter({ hasText: /Promote Widget/ })
|
|
|
|
await expect(promoteEntry).toBeVisible()
|
|
await promoteEntry.click()
|
|
await comfyPage.nextFrame()
|
|
|
|
await comfyPage.subgraph.exitViaBreadcrumb()
|
|
|
|
await fitToViewInstant(comfyPage)
|
|
await comfyPage.nextFrame()
|
|
await comfyPage.nextFrame()
|
|
|
|
await expectPromotedWidgetCountToBeGreaterThan(comfyPage, '2', 0)
|
|
const initialWidgetCount = await getPromotedWidgetCount(comfyPage, '2')
|
|
|
|
const subgraphNode2 = await comfyPage.nodeOps.getNodeRefById('2')
|
|
await subgraphNode2.navigateIntoSubgraph()
|
|
const ksampler2 = await comfyPage.nodeOps.getNodeRefById('1')
|
|
await ksampler2.click('title')
|
|
const stepsWidget2 = await ksampler2.getWidget(2)
|
|
const widgetPos2 = await stepsWidget2.getPosition()
|
|
|
|
await comfyPage.canvas.click({
|
|
position: widgetPos2,
|
|
button: 'right',
|
|
force: true
|
|
})
|
|
await comfyPage.nextFrame()
|
|
|
|
const unpromoteEntry = comfyPage.page
|
|
.locator('.litemenu-entry')
|
|
.filter({ hasText: /Un-Promote Widget/ })
|
|
|
|
await expect(unpromoteEntry).toBeVisible()
|
|
await unpromoteEntry.click()
|
|
await comfyPage.nextFrame()
|
|
|
|
await comfyPage.subgraph.exitViaBreadcrumb()
|
|
|
|
await expect
|
|
.poll(() => getPromotedWidgetCount(comfyPage, '2'), {
|
|
timeout: 5000
|
|
})
|
|
.toBeLessThan(initialWidgetCount)
|
|
})
|
|
})
|
|
|
|
test.describe('Textarea Widget Context Menu in Subgraph (Vue Mode)', () => {
|
|
test.beforeEach(async ({ comfyPage }) => {
|
|
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Top')
|
|
await comfyPage.settings.setSetting('Comfy.VueNodes.Enabled', true)
|
|
})
|
|
|
|
test('Right-click on textarea widget inside subgraph shows Promote Widget option', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.workflow.loadWorkflow(
|
|
'subgraphs/subgraph-with-text-widget'
|
|
)
|
|
await comfyPage.vueNodes.waitForNodes()
|
|
|
|
await comfyPage.vueNodes.enterSubgraph('11')
|
|
await comfyPage.nextFrame()
|
|
await comfyPage.vueNodes.waitForNodes()
|
|
|
|
const clipNode = comfyPage.vueNodes.getNodeLocator('10')
|
|
await expect(clipNode).toBeVisible()
|
|
|
|
await comfyPage.vueNodes.selectNode('10')
|
|
await comfyPage.nextFrame()
|
|
|
|
const textarea = clipNode.locator('textarea')
|
|
await expect(textarea).toBeVisible()
|
|
await textarea.dispatchEvent('contextmenu', {
|
|
bubbles: true,
|
|
cancelable: true,
|
|
button: 2
|
|
})
|
|
await comfyPage.nextFrame()
|
|
|
|
const promoteEntry = comfyPage.page
|
|
.locator('.p-contextmenu')
|
|
.locator('text=Promote Widget')
|
|
|
|
await expect(promoteEntry.first()).toBeVisible({ timeout: 5000 })
|
|
})
|
|
})
|
|
|
|
test.describe('Pseudo-Widget Promotion', () => {
|
|
test('Promoted preview nodes render custom content in Vue mode', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.workflow.loadWorkflow(
|
|
'subgraphs/subgraph-with-preview-node'
|
|
)
|
|
await comfyPage.nextFrame()
|
|
|
|
// The SaveImage node is in the recommendedNodes list, so its
|
|
// filename_prefix widget should be auto-promoted
|
|
await expectPromotedWidgetNamesToContain(
|
|
comfyPage,
|
|
'5',
|
|
'filename_prefix'
|
|
)
|
|
})
|
|
|
|
test('Converting SaveImage to subgraph promotes its widgets', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.workflow.loadWorkflow('default')
|
|
|
|
// Pan to SaveImage node (rightmost, may be off-screen in CI)
|
|
const saveNode = await comfyPage.nodeOps.getNodeRefById('9')
|
|
await saveNode.centerOnNode()
|
|
|
|
await saveNode.click('title')
|
|
const subgraphNode = await saveNode.convertToSubgraph()
|
|
await comfyPage.nextFrame()
|
|
|
|
// SaveImage is a recommended node, so filename_prefix should be promoted
|
|
const nodeId = String(subgraphNode.id)
|
|
await expectPromotedWidgetNamesToContain(
|
|
comfyPage,
|
|
nodeId,
|
|
'filename_prefix'
|
|
)
|
|
await expectPromotedWidgetCountToBeGreaterThan(comfyPage, nodeId, 0)
|
|
})
|
|
})
|
|
|
|
test.describe('Vue Mode - Promoted Preview Content', () => {
|
|
test.beforeEach(async ({ comfyPage }) => {
|
|
await comfyPage.settings.setSetting('Comfy.VueNodes.Enabled', true)
|
|
await comfyPage.workflow.loadWorkflow(
|
|
'subgraphs/subgraph-with-preview-node'
|
|
)
|
|
await comfyPage.vueNodes.waitForNodes()
|
|
|
|
const subgraphVueNode = comfyPage.vueNodes.getNodeLocator('5')
|
|
await expect(subgraphVueNode).toBeVisible()
|
|
|
|
const promotedNames = await getPromotedWidgetNames(comfyPage, '5')
|
|
expect(promotedNames).toContain('filename_prefix')
|
|
expect(promotedNames.some((name) => name.startsWith('$$'))).toBe(true)
|
|
|
|
const loadImageNode = await comfyPage.nodeOps.getNodeRefById('11')
|
|
const loadImagePosition = await loadImageNode.getPosition()
|
|
await comfyPage.dragDrop.dragAndDropFile('image64x64.webp', {
|
|
dropPosition: loadImagePosition
|
|
})
|
|
|
|
await comfyPage.command.executeCommand('Comfy.QueuePrompt')
|
|
|
|
const nodeBody = subgraphVueNode.locator('[data-testid="node-body-5"]')
|
|
await expect(nodeBody).toBeVisible()
|
|
await expect(
|
|
nodeBody.locator('.lg-node-widgets > div').first()
|
|
).toBeVisible()
|
|
|
|
await expect(nodeBody.locator('.image-preview img')).toHaveCount(1, {
|
|
timeout: 30_000
|
|
})
|
|
await expect(nodeBody.locator('.lg-node-widgets')).not.toContainText(
|
|
'$$canvas-image-preview'
|
|
)
|
|
})
|
|
})
|
|
|
|
test.describe('Nested Promoted Widget Disabled State', () => {
|
|
test('Externally linked promotions stay disabled while unlinked textareas remain editable', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.workflow.loadWorkflow(
|
|
'subgraphs/subgraph-nested-promotion'
|
|
)
|
|
await comfyPage.nextFrame()
|
|
|
|
const promotedNames = await getPromotedWidgetNames(comfyPage, '5')
|
|
expect(promotedNames).toContain('string_a')
|
|
expect(promotedNames).toContain('value')
|
|
|
|
const disabledState = await comfyPage.page.evaluate(() => {
|
|
const node = window.app!.canvas.graph!.getNodeById('5')
|
|
return (node?.widgets ?? []).map((w) => ({
|
|
name: w.name,
|
|
disabled: !!w.computedDisabled
|
|
}))
|
|
})
|
|
|
|
const linkedWidget = disabledState.find((w) => w.name === 'string_a')
|
|
expect(linkedWidget?.disabled).toBe(true)
|
|
|
|
const textareas = comfyPage.page.getByTestId(
|
|
TestIds.widgets.domWidgetTextarea
|
|
)
|
|
await expect(textareas.first()).toBeVisible()
|
|
|
|
let editedTextarea = false
|
|
const count = await textareas.count()
|
|
for (let i = 0; i < count; i++) {
|
|
const textarea = textareas.nth(i)
|
|
const wrapper = textarea.locator('..')
|
|
const opacity = await wrapper.evaluate(
|
|
(el) => getComputedStyle(el).opacity
|
|
)
|
|
|
|
if (opacity === '1' && (await textarea.isEditable())) {
|
|
const testContent = `nested-promotion-edit-${i}`
|
|
await textarea.fill(testContent)
|
|
await expect(textarea).toHaveValue(testContent)
|
|
editedTextarea = true
|
|
break
|
|
}
|
|
}
|
|
expect(editedTextarea).toBe(true)
|
|
})
|
|
})
|
|
|
|
test.describe('Promotion Cleanup', () => {
|
|
test('Removing subgraph node clears promotion store entries', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.workflow.loadWorkflow(
|
|
'subgraphs/subgraph-with-promoted-text-widget'
|
|
)
|
|
await comfyPage.nextFrame()
|
|
|
|
// Verify promotions exist
|
|
const namesBefore = await getPromotedWidgetNames(comfyPage, '11')
|
|
expect(namesBefore.length).toBeGreaterThan(0)
|
|
|
|
// Delete the subgraph node
|
|
const subgraphNode = await comfyPage.nodeOps.getNodeRefById('11')
|
|
await subgraphNode.delete()
|
|
|
|
// Node no longer exists, so promoted widgets should be gone
|
|
expect(await subgraphNode.exists()).toBe(false)
|
|
})
|
|
|
|
test('Nested promoted widget entries reflect interior changes after slot removal', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Top')
|
|
|
|
await comfyPage.workflow.loadWorkflow(
|
|
'subgraphs/subgraph-nested-promotion'
|
|
)
|
|
await comfyPage.nextFrame()
|
|
|
|
await expectPromotedWidgetCountToBeGreaterThan(comfyPage, '5', 0)
|
|
const initialNames = await getPromotedWidgetNames(comfyPage, '5')
|
|
|
|
const outerSubgraph = await comfyPage.nodeOps.getNodeRefById('5')
|
|
await outerSubgraph.navigateIntoSubgraph()
|
|
|
|
const removedSlotName = await comfyPage.page.evaluate(() => {
|
|
const graph = window.app!.canvas.graph
|
|
if (!graph || !('inputNode' in graph)) return null
|
|
return graph.inputs?.[0]?.name ?? null
|
|
})
|
|
expect(removedSlotName).not.toBeNull()
|
|
|
|
await comfyPage.subgraph.removeSlot('input')
|
|
|
|
await comfyPage.subgraph.exitViaBreadcrumb()
|
|
|
|
const expectedNames = [...initialNames]
|
|
const removedIndex = expectedNames.indexOf(removedSlotName!)
|
|
expect(removedIndex).toBeGreaterThanOrEqual(0)
|
|
expectedNames.splice(removedIndex, 1)
|
|
|
|
await expect
|
|
.poll(() => getPromotedWidgetNames(comfyPage, '5'), {
|
|
timeout: 5000
|
|
})
|
|
.toEqual(expectedNames)
|
|
})
|
|
|
|
test('Removing I/O slot removes associated promoted widget', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Top')
|
|
|
|
await comfyPage.workflow.loadWorkflow(
|
|
'subgraphs/subgraph-with-promoted-text-widget'
|
|
)
|
|
|
|
let initialWidgetCount = 0
|
|
await expect
|
|
.poll(() => getPromotedWidgetCount(comfyPage, '11'), {
|
|
timeout: 5000
|
|
})
|
|
.toBeGreaterThan(0)
|
|
initialWidgetCount = await getPromotedWidgetCount(comfyPage, '11')
|
|
|
|
// Navigate into subgraph
|
|
const subgraphNode = await comfyPage.nodeOps.getNodeRefById('11')
|
|
await subgraphNode.navigateIntoSubgraph()
|
|
|
|
// Remove the text input slot
|
|
await comfyPage.subgraph.removeSlot('input', 'text')
|
|
|
|
// Navigate back via breadcrumb
|
|
await comfyPage.subgraph.exitViaBreadcrumb()
|
|
|
|
// Widget count should be reduced
|
|
await expect
|
|
.poll(() => getPromotedWidgetCount(comfyPage, '11'), {
|
|
timeout: 5000
|
|
})
|
|
.toBeLessThan(initialWidgetCount)
|
|
})
|
|
})
|
|
}
|
|
)
|