ctrf
v0.2.0
Published
CTRF reference implementation in TypeScript for creating and validating CTRF documents.
Maintainers
Readme
CTRF Reference Implementation TypeScript
The reference implementation in TypeScript for the Common Test Report Format (CTRF) specification.
CTRF Open Standard
CTRF is a community-driven open standard for test reporting.
By standardizing test results, reports can be validated, merged, compared, and analyzed consistently across languages and frameworks.
- CTRF Specification: https://github.com/ctrf-io/ctrf
The official specification defining the format and semantics - Discussions: https://github.com/orgs/ctrf-io/discussions
Community forum for questions, ideas, and support
[!NOTE]
⭐ Starring the CTRF specification repository (https://github.com/ctrf-io/ctrf) helps support the standard.
Installation
npm install ctrfQuick Start
import { ReportBuilder, TestBuilder, validateStrict } from 'ctrf'
// Build a report using the fluent API
const report = new ReportBuilder()
.tool({ name: 'jest', version: '29.0.0' })
.addTest(
new TestBuilder()
.name('should add numbers')
.status('passed')
.duration(150)
.build()
)
.addTest(
new TestBuilder()
.name('should handle errors')
.status('failed')
.duration(200)
.message('Expected 5 but got 4')
.build()
)
.build()
// Validate the report
validateStrict(report)API Reference
📚 Full API Documentation: API Reference
Types
Full TypeScript types are provided for all CTRF entities.
import type { CTRFReport, Test } from 'ctrf'
const report: CTRFReport = { /* ... */ }
const test: Test = { /* ... */ }Validation
import { isValid, validate, validateStrict, isCTRFReport, ValidationError } from 'ctrf'
// Quick validation (returns boolean)
if (isValid(report)) {
console.log('Report is valid')
}
// Detailed validation (returns ValidationResult)
const result = validate(report)
if (!result.valid) {
result.errors?.forEach(err => console.error(err.message))
}
// Strict validation (throws on invalid)
try {
validateStrict(report)
} catch (error) {
if (error instanceof ValidationError) {
console.error('Invalid report:', error.errors)
}
}
// Type guards
if (isCTRFReport(data)) {
// data is typed as CTRFReport
}Building Reports
import { ReportBuilder, TestBuilder } from 'ctrf'
// ReportBuilder - fluent API for constructing reports
const report = new ReportBuilder()
.tool({ name: 'vitest', version: '1.0.0' })
.environment({ os: 'linux', arch: 'x64' })
.addTest(/* ... */)
.build()
// TestBuilder - fluent API for constructing tests
const test = new TestBuilder()
.name('User login test')
.status('passed')
.duration(1500)
.suite(['Authentication', 'Login'])
.tags(['smoke', 'critical'])
.filePath('tests/auth/login.test.ts')
.browser('chrome')
.build()Parsing Reports
import { parse, stringify } from 'ctrf'
// Parse from string
const parsed = parse(jsonString)
// Stringify with formatting
const json = stringify(report, { pretty: true, indent: 2 })Filtering & Querying
import { filterTests, findTest } from 'ctrf'
// Filter by criteria
const filtered = filterTests(report, {
status: 'failed',
suite: 'Authentication',
tags: ['smoke'],
})
// Find specific test
const test = findTest(report, { name: 'login test' })
const testById = findTest(report, { id: 'test-uuid' })Merging Reports
import { merge } from 'ctrf'
// Merge multiple reports into one
const merged = merge([report1, report2, report3], {
deduplicateTests: true, // Remove duplicate tests by ID
})ID Generation
import { generateTestId, generateReportId } from 'ctrf'
// Generate deterministic test ID from properties
const testId = generateTestId({
name: 'should add numbers',
suite: ['Math', 'Addition'],
filePath: 'tests/math.test.ts',
})
// Generate random report ID
const reportId = generateReportId()Insights & Analytics
import { addInsights, isTestFlaky } from 'ctrf'
// Enrich a report with insights from historical data
const enriched = addInsights(
currentReport,
historicalReports,
{ baseline: baselineReport }
)
// Access insights
console.log(enriched.insights?.passRate) // { current: 0.95, baseline: 0.90, change: 0.05 }
console.log(enriched.insights?.flakyRate) // { current: 0.02, baseline: 0.05, change: -0.03 }
// Check if a test is flaky
const isFlaky = isTestFlaky(test)Summary Calculation
import { calculateSummary } from 'ctrf'
// Calculate summary from tests
const summary = calculateSummary(tests)
// { tests: 10, passed: 8, failed: 1, skipped: 1, pending: 0, other: 0, ... }Constants
import {
REPORT_FORMAT,
CURRENT_SPEC_VERSION,
SUPPORTED_SPEC_VERSIONS,
TEST_STATUSES,
CTRF_NAMESPACE,
} from 'ctrf'
REPORT_FORMAT // 'CTRF'
CURRENT_SPEC_VERSION // '0.0.0'
SUPPORTED_SPEC_VERSIONS // ['0.0.0']
TEST_STATUSES // ['passed', 'failed', 'skipped', 'pending', 'other']
CTRF_NAMESPACE // UUID namespace for deterministic IDsError Handling
import { validateStrict, ValidationError, ParseError } from 'ctrf'
try {
validateStrict(report)
} catch (error) {
if (error instanceof ValidationError) {
console.error('Schema validation failed:', error.errors)
}
}
try {
const parsed = parse(jsonString)
} catch (error) {
if (error instanceof ParseError) {
console.error('Invalid JSON:', error.message)
}
}Schema Access
import { schema, getSchema, getCurrentSpecVersion, getSupportedSpecVersions } from 'ctrf'
// Get the current JSON Schema
console.log(schema)
// Get schema for specific version
const v0_0Schema = getSchema('0.0.0')
// Get version info
const version = getCurrentSpecVersion() // '0.0.0'
const supported = getSupportedSpecVersions() // ['0.0.0']⚠️ Upgrading from v0.0.17?
Version 0.1.0 contains breaking changes. See the Migration Guide for detailed upgrade instructions.
