mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-04 07:00:23 +00:00
* [feat] Add formatKeySequence function to format keybindings for commands * [feat] Add lock and unlock canvas commands with keybindings and update localization * feat: Implement canvas scale synchronization and zoom level adjustment * feat: Enhance GraphCanvasMenu with zoom controls and improved button functionality * feat: Refactor MiniMap component layout and remove unused bottomPanelStore * feat: Update zoom control shortcuts to use formatted key sequences * feat: Add tests for ZoomControlsModal and enhance GraphCanvasMenu tests * Update locales [skip ci] * Fix browser tests * ui: align minimap properly * Update locales [skip ci] * feat: focus zoom input when zoom modal loads * style: improve styling of zoom controls and add focus effect * fix styling and tests * styling: add divider to graph canvas menu * styling: position minimap properly * styling: add close button for minimap * styling: add horizontal divider to minimap * styling: update minimap toggle button text and remove old styles * Update locales [skip ci] * Update locales [skip ci] * feat: disable canvas menu in viewport settings after zoom adjustments * Update test expectations [skip ci] * fix: update canvas read-only property access to use state object * Update locales [skip ci] * fix: adjust button group and minimap positioning * feat: enhance zoom controls and adjust minimap positioning per PR comments * feat: implement zoom controls composable * feat: add timeout delays for headless tests * fix: update zoom input validation range in applyZoom function * [refactor] Update positioning and styles for GraphCanvasMenu, MiniMap, and ZoomControlsModal components * [refactor] Adjust z-index and positioning for GraphCanvasMenu, MiniMap, and ZoomControlsModal components * [style] Adjust margin for minimap button styles in GraphCanvasMenu component * [refactor] minimap should show on focus mode * [refactor] Update LiteGraphCanvasSplitterOverlay to conditionally render side and bottom panels based on focus mode * [style] Adjust right positioning for MiniMap and ZoomControlsModal components * [style] Adjust right positioning for MiniMap and ZoomControlsModal components --------- Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Christian Byrne <cbyrne@comfy.org>
113 lines
3.1 KiB
TypeScript
113 lines
3.1 KiB
TypeScript
import { Locator, Page } from '@playwright/test'
|
|
|
|
export class Topbar {
|
|
constructor(public readonly page: Page) {}
|
|
|
|
async getTabNames(): Promise<string[]> {
|
|
return await this.page
|
|
.locator('.workflow-tabs .workflow-label')
|
|
.allInnerTexts()
|
|
}
|
|
|
|
async getActiveTabName(): Promise<string> {
|
|
return this.page
|
|
.locator('.workflow-tabs .p-togglebutton-checked')
|
|
.innerText()
|
|
}
|
|
|
|
getMenuItem(itemLabel: string): Locator {
|
|
return this.page.locator(`.p-menubar-item-label:text-is("${itemLabel}")`)
|
|
}
|
|
|
|
getWorkflowTab(tabName: string): Locator {
|
|
return this.page
|
|
.locator(`.workflow-tabs .workflow-label:has-text("${tabName}")`)
|
|
.locator('..')
|
|
}
|
|
|
|
async closeWorkflowTab(tabName: string) {
|
|
const tab = this.getWorkflowTab(tabName)
|
|
await tab.locator('.close-button').click({ force: true })
|
|
}
|
|
|
|
getSaveDialog(): Locator {
|
|
return this.page.locator('.p-dialog-content input')
|
|
}
|
|
|
|
saveWorkflow(workflowName: string): Promise<void> {
|
|
return this._saveWorkflow(workflowName, 'Save')
|
|
}
|
|
|
|
saveWorkflowAs(workflowName: string): Promise<void> {
|
|
return this._saveWorkflow(workflowName, 'Save As')
|
|
}
|
|
|
|
exportWorkflow(workflowName: string): Promise<void> {
|
|
return this._saveWorkflow(workflowName, 'Export')
|
|
}
|
|
|
|
async _saveWorkflow(
|
|
workflowName: string,
|
|
command: 'Save' | 'Save As' | 'Export'
|
|
) {
|
|
await this.triggerTopbarCommand(['File', command])
|
|
await this.getSaveDialog().fill(workflowName)
|
|
await this.page.keyboard.press('Enter')
|
|
|
|
// Wait for workflow service to finish saving
|
|
await this.page.waitForFunction(
|
|
() => !window['app'].extensionManager.workflow.isBusy,
|
|
undefined,
|
|
{ timeout: 3000 }
|
|
)
|
|
// Wait for the dialog to close.
|
|
await this.getSaveDialog().waitFor({ state: 'hidden', timeout: 500 })
|
|
}
|
|
|
|
async openTopbarMenu() {
|
|
await this.page.waitForTimeout(1000)
|
|
await this.page.locator('.comfyui-logo-wrapper').click()
|
|
const menu = this.page.locator('.comfy-command-menu')
|
|
await menu.waitFor({ state: 'visible' })
|
|
return menu
|
|
}
|
|
|
|
async triggerTopbarCommand(path: string[]) {
|
|
if (path.length < 1) {
|
|
throw new Error('Path cannot be empty')
|
|
}
|
|
|
|
const menu = await this.openTopbarMenu()
|
|
const tabName = path[0]
|
|
const topLevelMenuItem = this.page.locator(
|
|
`.p-menubar-item-label:text-is("${tabName}")`
|
|
)
|
|
const topLevelMenu = menu
|
|
.locator('.p-tieredmenu-item')
|
|
.filter({ has: topLevelMenuItem })
|
|
await topLevelMenu.waitFor({ state: 'visible' })
|
|
|
|
// Handle top-level commands (like "New")
|
|
if (path.length === 1) {
|
|
await topLevelMenuItem.click()
|
|
return
|
|
}
|
|
|
|
await topLevelMenu.hover()
|
|
|
|
let currentMenu = topLevelMenu
|
|
for (let i = 1; i < path.length; i++) {
|
|
const commandName = path[i]
|
|
const menuItem = currentMenu
|
|
.locator(
|
|
`.p-tieredmenu-submenu .p-tieredmenu-item:has-text("${commandName}")`
|
|
)
|
|
.first()
|
|
await menuItem.waitFor({ state: 'visible' })
|
|
await menuItem.hover()
|
|
currentMenu = menuItem
|
|
}
|
|
await currentMenu.click()
|
|
}
|
|
}
|