@@ -4,6 +4,17 @@ import os from "node:os"
44import path from "node:path"
55import { execSync } from "node:child_process"
66import { modKey , serverUrl } from "./utils"
7+ import {
8+ sessionItemSelector ,
9+ dropdownMenuTriggerSelector ,
10+ dropdownMenuContentSelector ,
11+ titlebarRightSelector ,
12+ popoverBodySelector ,
13+ listItemSelector ,
14+ listItemKeySelector ,
15+ listItemKeyStartsWithSelector ,
16+ } from "./selectors"
17+ import type { createSdk } from "./utils"
718
819export async function defocus ( page : Page ) {
920 await page . mouse . click ( 5 , 5 )
@@ -158,3 +169,103 @@ export function sessionIDFromUrl(url: string) {
158169 const match = / \/ s e s s i o n \/ ( [ ^ / ? # ] + ) / . exec ( url )
159170 return match ?. [ 1 ]
160171}
172+
173+ export async function hoverSessionItem ( page : Page , sessionID : string ) {
174+ const sessionEl = page . locator ( sessionItemSelector ( sessionID ) ) . first ( )
175+ await expect ( sessionEl ) . toBeVisible ( )
176+ await sessionEl . hover ( )
177+ return sessionEl
178+ }
179+
180+ export async function openSessionMoreMenu ( page : Page , sessionID : string ) {
181+ const sessionEl = await hoverSessionItem ( page , sessionID )
182+
183+ const menuTrigger = sessionEl . locator ( dropdownMenuTriggerSelector ) . first ( )
184+ await expect ( menuTrigger ) . toBeVisible ( )
185+ await menuTrigger . click ( )
186+
187+ const menu = page . locator ( dropdownMenuContentSelector ) . first ( )
188+ await expect ( menu ) . toBeVisible ( )
189+ return menu
190+ }
191+
192+ export async function clickMenuItem ( menu : Locator , itemName : string | RegExp , options ?: { force ?: boolean } ) {
193+ const item = menu . getByRole ( "menuitem" ) . filter ( { hasText : itemName } ) . first ( )
194+ await expect ( item ) . toBeVisible ( )
195+ await item . click ( { force : options ?. force } )
196+ }
197+
198+ export async function confirmDialog ( page : Page , buttonName : string | RegExp ) {
199+ const dialog = page . getByRole ( "dialog" ) . first ( )
200+ await expect ( dialog ) . toBeVisible ( )
201+
202+ const button = dialog . getByRole ( "button" ) . filter ( { hasText : buttonName } ) . first ( )
203+ await expect ( button ) . toBeVisible ( )
204+ await button . click ( )
205+ }
206+
207+ export async function openSharePopover ( page : Page ) {
208+ const rightSection = page . locator ( titlebarRightSelector )
209+ const shareButton = rightSection . getByRole ( "button" , { name : "Share" } ) . first ( )
210+ await expect ( shareButton ) . toBeVisible ( )
211+
212+ const popoverBody = page
213+ . locator ( popoverBodySelector )
214+ . filter ( { has : page . getByRole ( "button" , { name : / ^ ( P u b l i s h | U n p u b l i s h ) $ / } ) } )
215+ . first ( )
216+
217+ const opened = await popoverBody
218+ . isVisible ( )
219+ . then ( ( x ) => x )
220+ . catch ( ( ) => false )
221+
222+ if ( ! opened ) {
223+ await shareButton . click ( )
224+ await expect ( popoverBody ) . toBeVisible ( )
225+ }
226+ return { rightSection, popoverBody }
227+ }
228+
229+ export async function clickPopoverButton ( page : Page , buttonName : string | RegExp ) {
230+ const button = page . getByRole ( "button" ) . filter ( { hasText : buttonName } ) . first ( )
231+ await expect ( button ) . toBeVisible ( )
232+ await button . click ( )
233+ }
234+
235+ export async function clickListItem (
236+ container : Locator | Page ,
237+ filter : string | RegExp | { key ?: string ; text ?: string | RegExp ; keyStartsWith ?: string } ,
238+ ) : Promise < Locator > {
239+ let item : Locator
240+
241+ if ( typeof filter === "string" || filter instanceof RegExp ) {
242+ item = container . locator ( listItemSelector ) . filter ( { hasText : filter } ) . first ( )
243+ } else if ( filter . keyStartsWith ) {
244+ item = container . locator ( listItemKeyStartsWithSelector ( filter . keyStartsWith ) ) . first ( )
245+ } else if ( filter . key ) {
246+ item = container . locator ( listItemKeySelector ( filter . key ) ) . first ( )
247+ } else if ( filter . text ) {
248+ item = container . locator ( listItemSelector ) . filter ( { hasText : filter . text } ) . first ( )
249+ } else {
250+ throw new Error ( "Invalid filter provided to clickListItem" )
251+ }
252+
253+ await expect ( item ) . toBeVisible ( )
254+ await item . click ( )
255+ return item
256+ }
257+
258+ export async function withSession < T > (
259+ sdk : ReturnType < typeof createSdk > ,
260+ title : string ,
261+ callback : ( session : { id : string ; title : string } ) => Promise < T > ,
262+ ) : Promise < T > {
263+ const session = await sdk . session . create ( { title } ) . then ( ( r ) => r . data )
264+ if ( ! session ?. id ) throw new Error ( "Session create did not return an id" )
265+
266+ try {
267+ return await callback ( session )
268+ } finally {
269+ await sdk . session . delete ( { sessionID : session . id } ) . catch ( ( ) => undefined )
270+ }
271+ }
0 commit comments