mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-20 14:30:41 +00:00
## Summary Alright, alright, alright. These e2e tests have been runnin' around like they're late for somethin', settin' tight little timeouts like the world's gonna end in 250 milliseconds. Man, you gotta *breathe*. Let the framework do its thing. Go slow to go fast, that's what I always say. ## Changes - **What**: Removed ~120 redundant timeout overrides from auto-retrying Playwright assertions (`toBeVisible`, `toBeHidden`, `toHaveCount`, `toBeEnabled`, `toHaveAttribute`, `toContainText`, `expect.poll`) where 5000ms is already the default. Also removed sub-5s timeouts (1s, 2s, 3s) that were just *begging* for flaky failures — like wearin' a belt and suspenders and also holdin' your pants up with both hands. Raised the absurdly short timeouts in `customMatchers.ts` (250ms `toPass` → 5000ms, 256ms poll → default). Kept `timeout: 5000` on `.toPass()` calls (defaults to 0), `.waitFor()`, `waitForRequest`, `waitForFunction`, intentionally-short timeouts inside retry loops, and conditional `.isVisible()/.catch()` checks — those fellas actually need the help. ## Review Focus Every remaining timeout in the diff is there for a *reason*. The ones on `.toPass()` stay because that API defaults to zero — it won't retry at all without one. The ones on `.waitFor()` and `waitForRequest` stay because those are locator actions, not auto-retrying assertions. The intentionally-short ones inside `toPass` retry loops (`interaction.spec.ts`) and the negative assertions (`actionbar.spec.ts` confirming no response arrives) — those are *supposed* to be tight. The short timeouts on regular assertions were actively *encouragin'* flaky failures. That's like settin' your alarm for 4 AM and then gettin' mad you're tired. Just... don't do that, man. Let things take the time they need. 38 files, net -115 lines. Less code, more chill. That's livin'. --------- Co-authored-by: Amp <amp@ampcode.com>
151 lines
4.7 KiB
TypeScript
151 lines
4.7 KiB
TypeScript
import { expect } from '@playwright/test'
|
|
|
|
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
|
|
|
|
test.describe('Workflow tabs', () => {
|
|
test.beforeEach(async ({ comfyPage }) => {
|
|
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Top')
|
|
await comfyPage.settings.setSetting(
|
|
'Comfy.Workflow.WorkflowTabsPosition',
|
|
'Topbar'
|
|
)
|
|
await comfyPage.setup()
|
|
})
|
|
|
|
test('Default workflow tab is visible on load', async ({ comfyPage }) => {
|
|
await expect
|
|
.poll(() => comfyPage.menu.topbar.getTabNames())
|
|
.toEqual([expect.stringContaining('Unsaved Workflow')])
|
|
})
|
|
|
|
test('Creating a new workflow adds a tab', async ({ comfyPage }) => {
|
|
const topbar = comfyPage.menu.topbar
|
|
|
|
await expect.poll(() => topbar.getTabNames()).toHaveLength(1)
|
|
|
|
await topbar.newWorkflowButton.click()
|
|
await expect
|
|
.poll(() => topbar.getTabNames())
|
|
.toEqual(
|
|
expect.arrayContaining([
|
|
expect.stringContaining('Unsaved Workflow (2)')
|
|
])
|
|
)
|
|
})
|
|
|
|
test('Switching tabs changes active workflow', async ({ comfyPage }) => {
|
|
const topbar = comfyPage.menu.topbar
|
|
|
|
await topbar.newWorkflowButton.click()
|
|
await expect.poll(() => topbar.getTabNames()).toHaveLength(2)
|
|
|
|
await expect(topbar.getActiveTab()).toContainText('Unsaved Workflow (2)')
|
|
|
|
await topbar.getTab(0).click()
|
|
await expect(topbar.getActiveTab()).toContainText('Unsaved Workflow')
|
|
await expect(topbar.getActiveTab()).not.toContainText('(2)')
|
|
})
|
|
|
|
test('Closing a tab removes it', async ({ comfyPage }) => {
|
|
const topbar = comfyPage.menu.topbar
|
|
|
|
await topbar.newWorkflowButton.click()
|
|
await expect.poll(() => topbar.getTabNames()).toHaveLength(2)
|
|
|
|
await topbar.closeWorkflowTab('Unsaved Workflow (2)')
|
|
await expect
|
|
.poll(() => topbar.getTabNames())
|
|
.toEqual([expect.stringContaining('Unsaved Workflow')])
|
|
})
|
|
|
|
test('Right-clicking a tab shows context menu', async ({ comfyPage }) => {
|
|
const topbar = comfyPage.menu.topbar
|
|
|
|
await topbar.getTab(0).click({ button: 'right' })
|
|
|
|
// Reka UI ContextMenuContent gets data-state="open" when active
|
|
const contextMenu = comfyPage.page.locator(
|
|
'[role="menu"][data-state="open"]'
|
|
)
|
|
await expect(contextMenu).toBeVisible()
|
|
|
|
await expect(
|
|
contextMenu.getByRole('menuitem', { name: /Close Tab/i }).first()
|
|
).toBeVisible()
|
|
await expect(
|
|
contextMenu.getByRole('menuitem', { name: /Save/i }).first()
|
|
).toBeVisible()
|
|
})
|
|
|
|
test('Context menu Close Tab action removes the tab', async ({
|
|
comfyPage
|
|
}) => {
|
|
const topbar = comfyPage.menu.topbar
|
|
|
|
await topbar.newWorkflowButton.click()
|
|
await expect.poll(() => topbar.getTabNames()).toHaveLength(2)
|
|
|
|
await topbar.getTab(1).click({ button: 'right' })
|
|
const contextMenu = comfyPage.page.locator(
|
|
'[role="menu"][data-state="open"]'
|
|
)
|
|
await expect(contextMenu).toBeVisible()
|
|
|
|
await contextMenu
|
|
.getByRole('menuitem', { name: /Close Tab/i })
|
|
.first()
|
|
.click()
|
|
await expect.poll(() => topbar.getTabNames()).toHaveLength(1)
|
|
})
|
|
|
|
test('Closing the last tab creates a new default workflow', async ({
|
|
comfyPage
|
|
}) => {
|
|
const topbar = comfyPage.menu.topbar
|
|
|
|
await expect.poll(() => topbar.getTabNames()).toHaveLength(1)
|
|
|
|
await topbar.closeWorkflowTab('Unsaved Workflow')
|
|
await expect
|
|
.poll(() => topbar.getTabNames())
|
|
.toEqual([expect.stringContaining('Unsaved Workflow')])
|
|
})
|
|
|
|
test('Modified workflow shows unsaved indicator', async ({ comfyPage }) => {
|
|
const topbar = comfyPage.menu.topbar
|
|
|
|
// Modify the graph via litegraph API to trigger unsaved state
|
|
await comfyPage.page.evaluate(() => {
|
|
const graph = window.app?.graph
|
|
const node = window.LiteGraph?.createNode('Note')
|
|
if (graph && node) graph.add(node)
|
|
})
|
|
|
|
// WorkflowTab renders "•" when the workflow has unsaved changes
|
|
const activeTab = topbar.getActiveTab()
|
|
await expect(activeTab.locator('text=•')).toBeVisible()
|
|
})
|
|
|
|
test('Multiple tabs can be created, switched, and closed', async ({
|
|
comfyPage
|
|
}) => {
|
|
const topbar = comfyPage.menu.topbar
|
|
|
|
// Create 2 additional tabs (3 total)
|
|
await topbar.newWorkflowButton.click()
|
|
await expect.poll(() => topbar.getTabNames()).toHaveLength(2)
|
|
await topbar.newWorkflowButton.click()
|
|
await expect.poll(() => topbar.getTabNames()).toHaveLength(3)
|
|
|
|
// Switch to first tab
|
|
await topbar.getTab(0).click()
|
|
await expect
|
|
.poll(() => topbar.getActiveTabName())
|
|
.toContain('Unsaved Workflow')
|
|
|
|
// Close the middle tab
|
|
await topbar.closeWorkflowTab('Unsaved Workflow (2)')
|
|
await expect.poll(() => topbar.getTabNames()).toHaveLength(2)
|
|
})
|
|
})
|