Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

README.md

@lytics/playwright-adapters

Storage adapters for the Playwright reporter framework (filesystem, Slack, Firestore).

Installation

npm install @lytics/playwright-adapters
# or
pnpm add @lytics/playwright-adapters
# or
yarn add @lytics/playwright-adapters

Adapters

FilesystemAdapter

Writes test results to JSON files on the local filesystem. Useful for local development, debugging, and CI artifact collection.

Features:

  • Creates organized directory structure (test-results/ and test-runs/)
  • Pretty-printed JSON by default (configurable)
  • Automatic directory creation
  • Writes latest.json for easy access to most recent run
  • Non-blocking error handling (allows other adapters to continue)

Example:

Create a reporter file:

// reporter.ts
import { CoreReporter } from '@lytics/playwright-reporter';
import { FilesystemAdapter } from '@lytics/playwright-adapters/filesystem';

class CustomReporter extends CoreReporter {
  constructor() {
    super({
      adapters: [
        new FilesystemAdapter({
          outputDir: './test-results',
          pretty: true, // default: true
        }),
      ],
    });
  }
}

export default CustomReporter;

Reference it in your config:

// playwright.config.ts
export default {
  reporter: [['list'], ['./reporter.ts']],
};

Configuration:

interface FilesystemAdapterConfig {
  /** Directory to write test results to (required) */
  outputDir: string;
  /** Whether to pretty-print JSON (default: true) */
  pretty?: boolean;
}

Output Structure:

test-results/
├── test-results/
│   ├── TEST-001-2024-01-01T00-00-00.000Z.json
│   ├── TEST-002-2024-01-01T00-01-00.000Z.json
│   └── ...
└── test-runs/
    ├── test-run-run-123-2024-01-01T00-00-00.000Z.json
    ├── test-run-run-456-2024-01-01T01-00-00.000Z.json
    └── latest.json

SlackAdapter

Sends test results to Slack channels using @lytics/playwright-slack. Automatically formats test summaries with pass/fail statistics, failed test details, and flaky test tracking.

Features:

  • Rich Slack formatting via @lytics/playwright-slack
  • Production-only mode (configurable)
  • Skip pull request notifications (configurable)
  • Automatic flaky test detection
  • Failed test details with error messages
  • Non-blocking error handling

Example:

// reporter.ts
import { CoreReporter } from '@lytics/playwright-reporter';
import { FilesystemAdapter } from '@lytics/playwright-adapters/filesystem';
import { SlackAdapter } from '@lytics/playwright-adapters/slack';

class CustomReporter extends CoreReporter {
  constructor() {
    super({
      adapters: [
        new FilesystemAdapter({ outputDir: './test-results' }),
        new SlackAdapter({
          webhookUrl: process.env.SLACK_WEBHOOK_URL!,
          environment: 'Production',
          productionOnly: true, // default: true
          skipPullRequests: true, // default: true
          dashboardUrl: 'https://dashboard.example.com',
          ciJobUrl: process.env.CI_JOB_URL,
          artifactBaseUrl: process.env.ARTIFACT_BASE_URL,
          triggerType: process.env.TRIGGER_TYPE,
        }),
      ],
    });
  }
}

export default CustomReporter;

Configuration:

interface SlackAdapterConfig {
  /** Slack webhook URL (can also be set via SLACK_WEBHOOK_URL env var) */
  webhookUrl?: string;
  /** Environment label (defaults to TEST_ENV or 'Production') */
  environment?: string;
  /** Only send notifications in production (default: true) */
  productionOnly?: boolean;
  /** Skip notifications for pull requests (default: true) */
  skipPullRequests?: boolean;
  /** Dashboard URL for test reports */
  dashboardUrl?: string;
  /** CI job URL (can also be set via CI_JOB_URL env var) */
  ciJobUrl?: string;
  /** Artifact base URL (can also be set via ARTIFACT_BASE_URL env var) */
  artifactBaseUrl?: string;
  /** Trigger type (can also be set via TRIGGER_TYPE env var) */
  triggerType?: string;
}

Environment Variables:

