# @wdio/xvfbA standalone utility to manage Xvfb (X Virtual Framebuffer) for headless testing on Linux systems.## Installation```bashnpm install @wdio/xvfb```## Usage### Automatic Integration**Most users don't need to use this package directly.** It's automatically integrated into:- **`@wdio/local-runner`** - Automatically ensures xvfb is available for headless browser testing- **`wdio-electron-service`** - Provides headless Electron testing capabilitiesSimply run your WebDriverIO tests normally, and xvfb will be managed automatically when needed.### Manual Usage (Advanced)For custom integrations or non-WDIO environments:```jsimport { xvfb } from "@wdio/xvfb";// Initialize xvfb-run (only works on Linux in headless environments)const ready = await xvfb.init();if (ready) {console.log("xvfb-run is ready for use");// Use xvfb-run to execute commands that need a display// e.g., xvfb-run npm test}```## API### XvfbManager Class#### Constructor Options```tsinterface XvfbOptions {enabled?: boolean; // Authoritative usage toggle (default: true). If false, never uses Xvfbforce?: boolean; // Force Xvfb even on non-Linux systems (for testing)autoInstall?: boolean; // Enable automatic installation of xvfb-run if missing (default: false)autoInstallMode?: 'root' | 'sudo'; // Installation mode when autoInstall is true (default: 'sudo')autoInstallCommand?: string | string[]; // Custom installation command (overrides built-in package manager detection)xvfbMaxRetries?: number; // Number of retry attempts for xvfb failures (default: 3)xvfbRetryDelay?: number; // Base delay between retries in milliseconds (default: 1000)}```#### Methods- **`shouldRun(capabilities?): boolean`** - Check if Xvfb should run on this system- **`init(capabilities?): Promise<boolean>`** - Initialize xvfb-run, returns true if ready, false if not needed- **`executeWithRetry<T>(commandFn, context?): Promise<T>`** - Execute a function with automatic retry on xvfb-related errors### Advanced Usage Examples#### Force Mode (Testing Only)For testing on non-Linux systems:```jsimport { XvfbManager } from "@wdio/xvfb";const manager = new XvfbManager({force: true,xvfbMaxRetries: 3,xvfbRetryDelay: 1000});const ready = await manager.init();```#### Custom Retry Configuration```jsimport { XvfbManager } from "@wdio/xvfb";// High-reliability setup for CI environmentsconst manager = new XvfbManager({xvfbMaxRetries: 10, // More retries for flaky CIxvfbRetryDelay: 500 // Faster retries});// Execute operation with automatic retryconst result = await manager.executeWithRetry(async () => {// Your operation that might fail due to xvfb issuesreturn await runHeadlessTests();}, 'Running headless tests');```## When does it run?The utility automatically detects when Xvfb is needed:- ✅ Linux systems without a DISPLAY environment variable- ✅ Linux systems when headless browser flags are detected:- **Chrome/Chromium**: `--headless`, `--headless=new`, `--headless=old`- **Firefox**: `--headless`, `-headless`- **Edge** (Chromium-based): `--headless`, `--headless=new`, `--headless=old`- ❌ Non-Linux systems (unless `force: true`)- ❌ Linux systems with existing DISPLAY (unless headless flags are detected)## Features- **Conditional execution**: Only runs on Linux systems in headless environments- **Smart headless detection**: Automatically detects browser headless flags (`--headless`, `--headless=new`, etc.) and forces XVFB usage for consistent behavior- **Automatic retry mechanism**: Built-in retry logic with progressive delays for handling xvfb startup failures- **Configurable retry behavior**: Customizable retry count and delay settings via WDIO configuration- **Universal package manager support**: Automatically detects and uses the system's package manager (`apt`, `dnf`, `yum`, `zypper`, `pacman`, `apk`, `xbps`)- **Cross-distro compatibility**: Works across hundreds of Linux distributions by supporting their underlying package managers- **Command execution**: Execute commands under Xvfb using `xvfb-run`- **Graceful cleanup**: Automatic cleanup when commands complete- **State tracking**: Prevents duplicate starts and handles multiple calls safely- **Flexible logging**: Configurable logger support## Retry MechanismThe package includes automatic retry functionality for handling xvfb-related failures:### Automatic Retry DetectionThe retry mechanism automatically detects xvfb-specific errors:- `xvfb-run: error: Xvfb failed to start`- `Xvfb failed to start`- `xvfb-run: error:`- `X server died`### Progressive Delay StrategyRetry delays increase progressively to avoid overwhelming the system:- Attempt 1: Immediate execution- Attempt 2: Wait `xvfbRetryDelay × 1` ms (default: 1000ms)- Attempt 3: Wait `xvfbRetryDelay × 2` ms (default: 2000ms)- Attempt N: Wait `xvfbRetryDelay × (N-1)` ms### Usage Example```jsimport { XvfbManager } from '@wdio/xvfb';const manager = new XvfbManager({xvfbMaxRetries: 5,xvfbRetryDelay: 1500});// Automatic retry on xvfb failuresconst result = await manager.executeWithRetry(async () => {// Your xvfb-dependent operationreturn await someXvfbDependentTask();}, 'Custom operation name');```## Implementation DetailsThis package uses `xvfb-run` to manage Xvfb sessions, which:- Automatically selects available display numbers with `--auto-servernum`- Configures screen resolution, DPI, and other display settings- Handles process cleanup automatically when commands complete- Supports custom arguments for advanced Xvfb configuration## Supported Package ManagersThe utility automatically detects the system's package manager and installs xvfb accordingly:| Package Manager | Command | Distributions | Package Name ||----------------|---------|---------------|--------------|| **`apt`** | `apt-get` | Ubuntu, Debian, Pop!_OS, Mint, Elementary, Zorin, etc. | `xvfb` || **`dnf`** | `dnf` | Fedora, Rocky Linux, AlmaLinux, Nobara, Bazzite, etc. | `xorg-x11-server-Xvfb` || **`yum`** | `yum` | CentOS, RHEL (legacy) | `xorg-x11-server-Xvfb` || **`zypper`** | `zypper` | openSUSE, SUSE Linux Enterprise | `xvfb-run` || **`pacman`** | `pacman` | Arch Linux, Manjaro, EndeavourOS, CachyOS, etc. | `xorg-server-xvfb` || **`apk`** | `apk` | Alpine Linux, PostmarketOS | `xvfb-run` || **`xbps`** | `xbps-install` | Void Linux | `xvfb` |### Future-Proof DesignThis package manager-focused approach means **new Linux distributions automatically work** without code changes, as long as they use one of the supported package managers. For example:- New Ubuntu derivatives automatically use `apt`- New Arch derivatives automatically use `pacman`- New Fedora derivatives automatically use `dnf`The 7 supported package managers cover **95%+ of all Linux users** and hundreds of distributions, making this solution both comprehensive and maintainable.## Examples### Basic Setup for Custom Tools```jsimport { xvfb } from "@wdio/xvfb";import { exec } from "child_process";import { promisify } from "util";const execAsync = promisify(exec);async function runCustomTests() {const ready = await xvfb.init();const command = ready? "xvfb-run your-custom-test-command": "your-custom-test-command";await execAsync(command);}```### WebDriverIO ConfigurationFor most users, no configuration is needed. WDIO automatically handles xvfb:```js// wdio.conf.js - Minimal configurationexport const config = {// No xvfb configuration needed - handled automaticallycapabilities: [{browserName: 'chrome','goog:chromeOptions': {args: ['--headless', '--no-sandbox'] // Automatically detected - will force XVFB}}],services: ['chromedriver',// xvfb is automatically managed by local-runner]};```#### Advanced WDIO ConfigurationYou can customize xvfb behavior and retry settings in your WDIO config file:```js// wdio.conf.js - Custom xvfb configurationexport const config = {// Xvfb configuration options (all optional)autoXvfb: true, // Authoritative usage toggle (default: true). If false, never uses XvfbxvfbAutoInstall: false, // Enable automatic installation of xvfb-run if missing (default: false)xvfbAutoInstallMode: 'sudo', // Installation mode: 'root' or 'sudo' (default: 'sudo')xvfbAutoInstallCommand: undefined, // Custom installation command (optional)xvfbMaxRetries: 5, // Max retry attempts for xvfb failures (default: 3)xvfbRetryDelay: 2000, // Base delay between retries in ms (default: 1000)capabilities: [{browserName: 'chrome','goog:chromeOptions': {args: ['--headless', '--no-sandbox']}}]};```**WDIO Testrunner Configuration Options:**- **`autoXvfb`** *(boolean, default: true)*: Authoritative usage toggle – if `false`, Xvfb is never used- **`xvfbAutoInstall`** *(boolean, default: false)*: Enable automatic installation when `xvfb-run` is missing- **`xvfbAutoInstallMode`** *('root' | 'sudo', default: 'sudo')*: Installation mode- 'root': install only if running as root (no sudo)- 'sudo': allow non-interactive sudo (`sudo -n`) when not root; skip if sudo not present- **`xvfbAutoInstallCommand`** *(string | string[], optional)*: Custom installation command that overrides built-in package manager detection- **`xvfbMaxRetries`** *(number, default: 3)*: Number of retry attempts when xvfb process fails- **`xvfbRetryDelay`** *(number, default: 1000)*: Base delay between retries in milliseconds. Uses progressive delay (delay × attempt number)### Headless Flag DetectionThe utility automatically detects browser headless flags and forces XVFB usage even when a DISPLAY is available:```js// These configurations will automatically trigger XVFB on Linux:// Chrome/Chromiumcapabilities: [{'goog:chromeOptions': {args: ['--headless'] // Detected}}]// Firefoxcapabilities: [{'moz:firefoxOptions': {args: ['--headless'] // Detected}}]// Edge (Chromium-based)capabilities: [{'ms:edgeOptions': {args: ['--headless=new'] // Detected}}]// Legacy formats also supportedcapabilities: [{chromeOptions: { args: ['--headless'] }, // Legacy ChromeedgeOptions: { args: ['--headless'] } // Legacy Edge}]// Multiremote scenarios are also supportedcapabilities: {browserA: { 'goog:chromeOptions': { args: ['--headless'] }},browserB: { 'ms:edgeOptions': { args: ['--no-sandbox'] }}// XVFB will be used because browserA has headless flag}```This ensures consistent headless behavior regardless of host environment setup.## LoggingThe utility uses `@wdio/logger` with the namespace `@wdio/xvfb`. Enable debug logging:```bashDEBUG=@wdio/xvfb npm run test```The logger is automatically created with the namespace `@wdio/xvfb` and cannot be customized in the current interface.## LicenseMIT