reg-cli Documentation

repository·main·Indexed 19 days ago

https://github.com/reg-viz/reg-cli

A high-performance visual regression testing tool featuring a Rust-based WebAssembly engine for image comparison. reg-cli provides a CLI for automated testing, a programmatic compare() API, and an HTML reporter for visualizing differences. It supports various image formats (tiff, jpeg, jpg, gif, png, bmp, webp) and offers configurable thresholds for pixel-difference and matching rates.

Tokens
9.8K
Snippets
28
Records
40
Agent score
55%

What's inside reg-cli

  1. How reg-cli architecture works

    main

    The reg-cli tool uses a hybrid architecture:

    1. Node.js Host: Handles CLI argument parsing, the compare() EventEmitter API, and manages worker threads.
    2. Wasm Engine: A Wasm32-WASIp1-threads bundle (reg.wasm) that performs the heavy lifting. It is compiled from Rust and uses Rayon for parallel image diffing.

    Key Design Choices:

    • Portability: The Wasm engine runs identically on Linux, macOS, and Windows without requiring native build tools like node-gyp.
    • Sandboxing: File I/O is constrained via WASI preopens, ensuring the Wasm engine only accesses the directories explicitly provided.
    • Performance: By using Rust and Rayon inside a WASI thread pool, the engine achieves significant speedups (up to 2.9x for 4K images) compared to pure JS implementations.
  2. Understand the tracing architecture and data flow

    main

    reg-cli uses a hybrid tracing model that bridges JavaScript (Node.js) and Rust/WASM execution.

    How it works:

    1. JS Root Span: The process starts by creating a root span in the JavaScript layer using startRootSpan. This generates a TraceContext (containing traceId and spanId).
    2. Rust Propagation: The TraceContext is passed to the Rust/WASM side. This allows Rust-side operations to be children of the initial JavaScript operation.
    3. Rust Span Collection: As Rust executes, it collects span data (RustSpanData). When the Rust execution completes, this data is sent back to the JavaScript side.
    4. Reconstruction: The processRustTraceData function takes the raw Rust spans, topologically sorts them (ensuring parents are processed before children), and reconstructs them as OpenTelemetry spans in the JS environment. This allows a single unified trace in your observability backend.
    5. Worker Spans: Timing events from worker threads (capturing JS-bridge costs like WASM instantiation) are processed via processWorkerSpans and attached to the current root span.
  3. Enable OpenTelemetry tracing in reg-cli

    main

    Tracing is an optional feature in reg-cli that uses OpenTelemetry to export execution traces to backends like Jaeger. It is not enabled by default and requires specific environment variables and peer dependencies.

    1. Install Peer Dependencies

    Because @opentelemetry/* packages are optional peer dependencies, you must install them manually to enable tracing.

    If reg-cli is installed globally:

    npm i -g @opentelemetry/api @opentelemetry/exporter-trace-otlp-http @opentelemetry/resources @opentelemetry/sdk-trace-base @opentelemetry/sdk-trace-node @opentelemetry/semantic-conventions

    If reg-cli is a project dependency:

    npm i @opentelemetry/api @opentelemetry/exporter-trace-otlp-http @opentelemetry/resources @opentelemetry/sdk-trace-base @opentelemetry/sdk-trace-node @opentelemetry/semantic-conventions

    2. Configure Environment Variables

    Set one of the following to true to activate the tracing logic:

    • OTEL_ENABLED=true
    • JAEGER_ENABLED=true

    You can also specify the OTLP endpoint via:

    • OTEL_EXPORTER_OTLP_ENDPOINT (defaults to http://localhost:4318/v1/traces)

    To debug the tracing setup, set:

    • OTEL_DEBUG=true
    export OTEL_ENABLED=true
    export OTEL_EXPORTER_OTLP_ENDPOINT=http://your-jaeger-endpoint:4318/v1/traces
    reg-cli <args>
  4. Build reg-cli from source

    main

    To build the project from source, follow these steps to build the UI, the Wasm engine, and then bundle the final package.

    1. Build the report UI (requires pnpm): sh ./scripts/build-ui.sh v0.5.0
    2. Build the Wasm engine (downloads wasi-sdk on first run): bash ./scripts/build-wasm.sh or pnpm build:wasm
    3. Bundle everything: pnpm build
    # 1. Build report-ui
    sh ./scripts/build-ui.sh v0.5.0
    
    # 2. Build reg.wasm
    bash ./scripts/build-wasm.sh
    
    # 3. Bundle everything into dist/
    pnpm build
  5. Run visual regression testing via CLI

    main

    Execute visual regression comparisons by providing paths to the actual images, expected images, and the directory where diffs should be saved. Use the -R flag to generate an HTML report.

    Basic Syntax: reg-cli <actual-dir> <expected-dir> <diff-dir> [options]

    $ reg-cli /path/to/actual-dir /path/to/expected-dir /path/to/diff-dir -R ./report.html
  6. Configure error handling and exit codes

    main

    By default, reg-cli exits with a non-zero code if image changes are detected. You can modify this behavior using the following flags:

    • --ignoreChange (-I): Forces the CLI to exit with code 0 even if image changes are detected.
    • --extendedErrors (-E): Escalates the status of added or deleted images to a failure. When used, the CLI will exit with a non-zero code if any images were added or deleted, in addition to changed images.
    • --customDiffMessage (-D): Allows you to specify a custom trailing message to be printed to the console when a diff is detected.
  7. Understand the progress event wire format

    main

    When running in environments where stderr is captured (like a JS host via WASI), reg-cli emits live progress events. These events are prefixed with __REG_CLI_EVT__ followed by a TAB and a JSON payload.

    Format: __REG_CLI_EVT__\t{"path":"...","type":"..."}\n

    Supported type values:

    • pass: Image matches within thresholds.
    • fail: Image differs beyond thresholds or failed to load/decode.
    • new: Image exists in actual but not in expected.
    • delete: Image exists in expected but not in actual.
  8. Update expected images with --update

    main

    Use the -U or --update flag to refresh your baseline images. This command performs a smart update:

    1. Pruning: It removes images from the expected directory that were either deleted or failed comparison.
    2. Refreshing: It copies new images and failed images from the actual directory to the expected directory.
    3. Preservation: Unchanged (passed) images are left untouched to preserve mtime and keep Git status clean.

    Note: --update requires both actualDir and expectedDir to be specified and is incompatible with --from mode.

    $ reg-cli /path/to/actual-dir /path/to/expected-dir /path/to/diff-dir --update
  9. Usage of reg-cli

    main

    The reg-cli tool is used for visual regression testing by comparing actual images against expected baselines.

    Standard Mode To run a comparison, provide the paths to the actual directory, the expected directory, and the directory where diffs should be stored:

    $ reg-cli /path/to/actual-dir /path/to/expected-dir /path/to/diff-dir

    Render Mode To render an HTML report from an existing reg.json file without performing a new comparison, use the --from flag. In this mode, positional directory arguments are not required:

    $ reg-cli --from ./reg.json
    $ reg-cli /path/to/actual-dir /path/to/expected-dir /path/to/diff-dir
  10. Enable browser-side second-pass detection

    main

    To enable advanced browser-side pixel detection, use the --additionalDetection client flag.

    When this mode is active and a --report path is provided, reg-cli will automatically write the necessary assets (worker.js and detector.wasm) next to the HTML report. This allows the browser to perform a second-pass detection using the ximgdiff engine.

    $ reg-cli /actual /expected /diff --report ./report.html --additionalDetection client
  11. Generate a report from an existing reg.json

    main

    If you already have a reg.json file, you can render the report without running new image comparisons by using the -F flag.

    $ reg-cli -F ./sample/reg.json -R ./sample/index.html