test(browser): add BaseDialog class (Phase 5.2)

Amp-Thread-ID: https://ampcode.com/threads/T-019c137b-34ba-736a-afb6-0a41baf9358f
Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
Alexander Brown
2026-01-31 01:57:43 -08:00
parent 4ffbcc7165
commit ea1d284b22
3 changed files with 49 additions and 9 deletions

View File

@@ -12,6 +12,7 @@ import { ComfyTemplates } from '../helpers/templates'
import { ComfyMouse } from './ComfyMouse'
import { VueNodeHelpers } from './VueNodeHelpers'
import { ComfyNodeSearchBox } from './components/ComfyNodeSearchBox'
import { ContextMenu } from './components/ContextMenu'
import { SettingDialog } from './components/SettingDialog'
import {
NodeLibrarySidebarTab,
@@ -184,6 +185,7 @@ export class ComfyPage {
public readonly keyboard: KeyboardHelper
public readonly clipboard: ClipboardHelper
public readonly workflow: WorkflowHelper
public readonly contextMenu: ContextMenu
/** Worker index to test user ID */
public readonly userIds: string[] = []
@@ -224,6 +226,7 @@ export class ComfyPage {
this.keyboard = new KeyboardHelper(page, this.canvas)
this.clipboard = new ClipboardHelper(page, this.canvas)
this.workflow = new WorkflowHelper(this)
this.contextMenu = new ContextMenu(page)
}
convertLeafToContent(structure: FolderStructure): FolderStructure {
@@ -736,17 +739,21 @@ export class ComfyPage {
await this.nextFrame()
}
/**
* @deprecated Use `comfyPage.contextMenu.clickMenuItem(name)` instead.
*/
async clickContextMenuItem(name: string): Promise<void> {
await this.page.getByRole('menuitem', { name }).click()
await this.contextMenu.clickMenuItem(name)
await this.nextFrame()
}
/**
* @deprecated Use `comfyPage.contextMenu.clickLitegraphMenuItem(name)` instead.
* Clicks on a litegraph context menu item (uses .litemenu-entry selector).
* Use this for canvas/node context menus, not PrimeVue menus.
*/
async clickLitegraphContextMenuItem(name: string): Promise<void> {
await this.page.locator(`.litemenu-entry:has-text("${name}")`).click()
await this.contextMenu.clickLitegraphMenuItem(name)
await this.nextFrame()
}
@@ -828,6 +835,9 @@ export class ComfyPage {
await this.nextFrame()
}
/**
* @deprecated Use dialog-specific close methods instead (e.g., settingDialog.close())
*/
async closeDialog() {
await this.page.locator('.p-dialog-close-button').click({ force: true })
await this.page.locator('.p-dialog').waitFor({ state: 'hidden' })

View File

@@ -0,0 +1,31 @@
import type { Locator, Page } from '@playwright/test'
export class BaseDialog {
readonly root: Locator
readonly closeButton: Locator
constructor(
public readonly page: Page,
testId?: string
) {
this.root = testId ? page.getByTestId(testId) : page.locator('.p-dialog')
this.closeButton = this.root.locator('.p-dialog-close-button')
}
async isVisible(): Promise<boolean> {
return this.root.isVisible()
}
async waitForVisible(): Promise<void> {
await this.root.waitFor({ state: 'visible' })
}
async waitForHidden(): Promise<void> {
await this.root.waitFor({ state: 'hidden' })
}
async close(): Promise<void> {
await this.closeButton.click({ force: true })
await this.waitForHidden()
}
}

View File

@@ -2,20 +2,19 @@ import type { Page } from '@playwright/test'
import type { ComfyPage } from '../ComfyPage'
import { TestIds } from '../selectors'
import { BaseDialog } from './BaseDialog'
export class SettingDialog {
export class SettingDialog extends BaseDialog {
constructor(
public readonly page: Page,
page: Page,
public readonly comfyPage: ComfyPage
) {}
get root() {
return this.page.getByTestId(TestIds.dialogs.settings)
) {
super(page, TestIds.dialogs.settings)
}
async open() {
await this.comfyPage.executeCommand('Comfy.ShowSettingsDialog')
await this.root.waitFor({ state: 'visible' })
await this.waitForVisible()
}
/**