import { z } from 'zod'; /** * PageLike — structural interface that both Playwright's Page and CompatPage satisfy. * Use this as the parameter type in functions that need to work with either. */ interface ElementHandleLike { screenshot(options?: { path?: string; type?: string; }): Promise; textContent(): Promise; boundingBox(): Promise<{ x: number; y: number; width: number; height: number; } | null>; getAttribute?(name: string): Promise; click?(options?: any): Promise; fill?(value: string, options?: any): Promise; check?(options?: any): Promise; uncheck?(options?: any): Promise; selectOption?(value: string | string[], options?: any): Promise; press?(key: string, options?: any): Promise; focus?(options?: any): Promise; type?(text: string, options?: any): Promise; } interface LocatorLike { filter(options: { visible?: boolean; }): LocatorLike; first(): LocatorLike; click(options?: { timeout?: number; force?: boolean; }): Promise; fill(text: string, options?: { timeout?: number; }): Promise; focus(options?: { timeout?: number; }): Promise; press(key: string, options?: { timeout?: number; }): Promise; pressSequentially(text: string, options?: { delay?: number; timeout?: number; }): Promise; waitFor(options?: { state?: string; timeout?: number; }): Promise; } interface PageLike { goto(url: string, options?: { waitUntil?: string; timeout?: number; }): Promise; evaluate(fn: any, ...args: any[]): Promise; $(selector: string): Promise; $$(selector: string): Promise; screenshot(options?: { path?: string; fullPage?: boolean; type?: string; }): Promise; addStyleTag(options: { content: string; }): Promise; waitForSelector(selector: string, options?: { timeout?: number; }): Promise; waitForTimeout(ms: number): Promise; content(): Promise; title(): Promise; textContent(selector: string): Promise; getAttribute?(selector: string, name: string): Promise; click?(selector: string, options?: { timeout?: number; }): Promise; fill?(selector: string, value: string): Promise; type?(selector: string, text: string, options?: { delay?: number; }): Promise; hover?(selector: string, options?: { timeout?: number; }): Promise; check?(selector: string): Promise; uncheck?(selector: string): Promise; selectOption?(selector: string, value: string): Promise; locator?(selector: string): LocatorLike; on?(event: string, handler: any): void; off?(event: string, handler: any): void; url?(): string; keyboard?: { press(key: string): Promise; }; innerText?(selector: string): Promise; waitForNavigation?(): Promise; waitForLoadState?(state?: string, options?: { timeout?: number; }): Promise; } type Page = PageLike & { on(event: string, handler: any): void; off?(event: string, handler: any): void; }; /** * API request timing info */ interface ApiRequestTiming { url: string; method: string; duration: number; status: number; size: number; resourceType: string; timing: { dnsLookup?: number; tcpConnect?: number; tlsHandshake?: number; requestSent?: number; waiting?: number; contentDownload?: number; }; } /** * API timing measurement result */ interface ApiTimingResult { requests: ApiRequestTiming[]; summary: { totalRequests: number; totalTime: number; totalSize: number; averageTime: number; slowestRequest: { url: string; duration: number; } | null; fastestRequest: { url: string; duration: number; } | null; failedRequests: number; byStatus: Record; }; } /** * Options for API timing measurement */ interface ApiTimingOptions { /** Filter to only track URLs matching this pattern */ filter?: RegExp; /** Include static resources (images, fonts, etc.) */ includeStatic?: boolean; /** Timeout to wait for requests to complete (ms) */ timeout?: number; /** Minimum duration to report (ms) - filters out fast requests */ minDuration?: number; } /** * Measure API/network request timing on a page * * Call this before navigating to the page, then call stopMeasuring after navigation */ declare function measureApiTiming(page: Page, options?: ApiTimingOptions): Promise; /** * Create an API timing tracker that records during page interactions */ declare function createApiTracker(page: Page, options?: ApiTimingOptions): { start(): void; stop(): ApiTimingResult; getRequests(): ApiRequestTiming[]; }; /** * Format API timing result for console output */ declare function formatApiTimingResult(result: ApiTimingResult): string; /** * Interactive element info */ interface InteractiveElement { selector: string; tagName: string; type?: string; text?: string; hasHandler: boolean; isDisabled: boolean; isVisible: boolean; a11y: { role?: string; ariaLabel?: string; tabIndex?: number; }; } /** * Button analysis result */ interface ButtonInfo extends InteractiveElement { buttonType?: 'submit' | 'button' | 'reset'; formId?: string; } /** * Link analysis result */ interface LinkInfo extends InteractiveElement { href: string; isPlaceholder: boolean; opensNewTab: boolean; isExternal: boolean; } /** * Form analysis result */ interface FormInfo { selector: string; action?: string; method?: string; hasSubmitHandler: boolean; fields: FormFieldInfo[]; hasValidation: boolean; submitButton?: ButtonInfo; } /** * Form field info */ interface FormFieldInfo { selector: string; name?: string; type: string; label?: string; required: boolean; hasValidation: boolean; } /** * Interactivity issue */ interface InteractivityIssue { type: 'NO_HANDLER' | 'PLACEHOLDER_LINK' | 'MISSING_LABEL' | 'DISABLED_NO_VISUAL' | 'SMALL_TOUCH_TARGET' | 'FORM_NO_SUBMIT' | 'ORPHAN_SUBMIT' | 'NO_KEYBOARD_ACCESS'; element: string; severity: 'error' | 'warning' | 'info'; description: string; } /** * Full interactivity test result */ interface InteractivityResult { buttons: ButtonInfo[]; links: LinkInfo[]; forms: FormInfo[]; issues: InteractivityIssue[]; summary: { totalInteractive: number; withHandlers: number; withoutHandlers: number; issueCount: { error: number; warning: number; info: number; }; }; } /** * Test interactivity of all interactive elements on a page */ declare function testInteractivity(page: PageLike): Promise; /** * Format interactivity result for console output */ declare function formatInteractivityResult(result: InteractivityResult): string; /** * Web Vitals metrics * @see https://web.dev/vitals/ */ interface WebVitals { /** Largest Contentful Paint (ms) - loading performance */ LCP: number | null; /** First Input Delay (ms) - interactivity (requires user interaction) */ FID: number | null; /** Cumulative Layout Shift (score) - visual stability */ CLS: number | null; /** Time to First Byte (ms) - server response time */ TTFB: number | null; /** First Contentful Paint (ms) - initial render */ FCP: number | null; /** Time to Interactive (ms) - when page becomes fully interactive */ TTI: number | null; } /** * Performance thresholds for each metric * Based on Core Web Vitals guidelines */ declare const PERFORMANCE_THRESHOLDS: { LCP: { good: number; poor: number; }; FID: { good: number; poor: number; }; CLS: { good: number; poor: number; }; TTFB: { good: number; poor: number; }; FCP: { good: number; poor: number; }; TTI: { good: number; poor: number; }; }; /** * Performance rating */ type PerformanceRating = 'good' | 'needs-improvement' | 'poor'; /** * Rated metric with value and rating */ interface RatedMetric { value: number | null; rating: PerformanceRating | null; } /** * Full performance result with ratings */ interface PerformanceResult { metrics: WebVitals; ratings: Record; summary: { overallRating: PerformanceRating; passedVitals: number; totalVitals: number; issues: string[]; recommendations: string[]; }; } /** * Measure Core Web Vitals from a page * * Note: FID requires actual user interaction, so it will be null * for automated tests. Use TTI as an alternative measure. */ declare function measureWebVitals(page: PageLike): Promise; /** * Measure performance and return rated results */ declare function measurePerformance(page: PageLike): Promise; /** * Format performance result for console output */ declare function formatPerformanceResult(result: PerformanceResult): string; /** * Flow Types * * Common types used across all built-in flows. */ interface FlowStep { action: string; success: boolean; duration?: number; error?: string; } interface FlowResult { success: boolean; steps: FlowStep[]; error?: string; /** Time taken in ms */ duration: number; } interface FlowOptions { /** Timeout for the entire flow in ms */ timeout?: number; /** Whether to take screenshots at each step */ debug?: boolean; } /** * Find a form field by common label patterns. * * Order: * 1. Plain attribute selectors (name/id/placeholder/aria-label). * 2. In-page