npm-модуль для унифицированного запуска тестов с поддержкой Jest и Playwright.
- Runtime: Node.js 20+
- Language: TypeScript (strict mode)
- Package Manager: npm
- Testing: Jest
- Validation: Zod
Модуль основан на наработках из:
- MCP Moira:
/Users/mike/WebstormProjects/mcp-moira-dev2/tests/scripts/ - Claude Supervisor:
/Users/mike/WebstormProjects/claude-supervisor-dev/tests/scripts/
FORBIDDEN:
- Direct commits to
masterbranch - Amend commits in
master
ALWAYS:
- Create feature branch from master
- Make commits in feature branch
- Create PR
- Merge via GitHub after approval
npm install
npm run dev| Script | Purpose |
|---|---|
npm run dev |
Watch mode for CLI |
npm run build |
Build TypeScript |
npm test |
Run all tests |
npm run test:unit |
Unit tests only |
npm run lint |
Run ESLint |
npm run format |
Run Prettier |
# Basic usage
testfold # Run all suites
testfold unit integration # Run specific suites
# Options
testfold -c custom.config.ts # Custom config
testfold -e staging # Environment
testfold -r json # Override reporter
testfold -r console,json,timing-text # Multiple reporters
testfold -r ./my-reporter.ts # Custom reporter from file
testfold -g "auth" # Filter by test name
testfold --grep-invert "slow" # Exclude tests by pattern
testfold -f auth.test.ts # Filter by file
testfold --dry-run # Preview commands without running
testfold --dry-run unit # Preview only unit suite
# Pass-through to test framework
testfold -- --testNamePattern="auth" # Args after -- passed to test command
testfold -- --verbose --coverage # Multiple pass-through args
# Path prefix resolution (automatic)
testfold unit -- user # "user" resolved to tests/unit/user.test.ts
testfold unit -- auth # If unique match, resolved to full path| Code | Meaning |
|---|---|
| 0 | All tests passed |
| 1 | One or more tests failed |
| 2 | Infrastructure error (config, parse, spawn failure) |
| 3 | Suite killed by timeout |
npm test # All tests
npm run test:unit [file] # Unit only
npm run test:integration # Integration only{category}.json- structured results{category}.log- full outputfailures/{category}/- individual failure reports
ALWAYS use project temp directory:
./claude-temp-files/script.ts
./claude-temp-files/analysis.jsonFORBIDDEN:
/tmp/file.ts
./tmp/file.tssrc/
├── index.ts # Public exports
├── config/ # Config loading & validation
├── core/ # Runner, orchestrator, executor
├── parsers/ # Jest, Playwright, Custom parsers
├── reporters/ # Console, JSON, Markdown, Timing, Timing-Text, Text, Summary-Log, Custom reporters
├── utils/ # ANSI strip, file ops, sanitization, path resolver, progress formatter
└── cli/ # CLI entry point
const ConfigSchema = z.object({
artifactsDir: z.string(),
testsDir: z.string().optional().default('./tests'), // For path prefix resolution
suites: z.array(SuiteSchema),
parallel: z.boolean().optional().default(true),
failFast: z.boolean().optional().default(false),
reporters: z.array(z.string()).optional(),
});interface Parser {
parse(jsonPath: string, logPath: string): Promise<ParseResult>;
}
interface ParseResult {
passed: number;
failed: number;
skipped: number;
duration: number;
failures: FailureDetail[];
}// Suite config with custom parser
{
name: 'my-suite',
type: 'custom',
command: 'my-test-runner',
resultFile: 'results.json',
parser: './parsers/my-parser.ts' // Path to custom parser
}
// Custom parser module (supports default class, default object, or named 'parser' export)
import type { Parser, ParseResult } from 'testfold';
export default class MyParser implements Parser {
async parse(jsonPath: string, logPath?: string): Promise<ParseResult> {
// Parse logic
return { passed: 0, failed: 0, skipped: 0, duration: 0, success: true, failures: [] };
}
}interface Reporter {
onStart(suites: string[]): void;
onSuiteComplete(suite: string, result: SuiteResult): void;
onComplete(results: AggregatedResults): void;
}| Reporter | Output |
|---|---|
console |
Terminal output with colors, test hierarchy, consolidated failures, re-run instructions, agent block, JSON summary line, coverage hint. Progress to stderr |
json |
summary.json with failedTests[], errors[], per-suite testResults[] |
markdown-failures |
Per-test failure reports in failures/ |
timing |
timing.json with slowest tests sorted by duration |
timing-text |
Per-suite .txt files with top slowest tests and file grouping |
text |
Plain text output for CI (no ANSI, no markdown) |
summary-log |
ANSI-free test-summary.log with summary table |
| Custom path | ./my-reporter.ts — custom Reporter loaded from file |
Orchestrator attempts to parse test results even when executor returns non-zero exit code. Partial results extracted from failed runs.
Load environment-specific .env files via CLI flag -e. Supports static baseUrl or dynamic URL extraction via urlExtractor function.
Running a single suite only cleans that suite's artifacts. Previous runs of other suites are preserved.
Pass-through arguments that look like file prefixes are resolved to full paths. Single-match prefixes resolved automatically, multi-match kept unchanged.
Локальная папка проекта временно называется claude-test-runner, но пакет и репозиторий переименованы в testfold.
Exit codes 0-3 instead of boolean. See exit codes table above. ErrorCategory on SuiteResult enables categorization.
--dry-run prints resolved commands for each suite without execution.
On failure, all failing tests across all suites shown in one section with suite name, test name, file path, truncated error.
Exact CLI commands to re-run failed tests. Framework-appropriate flags, grouped by suite, per-file commands (≤5 unique files).
=== AGENT INSTRUCTIONS === delimited block with failure count, affected suites, top error patterns, suggested actions. Only on failure.
TESTFOLD_RESULT:{json} as the very last line of console output. Always printed. Contains success, passed, failed, skipped, duration, exitCode.
Checks for coverage/ directory in project root. Prints path when found.
Orchestrator streams executor output through progress formatter. Emits [SuiteName] … N tests (X passed, Y failed) Ns to stderr every 10 tests. Supports Jest and Playwright patterns.