mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-05-11 16:30:57 +00:00
*PR Created by the Glary-Bot Agent* --- ## Summary - Adds `browser_tests/tests/queueNotificationBanners.spec.ts` covering `useQueueNotificationBanners` composable E2E behavior - Adds `data-testid="queue-notification-banner"` to `QueueNotificationBannerHost.vue` for stable test targeting - Registers the new test ID in `TestIds.queue.notificationBanner` ### Test coverage added (7 tests) | Group | Tests | Behavior | |---|---|---| | Queuing lifecycle | 4 | `promptQueueing` → banner appears, `promptQueued` upgrades to queued, batch plural text, requestId mismatch doesn't upgrade | | Auto-dismiss | 1 | Banner disappears after 4s timeout | | FIFO queue | 1 | Second notification shows after first auto-dismisses | | Direct queued | 1 | `promptQueued` without prior `promptQueueing` shows banner directly | ### Approach Tests dispatch `promptQueueing`/`promptQueued` custom events directly via `window.app.api.dispatchCustomEvent()` inside `page.evaluate()`, matching how `app.ts` triggers these events during real queue operations. This avoids needing a running execution pipeline while exercising the full composable → component → DOM rendering chain. ### Verification - TypeScript: zero errors - ESLint: clean - oxlint: clean - oxfmt: formatted - Playwright execution requires running ComfyUI backend (not available in sandbox) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-11366-test-add-queue-notification-banners-lifecycle-browser-tests-3466d73d36508172a7ffd3fe3b4fd925) by [Unito](https://www.unito.io) --------- Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com> Co-authored-by: Amp <amp@ampcode.com>
165 lines
4.9 KiB
TypeScript
165 lines
4.9 KiB
TypeScript
import type { Page } from '@playwright/test'
|
|
import { expect } from '@playwright/test'
|
|
|
|
import { comfyPageFixture as test } from '@e2e/fixtures/ComfyPage'
|
|
import { TestIds } from '@e2e/fixtures/selectors'
|
|
|
|
// Mirrors BANNER_DISMISS_DELAY_MS in src/composables/queue/useQueueNotificationBanners.ts.
|
|
// Duplicated here to avoid pulling production source (and its litegraph
|
|
// transitive deps) into the Playwright TS loader.
|
|
const BANNER_DISMISS_DELAY_MS = 4000
|
|
const BANNER_ASSERT_TIMEOUT_MS = BANNER_DISMISS_DELAY_MS + 2000
|
|
|
|
const REQUEST_ID_PRIMARY = 1
|
|
const REQUEST_ID_SECONDARY = 2
|
|
const REQUEST_ID_MISMATCH = 999
|
|
|
|
let nextRequestId = 1000
|
|
const newRequestId = () => nextRequestId++
|
|
|
|
function bannerLocator(page: Page) {
|
|
return page.getByTestId(TestIds.queue.notificationBanner)
|
|
}
|
|
|
|
type DispatchOpts = { batchCount?: number; requestId?: number }
|
|
|
|
function dispatchPromptQueueing(page: Page, opts: DispatchOpts = {}) {
|
|
return page.evaluate(
|
|
([batchCount, requestId]) => {
|
|
window.app!.api.dispatchCustomEvent('promptQueueing', {
|
|
batchCount,
|
|
requestId
|
|
})
|
|
},
|
|
[opts.batchCount ?? 1, opts.requestId ?? newRequestId()]
|
|
)
|
|
}
|
|
|
|
function dispatchPromptQueued(page: Page, opts: DispatchOpts = {}) {
|
|
return page.evaluate(
|
|
([batchCount, requestId]) => {
|
|
window.app!.api.dispatchCustomEvent('promptQueued', {
|
|
number: 0,
|
|
batchCount,
|
|
requestId
|
|
})
|
|
},
|
|
[opts.batchCount ?? 1, opts.requestId ?? newRequestId()]
|
|
)
|
|
}
|
|
|
|
test.describe('Queue notification banners', { tag: ['@ui'] }, () => {
|
|
test.describe('Queuing lifecycle', () => {
|
|
test('promptQueueing event shows a queueing banner', async ({
|
|
comfyPage
|
|
}) => {
|
|
await dispatchPromptQueueing(comfyPage.page)
|
|
|
|
const banner = bannerLocator(comfyPage.page)
|
|
await expect(banner).toBeVisible()
|
|
await expect(banner).toContainText('queuing')
|
|
})
|
|
|
|
test('promptQueued upgrades a pending banner to queued', async ({
|
|
comfyPage
|
|
}) => {
|
|
await dispatchPromptQueueing(comfyPage.page, {
|
|
batchCount: 1,
|
|
requestId: REQUEST_ID_PRIMARY
|
|
})
|
|
|
|
const banner = bannerLocator(comfyPage.page)
|
|
await expect(banner).toContainText('queuing')
|
|
|
|
await dispatchPromptQueued(comfyPage.page, {
|
|
batchCount: 1,
|
|
requestId: REQUEST_ID_PRIMARY
|
|
})
|
|
|
|
await expect(banner).toContainText('queued')
|
|
})
|
|
|
|
test('promptQueued with batch count > 1 shows plural text', async ({
|
|
comfyPage
|
|
}) => {
|
|
await dispatchPromptQueued(comfyPage.page, { batchCount: 3 })
|
|
|
|
const banner = bannerLocator(comfyPage.page)
|
|
await expect(banner).toBeVisible()
|
|
await expect(banner).toContainText('3')
|
|
await expect(banner).toContainText('jobs added to queue')
|
|
})
|
|
|
|
test('promptQueued with mismatched requestId enqueues a separate queued banner', async ({
|
|
comfyPage
|
|
}) => {
|
|
await dispatchPromptQueueing(comfyPage.page, {
|
|
batchCount: 1,
|
|
requestId: REQUEST_ID_PRIMARY
|
|
})
|
|
|
|
const banner = bannerLocator(comfyPage.page)
|
|
await expect(banner).toContainText('queuing')
|
|
|
|
await dispatchPromptQueued(comfyPage.page, {
|
|
batchCount: 1,
|
|
requestId: REQUEST_ID_MISMATCH
|
|
})
|
|
|
|
// Pending banner is not upgraded — still shows "queuing".
|
|
await expect(banner).toContainText('queuing')
|
|
|
|
// After the pending banner auto-dismisses, the queued banner appears.
|
|
await expect(banner).toContainText('queued', {
|
|
timeout: BANNER_ASSERT_TIMEOUT_MS
|
|
})
|
|
})
|
|
})
|
|
|
|
test.describe('Auto-dismiss', () => {
|
|
test('Banner auto-dismisses after timeout', async ({ comfyPage }) => {
|
|
await dispatchPromptQueued(comfyPage.page)
|
|
|
|
const banner = bannerLocator(comfyPage.page)
|
|
await expect(banner).toBeVisible()
|
|
await expect(banner).toBeHidden({ timeout: BANNER_ASSERT_TIMEOUT_MS })
|
|
})
|
|
})
|
|
|
|
test.describe('Notification queue (FIFO)', () => {
|
|
test('Second notification shows after first auto-dismisses', async ({
|
|
comfyPage
|
|
}) => {
|
|
await dispatchPromptQueued(comfyPage.page, {
|
|
batchCount: 1,
|
|
requestId: REQUEST_ID_PRIMARY
|
|
})
|
|
await dispatchPromptQueued(comfyPage.page, {
|
|
batchCount: 2,
|
|
requestId: REQUEST_ID_SECONDARY
|
|
})
|
|
|
|
const banner = bannerLocator(comfyPage.page)
|
|
await expect(banner).toContainText('Job queued')
|
|
await expect(banner).toContainText('2 jobs added to queue', {
|
|
timeout: BANNER_ASSERT_TIMEOUT_MS
|
|
})
|
|
})
|
|
})
|
|
|
|
test.describe('Direct queued event (no pending predecessor)', () => {
|
|
test('promptQueued without prior queueing shows queued banner directly', async ({
|
|
comfyPage
|
|
}) => {
|
|
await dispatchPromptQueued(comfyPage.page, {
|
|
batchCount: 1,
|
|
requestId: REQUEST_ID_PRIMARY
|
|
})
|
|
|
|
const banner = bannerLocator(comfyPage.page)
|
|
await expect(banner).toBeVisible()
|
|
await expect(banner).toContainText('queued')
|
|
})
|
|
})
|
|
})
|