The adapter automatically reads from environment variables if not provided in config:

  • SLACK_WEBHOOK_URL - Slack webhook URL (required)
  • TEST_ENV - Environment name (e.g., 'Production', 'Staging')
  • TRIGGER_TYPE - What triggered the test run (e.g., 'schedule', 'pull_request')
  • CI_JOB_URL - URL to CI job for action links
  • ARTIFACT_BASE_URL - Base URL for test artifacts

Note: This adapter requires @lytics/playwright-slack and @lytics/slack-client to be installed as dependencies.

FirestoreAdapter

Writes test results to Google Cloud Firestore. Supports automatic retry with exponential backoff for transient failures.

Features:

  • Writes to three configurable Firestore collections (you define the collection names)
  • Automatic retry with exponential backoff for transient failures
  • GCP authentication via Application Default Credentials (ADC) or Service Account JSON
  • Optional skip conditions (e.g., skip PR runs)
  • Non-blocking error handling (allows other adapters to continue)
  • Schema-agnostic (you configure your own collection names and structure)

Example:

// reporter.ts
import { CoreReporter } from '@lytics/playwright-reporter';
import { FirestoreAdapter } from '@lytics/playwright-adapters/firestore';

class CustomReporter extends CoreReporter {
  constructor() {
    super({
      adapters: [
        new FirestoreAdapter({
          projectId: 'my-gcp-project',
          credentials: process.env.GOOGLE_APPLICATION_CREDENTIALS_JSON,
          // Configure your own collection names to match your Firestore schema
          collections: {
            testRuns: 'your_test_runs_collection',
            testCases: 'your_test_cases_collection',
            latestTestCases: 'your_latest_test_cases_collection',
          },
          skipConditions: {
            skipPullRequests: true,
          },
        }),
      ],
    });
  }
}

export default CustomReporter;

Configuration:

interface FirestoreAdapterConfig {
  /** GCP project ID (required) */
  projectId: string;
  /** Service account credentials (JSON string or object). If not provided, uses Application Default Credentials */
  credentials?: string | Record<string, unknown>;
  /** Collection names for different data types (required - configure your own schema) */
  collections: {
    /** Collection for test run summaries */
    testRuns: string;
    /** Collection for individual test executions */
    testCases: string;
    /** Collection for latest test case status */
    latestTestCases: string;
  };
  /** Optional conditions to skip writes */
  skipConditions?: {
    /** Skip writes for pull requests (default: false) */
    skipPullRequests?: boolean;
  };
  /** Retry configuration */
  retry?: {
    /** Maximum number of retries (default: 3) */
    maxRetries?: number;
    /** Initial delay in milliseconds (default: 1000) */
    initialDelayMs?: number;
    /** Maximum delay in milliseconds (default: 10000) */
    maxDelayMs?: number;
  };
}

Authentication:

The FirestoreAdapter supports two authentication methods:

  1. Application Default Credentials (ADC) - Recommended: When credentials is not provided, the adapter uses Application Default Credentials.
# Set the GOOGLE_APPLICATION_CREDENTIALS environment variable
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/service-account-key.json

# Or use gcloud CLI to authenticate
gcloud auth application-default login
  1. Service Account JSON: Provide service account credentials directly as a JSON string or object.
// From environment variable (JSON string)
new FirestoreAdapter({
  projectId: 'my-gcp-project',
  credentials: process.env.GOOGLE_APPLICATION_CREDENTIALS_JSON,
});

Retry Logic:

The adapter automatically retries failed operations with exponential backoff. Retries are only attempted for transient errors (network issues, rate limits, etc.). Non-retryable errors (authentication, invalid data) fail immediately.

Environment Variables:

  • TRIGGER_TYPE: Used by skipPullRequests condition. Set to 'pull_request' to skip writes.

Note: This adapter requires @google-cloud/firestore to be installed as a dependency.

Creating Custom Adapters

Adapters implement the ResultAdapter interface:

import type { ResultAdapter, CoreTestResult, CoreTestRun } from '@lytics/playwright-reporter';

export class MyCustomAdapter implements ResultAdapter {
  async initialize(): Promise<void> {
    // Setup connection, create resources, etc.
  }

  async writeTestResult(result: CoreTestResult): Promise<void> {
    // Write individual test result
  }

  async writeTestRun(run: CoreTestRun): Promise<void> {
    // Write test run summary
  }

  async close(): Promise<void> {
    // Cleanup resources, close connections, etc.
  }
}

License

MIT