Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion browser_tests/fixtures/components/SidebarTab.ts
Original file line number Diff line number Diff line change
Expand Up @@ -384,11 +384,14 @@ export class AssetsSidebarTab extends SidebarTab {
return this.page.locator('.p-contextmenu').getByText(label)
}

override async open() {
override async open({ waitForAssets = true } = {}) {
// Remove any toast notifications that may overlay the sidebar button
await this.dismissToasts()
await super.open()
await this.generatedTab.waitFor({ state: 'visible' })
if (waitForAssets) {
await this.waitForAssets()
}
}

/** Dismiss all visible toast notifications by clicking their close buttons. */
Expand Down
6 changes: 6 additions & 0 deletions browser_tests/fixtures/helpers/ToastHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@ import type { Locator, Page } from '@playwright/test'
export class ToastHelper {
public readonly visibleToasts: Locator
public readonly toastErrors: Locator
public readonly toastSuccesses: Locator
public readonly toastWarnings: Locator

constructor(private readonly page: Page) {
this.visibleToasts = page.locator('.p-toast-message:visible')
this.toastErrors = page.locator('.p-toast-message.p-toast-message-error')
this.toastSuccesses = page.locator(
'.p-toast-message.p-toast-message-success'
)
this.toastWarnings = page.locator('.p-toast-message.p-toast-message-warn')
}

async closeToasts(requireCount = 0): Promise<void> {
Expand Down
117 changes: 84 additions & 33 deletions browser_tests/tests/sidebar/assets.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,19 @@ const JOB_GAMMA_DETAIL: JobDetail = {
}
]
}
},
workflow: {
extra_data: {
extra_pnginfo: {
workflow: {
version: 0.4,
last_node_id: 0,
last_link_id: 0,
nodes: [],
links: []
}
}
}
}
}

