import type { Locator, Page } from '@playwright/test'; export class NotificationsPage { readonly page: Page; constructor(page: Page) { this.page = page; } /** * Gets the main container locator for a notification by searching in its title text. * @param text The text or a regular expression to find within the notification's title. * @returns A Locator for the notification container element. */ getNotificationByTitle(text: string | RegExp): Locator { return this.page.getByRole('alert').filter({ has: this.page.locator('.el-notification__title').filter({ hasText: text }), }); } /** * Gets the main container locator for a notification by searching in its content/body text. * This is useful for finding notifications where the detailed message is in the content * rather than the title (e.g., error messages with detailed descriptions). * @param text The text or a regular expression to find within the notification's content. * @returns A Locator for the notification container element. */ getNotificationByContent(text: string | RegExp): Locator { return this.page.getByRole('alert').filter({ has: this.page.locator('.el-notification__content').filter({ hasText: text }), }); } /** * Gets the main container locator for a notification by searching in both title and content. * This is the most flexible method as it will find notifications regardless of whether * the text appears in the title or content section. * @param text The text or a regular expression to find within the notification's title or content. * @returns A Locator for the notification container element. */ getNotificationByTitleOrContent(text: string | RegExp): Locator { return this.page.getByRole('alert').filter({ hasText: text }); } /** * Clicks the close button on the FIRST notification matching the text. * Fast execution with short timeouts for snappy notifications. * @param text The text of the notification to close. * @param options Optional configuration */ async closeNotificationByText( text: string | RegExp, options: { timeout?: number } = {}, ): Promise { const { timeout = 2000 } = options; try { const notification = this.getNotificationByTitle(text).first(); await notification.waitFor({ state: 'visible', timeout }); const closeBtn = notification.locator('.el-notification__closeBtn'); await closeBtn.click({ timeout: 500 }); // Quick check that it's gone - don't wait long await notification.waitFor({ state: 'hidden', timeout: 1000 }); return true; } catch (error) { return false; } } /** * Wait for a notification to appear with specific text. * Reasonable timeout for waiting, but still faster than before. * @param text The text to search for in notification title. * @param options Optional configuration */ async waitForNotification( text: string | RegExp, options: { timeout?: number } = {}, ): Promise { const { timeout = 5000 } = options; try { const notification = this.getNotificationByTitle(text).first(); await notification.waitFor({ state: 'visible', timeout }); return true; } catch { return false; } } // Wait for notification and then close it async waitForNotificationAndClose( text: string | RegExp, options: { timeout?: number } = {}, ): Promise { const { timeout = 3000 } = options; const isVisible = await this.waitForNotification(text, { timeout }); if (!isVisible) { return false; } return await this.closeNotificationByText(text, { timeout }); } /** * Get all visible notification texts. * @returns Array of notification title texts */ async getAllNotificationTexts(): Promise { try { const titles = this.page.getByRole('alert').locator('.el-notification__title'); return await titles.allTextContents(); } catch { return []; } } /** * Nuclear option: Close everything as fast as possible. * No waiting, no error handling, just close and move on. */ async quickCloseAll(): Promise { try { const closeButtons = this.page.locator('.el-notification__closeBtn'); const count = await closeButtons.count(); for (let i = 0; i < count; i++) { try { await closeButtons.nth(i).click({ timeout: 100 }); } catch { // Continue silently } } } catch { // Silent fail } } getModalOverlay(): Locator { return this.page.locator('.el-overlay').first(); } getErrorNotifications(): Locator { return this.page.locator('.el-notification:has(.el-notification--error)'); } getSuccessNotifications(): Locator { return this.page.locator('.el-notification:has(.el-notification--success)'); } getWarningNotifications(): Locator { return this.page.locator('.el-notification:has(.el-notification--warning)'); } }