Capture video recordings of automated test runs with synchronized browser logs, application events, and file changes. Built for CI pipelines, custom VMs, and computer-use agents.
Quick Start β’ CI/CD β’ Examples β’ API
# Install in your CI environment
npm install -g dashcam
# Authenticate with your API key (get it from app.testdriver.ai/team)
dashcam auth $TD_API_KEY
# Wrap your test command
dashcam record --title "E2E Test Run" &
DASHCAM_PID=$!
# Run your tests
npm run test:e2e
# Stop recording and auto-upload
dashcam stopThat's it! Your test run is recorded, uploaded, and ready to debug. π
π‘ Get your API key from app.testdriver.ai/team
- Capture full video of test executions in CI/CD
- High-quality video powered by FFmpeg
- Background recording that runs alongside your tests
- Works with any test framework (Playwright, Selenium, Cypress, Puppeteer, etc.)
Synchronize logs with video timeline for complete observability:
-
π Application Logs: Tail any log file in real-time
dashcam logs --add --name=app-logs --type=file --file=/var/log/myapp.log
-
π Browser Events: Capture console logs, network requests, and navigation
dashcam logs --add --name=webapp --type=web --pattern="*localhost:3000*" -
π Perfect Sync: All events timestamped and aligned with video
- Automatic cloud storage after test completion
- Instant shareable links for team debugging
- Project organization and retention policies
- No manual intervention required
- π€ CI/CD Pipelines: Record test runs in GitHub Actions, GitLab CI, Jenkins, etc.
- π₯οΈ Custom VMs: Capture agent behavior on headless or virtual machines
- π§ AI Agents: Record computer-use agents (Claude, OpenAI, AutoGPT, etc.)
- οΏ½ Test Debugging: See exactly what happened when tests fail
- π QA Validation: Visual proof of test coverage and behavior
name: E2E Tests with Video Recording
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: npm install
- name: Install Dashcam
run: npm install -g dashcam
- name: Authenticate Dashcam
run: dashcam auth ${{ secrets.TD_API_KEY }}
- name: Start recording
run: |
dashcam record --title "E2E Tests - ${{ github.sha }}" \
--description "Automated test run on branch ${{ github.ref_name }}" \
--project ${{ secrets.DASHCAM_PROJECT_ID }} &
sleep 2
- name: Run tests
run: npm run test:e2e
- name: Stop recording and upload
if: always()
run: dashcam stope2e-tests:
stage: test
image: node:18
before_script:
- npm install -g dashcam
- dashcam auth $TD_API_KEY
script:
- dashcam record --title "E2E Tests - $CI_COMMIT_SHORT_SHA" &
- sleep 2
- npm run test:e2e
after_script:
- dashcam stop
variables:
TD_API_KEY: $TD_API_KEY
DASHCAM_PROJECT_ID: $DASHCAM_PROJECT_IDpipeline {
agent any
environment {
TD_API_KEY = credentials('dashcam-api-key')
}
stages {
stage('Setup') {
steps {
sh 'npm install -g dashcam'
sh 'dashcam auth $TD_API_KEY'
}
}
stage('Test') {
steps {
sh 'dashcam record --title "E2E Tests - ${BUILD_NUMBER}" &'
sh 'sleep 2'
sh 'npm run test:e2e'
}
}
}
post {
always {
sh 'dashcam stop'
}
}
}FROM node:18
# Install Dashcam
RUN npm install -g dashcam
# Your app setup
WORKDIR /app
COPY . .
RUN npm install
# Authenticate (use build args or runtime env)
ARG TD_API_KEY
RUN dashcam auth $TD_API_KEY
# Run tests with recording
CMD ["sh", "-c", "dashcam record --title 'Container Tests' & sleep 2 && npm test && dashcam stop"]Perfect for capturing AI agent behavior (Claude Computer Use, OpenAI Agents, AutoGPT, etc.):
import { spawn } from 'child_process';
async function runAgentWithRecording(agentTask) {
// Start recording
const recording = spawn('dashcam', [
'record',
'--title', `Agent Task: ${agentTask}`,
'--description', 'AI agent execution recording'
]);
// Wait for recording to initialize
await new Promise(resolve => setTimeout(resolve, 2000));
try {
// Run your AI agent
await runAgent(agentTask);
} finally {
// Always stop and upload recording
spawn('dashcam', ['stop']);
}
}import subprocess
import time
def record_agent_execution(task_description):
# Start recording
recording = subprocess.Popen([
'dashcam', 'record',
'--title', f'Agent Task: {task_description}',
'--description', 'AI agent execution'
])
time.sleep(2) # Let recording initialize
try:
# Run your agent code
run_my_agent()
finally:
# Stop and upload
subprocess.run(['dashcam', 'stop'])
# Usage
record_agent_execution("Browse web and fill form")npm install -g dashcamnpm install --save-dev dashcamThen in your package.json:
{
"scripts": {
"test:recorded": "dashcam record --title 'Test Run' & sleep 2 && npm test; dashcam stop"
}
}git clone https://github.com/testdriverai/dashcam.git
cd dashcam
npm install
npm link- Node.js 14.0.0 or higher
- FFmpeg (bundled automatically via ffmpeg-static)
- Display server (X11, Wayland, or macOS windowing system)
#!/bin/bash
set -e
# Setup
dashcam auth $TD_API_KEY
# Configure browser log tracking
dashcam logs --add --name=playwright --type=web --pattern="*localhost:*"
# Start recording
dashcam record --title "Playwright E2E Suite" \
--description "Full test suite execution" &
sleep 2
# Run Playwright tests
npx playwright test
# Stop and upload
dashcam stop#!/bin/bash
# Track application logs
dashcam logs --add --name=app --type=file --file=/var/log/app.log
dashcam logs --add --name=selenium --type=file --file=/var/log/selenium.log
# Start recording
dashcam record --title "Selenium Grid Tests" --project my-project &
sleep 2
# Run tests on Selenium Grid
pytest tests/selenium/ --hub=http://selenium-hub:4444
# Cleanup
dashcam stop// test-runner.js
import { exec } from 'child_process';
import { promisify } from 'util';
const execAsync = promisify(exec);
async function runTestsWithRecording() {
// Start recording
exec('dashcam record --title "Custom Tests" &');
// Wait for initialization
await new Promise(resolve => setTimeout(resolve, 2000));
try {
// Run your custom test framework
await execAsync('node tests/runner.js');
console.log('Tests completed successfully');
} catch (error) {
console.error('Tests failed:', error);
throw error;
} finally {
// Always upload the recording
await execAsync('dashcam stop');
}
}
runTestsWithRecording().catch(console.error);#!/bin/bash
# Setup log tracking for all services
dashcam logs --add --name=frontend --type=file --file=/var/log/frontend.log
dashcam logs --add --name=backend --type=file --file=/var/log/backend.log
dashcam logs --add --name=database --type=file --file=/var/log/postgres.log
# Track web apps
dashcam logs --add --name=app --type=web --pattern="*localhost:3000*"
dashcam logs --add --name=admin --type=web --pattern="*localhost:8080*"
# Start recording
dashcam record --title "Integration Tests" \
--description "# Multi-service test\n\nFrontend, backend, and database" &
sleep 2
# Start services
docker-compose up -d
# Wait for services to be ready
sleep 10
# Run integration tests
npm run test:integration
# Cleanup
docker-compose down
dashcam stopAuthenticate with your TestDriver API key.
π‘ Get your API key from app.testdriver.ai/team
dashcam auth 4e93d8bf-3886-4d26-a144-116c4063522dIn CI environments:
# Use environment variable
dashcam auth $TD_API_KEYStart a new background recording for your test run.
Options:
-t, --title <title>- Recording title (e.g., "E2E Test Suite")-d, --description <description>- Description (supports Markdown)-p, --project <project>- Project ID for organization-f, --fps <fps>- Frames per second (default: 30)-a, --audio- Include audio (experimental)-o, --output <path>- Custom output path-v, --verbose- Enable verbose logging
Examples:
# Basic test recording
dashcam record --title "Nightly E2E Tests" &
# With project and metadata
dashcam record --title "Sprint 23 Tests" \
--description "Testing new authentication flow" \
--project proj_abc123 &
# High FPS for smooth playback
dashcam record --fps 60 --title "UI Animation Tests" &Stop the current recording and upload it. Always call this in CI, even if tests fail.
dashcam stopCI Best Practice:
# GitHub Actions
- name: Stop recording and upload
if: always() # Run even if tests fail
run: dashcam stopCheck if a recording is in progress.
dashcam status
# Output:
# Recording in progress
# Duration: 45.2 seconds
# PID: 12345
# Started: 11/6/2025, 2:30:15 PM
# Title: Bug InvestigationManage log tracking configurations.
Options:
--add- Add a new log tracker--remove <id>- Remove a tracker by ID--list- List all configured trackers--status- Show tracking status with event counts--name <name>- Tracker name (required with --add)--type <type>- Type: "web" or "file" (required with --add)--pattern <pattern>- URL pattern for web trackers (can specify multiple)--file <file>- File path for file trackers
Examples:
# Add web tracker with multiple patterns
dashcam logs --add --name=social --type=web \
--pattern="*facebook.com*" \
--pattern="*twitter.com*"
# Add file tracker
dashcam logs --add --name=app --type=file --file=/var/log/app.log
# List all trackers
dashcam logs --list
# Check activity
dashcam logs --statusUpload a recording file or recover from interruption.
Options:
-t, --title <title>- Recording title-d, --description <description>- Description-p, --project <project>- Project ID--recover- Recover interrupted recording
Examples:
# Upload specific file
dashcam upload /path/to/recording.webm --title "My Recording"
# Recover from interruption
dashcam upload --recoverClear authentication credentials.
dashcam logoutWeb trackers support powerful wildcard patterns for capturing browser events during automated tests:
# Match any subdomain
dashcam logs --add --name=app --type=web --pattern="*.myapp.com*"
# Match specific paths
dashcam logs --add --name=admin --type=web --pattern="*app.com/admin/*"
# Match local dev servers (common in tests)
dashcam logs --add --name=dev --type=web --pattern="*localhost:*"
# Match test environments
dashcam logs --add --name=staging --type=web \
--pattern="*staging.myapp.com*" \
--pattern="*test.myapp.com*"# Ensure log files exist before starting
mkdir -p /var/log/myapp
touch /var/log/myapp/app.log
touch /var/log/myapp/error.log
# Add to tracking
dashcam logs --add --name=app --type=file --file=/var/log/myapp/app.log
dashcam logs --add --name=errors --type=file --file=/var/log/myapp/error.log
# Start recording
dashcam record --title "Test Run with Logs" &
sleep 2
# Your tests run and write logs
npm test
# All logs are synchronized with video
dashcam stopFor CI/CD environments, use environment variables instead of hardcoding:
# Set in CI environment
export TD_API_KEY="your-api-key"
export DASHCAM_PROJECT_ID="proj_abc123"
# Use in scripts
dashcam auth $TD_API_KEY
dashcam record --title "Tests" --project $DASHCAM_PROJECT_ID &// jest.config.js
module.exports = {
globalSetup: './test/setup.js',
globalTeardown: './test/teardown.js'
};
// test/setup.js
import { exec } from 'child_process';
export default async function globalSetup() {
console.log('Starting Dashcam recording...');
exec('dashcam record --title "Jest Test Suite" &');
await new Promise(resolve => setTimeout(resolve, 2000));
}
// test/teardown.js
import { execSync } from 'child_process';
export default async function globalTeardown() {
console.log('Stopping Dashcam recording...');
execSync('dashcam stop');
}// test/hooks.js
import { exec, execSync } from 'child_process';
before(async function() {
this.timeout(5000);
console.log('Starting recording...');
exec('dashcam record --title "Mocha Tests" &');
await new Promise(resolve => setTimeout(resolve, 2000));
});
after(function() {
this.timeout(10000);
console.log('Uploading recording...');
execSync('dashcam stop');
});# conftest.py
import subprocess
import time
import pytest
@pytest.fixture(scope="session", autouse=True)
def record_session():
# Start recording
print("Starting Dashcam recording...")
subprocess.Popen([
'dashcam', 'record',
'--title', 'Pytest Test Suite'
])
time.sleep(2)
yield
# Stop and upload
print("Stopping recording...")
subprocess.run(['dashcam', 'stop'])For web test automation (Playwright, Selenium, Puppeteer, etc.), install the Dashcam browser extension to capture:
- Console logs from your application
- Network requests and responses
- JavaScript errors and warnings
- Page navigation events
- Install extension (Chrome/Firefox)
- Start Dashcam CLI - Extension auto-connects via WebSocket
- Run your tests - All browser events captured automatically
- Upload recording - Browser logs included alongside video
The CLI automatically starts a WebSocket server on available ports (10368, 16240, 21855, 24301, or 25928).
For headless browsers in CI, browser extension features won't be available, but you can still:
- Record the full test execution video
- Track application log files
- Capture system-level events
# GitHub Actions - Always upload recording
- name: Stop recording
if: always()
run: dashcam stop# Give recording time to initialize
dashcam record --title "Tests" &
sleep 2 # Important!
npm test# Include branch, commit, or build number
dashcam record --title "E2E Tests - ${GITHUB_SHA}" \
--description "Branch: ${GITHUB_REF_NAME}"# Group recordings by project
dashcam record --project $DASHCAM_PROJECT_ID# Bash script with proper error handling
set -e
dashcam record --title "Tests" &
sleep 2
# Tests might fail, but still upload
npm test || TEST_FAILED=true
dashcam stop
# Exit with test status
if [ "$TEST_FAILED" = true ]; then
exit 1
fidashcam/
βββ bin/
β βββ dashcam.js # CLI entry point
βββ lib/
β βββ auth.js # Authentication
β βββ recorder.js # Screen recording engine
β βββ uploader.js # Cloud upload
β βββ processManager.js # Background process handling
β βββ logs/ # Log tracking core
β βββ tracking/ # File & activity tracking
β βββ extension-logs/ # Browser extension integration
β βββ websocket/ # WebSocket server
βββ examples/ # Example scripts
We love contributions! Here's how you can help:
- π Report bugs via GitHub issues
- π‘ Suggest features we should build
- π§ Submit PRs with improvements
- π Improve docs for clarity
MIT Β© TestDriver.ai
- Documentation: Full Guide
- Issues: GitHub Issues
- Website: testdriver.ai
Made with β€οΈ by the TestDriver.ai team