UNPKG

@progress/kendo-e2e

Version:

Kendo UI end-to-end test utilities.

371 lines (370 loc) 13.7 kB
import { By, IRectangle, ThenableWebDriver } from "selenium-webdriver"; import { Level } from "selenium-webdriver/lib/logging"; import { WebApp } from "./web-app"; export { By, Key, ThenableWebDriver, until, WebElement, WebElementCondition } from "selenium-webdriver"; interface BrowserOptions { driver?: ThenableWebDriver; mobileEmulation?: { deviceName: string; } | { width: number; height: number; pixelRatio: number; } | any; enableBidi?: boolean; } /** * Browser automation class with automatic waiting and modern web testing features. * * Extends {@link WebApp} with browser-specific capabilities like navigation, window management, * accessibility testing, and console log monitoring. Perfect for testing web applications in * real browsers (Chrome, Firefox, Safari, Edge). * * **Key features:** * - Browser navigation and URL management * - Window resizing and iframe handling * - Mobile device emulation * - Accessibility (a11y) testing with axe-core * - Console error detection * - BiDi protocol support * * @example * ```typescript * // Basic browser test * const browser = new Browser(); * await browser.navigateTo('https://example.com'); * await browser.click('#login-button'); * await browser.expect('.welcome-message').toBeVisible(); * await browser.close(); * * // Mobile emulation * const mobile = new Browser({ mobileEmulation: { deviceName: 'iPhone 14 Pro Max' } }); * await mobile.navigateTo('https://example.com'); * * // With BiDi for advanced features * const browser = new Browser({ enableBidi: true }); * * // Check for console errors * await browser.clearLogs(); * await browser.click('#trigger-error'); * const errors = await browser.getErrorLogs(); * expect(errors).toHaveLength(0); * * // Accessibility testing * const violations = await browser.getAccessibilityViolations(); * expect(violations).toHaveLength(0); * ``` */ export declare class Browser extends WebApp { /** * Creates an instance of the Browser class. * * @param {ThenableWebDriver | BrowserOptions} [driverOrOptions] - Either a WebDriver instance or an options object. * If a WebDriver instance is provided, it will be used as the driver. If an options object is provided, a new driver will be created with those options. * @param {Object} [mobileEmulation] - (Optional) Mobile emulation options, used only if the first parameter is a WebDriver instance. * Mobile options can be an object with either a `deviceName` or `width`, `height`, and `pixelRatio`. * @param {boolean} [enableBidi] - (Optional) Enables BiDi (Bidirectional communication) if set to `true`. * * __Usage Examples:__ * * __Example 1: Using a Pre-configured Device__ * ```typescript * const mobileEmulation = { deviceName: "iPhone 14 Pro Max" }; * const browser = new Browser(mobileEmulation); * ``` * * __Example 2: Using Custom Screen Configuration__ * ```typescript * const mobileEmulation = { deviceMetrics: { width: 360, height: 640, pixelRatio: 3.0 }, userAgent: 'My Agent' }; * const browser = new Browser(mobileEmulation); * ``` * * __Example 3: Providing a WebDriver Instance With Mobile Emulation__ * ```typescript * const driver = new Builder().forBrowser('chrome').build(); * const mobileEmulation = { deviceName: "iPhone 14 Pro Max" }; * const browser = new Browser(driver, mobileEmulation); * ``` * * __Example 4: Enabling BiDi Mode__ * ```typescript * const browser = new Browser({ enableBidi: true }); * ``` * * __Example 5: Combining Mobile Emulation and BiDi Mode__ * ```typescript * const browser = new Browser({ mobileEmulation: { deviceName: "iPhone 14 Pro Max" }, enableBidi: true }); * ``` * * [em]: https://chromedriver.chromium.org/mobile-emulation * [devem]: https://developer.chrome.com/devtools/docs/device-mode */ constructor(driverOrOptions?: ThenableWebDriver | BrowserOptions, mobileEmulation?: { deviceName: string; } | { width: number; height: number; pixelRatio: number; } | any, enableBidi?: boolean); /** * Closes the browser and ends the WebDriver session. * * Should be called at the end of each test to clean up resources. * Closes all browser windows and terminates the driver. * * @returns Promise that resolves when browser is closed * * @example * ```typescript * const browser = new Browser(); * try { * await browser.navigateTo('https://example.com'); * // ... test code ... * } finally { * await browser.close(); // Always close to free resources * } * ``` */ close(): Promise<void>; /** * Navigates the browser to a specified URL. * * Opens the URL in the current browser window. Waits for the page to load before * the promise resolves. * * @param url - The URL to navigate to (must include protocol: http:// or https://) * @returns Promise that resolves when navigation completes * * @example * ```typescript * // Navigate to a website * await browser.navigateTo('https://example.com'); * * // Navigate to local development server * await browser.navigateTo('http://localhost:3000'); * * // Navigate to specific page * await browser.navigateTo('https://example.com/products/123'); * ``` */ navigateTo(url: string): Promise<void>; getRect(): Promise<IRectangle>; setRect(rect: { width?: number; height?: number; x?: number; y?: number; }): Promise<void>; resizeToDocumentScrollHeight(): Promise<void>; /** * Resizes the browser window to the specified width and height. * * @param width - The new width of the window in pixels * @param height - The new height of the window in pixels * @throws Error if the window resize operation fails * * @example * ```typescript * // Resize window to 1920x1080 * await browser.resizeWindow(1920, 1080); * * // Resize to mobile size * await browser.resizeWindow(375, 667); * ``` */ resizeWindow(width: number, height: number): Promise<void>; /** * Refreshes the current page (like pressing F5 or clicking browser refresh). * * Reloads the page from the server, resetting all JavaScript state. * * @returns Promise that resolves when page reload completes * * @example * ```typescript * // Refresh after making changes * await browser.click('#update-settings'); * await browser.refresh(); * * // Verify data persists after refresh * await browser.type('#input', 'test'); * await browser.click('#save'); * await browser.refresh(); * const value = await browser.getAttribute('#input', 'value'); * expect(value).toBe('test'); * ``` */ refresh(): Promise<void>; /** * Switches the WebDriver context to an iframe. * * After calling this, all subsequent commands will target elements within the iframe. * To switch back to the main page, use `driver.switchTo().defaultContent()`. * * @param elementLocator - By locator for the iframe element * @returns Promise that resolves when context is switched * * @example * ```typescript * // Switch to iframe and interact with its content * await browser.switchToIFrame(By.css('#my-iframe')); * await browser.click('#button-inside-iframe'); * * // Switch back to main page * await browser.driver.switchTo().defaultContent(); * await browser.click('#button-on-main-page'); * * // Work with nested iframes * await browser.switchToIFrame(By.css('#outer-frame')); * await browser.switchToIFrame(By.css('#inner-frame')); * ``` */ switchToIFrame(elementLocator: By): Promise<void>; /** * Gets the current URL of the browser. * * Returns the complete URL including protocol, domain, path, and query parameters. * * @returns Promise resolving to the current URL string * * @example * ```typescript * // Verify navigation occurred * await browser.click('#products-link'); * const url = await browser.getCurrentUrl(); * expect(url).toContain('/products'); * * // Check URL parameters * const currentUrl = await browser.getCurrentUrl(); * expect(currentUrl).toContain('?filter=active'); * * // Verify redirect * await browser.navigateTo('http://example.com/old-page'); * const redirectedUrl = await browser.getCurrentUrl(); * expect(redirectedUrl).toBe('http://example.com/new-page'); * ``` */ getCurrentUrl(): Promise<string>; /** * Gets the name of the current browser. * * Returns lowercase browser name: 'chrome', 'firefox', 'safari', 'edge', etc. * Useful for browser-specific test logic. * * @returns Promise resolving to lowercase browser name * * @example * ```typescript * const browserName = await browser.getBrowserName(); * * if (browserName === 'safari') { * // Skip Safari-incompatible test * console.log('Skipping on Safari'); * return; * } * * // Browser-specific assertions * if (browserName === 'firefox') { * // Firefox-specific validation * } * ``` */ getBrowserName(): Promise<string>; /** * Runs accessibility (a11y) tests using axe-core and returns violations. * * Scans the page for accessibility issues like missing alt text, insufficient color contrast, * missing ARIA labels, etc. Returns an array of violations that should be addressed. * * @param cssSelector - CSS selector to limit scanning scope (default: 'html' for full page) * @param disableRules - Array of axe rule IDs to disable (default: ['color-contrast']) * @returns Promise resolving to array of accessibility violations * * @example * ```typescript * // Scan entire page * const violations = await browser.getAccessibilityViolations(); * expect(violations).toHaveLength(0); * * // Scan specific component * const formViolations = await browser.getAccessibilityViolations('#login-form'); * * // Enable all rules including color contrast * const allViolations = await browser.getAccessibilityViolations('html', []); * * // Disable specific rules * const violations = await browser.getAccessibilityViolations('html', [ * 'color-contrast', * 'landmark-one-main' * ]); * ``` */ getAccessibilityViolations(cssSelector?: string, disableRules?: string[]): Promise<[]>; /** * Clears the browser console logs. * * Call this before performing actions to get a clean slate for error detection. * Useful when you want to check if a specific action causes console errors. * * @returns Promise that resolves when logs are cleared * * @example * ```typescript * // Clear logs before action * await browser.clearLogs(); * await browser.click('#potential-error-button'); * const errors = await browser.getErrorLogs(); * ``` */ clearLogs(): Promise<void>; /** * Gets console errors from the browser (Chrome only). * * Retrieves console errors logged by the browser. Only works in Chrome on desktop platforms. * Firefox and mobile platforms don't support log retrieval. * * @param excludeList - Array of strings to filter out from errors (default: ['favicon.ico']) * @param logLevel - Minimum log level to collect (default: Level.SEVERE for errors) * @returns Promise resolving to array of error message strings * * @example * ```typescript * // Check for any console errors * const errors = await browser.getErrorLogs(); * expect(errors.length).toBe(0); * * // Exclude known non-critical errors * const errors = await browser.getErrorLogs(['favicon', 'analytics']); * * // Get all warnings and errors * const logs = await browser.getErrorLogs([], Level.WARNING); * * // Check for specific error * const errors = await browser.getErrorLogs(); * expect(errors.some(e => e.includes('TypeError'))).toBe(false); * ``` */ getErrorLogs(excludeList?: string[], logLevel?: Level): Promise<string[]>; /** * Executes a JavaScript script in the browser context. * * @param script - The JavaScript code to execute as a string * @param waitBeforeMs - Optional wait time in milliseconds before executing the script (default: 0) * @param waitAfterMs - Optional wait time in milliseconds after executing the script (default: 0) * @returns Promise<unknown> - The result of the script execution * @throws Error if the script execution fails * * @example * ```typescript * // Basic script execution * const result = await browser.executeScript('return document.title;'); * * // With wait before execution * await browser.executeScript('document.body.style.background = "red";', 1000); * * // With waits before and after execution * const height = await browser.executeScript('return document.body.scrollHeight;', 500, 200); * ``` */ executeScript(script: string, waitBeforeMs?: number, waitAfterMs?: number): Promise<unknown>; }