@progress/kendo-e2e
Version:
Kendo UI end-to-end test utilities.
371 lines (370 loc) • 13.7 kB
TypeScript
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>;
}