Expand Down Expand Up @@ -112,15 +125,15 @@ test.describe('Assets sidebar - empty states', () => {

test('Shows empty-state copy for generated tab', async ({ comfyPage }) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.open({ waitForAssets: false })

await expect(tab.emptyStateTitle('No generated files found')).toBeVisible()
await expect(tab.emptyStateMessage).toBeVisible()
})

test('Shows empty-state copy for imported tab', async ({ comfyPage }) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.open({ waitForAssets: false })
await tab.switchToImported()

await expect(tab.emptyStateTitle('No imported files found')).toBeVisible()
Expand All @@ -129,7 +142,7 @@ test.describe('Assets sidebar - empty states', () => {

test('No asset cards are rendered when empty', async ({ comfyPage }) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.open({ waitForAssets: false })

await expect(tab.assetCards).toHaveCount(0)
})
Expand Down Expand Up @@ -209,7 +222,6 @@ test.describe('Assets sidebar - grid view display', () => {
const tab = comfyPage.menu.assetsTab
await tab.open()

await tab.waitForAssets()
await expect.poll(() => tab.assetCards.count()).toBeGreaterThanOrEqual(1)
})

Expand Down Expand Up @@ -270,7 +282,6 @@ test.describe('Assets sidebar - view mode toggle', () => {
test('Can switch to list view via settings menu', async ({ comfyPage }) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

// Open settings menu and select list view
await tab.openSettingsMenu()
Expand All @@ -283,7 +294,6 @@ test.describe('Assets sidebar - view mode toggle', () => {
test('Can switch back to grid view', async ({ comfyPage }) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

// Switch to list view
await tab.openSettingsMenu()
Expand Down Expand Up @@ -326,7 +336,6 @@ test.describe('Assets sidebar - search', () => {
}) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

const initialCount = await tab.assetCards.count()

Expand All @@ -340,7 +349,6 @@ test.describe('Assets sidebar - search', () => {
test('Clearing search restores all assets', async ({ comfyPage }) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

const initialCount = await tab.assetCards.count()

Expand All @@ -355,7 +363,6 @@ test.describe('Assets sidebar - search', () => {
test('Search with no matches shows empty state', async ({ comfyPage }) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

await tab.searchInput.fill('nonexistent_file_xyz')
await expect(tab.assetCards).toHaveCount(0)
Expand All @@ -380,7 +387,6 @@ test.describe('Assets sidebar - selection', () => {
test('Clicking an asset card selects it', async ({ comfyPage }) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

// Click first asset card
await tab.assetCards.first().click()
Expand All @@ -392,7 +398,6 @@ test.describe('Assets sidebar - selection', () => {
test('Ctrl+click adds to selection', async ({ comfyPage }) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

const cards = tab.assetCards
await expect.poll(() => cards.count()).toBeGreaterThanOrEqual(2)
Expand All @@ -411,7 +416,6 @@ test.describe('Assets sidebar - selection', () => {
}) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

// Select an asset
await tab.assetCards.first().click()
Expand All @@ -423,7 +427,6 @@ test.describe('Assets sidebar - selection', () => {
test('Deselect all clears selection', async ({ comfyPage }) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

// Select an asset
await tab.assetCards.first().click()
Expand All @@ -441,7 +444,6 @@ test.describe('Assets sidebar - selection', () => {
test('Selection is cleared when switching tabs', async ({ comfyPage }) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

// Select an asset
await tab.assetCards.first().click()
Expand Down Expand Up @@ -475,7 +477,6 @@ test.describe('Assets sidebar - context menu', () => {
test('Right-clicking an asset shows context menu', async ({ comfyPage }) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

// Right-click first asset
await tab.assetCards.first().click({ button: 'right' })
Expand All @@ -490,7 +491,6 @@ test.describe('Assets sidebar - context menu', () => {
}) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

await tab.assetCards.first().click({ button: 'right' })
await comfyPage.page
Expand All @@ -505,7 +505,6 @@ test.describe('Assets sidebar - context menu', () => {
}) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

await tab.assetCards.first().click({ button: 'right' })
await comfyPage.page
Expand All @@ -520,7 +519,6 @@ test.describe('Assets sidebar - context menu', () => {
}) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

await tab.assetCards.first().click({ button: 'right' })
await comfyPage.page
Expand All @@ -535,7 +533,6 @@ test.describe('Assets sidebar - context menu', () => {
}) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

await tab.assetCards.first().click({ button: 'right' })
await comfyPage.page
Expand All @@ -550,7 +547,6 @@ test.describe('Assets sidebar - context menu', () => {
}) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

await tab.assetCards.first().click({ button: 'right' })

Expand All @@ -563,12 +559,79 @@ test.describe('Assets sidebar - context menu', () => {
await expect(tab.contextMenuItem('Export workflow')).toBeVisible()
})

test('Cancelling export-workflow filename prompt does not show an error toast', async ({
comfyPage
}) => {
// job-gamma is the first card; its detail carries a valid workflow so
// extraction succeeds and the filename prompt opens.
await comfyPage.assets.mockJobDetail('job-gamma', JOB_GAMMA_DETAIL)

const tab = comfyPage.menu.assetsTab
await tab.open()

await tab.assetCards.first().click({ button: 'right' })
await tab.contextMenuItem('Export workflow').click()

const promptDialog = comfyPage.page.getByRole('dialog', {
name: 'Export Workflow'
})
await expect(promptDialog).toBeVisible()

await comfyPage.page.keyboard.press('Escape')
await expect(promptDialog).toBeHidden()

await expect(comfyPage.toast.toastErrors).toBeHidden({ timeout: 1500 })
})

test('Confirming export-workflow prompt downloads the file and shows a success toast', async ({
comfyPage
}) => {
await comfyPage.assets.mockJobDetail('job-gamma', JOB_GAMMA_DETAIL)

const tab = comfyPage.menu.assetsTab
await tab.open()

await tab.assetCards.first().click({ button: 'right' })
await tab.contextMenuItem('Export workflow').click()

const promptDialog = comfyPage.page.getByRole('dialog', {
name: 'Export Workflow'
})
await expect(promptDialog).toBeVisible()

const downloadPromise = comfyPage.page.waitForEvent('download')
await promptDialog.getByRole('button', { name: 'Confirm' }).click()

const download = await downloadPromise
expect(download.suggestedFilename()).toBe('abstract_art.json')

await expect(comfyPage.toast.toastSuccesses).toBeVisible()
})

test('Export-workflow shows a warning toast when the asset has no workflow', async ({
comfyPage
}) => {
// Strip the workflow field so extraction yields null and the export
// action returns { success: false, error: 'No workflow…' }.
const { workflow: _, ...detailWithoutWorkflow } = JOB_GAMMA_DETAIL
await comfyPage.assets.mockJobDetail('job-gamma', detailWithoutWorkflow)

const tab = comfyPage.menu.assetsTab
await tab.open()

await tab.assetCards.first().click({ button: 'right' })
await tab.contextMenuItem('Export workflow').click()

// Filename prompt should be skipped: extraction fails before the prompt.
await expect(comfyPage.toast.toastWarnings).toBeVisible()
await expect(comfyPage.toast.toastSuccesses).toBeHidden({ timeout: 1500 })
})

test('Bulk context menu shows when multiple assets selected', async ({
comfyPage
}) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

const cards = tab.assetCards
await expect.poll(() => cards.count()).toBeGreaterThanOrEqual(2)
Expand Down Expand Up @@ -623,7 +686,6 @@ test.describe('Assets sidebar - bulk actions', () => {
}) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

await tab.assetCards.first().click()

Expand All @@ -636,7 +698,6 @@ test.describe('Assets sidebar - bulk actions', () => {
}) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

await tab.assetCards.first().click()

Expand All @@ -647,7 +708,6 @@ test.describe('Assets sidebar - bulk actions', () => {
test('Selection count displays correct number', async ({ comfyPage }) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

// Select the two single-output assets (job-alpha, job-beta).
// The count reflects total outputs, not cards — job-gamma has
Expand Down Expand Up @@ -676,7 +736,6 @@ cloudTest.describe('Assets sidebar - cloud exports', { tag: '@cloud' }, () => {

const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

await tab.assetCards.first().click()
await expect(tab.downloadSelectedButton).toBeVisible()
Expand All @@ -701,7 +760,6 @@ cloudTest.describe('Assets sidebar - cloud exports', { tag: '@cloud' }, () => {

const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

await tab.assetCards
.first()
Expand Down Expand Up @@ -737,7 +795,6 @@ cloudTest.describe('Assets sidebar - cloud exports', { tag: '@cloud' }, () => {

const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

await tab.assetCards.nth(1).click()
await comfyPage.page.keyboard.down('Control')
Expand Down Expand Up @@ -784,7 +841,6 @@ test.describe('Assets sidebar - pagination', () => {

const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

const req = await firstRequest
const url = new URL(req.url())
Expand Down Expand Up @@ -840,7 +896,6 @@ test.describe('Assets sidebar - delete confirmation', () => {
}) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

await tab.assetCards.first().click({ button: 'right' })
await tab.contextMenuItem('Delete').click()
Expand All @@ -858,7 +913,6 @@ test.describe('Assets sidebar - delete confirmation', () => {
}) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

const initialCount = await tab.assetCards.count()

Expand All @@ -880,7 +934,6 @@ test.describe('Assets sidebar - delete confirmation', () => {
test('Cancelling delete preserves asset', async ({ comfyPage }) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

const initialCount = await tab.assetCards.count()

Expand Down Expand Up @@ -977,7 +1030,6 @@ test.describe('Assets sidebar - media type filter', () => {
test('Unchecking image filter hides image assets', async ({ comfyPage }) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

const initialCount = tab.assetCards
await expect(
Expand All @@ -998,7 +1050,6 @@ test.describe('Assets sidebar - media type filter', () => {
test('Re-enabling filter restores hidden assets', async ({ comfyPage }) => {
const tab = comfyPage.menu.assetsTab
await tab.open()
await tab.waitForAssets()

const initialCount = await tab.assetCards.count()

Expand Down
Loading
Loading