mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-19 22:09:37 +00:00
## Summary
Replace remaining inline `getByRole('dialog')` calls in E2E tests with
page object accessors, following the pattern from PR #10586.
**Note:** The original scope covered 9 calls across 5 files. Three of
those refactors (ConfirmDialog, MediaLightbox, TemplatesDialog) were
already merged into main via other PRs, so this PR now covers only the
remaining 3 files.
## Changes
- **ComfyNodeSearchBox.ts**: Extract a `root` locator on
`ComfyNodeSearchFilterSelectionPanel` so `header` getter uses
`this.root` instead of an inline `page.getByRole('dialog')`
- **AppModeHelper.ts**: Add `imagePickerPopover` getter that locates the
PrimeVue Popover (`role="dialog"`) filtered by a button named "All"
- **appModeDropdownClipping.spec.ts**: Replace 4-line inline
`getByRole('dialog')` chain with `comfyPage.appMode.imagePickerPopover`
## Review Focus
Pure test infrastructure refactor — no production code changes. Each
page object follows existing conventions.
Fixes #10723
101 lines
2.7 KiB
TypeScript
101 lines
2.7 KiB
TypeScript
import type { Locator, Page } from '@playwright/test'
|
|
|
|
export class ComfyNodeSearchFilterSelectionPanel {
|
|
readonly root: Locator
|
|
|
|
constructor(public readonly page: Page) {
|
|
this.root = page.getByRole('dialog')
|
|
}
|
|
|
|
get header() {
|
|
return this.root
|
|
.locator('div')
|
|
.filter({ hasText: 'Add node filter condition' })
|
|
}
|
|
|
|
async selectFilterType(filterType: string) {
|
|
await this.page
|
|
.locator(
|
|
`.filter-type-select .p-togglebutton-label:has-text("${filterType}")`
|
|
)
|
|
.click()
|
|
}
|
|
|
|
async selectFilterValue(filterValue: string) {
|
|
await this.page.locator('.filter-value-select .p-select-dropdown').click()
|
|
await this.page
|
|
.locator(
|
|
`.p-select-overlay .p-select-list .p-select-option-label:text-is("${filterValue}")`
|
|
)
|
|
.click()
|
|
}
|
|
|
|
async addFilter(filterValue: string, filterType: string) {
|
|
await this.selectFilterType(filterType)
|
|
await this.selectFilterValue(filterValue)
|
|
await this.page.getByRole('button', { name: 'Add', exact: true }).click()
|
|
}
|
|
}
|
|
|
|
export class ComfyNodeSearchBox {
|
|
public readonly input: Locator
|
|
public readonly dropdown: Locator
|
|
public readonly filterSelectionPanel: ComfyNodeSearchFilterSelectionPanel
|
|
|
|
constructor(public readonly page: Page) {
|
|
this.input = page.locator(
|
|
'.comfy-vue-node-search-container input[type="text"]'
|
|
)
|
|
this.dropdown = page.locator(
|
|
'.comfy-vue-node-search-container .p-autocomplete-list'
|
|
)
|
|
this.filterSelectionPanel = new ComfyNodeSearchFilterSelectionPanel(page)
|
|
}
|
|
|
|
get filterButton() {
|
|
return this.page.locator('.comfy-vue-node-search-container .filter-button')
|
|
}
|
|
|
|
async fillAndSelectFirstNode(
|
|
nodeName: string,
|
|
options?: { suggestionIndex?: number; exact?: boolean }
|
|
) {
|
|
await this.input.waitFor({ state: 'visible' })
|
|
await this.input.fill(nodeName)
|
|
await this.dropdown.waitFor({ state: 'visible' })
|
|
if (options?.exact) {
|
|
await this.dropdown
|
|
.locator(`li[aria-label="${nodeName}"]`)
|
|
.first()
|
|
.click()
|
|
} else {
|
|
await this.dropdown
|
|
.locator('li')
|
|
.nth(options?.suggestionIndex || 0)
|
|
.click()
|
|
}
|
|
}
|
|
|
|
async addFilter(filterValue: string, filterType: string) {
|
|
await this.filterButton.click()
|
|
await this.filterSelectionPanel.addFilter(filterValue, filterType)
|
|
}
|
|
|
|
get filterChips() {
|
|
return this.page.locator(
|
|
'.comfy-vue-node-search-container .p-autocomplete-chip-item'
|
|
)
|
|
}
|
|
|
|
async removeFilter(index: number) {
|
|
await this.filterChips.nth(index).locator('.p-chip-remove-icon').click()
|
|
}
|
|
|
|
/**
|
|
* Returns a locator for a search result containing the specified text.
|
|
*/
|
|
findResult(text: string): Locator {
|
|
return this.dropdown.locator('li').filter({ hasText: text })
|
|
}
|
|
}
|