CFN E2E Skill
Purpose
Smart parallel E2E test execution with automatic batching optimization. Reduces test execution time by 2-3x while staying within memory limits.
Core Innovation: Runs fast batches in parallel (2-3 concurrent), large batches sequentially to avoid overwhelming RAM while maximizing throughput.
Leaked workers: If a Playwright/test runner dies and orphans worker processes (reparented to PID 1),
.claude/hooks/reap-orphan-test-workers.shreaps them so they do not burn CPU/RAM.
Inputs
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
TEST_DIR |
string | No | tests/e2e |
Path to E2E test directory |
PARALLELISM |
integer | No | 3 |
Number of batches to run in parallel |
BATCH_SIZE |
enum | No | all |
fast, medium, large, all, smoke |
WORKERS |
integer | No | 3 |
Playwright workers per batch |
HEAP_SIZE_MB |
integer | No | 6144 |
Node heap size in MB |
TIMEOUT_MS |
integer | No | 30000 |
Per-test timeout in milliseconds |
Outputs
- stdout: Test progress and results summary
- exit code: 0 = all passed, 1 = failures, 2 = configuration error
- JSON report:
/tmp/cfn-e2e-results-<timestamp>.json
Usage
Basic Usage
# Run all E2E tests with smart batching
$HOME/.claude/skills/cfn-e2e/run-e2e-smart.sh
# Run only smoke tests
BATCH_SIZE=smoke ./.claude/skills/cfn-e2e/run-e2e-smart.sh
# Custom test directory
TEST_DIR=e2e ./.claude/skills/cfn-e2e/run-e2e-smart.sh
# Lower parallelism for 16GB RAM
PARALLELISM=2 WORKERS=2 HEAP_SIZE_MB=4096 ./.claude/skills/cfn-e2e/run-e2e-smart.sh
Analyze Batches Only
# Discover and categorize tests without running
$HOME/.claude/skills/cfn-e2e/analyze-batches.sh tests/e2e
Console / Network Guard (strict mode)
E2E runs pass even when a page logs console.error, throws an uncaught error, or
serves a 4xx/5xx: the assertions never look at the console or network. The
console-guard fixture closes that gap by failing any test whose page produced a
console error, a page error, a same-origin 4xx/5xx response, or a failed request.
Install (copy the fixture into your project)
Copy
lib/console-guard.tsto your project'stests/e2e/fixtures/console-guard.ts.Swap the import in each spec (the extended
test/expectare drop-in):// before import { test, expect } from '@playwright/test'; // after import { test, expect } from '../fixtures/console-guard';Adjust the relative path to where the spec lives. Dependency-free beyond
@playwright/test.
Opt out (per test)
Some tests exercise the error path on purpose. Annotate those with
allow-console-errors and the guard skips its teardown assertions:
test('renders the client-side error banner',
{ annotation: { type: 'allow-console-errors', description: 'asserts the error path' } },
async ({ page }) => { /* ... */ });
Enforce wiring in CI (--strict-console)
# Fail the run if no spec imports the console-guard fixture.
$HOME/.claude/skills/cfn-e2e/run-e2e-smart.sh --strict-console
# Equivalent via env:
CFN_E2E_STRICT_CONSOLE=1 ./.claude/skills/cfn-e2e/run-e2e-smart.sh
Strict mode greps the spec files and records console_guard in the results JSON:
present (every spec imports the fixture), partial (some do), or absent
(none). absent exits 1. Strict mode also aggregates any console-violation
attachments and screenshots from test-results/** into two new results-JSON
arrays: artifacts and failed_files. Non-strict output is unchanged.
WSL2 note
The guard adds zero extra memory: listeners run in-process on the existing
page object (no new browser, worker, or process), so it does not affect batch
sizing or the WSL2 memory profile.
Batch Heuristics
| Category | Test Count | Typical Duration | Parallelism |
|---|---|---|---|
| Fast | < 10 tests | 30-60 sec | 3-4 concurrent |
| Medium | 10-50 tests | 2-5 min | 2-3 concurrent |
| Large | 50+ tests | 4-8 min | Sequential |
Configuration
Environment Variables
# Node.js heap size (default: 6GB for 48GB RAM systems)
export NODE_OPTIONS="--max-old-space-size=6144"
# Playwright workers per batch
export PLAYWRIGHT_WORKERS=3
# Test timeout
export PLAYWRIGHT_TIMEOUT=30000
Project Requirements
- Playwright installed:
npx playwright --version - Test files pattern:
*.spec.tsor*.test.ts - playwright.config.ts: Standard Playwright configuration
Memory Profiles
| RAM | HEAP_SIZE_MB | WORKERS | PARALLELISM |
|---|---|---|---|
| 16GB | 4096 | 2 | 2 |
| 32GB | 5120 | 2-3 | 3 |
| 48GB | 6144 | 3 | 3 |
| 64GB+ | 8192 | 4 | 4 |
Performance Metrics
| Metric | Single Run | Smart Batched | Improvement |
|---|---|---|---|
| Total Time | 90 min | 33 min | 2.7x faster |
| Peak RAM | ~2GB | 9-14GB | Safe for 48GB |
| Test Count | 568 tests | 568 tests | Same coverage |
Dependencies
- Node.js v18+
- Playwright v1.40+
- Bash 4.0+
- CFN Utilities (optional, for structured logging)
Execution Modes
Task Mode (CFN Loop)
For autonomous E2E execution with iteration on failures:
/cfn-loop-task "Run E2E tests and fix failures" --mode=standard
This triggers the full CFN Loop workflow:
- Loop 3: Implementation agents run E2E tests
- Gate Check: Validates pass rate against threshold
- Loop 2: Validator agents review failures
- Product Owner: Decides PROCEED/ITERATE/ABORT
Command reference: .claude/commands/cfn-loop-task.md
Error Mode (Fix Failures)
When E2E tests fail and need fixing:
/cfn-fix-errors typescript --max-parallel=5
This triggers the error coordination workflow:
- Phase 0: Fix root-cause files (type definitions, configs)
- Phase 1: Parallel fixes for remaining files
- Phase 2: Cross-file cleanup
Command reference: .claude/commands/cfn-fix-errors.md
Parallel Mode (Pipeline Execution)
Not available. cfn-parallel-execute was documented but never built: no skill of that name
exists on disk or in git history. Route "in parallel" and "parallel execution" requests to Task
Mode (/cfn-loop-task), which spawns and replaces agents itself, or to Direct Mode below.
Direct Mode (Script Only)
For simple test execution without CFN orchestration:
$HOME/.claude/skills/cfn-e2e/run-e2e-smart.sh
Integration
CFN Loop Integration
# Full autonomous loop with E2E validation
/cfn-loop-task "Run E2E tests" --mode=standard --config='{"batch_size":"smoke"}'
# On failures, trigger error fixing
/cfn-fix-errors typescript
CI/CD Integration
# GitHub Actions example
- name: Run E2E Tests
run: |
PARALLELISM=2 WORKERS=2 ./.claude/skills/cfn-e2e/run-e2e-smart.sh
env:
NODE_OPTIONS: --max-old-space-size=4096
Files
| File | Purpose |
|---|---|
SKILL.md |
This documentation |
run-e2e-smart.sh |
Main batched test runner (supports --strict-console) |
analyze-batches.sh |
Test discovery and categorization |
lib/batch-runner.sh |
Batch execution utilities |
lib/console-guard.ts |
Playwright console/network guard fixture (copy into project) |
tests/test-strict-console.sh |
Bash test for --strict-console wiring detection |
tests/console-guard.selftest.spec.ts |
Playwright self-test pair for the guard fixture |
Known Limitations
- WSL2 Memory Monitor: Kills processes >10% RAM per process
- Dev Server Overhead: Each batch may start/stop dev server
- Test Isolation: No shared state between batches
- Browser Instances: 2-3 workers × 2-3 batches = 4-9 browsers max
Troubleshooting
Tests killed unexpectedly
- Check WSL memory monitor:
~/.local/bin/wsl-memory-monitor.sh --status - Reduce WORKERS or PARALLELISM
- Reduce HEAP_SIZE_MB
Tests timing out
- Increase TIMEOUT_MS
- Check if dev server is running
- Verify network connectivity for external APIs
Batch analyzer finds no tests
- Verify TEST_DIR path
- Check file patterns (*.spec.ts, *.test.ts)
- Ensure playwright.config.ts exists
Version History
- 1.1.0 (2026-07-09): Console/network guard fixture (
lib/console-guard.ts) +--strict-consolewiring gate (W7/G43). Hardened batch arithmetic forset -e. - 1.0.0 (2025-01-17): Initial release with smart batching