/** * QA360 Advanced Interactions Handler * * P0 Features for Enterprise-Grade Testing: * - Shadow DOM support (auto-piercing) * - Iframe handling (same-origin + cross-origin) * - File upload/download * * @since 2.3.0 */ import type { Page, Locator, Frame } from '@playwright/test'; /** * Configuration for advanced interactions */ export interface AdvancedInteractionsOptions { /** Maximum shadow DOM depth to pierce (default: 5) */ maxShadowDepth?: number; /** Whether to automatically pierce shadow DOM (default: true) */ autoShadowPiercing?: boolean; /** Whether to handle iframes (default: true) */ handleIframes?: boolean; /** Timeout for frame operations (default: 5000ms) */ frameTimeout?: number; } /** * Element location result with context */ export interface ElementLocation { /** The element locator */ locator: Locator; /** Whether element is in shadow DOM */ isInShadowDom: boolean; /** Shadow DOM depth (0 = not in shadow DOM) */ shadowDepth: number; /** Nested shadow DOM depth (tracks shadow roots within shadow roots) */ nestedShadowDepth?: number; /** Whether element is in iframe */ isInIframe: boolean; /** Whether iframe is cross-origin (only meaningful if isInIframe is true) */ isCrossOrigin?: boolean; /** Frame selector if in iframe */ frameSelector?: string; /** The path taken to find the element */ path: string[]; } /** * File upload result */ export interface FileUploadResult { /** Whether upload succeeded */ success: boolean; /** Number of files uploaded */ count: number; /** File names uploaded */ fileNames: string[]; /** Error message if failed */ error?: string; } /** * File download result */ export interface FileDownloadResult { /** Whether download was intercepted */ success: boolean; /** Downloaded file path */ path?: string; /** File name */ fileName?: string; /** File size in bytes */ size?: number; /** Error message if failed */ error?: string; } /** * Advanced Interactions Handler * * Handles complex DOM interactions that go beyond simple element selection. */ export declare class AdvancedInteractionsHandler { private page; private options; private shadowRootCache; private frameCache; constructor(page: Page, options?: AdvancedInteractionsOptions); /** * ═══════════════════════════════════════════════════════════════════════════════ * SHADOW DOM SUPPORT * ═══════════════════════════════════════════════════════════════════════════════ */ /** * Find an element with automatic shadow DOM piercing * * Attempts to find an element in the main DOM first, * then recursively searches through shadow DOM trees. * * @param selector - CSS selector to search for * @param options - Search options * @returns Element location with context */ findWithShadowPiercing(selector: string, options?: { timeout?: number; maxDepth?: number; }): Promise; /** * Recursively search for element in shadow DOM * Supports nested shadow DOM (shadow roots within shadow roots) */ private searchInShadowDom; /** * Build a Playwright-compatible selector for shadow DOM elements * * Playwright supports shadow DOM piercing with >> >> */ private buildShadowDomSelector; /** * Click an element with shadow DOM support */ clickWithShadowPiercing(selector: string): Promise; /** * Fill an input with shadow DOM support */ fillWithShadowPiercing(selector: string, value: string): Promise; /** * ═══════════════════════════════════════════════════════════════════════════════ * IFRAME HANDLING * ═══════════════════════════════════════════════════════════════════════════════ */ /** * Find an element within iframes * * Searches through same-origin iframes recursively. * * @param selector - CSS selector to search for * @param options - Search options * @returns Element location with iframe context */ findInIframes(selector: string, options?: { timeout?: number; maxDepth?: number; allowCrossOrigin?: boolean; }): Promise; /** * Find element in same-origin iframes (faster, direct frame access) */ private findInSameOriginIframes; /** * Find element in cross-origin iframes using frameLocator * * For cross-origin iframes, we cannot use frame.waitForSelector() due to SOP. * Instead, we use Playwright's frameLocator which handles cross-origin transparently. */ private findInCrossOriginIframes; /** * Recursively search nested iframes */ private findInNestedFrames; /** * Get the selector for a frame */ private getFrameSelector; /** * Get the selector for an iframe element * Used for cross-origin iframe handling where we have an ElementHandle */ private getFrameSelectorForElement; /** * Check if two URLs are same-origin */ private isSameOrigin; /** * Interact with element in iframe * * @param iframeSelector - Selector for the iframe * @param elementSelector - Selector for element within iframe * @param action - Action to perform * @returns Action result */ interactInIframe(iframeSelector: string, elementSelector: string, action: (frame: Frame) => Promise): Promise; /** * ═══════════════════════════════════════════════════════════════════════════════ * FILE OPERATIONS * ═══════════════════════════════════════════════════════════════════════════════ */ /** * Upload files to an input element * * @param selector - File input selector * @param filePaths - Paths to files to upload * @returns Upload result */ uploadFiles(selector: string, filePaths: string | string[]): Promise; /** * Upload files to an input in shadow DOM */ private uploadFilesInShadowDom; /** * Handle file download with interception * * @param triggerSelector - Selector for element that triggers download * @param options - Download options * @returns Download result */ handleDownload(triggerSelector: string, options?: { action?: 'click' | 'submit'; timeout?: number; savePath?: string; }): Promise; /** * ═══════════════════════════════════════════════════════════════════════════════ * COMBINED SEARCH (Shadow DOM + Iframes) * ═══════════════════════════════════════════════════════════════════════════════ */ /** * Find element anywhere (normal DOM, shadow DOM, or iframes) * * This is the main entry point for finding elements that may be * hidden in shadow DOM or inside iframes. * * @param selector - CSS selector * @param options - Search options * @returns Element location or null */ findElementAnywhere(selector: string, options?: { timeout?: number; }): Promise; /** * P0: Handle print dialog (window.print()) * * Uses CDP to automatically dismiss or capture print dialogs. * * @param options - Print handling options * @returns Promise that resolves when print dialog is handled */ handlePrintDialog(options?: { /** Action to take: 'dismiss' to cancel, 'capture' to generate PDF */ action?: 'dismiss' | 'capture'; /** Output path for PDF (when action is 'capture') */ path?: string; }): Promise<{ handled: boolean; pdfPath?: string; }>; /** * P0: Hover over an element * * Triggers hover state and waits for any visual changes. * Supports elements in shadow DOM and iframes. * * @param selector - CSS selector for the element * @param options - Hover options * @returns Hover result */ hover(options: { /** CSS selector for the element */ selector: string; /** Whether to wait for animations after hover (default: true) */ waitForAnimation?: boolean; /** Animation wait time in ms (default: 100) */ animationWait?: number; /** Force hover even if element is not visible */ force?: boolean; }): Promise<{ success: boolean; error?: string; }>; /** * P0: Drag and drop operation * * Drags an element and drops it onto a target element. * Supports elements in shadow DOM and iframes. * * @param options - Drag and drop options * @returns Drag result */ dragAndDrop(options: { /** CSS selector for the source element to drag */ from: string; /** CSS selector for the target element to drop on */ to: string; /** Drop position relative to target (default: 'center') */ position?: 'top' | 'right' | 'bottom' | 'left' | 'center'; /** Whether to verify the drop was successful */ verifyDrop?: boolean; }): Promise<{ success: boolean; error?: string; }>; /** * P0: Drag element to specific coordinates * * Drags an element from its current position to specific x, y coordinates. * * @param options - Drag to coordinates options * @returns Drag result */ dragToCoordinates(options: { /** CSS selector for the element to drag */ selector: string; /** Target X coordinate */ x: number; /** Target Y coordinate */ y: number; /** Starting X coordinate (default: element center) */ fromX?: number; /** Starting Y coordinate (default: element center) */ fromY?: number; /** Number of steps for smooth drag (default: 10) */ steps?: number; }): Promise<{ success: boolean; error?: string; }>; /** * P0: Multi-select drag (select multiple elements) * * Performs Ctrl+Click on multiple elements to select them. * * @param selectors - Array of CSS selectors to select * @returns Selection result */ multiSelect(selectors: string[]): Promise<{ success: boolean; selected: number; errors: string[]; }>; /** * Get position offset for drop position */ private getPositionForDrop; /** * Sleep utility for waiting */ private sleep; /** * Clear caches */ clearCache(): void; } /** * Factory function to create handler */ export declare function createAdvancedInteractionsHandler(page: Page, options?: AdvancedInteractionsOptions): AdvancedInteractionsHandler;