mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-20 06:20:11 +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>
202 lines
6.2 KiB
TypeScript
202 lines
6.2 KiB
TypeScript
import type { Page } from '@playwright/test'
|
|
|
|
import {
|
|
comfyPageFixture as test,
|
|
comfyExpect as expect
|
|
} from '@e2e/fixtures/ComfyPage'
|
|
import { TestIds } from '@e2e/fixtures/selectors'
|
|
|
|
test.describe('Error overlay', { tag: '@ui' }, () => {
|
|
test.beforeEach(async ({ comfyPage }) => {
|
|
await comfyPage.settings.setSetting('Comfy.UseNewMenu', 'Top')
|
|
await comfyPage.settings.setSetting(
|
|
'Comfy.RightSidePanel.ShowErrorsTab',
|
|
true
|
|
)
|
|
})
|
|
|
|
function getOverlay(page: Page) {
|
|
return page.getByTestId(TestIds.dialogs.errorOverlay)
|
|
}
|
|
|
|
function getSeeErrorsButton(page: Page) {
|
|
return getOverlay(page).getByTestId(TestIds.dialogs.errorOverlaySeeErrors)
|
|
}
|
|
|
|
test.describe('Labels', () => {
|
|
test('Should display singular error count label for single error', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.workflow.loadWorkflow('missing/missing_nodes')
|
|
|
|
await expect(getOverlay(comfyPage.page)).toBeVisible()
|
|
await expect(getOverlay(comfyPage.page)).toContainText(/1 ERROR/i)
|
|
})
|
|
|
|
test('Should display "Show missing nodes" button for missing node errors', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.workflow.loadWorkflow('missing/missing_nodes')
|
|
|
|
await expect(getOverlay(comfyPage.page)).toBeVisible()
|
|
await expect(getSeeErrorsButton(comfyPage.page)).toContainText(
|
|
/Show missing nodes/i
|
|
)
|
|
})
|
|
|
|
test('Should display "Show missing models" button for missing model errors', async ({
|
|
comfyPage
|
|
}) => {
|
|
await expect
|
|
.poll(() =>
|
|
comfyPage.page.evaluate(async (url: string) => {
|
|
const response = await fetch(
|
|
`${url}/api/devtools/cleanup_fake_model`
|
|
)
|
|
return response.ok
|
|
}, comfyPage.url)
|
|
)
|
|
.toBeTruthy()
|
|
|
|
await comfyPage.workflow.loadWorkflow('missing/missing_models')
|
|
|
|
await expect(getOverlay(comfyPage.page)).toBeVisible()
|
|
await expect(getSeeErrorsButton(comfyPage.page)).toContainText(
|
|
/Show missing models/i
|
|
)
|
|
})
|
|
|
|
test('Should display "Show missing inputs" button for missing media errors', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.workflow.loadWorkflow('missing/missing_media_single')
|
|
|
|
await expect(getOverlay(comfyPage.page)).toBeVisible()
|
|
await expect(getSeeErrorsButton(comfyPage.page)).toContainText(
|
|
/Show missing inputs/i
|
|
)
|
|
})
|
|
|
|
test('Should display generic "See Errors" button for multiple error types', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.workflow.loadWorkflow('missing/missing_nodes_and_media')
|
|
|
|
await expect(getOverlay(comfyPage.page)).toBeVisible()
|
|
await expect(getSeeErrorsButton(comfyPage.page)).toContainText(
|
|
/See Errors/i
|
|
)
|
|
})
|
|
})
|
|
|
|
test.describe('Persistence', () => {
|
|
test('Does not resurface missing nodes on undo/redo', async ({
|
|
comfyPage
|
|
}) => {
|
|
await comfyPage.workflow.loadWorkflow('missing/missing_nodes')
|
|
|
|
const errorOverlay = getOverlay(comfyPage.page)
|
|
await expect(errorOverlay).toBeVisible()
|
|
await errorOverlay
|
|
.getByTestId(TestIds.dialogs.errorOverlayDismiss)
|
|
.click()
|
|
await expect(errorOverlay).not.toBeVisible()
|
|
|
|
await comfyPage.canvas.click()
|
|
await comfyPage.nextFrame()
|
|
await comfyPage.page.keyboard.press('Control+a')
|
|
await comfyPage.page.mouse.move(400, 300)
|
|
await comfyPage.page.mouse.down()
|
|
await comfyPage.page.mouse.move(450, 350, { steps: 5 })
|
|
await comfyPage.page.mouse.up()
|
|
await comfyPage.nextFrame()
|
|
|
|
await comfyPage.keyboard.undo()
|
|
await expect(errorOverlay).not.toBeVisible()
|
|
|
|
await comfyPage.keyboard.redo()
|
|
await expect(errorOverlay).not.toBeVisible()
|
|
})
|
|
})
|
|
|
|
test.describe('See Errors flow', () => {
|
|
test.beforeEach(async ({ comfyPage }) => {
|
|
await comfyPage.setup()
|
|
})
|
|
|
|
async function triggerExecutionError(comfyPage: {
|
|
canvasOps: { disconnectEdge: () => Promise<void> }
|
|
page: Page
|
|
command: { executeCommand: (cmd: string) => Promise<void> }
|
|
}) {
|
|
await comfyPage.canvasOps.disconnectEdge()
|
|
await comfyPage.page.keyboard.press('Escape')
|
|
await comfyPage.command.executeCommand('Comfy.QueuePrompt')
|
|
}
|
|
|
|
test('Error overlay appears on execution error', async ({ comfyPage }) => {
|
|
await triggerExecutionError(comfyPage)
|
|
|
|
await expect(getOverlay(comfyPage.page)).toBeVisible()
|
|
})
|
|
|
|
test('Error overlay shows error message', async ({ comfyPage }) => {
|
|
await triggerExecutionError(comfyPage)
|
|
|
|
const overlay = getOverlay(comfyPage.page)
|
|
await expect(overlay).toBeVisible()
|
|
await expect(overlay).toHaveText(/\S/)
|
|
})
|
|
|
|
test('"See Errors" opens right side panel', async ({ comfyPage }) => {
|
|
await triggerExecutionError(comfyPage)
|
|
|
|
const overlay = getOverlay(comfyPage.page)
|
|
await expect(overlay).toBeVisible()
|
|
|
|
await overlay.getByTestId(TestIds.dialogs.errorOverlaySeeErrors).click()
|
|
|
|
await expect(overlay).not.toBeVisible()
|
|
await expect(comfyPage.page.getByTestId('properties-panel')).toBeVisible()
|
|
})
|
|
|
|
test('"See Errors" dismisses the overlay', async ({ comfyPage }) => {
|
|
await triggerExecutionError(comfyPage)
|
|
|
|
const overlay = getOverlay(comfyPage.page)
|
|
await expect(overlay).toBeVisible()
|
|
|
|
await overlay.getByTestId(TestIds.dialogs.errorOverlaySeeErrors).click()
|
|
|
|
await expect(overlay).not.toBeVisible()
|
|
})
|
|
|
|
test('"Dismiss" closes overlay without opening panel', async ({
|
|
comfyPage
|
|
}) => {
|
|
await triggerExecutionError(comfyPage)
|
|
|
|
const overlay = getOverlay(comfyPage.page)
|
|
await expect(overlay).toBeVisible()
|
|
|
|
await overlay.getByTestId(TestIds.dialogs.errorOverlayDismiss).click()
|
|
|
|
await expect(overlay).not.toBeVisible()
|
|
await expect(
|
|
comfyPage.page.getByTestId('properties-panel')
|
|
).not.toBeVisible()
|
|
})
|
|
|
|
test('Close button (X) dismisses overlay', async ({ comfyPage }) => {
|
|
await triggerExecutionError(comfyPage)
|
|
|
|
const overlay = getOverlay(comfyPage.page)
|
|
await expect(overlay).toBeVisible()
|
|
|
|
await overlay.getByRole('button', { name: /close/i }).click()
|
|
|
|
await expect(overlay).not.toBeVisible()
|
|
})
|
|
})
|
|
})
|