Skip to content

feat: add Visual Trace Service for automatic screenshot capture during test execution#251

Open
bheemreddy-samsara wants to merge 2 commits intoempirical-run:mainfrom
bheemreddy-samsara:feat/visual-trace-clean
Open

feat: add Visual Trace Service for automatic screenshot capture during test execution#251
bheemreddy-samsara wants to merge 2 commits intoempirical-run:mainfrom
bheemreddy-samsara:feat/visual-trace-clean

Conversation

@bheemreddy-samsara
Copy link
Copy Markdown

Summary

This PR implements the Visual Trace Service functionality, adding automatic screenshot capture during test execution with smart defaults that only capture screenshots for failed tests.

Key Features

🎯 Smart Screenshot Capture

  • Default behavior: Screenshots are only captured for failed tests (retain-on-failure mode)
  • Respects Playwright's trace configuration modes
  • Captures screenshots when steps throw errors (using try-finally pattern)
  • Properly detects failures during test execution

📸 Advanced Screenshot Management

  • Deduplication: Automatically skips duplicate screenshots using SHA-256 hashing
  • Screenshot limits: Configurable maximum screenshots per test (default: 50)
  • Smart naming: Screenshots include timestamps and step names
  • State isolation: Maintains separate state for each test retry

🔧 Configuration Options

export type VisualTraceConfig = {
  enableScreenshots?: boolean | 'on' | 'off' | 'retain-on-failure';
  maxScreenshots?: number;
  dedupe?: boolean;
};

🏗️ Architecture Improvements

  • Test-scoped device fixture support: Works with standard device fixture
  • Worker-scoped persistentDevice support: Lazy initialization for worker-scoped fixtures
  • Service reinitialization: Properly reinitializes between tests to prevent cross-test contamination
  • Object trace config support: Handles both string and object Playwright trace configurations

Implementation Details

Core Components

  1. Visual Trace Service (/src/visualTrace/service.ts)

    • Manages screenshot capture, deduplication, and limits
    • Integrates with Playwright's trace modes
    • Provides singleton instance management
    • Includes test isolation and reinitialization support
  2. boxedStep Decorator Enhancement (/src/utils.ts)

    • Intercepts test steps to capture screenshots
    • Handles both Device and Locator contexts
    • Implements lazy initialization for persistentDevice
    • Ensures correct test context for screenshot attachment
  3. Device Integration (/src/device/index.ts)

    • Exposes takeScreenshot method
    • Manages Visual Trace Service lifecycle
    • Provides initialization and cleanup methods

Test Coverage

Comprehensive unit tests covering:

  • Configuration management
  • Screenshot capture conditions
  • Deduplication logic
  • Screenshot limits
  • State management and isolation
  • Singleton instance management
  • Runtime configuration updates

Usage

The Visual Trace Service works automatically with your existing tests:

// Screenshots are captured automatically for failed tests
test('my test', async ({ device }) => {
  await device.click(selector); // Screenshot captured if this step fails
  // ...
});

Configuration in playwright.config.ts

export default {
  use: {
    trace: 'retain-on-failure', // Default: only capture on failure
    visualTrace: {
      enableScreenshots: 'retain-on-failure',
      maxScreenshots: 50,
      dedupe: true
    }
  }
};

Changelog

Includes changeset for proper version management marking this as a minor version bump.

Testing

  • ✅ All existing tests pass
  • ✅ Added 25 new unit tests for Visual Trace Service
  • ✅ CI/CD pipeline passes

Breaking Changes

None. The feature is fully backward compatible and works transparently with existing test suites.

Related

This is a clean PR containing only the Visual Trace Service implementation without any unrelated commits.

