diff --git a/browser_tests/fixtures/ComfyPage.ts b/browser_tests/fixtures/ComfyPage.ts index 1660231138..f3942d415c 100644 --- a/browser_tests/fixtures/ComfyPage.ts +++ b/browser_tests/fixtures/ComfyPage.ts @@ -11,6 +11,7 @@ import { VueNodeHelpers } from './VueNodeHelpers' import { ComfyNodeSearchBox } from './components/ComfyNodeSearchBox' import { ContextMenu } from './components/ContextMenu' import { SettingDialog } from './components/SettingDialog' +import { BottomPanel } from './components/BottomPanel' import { NodeLibrarySidebarTab, WorkflowsSidebarTab @@ -177,6 +178,7 @@ export class ComfyPage { public readonly toast: ToastHelper public readonly dragDrop: DragDropHelper public readonly command: CommandHelper + public readonly bottomPanel: BottomPanel /** Worker index to test user ID */ public readonly userIds: string[] = [] @@ -223,6 +225,7 @@ export class ComfyPage { this.toast = new ToastHelper(page) this.dragDrop = new DragDropHelper(page, this.assetPath.bind(this)) this.command = new CommandHelper(page) + this.bottomPanel = new BottomPanel(page) } get visibleToasts() { diff --git a/browser_tests/fixtures/components/BottomPanel.ts b/browser_tests/fixtures/components/BottomPanel.ts new file mode 100644 index 0000000000..85ef2694ab --- /dev/null +++ b/browser_tests/fixtures/components/BottomPanel.ts @@ -0,0 +1,35 @@ +import type { Locator, Page } from '@playwright/test' + +class ShortcutsTab { + readonly essentialsTab: Locator + readonly viewControlsTab: Locator + readonly manageButton: Locator + readonly keyBadges: Locator + readonly subcategoryTitles: Locator + + constructor(readonly page: Page) { + this.essentialsTab = page.getByRole('tab', { name: /Essential/i }) + this.viewControlsTab = page.getByRole('tab', { name: /View Controls/i }) + this.manageButton = page.getByRole('button', { name: /Manage Shortcuts/i }) + this.keyBadges = page.locator('.key-badge') + this.subcategoryTitles = page.locator('.subcategory-title') + } +} + +export class BottomPanel { + readonly root: Locator + readonly keyboardShortcutsButton: Locator + readonly toggleButton: Locator + readonly shortcuts: ShortcutsTab + + constructor(readonly page: Page) { + this.root = page.locator('.bottom-panel') + this.keyboardShortcutsButton = page.getByRole('button', { + name: /Keyboard Shortcuts/i + }) + this.toggleButton = page.getByRole('button', { + name: /Toggle Bottom Panel/i + }) + this.shortcuts = new ShortcutsTab(page) + } +} diff --git a/browser_tests/tests/bottomPanelShortcuts.spec.ts b/browser_tests/tests/bottomPanelShortcuts.spec.ts index d89de7c613..1a1e4ce79e 100644 --- a/browser_tests/tests/bottomPanelShortcuts.spec.ts +++ b/browser_tests/tests/bottomPanelShortcuts.spec.ts @@ -8,49 +8,29 @@ test.describe('Bottom Panel Shortcuts', { tag: '@ui' }, () => { }) test('should toggle shortcuts panel visibility', async ({ comfyPage }) => { - // Initially shortcuts panel should be hidden - await expect(comfyPage.page.locator('.bottom-panel')).not.toBeVisible() + const { bottomPanel } = comfyPage - // Click shortcuts toggle button in sidebar - await comfyPage.page - .getByRole('button', { name: /Keyboard Shortcuts/i }) - .click() - - // Shortcuts panel should now be visible - await expect(comfyPage.page.locator('.bottom-panel')).toBeVisible() - - // Click toggle button again to hide - await comfyPage.page - .getByRole('button', { name: /Keyboard Shortcuts/i }) - .click() - - // Panel should be hidden again - await expect(comfyPage.page.locator('.bottom-panel')).not.toBeVisible() + await expect(bottomPanel.root).not.toBeVisible() + await bottomPanel.keyboardShortcutsButton.click() + await expect(bottomPanel.root).toBeVisible() + await bottomPanel.keyboardShortcutsButton.click() + await expect(bottomPanel.root).not.toBeVisible() }) test('should display essentials shortcuts tab', async ({ comfyPage }) => { - // Open shortcuts panel - await comfyPage.page - .getByRole('button', { name: /Keyboard Shortcuts/i }) - .click() + const { bottomPanel } = comfyPage - // Essentials tab should be visible and active by default - await expect( - comfyPage.page.getByRole('tab', { name: /Essential/i }) - ).toBeVisible() - await expect( - comfyPage.page.getByRole('tab', { name: /Essential/i }) - ).toHaveAttribute('aria-selected', 'true') + await bottomPanel.keyboardShortcutsButton.click() - // Should display shortcut categories - await expect( - comfyPage.page.locator('.subcategory-title').first() - ).toBeVisible() + await expect(bottomPanel.shortcuts.essentialsTab).toBeVisible() + await expect(bottomPanel.shortcuts.essentialsTab).toHaveAttribute( + 'aria-selected', + 'true' + ) - // Should display some keyboard shortcuts - await expect(comfyPage.page.locator('.key-badge').first()).toBeVisible() + await expect(bottomPanel.shortcuts.subcategoryTitles.first()).toBeVisible() + await expect(bottomPanel.shortcuts.keyBadges.first()).toBeVisible() - // Should have workflow, node, and queue sections await expect( comfyPage.page.getByRole('heading', { name: 'Workflow' }) ).toBeVisible() @@ -63,23 +43,18 @@ test.describe('Bottom Panel Shortcuts', { tag: '@ui' }, () => { }) test('should display view controls shortcuts tab', async ({ comfyPage }) => { - // Open shortcuts panel - await comfyPage.page - .getByRole('button', { name: /Keyboard Shortcuts/i }) - .click() + const { bottomPanel } = comfyPage - // Click view controls tab - await comfyPage.page.getByRole('tab', { name: /View Controls/i }).click() + await bottomPanel.keyboardShortcutsButton.click() + await bottomPanel.shortcuts.viewControlsTab.click() - // View controls tab should be active - await expect( - comfyPage.page.getByRole('tab', { name: /View Controls/i }) - ).toHaveAttribute('aria-selected', 'true') + await expect(bottomPanel.shortcuts.viewControlsTab).toHaveAttribute( + 'aria-selected', + 'true' + ) - // Should display view controls shortcuts - await expect(comfyPage.page.locator('.key-badge').first()).toBeVisible() + await expect(bottomPanel.shortcuts.keyBadges.first()).toBeVisible() - // Should have view and panel controls sections await expect( comfyPage.page.getByRole('heading', { name: 'View' }) ).toBeVisible() @@ -89,54 +64,48 @@ test.describe('Bottom Panel Shortcuts', { tag: '@ui' }, () => { }) test('should switch between shortcuts tabs', async ({ comfyPage }) => { - // Open shortcuts panel - await comfyPage.page - .getByRole('button', { name: /Keyboard Shortcuts/i }) - .click() + const { bottomPanel } = comfyPage - // Essentials should be active initially - await expect( - comfyPage.page.getByRole('tab', { name: /Essential/i }) - ).toHaveAttribute('aria-selected', 'true') + await bottomPanel.keyboardShortcutsButton.click() - // Click view controls tab - await comfyPage.page.getByRole('tab', { name: /View Controls/i }).click() + await expect(bottomPanel.shortcuts.essentialsTab).toHaveAttribute( + 'aria-selected', + 'true' + ) - // View controls should now be active - await expect( - comfyPage.page.getByRole('tab', { name: /View Controls/i }) - ).toHaveAttribute('aria-selected', 'true') - await expect( - comfyPage.page.getByRole('tab', { name: /Essential/i }) - ).not.toHaveAttribute('aria-selected', 'true') + await bottomPanel.shortcuts.viewControlsTab.click() - // Switch back to essentials - await comfyPage.page.getByRole('tab', { name: /Essential/i }).click() + await expect(bottomPanel.shortcuts.viewControlsTab).toHaveAttribute( + 'aria-selected', + 'true' + ) + await expect(bottomPanel.shortcuts.essentialsTab).not.toHaveAttribute( + 'aria-selected', + 'true' + ) - // Essentials should be active again - await expect( - comfyPage.page.getByRole('tab', { name: /Essential/i }) - ).toHaveAttribute('aria-selected', 'true') - await expect( - comfyPage.page.getByRole('tab', { name: /View Controls/i }) - ).not.toHaveAttribute('aria-selected', 'true') + await bottomPanel.shortcuts.essentialsTab.click() + + await expect(bottomPanel.shortcuts.essentialsTab).toHaveAttribute( + 'aria-selected', + 'true' + ) + await expect(bottomPanel.shortcuts.viewControlsTab).not.toHaveAttribute( + 'aria-selected', + 'true' + ) }) test('should display formatted keyboard shortcuts', async ({ comfyPage }) => { - // Open shortcuts panel - await comfyPage.page - .getByRole('button', { name: /Keyboard Shortcuts/i }) - .click() + const { bottomPanel } = comfyPage - // Wait for shortcuts to load + await bottomPanel.keyboardShortcutsButton.click() await comfyPage.page.waitForSelector('.key-badge') - // Check for common formatted keys - const keyBadges = comfyPage.page.locator('.key-badge') + const keyBadges = bottomPanel.shortcuts.keyBadges const count = await keyBadges.count() expect(count).toBeGreaterThanOrEqual(1) - // Should show formatted modifier keys const badgeText = await keyBadges.allTextContents() const hasModifiers = badgeText.some((text) => ['Ctrl', 'Cmd', 'Shift', 'Alt'].includes(text) @@ -147,88 +116,60 @@ test.describe('Bottom Panel Shortcuts', { tag: '@ui' }, () => { test('should maintain panel state when switching to terminal', async ({ comfyPage }) => { - // Open shortcuts panel first - await comfyPage.page - .getByRole('button', { name: /Keyboard Shortcuts/i }) - .click() - await expect(comfyPage.page.locator('.bottom-panel')).toBeVisible() + const { bottomPanel } = comfyPage - // Open terminal panel (should switch panels) - await comfyPage.page - .getByRole('button', { name: /Toggle Bottom Panel/i }) - .click() + await bottomPanel.keyboardShortcutsButton.click() + await expect(bottomPanel.root).toBeVisible() - // Panel should still be visible but showing terminal content - await expect(comfyPage.page.locator('.bottom-panel')).toBeVisible() + await bottomPanel.toggleButton.click() + await expect(bottomPanel.root).toBeVisible() - // Switch back to shortcuts - await comfyPage.page - .getByRole('button', { name: /Keyboard Shortcuts/i }) - .click() - - // Should show shortcuts content again + await bottomPanel.keyboardShortcutsButton.click() await expect( comfyPage.page.locator('[id*="tab_shortcuts-essentials"]') ).toBeVisible() }) test('should handle keyboard navigation', async ({ comfyPage }) => { - // Open shortcuts panel - await comfyPage.page - .getByRole('button', { name: /Keyboard Shortcuts/i }) - .click() + const { bottomPanel } = comfyPage - // Focus the first tab - await comfyPage.page.getByRole('tab', { name: /Essential/i }).focus() + await bottomPanel.keyboardShortcutsButton.click() + await bottomPanel.shortcuts.essentialsTab.focus() - // Use arrow keys to navigate between tabs await comfyPage.page.keyboard.press('ArrowRight') - // View controls tab should now have focus - await expect( - comfyPage.page.getByRole('tab', { name: /View Controls/i }) - ).toBeFocused() + await expect(bottomPanel.shortcuts.viewControlsTab).toBeFocused() - // Press Enter to activate the tab await comfyPage.page.keyboard.press('Enter') - // Tab should be selected - await expect( - comfyPage.page.getByRole('tab', { name: /View Controls/i }) - ).toHaveAttribute('aria-selected', 'true') + await expect(bottomPanel.shortcuts.viewControlsTab).toHaveAttribute( + 'aria-selected', + 'true' + ) }) test('should close panel by clicking shortcuts button again', async ({ comfyPage }) => { - // Open shortcuts panel - await comfyPage.page - .getByRole('button', { name: /Keyboard Shortcuts/i }) - .click() - await expect(comfyPage.page.locator('.bottom-panel')).toBeVisible() + const { bottomPanel } = comfyPage - // Click shortcuts button again to close - await comfyPage.page - .getByRole('button', { name: /Keyboard Shortcuts/i }) - .click() + await bottomPanel.keyboardShortcutsButton.click() + await expect(bottomPanel.root).toBeVisible() - // Panel should be hidden - await expect(comfyPage.page.locator('.bottom-panel')).not.toBeVisible() + await bottomPanel.keyboardShortcutsButton.click() + await expect(bottomPanel.root).not.toBeVisible() }) test('should display shortcuts in organized columns', async ({ comfyPage }) => { - // Open shortcuts panel - await comfyPage.page - .getByRole('button', { name: /Keyboard Shortcuts/i }) - .click() + const { bottomPanel } = comfyPage + + await bottomPanel.keyboardShortcutsButton.click() - // Should have 3-column grid layout await expect(comfyPage.page.locator('.md\\:grid-cols-3')).toBeVisible() - // Should have multiple subcategory sections - const subcategoryTitles = comfyPage.page.locator('.subcategory-title') + const subcategoryTitles = bottomPanel.shortcuts.subcategoryTitles const titleCount = await subcategoryTitles.count() expect(titleCount).toBeGreaterThanOrEqual(2) }) @@ -236,43 +177,30 @@ test.describe('Bottom Panel Shortcuts', { tag: '@ui' }, () => { test('should open shortcuts panel with Ctrl+Shift+K', async ({ comfyPage }) => { - // Initially shortcuts panel should be hidden - await expect(comfyPage.page.locator('.bottom-panel')).not.toBeVisible() + const { bottomPanel } = comfyPage + + await expect(bottomPanel.root).not.toBeVisible() - // Press Ctrl+Shift+K to open shortcuts panel await comfyPage.page.keyboard.press('Control+Shift+KeyK') - // Shortcuts panel should now be visible - await expect(comfyPage.page.locator('.bottom-panel')).toBeVisible() - - // Should show essentials tab by default - await expect( - comfyPage.page.getByRole('tab', { name: /Essential/i }) - ).toHaveAttribute('aria-selected', 'true') + await expect(bottomPanel.root).toBeVisible() + await expect(bottomPanel.shortcuts.essentialsTab).toHaveAttribute( + 'aria-selected', + 'true' + ) }) test('should open settings dialog when clicking manage shortcuts button', async ({ comfyPage }) => { - // Open shortcuts panel - await comfyPage.page - .getByRole('button', { name: /Keyboard Shortcuts/i }) - .click() + const { bottomPanel } = comfyPage - // Manage shortcuts button should be visible - await expect( - comfyPage.page.getByRole('button', { name: /Manage Shortcuts/i }) - ).toBeVisible() + await bottomPanel.keyboardShortcutsButton.click() - // Click manage shortcuts button - await comfyPage.page - .getByRole('button', { name: /Manage Shortcuts/i }) - .click() + await expect(bottomPanel.shortcuts.manageButton).toBeVisible() + await bottomPanel.shortcuts.manageButton.click() - // Settings dialog should open with keybinding tab await expect(comfyPage.page.getByRole('dialog')).toBeVisible() - - // Should show keybinding settings (check for keybinding-related content) await expect( comfyPage.page.getByRole('option', { name: 'Keybinding' }) ).toBeVisible() diff --git a/browser_tests/tests/menu.spec.ts b/browser_tests/tests/menu.spec.ts index ae74784aaa..a17ddeab61 100644 --- a/browser_tests/tests/menu.spec.ts +++ b/browser_tests/tests/menu.spec.ts @@ -101,8 +101,8 @@ test.describe('Menu', { tag: '@ui' }, () => { const checkmark = bottomPanelMenuItem.locator('.pi-check') // Check initial state of bottom panel (it's initially hidden) - const bottomPanel = comfyPage.page.locator('.bottom-panel') - await expect(bottomPanel).not.toBeVisible() + const { bottomPanel } = comfyPage + await expect(bottomPanel.root).not.toBeVisible() // Checkmark should be invisible initially (panel is hidden) await expect(checkmark).toHaveClass(/invisible/) @@ -115,7 +115,7 @@ test.describe('Menu', { tag: '@ui' }, () => { await expect(viewSubmenu).toBeVisible() // Verify bottom panel is now visible - await expect(bottomPanel).toBeVisible() + await expect(bottomPanel.root).toBeVisible() // Checkmark should now be visible (panel is shown) await expect(checkmark).not.toHaveClass(/invisible/) @@ -128,7 +128,7 @@ test.describe('Menu', { tag: '@ui' }, () => { await expect(viewSubmenu).toBeVisible() // Verify bottom panel is hidden again - await expect(bottomPanel).not.toBeVisible() + await expect(bottomPanel.root).not.toBeVisible() // Checkmark should be invisible again (panel is hidden) await expect(checkmark).toHaveClass(/invisible/)