1
- import { Locator , Page } from '@playwright/test'
1
+ import { Locator , Page , expect } from '@playwright/test'
2
2
3
3
export class Topbar {
4
- constructor ( public readonly page : Page ) { }
4
+ private readonly menuLocator : Locator
5
+ private readonly menuTrigger : Locator
6
+
7
+ constructor ( public readonly page : Page ) {
8
+ this . menuLocator = page . locator ( '.comfy-command-menu' )
9
+ this . menuTrigger = page . locator ( '.comfyui-logo-wrapper' )
10
+ }
5
11
6
12
async getTabNames ( ) : Promise < string [ ] > {
7
13
return await this . page
@@ -15,10 +21,33 @@ export class Topbar {
15
21
. innerText ( )
16
22
}
17
23
18
- getMenuItem ( itemLabel : string ) : Locator {
24
+ /**
25
+ * Get a menu item by its label, optionally within a specific parent container
26
+ */
27
+ getMenuItem ( itemLabel : string , parent ?: Locator ) : Locator {
28
+ if ( parent ) {
29
+ return parent . locator ( `.p-tieredmenu-item:has-text("${ itemLabel } ")` )
30
+ }
31
+
19
32
return this . page . locator ( `.p-menubar-item-label:text-is("${ itemLabel } ")` )
20
33
}
21
34
35
+ /**
36
+ * Get the visible submenu (last visible submenu in case of nested menus)
37
+ */
38
+ getVisibleSubmenu ( ) : Locator {
39
+ return this . page . locator ( '.p-tieredmenu-submenu:visible' ) . last ( )
40
+ }
41
+
42
+ /**
43
+ * Check if a menu item has an active checkmark
44
+ */
45
+ async isMenuItemActive ( menuItem : Locator ) : Promise < boolean > {
46
+ const checkmark = menuItem . locator ( '.pi-check' )
47
+ const classes = await checkmark . getAttribute ( 'class' )
48
+ return classes ? ! classes . includes ( 'invisible' ) : false
49
+ }
50
+
22
51
getWorkflowTab ( tabName : string ) : Locator {
23
52
return this . page
24
53
. locator ( `.workflow-tabs .workflow-label:has-text("${ tabName } ")` )
@@ -66,10 +95,50 @@ export class Topbar {
66
95
67
96
async openTopbarMenu ( ) {
68
97
await this . page . waitForTimeout ( 1000 )
69
- await this . page . locator ( '.comfyui-logo-wrapper' ) . click ( )
70
- const menu = this . page . locator ( '.comfy-command-menu' )
71
- await menu . waitFor ( { state : 'visible' } )
72
- return menu
98
+ await this . menuTrigger . click ( )
99
+ await this . menuLocator . waitFor ( { state : 'visible' } )
100
+ return this . menuLocator
101
+ }
102
+
103
+ /**
104
+ * Close the topbar menu by clicking outside
105
+ */
106
+ async closeTopbarMenu ( ) {
107
+ await this . page . locator ( 'body' ) . click ( { position : { x : 10 , y : 10 } } )
108
+ await expect ( this . menuLocator ) . not . toBeVisible ( )
109
+ }
110
+
111
+ /**
112
+ * Navigate to a submenu by hovering over a menu item
113
+ */
114
+ async openSubmenu ( menuItemLabel : string ) : Promise < Locator > {
115
+ const menuItem = this . getMenuItem ( menuItemLabel )
116
+ await menuItem . hover ( )
117
+ const submenu = this . getVisibleSubmenu ( )
118
+ await submenu . waitFor ( { state : 'visible' } )
119
+ return submenu
120
+ }
121
+
122
+ /**
123
+ * Get theme menu items and interact with theme switching
124
+ */
125
+ async getThemeMenuItems ( ) {
126
+ const themeSubmenu = await this . openSubmenu ( 'Theme' )
127
+ return {
128
+ submenu : themeSubmenu ,
129
+ darkTheme : this . getMenuItem ( 'Dark (Default)' , themeSubmenu ) ,
130
+ lightTheme : this . getMenuItem ( 'Light' , themeSubmenu )
131
+ }
132
+ }
133
+
134
+ /**
135
+ * Switch to a specific theme
136
+ */
137
+ async switchTheme ( theme : 'dark' | 'light' ) {
138
+ const { darkTheme, lightTheme } = await this . getThemeMenuItems ( )
139
+ const themeItem = theme === 'dark' ? darkTheme : lightTheme
140
+ const themeLabel = themeItem . locator ( '.p-menubar-item-label' )
141
+ await themeLabel . click ( )
73
142
}
74
143
75
144
async triggerTopbarCommand ( path : string [ ] ) {
@@ -79,9 +148,7 @@ export class Topbar {
79
148
80
149
const menu = await this . openTopbarMenu ( )
81
150
const tabName = path [ 0 ]
82
- const topLevelMenuItem = this . page . locator (
83
- `.p-menubar-item-label:text-is("${ tabName } ")`
84
- )
151
+ const topLevelMenuItem = this . getMenuItem ( tabName )
85
152
const topLevelMenu = menu
86
153
. locator ( '.p-tieredmenu-item' )
87
154
. filter ( { has : topLevelMenuItem } )
0 commit comments