…tests (#12)

* feat: add Visual Trace Service for automatic screenshot capture on test failures

Port of empirical-run#249 with enhancements for failed-test-only screenshots.

## Overview
Implements a Visual Trace Service that automatically captures screenshots during test execution,
with a focus on capturing screenshots only when tests fail to minimize performance impact and
storage requirements.

## Key Features
- **Automatic Screenshot Capture**: Integrates with @boxedStep decorator to capture screenshots
- **Failed-Test-Only Mode**: Default configuration only captures screenshots on test failures
- **Deduplication**: Prevents capturing identical screenshots using content hashing
- **Test Retry Isolation**: Maintains separate screenshot state for each test retry attempt
- **Configurable Limits**: Supports max screenshot limits per test (default: 50)
- **Playwright Trace Integration**: Respects Playwright's built-in trace configuration modes

## Implementation Details
- Visual Trace Service manages screenshot lifecycle and state
- Integrates seamlessly with existing Device and Locator classes
- Hooks into test fixtures for automatic initialization
- Supports all Playwright trace modes (on, off, retain-on-failure, on-first-retry, etc.)

## Configuration
Users can configure via Playwright config:
- `visualTrace.enableScreenshots`: 'retain-on-failure' (default) | 'on' | 'off'
- `visualTrace.maxScreenshots`: Maximum screenshots per test
- `visualTrace.dedupe`: Enable/disable screenshot deduplication

## Testing
Comprehensive unit tests cover all configuration modes, state management,
deduplication logic, and error handling scenarios.

* fix: capture screenshots on test failures in Visual Trace Service

## Critical Fixes

### 1. Capture screenshots even when steps throw errors
- Modified boxedStep decorator to use try-catch-finally pattern
- Screenshots are now captured in finally block, ensuring they're taken even when steps fail
- This fixes the main issue where 'retain-on-failure' mode was missing the actual failure screenshots

### 2. Fix failure detection during test execution
- Added stepFailed parameter to captureScreenshot method
- During test execution, testInfo.status and testInfo.errors are not populated
- Now properly detects failures at the step level when they occur
- 'retain-on-failure' mode now correctly captures screenshots when steps fail

### 3. Test improvements
- Switched from Jest to Vitest syntax (vi.fn, vi.spyOn)
- Fixed screenshot limit tests by disabling deduplication
- Added test for step failure detection

## Technical Details
- boxedStep decorator now catches errors, marks step as failed, and re-throws
- Visual Trace Service accepts stepFailed flag to determine capture behavior
- Ensures the default 'retain-on-failure' mode actually captures failures

These fixes address the critical issue where the most important screenshots
(when tests actually fail) were being missed due to execution flow and
timing of status checks.

* fix: resolve TypeScript build errors in Visual Trace Service

- Fixed type re-export to use 'export type' for isolatedModules compatibility
- Corrected screenshot config check (removed invalid boolean comparison)
- Fixed Vitest mockImplementation call with required function argument
- Build and all tests now passing

* fix: complete Visual Trace Service fixes for production readiness

## Critical Fixes

1. **Prettier formatting fixes**
   - Fixed all formatting issues to pass linting
   - Consistent use of double quotes and proper indentation

2. **Screenshot capture for Device methods**
   - Fixed critical issue where Device methods (tap, scroll, etc.) weren't capturing screenshots
   - Now properly handles both Device methods (where 'this' is Device) and Locator methods (where 'this.device' is Device)
   - Ensures Visual Trace works for all high-level APIs

3. **Proper error handling and test execution flow**
   - Screenshots now captured even when steps throw errors (using try-finally)
   - Step failure detection works during test execution
   - 'retain-on-failure' mode now properly captures failures

This completes the Visual Trace Service implementation with all critical issues resolved.
The service now properly captures screenshots for failed tests across all API methods.

* fix: final formatting adjustment for linter

* fix: handle object trace configuration in Visual Trace Service

## Problem
When Playwright's trace config is an object (e.g., `{ mode: 'on', screenshots: true }`),
the service was falling back to 'retain-on-failure' mode instead of respecting the
configured mode, causing screenshots to be missed for always-on traces.

## Solution
- Added proper handling for object trace configurations
- Extract mode from traceConfig.mode when it's an object
- Respect screenshots: false in trace config when explicitly set
- Added tests for object configuration scenarios

This ensures the Visual Trace Service works correctly with all common Playwright
trace configuration formats, including the object format which is widely used.

* fix: enable Visual Trace for persistentDevice fixture

## Problem
Visual Trace Service was only initialized for test-scoped `device` fixture,
not for worker-scoped `persistentDevice` fixture. This meant tests using
persistentDevice (which is documented and commonly used) had no screenshot
capture functionality at all.

## Solution
Implemented lazy initialization of Visual Trace Service in the boxedStep
decorator. When Visual Trace is not already initialized (e.g., for
persistentDevice), it now:

1. Uses Playwright's test.info() API to get current test information
2. Initializes Visual Trace with the current TestInfo
3. Continues with screenshot capture as normal

This approach works for both:
- Test-scoped `device` fixture (initialized as before)
- Worker-scoped `persistentDevice` fixture (lazy initialization)

The fix ensures all tests get screenshot capture on failures, regardless
of which fixture they use.

* fix: reinitialize Visual Trace Service between tests for persistentDevice

- Add testId and retryIndex as public readonly properties to VisualTraceService
- Add needsVisualTraceReinitialization() function to check if service needs reinit
- Modify boxedStep to check and reinitialize service when testId or retry changes
- Ensures screenshots are attached to the correct test when using persistentDevice
- Fixes P1 issue where screenshots from one test were being attached to another test
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Oct 30, 2025

🦋 Changeset detected

Latest commit: 688a3e3

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
appwright Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant