junit-converter
Version:
Test report files to JUnit XML converter
541 lines (511 loc) • 13.3 kB
TypeScript
/**
* Source: https://github.com/ctrf-io/ctrf-js/
*/
/**
* MIT License
*
* Copyright (c) 2024 Matthew Poulton-White
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/**
* CTRF TypeScript Types
* Generated from the CTRF JSON Schema specification
*/
// ============================================================================
// Core Types
// ============================================================================
/**
* The root CTRF report object
*
* @group Core Types
*/
export interface CTRFReport {
/** Must be 'CTRF' */
reportFormat: "CTRF";
/** Semantic version of the CTRF specification */
specVersion: string;
/** Unique identifier for this report (UUID v4) */
reportId?: string;
/** ISO 8601 timestamp when the report was generated */
timestamp?: string;
/** Name of the tool/library that generated this report */
generatedBy?: string;
/** The test results */
results: Results;
/** Run-level insights computed from historical data */
insights?: Insights;
/** Reference to a baseline report for comparison */
baseline?: Baseline;
/** Custom metadata */
extra?: Record<string, unknown>;
}
/**
* Container for test results
*
* @group Core Types
*/
export interface Results {
/** Information about the test tool */
tool: Tool;
/** Aggregated test statistics */
summary: Summary;
/** Array of individual test results */
tests: Test[];
/** Environment information */
environment?: Environment;
/** Custom metadata */
extra?: Record<string, unknown>;
}
/**
* Test tool information
*
* @group Core Types
*/
export interface Tool {
/** Name of the test tool (e.g., 'jest', 'playwright') */
name: string;
/** Version of the test tool */
version?: string;
/** Custom metadata */
extra?: Record<string, unknown>;
}
/**
* Aggregated test statistics
*
* @group Core Types
*/
export interface Summary {
/** Total number of tests */
tests: number;
/** Number of passed tests */
passed: number;
/** Number of failed tests */
failed: number;
/** Number of skipped tests */
skipped: number;
/** Number of pending tests */
pending: number;
/** Number of tests with other status */
other: number;
/** Number of flaky tests */
flaky?: number;
/** Number of test suites */
suites?: number;
/** Start timestamp (Unix epoch milliseconds) */
start: number;
/** Stop timestamp (Unix epoch milliseconds) */
stop: number;
/** Total duration in milliseconds */
duration?: number;
/** Custom metadata */
extra?: Record<string, unknown>;
}
/**
* Individual test result
*
* @group Core Types
*/
export interface Test {
/** Unique test identifier (UUID) */
id?: string;
/** Test name */
name: string;
/** Test execution status */
status: TestStatus;
/** Test duration in milliseconds */
duration: number;
/** Start timestamp (Unix epoch milliseconds) */
start?: number;
/** Stop timestamp (Unix epoch milliseconds) */
stop?: number;
/** Test suite hierarchy */
suite?: string[];
/** Error message (for failed tests) */
message?: string;
/** Stack trace (for failed tests) */
trace?: string;
/** Code snippet where failure occurred */
snippet?: string;
/** AI-generated analysis or suggestion */
ai?: string;
/** Line number where test is defined or failed */
line?: number;
/** Original status from the test framework */
rawStatus?: string;
/** Tags for categorization */
tags?: string[];
/** Test type (e.g., 'unit', 'integration', 'e2e') */
type?: string;
/** Path to the test file */
filePath?: string;
/** Number of retry attempts */
retries?: number;
/** Details of each retry attempt */
retryAttempts?: RetryAttempt[];
/** Whether the test is flaky */
flaky?: boolean;
/** Standard output captured during test */
stdout?: string[];
/** Standard error captured during test */
stderr?: string[];
/** Thread/worker ID that ran this test */
threadId?: string;
/** Browser name (for browser tests) */
browser?: string;
/** Device name (for device tests) */
device?: string;
/** Base64 encoded screenshot */
screenshot?: string;
/** File attachments */
attachments?: Attachment[];
/** Test parameters (for parameterized tests) */
parameters?: Record<string, unknown>;
/** Test steps */
steps?: Step[];
/** Test-level insights */
insights?: TestInsights;
/** Custom metadata */
extra?: Record<string, unknown>;
}
/**
* Test status enum
*
* @group Core Types
*/
export type TestStatus = "passed" | "failed" | "skipped" | "pending" | "other";
/**
* Details of a test retry attempt
*
* @group Core Types
*/
export interface RetryAttempt {
/** Attempt number (1-indexed) */
attempt: number;
/** Status of this attempt */
status: TestStatus;
/** Duration of this attempt in milliseconds */
duration?: number;
/** Error message */
message?: string;
/** Stack trace */
trace?: string;
/** Line number */
line?: number;
/** Code snippet */
snippet?: string;
/** Standard output */
stdout?: string[];
/** Standard error */
stderr?: string[];
/** Start timestamp */
start?: number;
/** Stop timestamp */
stop?: number;
/** Attachments for this attempt */
attachments?: Attachment[];
/** Custom metadata */
extra?: Record<string, unknown>;
}
/**
* File attachment
*
* @group Core Types
*/
export interface Attachment {
/** Attachment name */
name: string;
/** MIME content type */
contentType: string;
/** Path to the attachment file */
path: string;
/** Custom metadata */
extra?: Record<string, unknown>;
}
/**
* Test step
*
* @group Core Types
*/
export interface Step {
/** Step name */
name: string;
/** Step status */
status: TestStatus;
/** Custom metadata */
extra?: Record<string, unknown>;
}
/**
* Environment information
*
* @group Core Types
*/
export interface Environment {
/** Custom report name */
reportName?: string;
/** Application name */
appName?: string;
/** Application version */
appVersion?: string;
/** Build identifier */
buildId?: string;
/** Build name */
buildName?: string;
/** Build number */
buildNumber?: number;
/** Build URL */
buildUrl?: string;
/** Repository name */
repositoryName?: string;
/** Repository URL */
repositoryUrl?: string;
/** Git commit SHA */
commit?: string;
/** Git branch name */
branchName?: string;
/** Operating system platform */
osPlatform?: string;
/** Operating system release */
osRelease?: string;
/** Operating system version */
osVersion?: string;
/** Test environment name */
testEnvironment?: string;
/** Whether the environment is healthy */
healthy?: boolean;
/** Custom metadata */
extra?: Record<string, unknown>;
}
// ============================================================================
// Insights Types
// ============================================================================
/**
* Run-level insights computed from historical data
*
* @group Insights
*/
export interface Insights {
/** Pass rate metric */
passRate?: MetricDelta;
/** Fail rate metric */
failRate?: MetricDelta;
/** Flaky rate metric */
flakyRate?: MetricDelta;
/** Average run duration metric */
averageRunDuration?: MetricDelta;
/** 95th percentile run duration metric */
p95RunDuration?: MetricDelta;
/** Average test duration metric */
averageTestDuration?: MetricDelta;
/** Number of historical runs analyzed */
runsAnalyzed?: number;
/** Custom metadata */
extra?: Record<string, unknown>;
}
/**
* Test-level insights computed from historical data
*
* @group Insights
*/
export interface TestInsights {
/** Pass rate metric */
passRate?: MetricDelta;
/** Fail rate metric */
failRate?: MetricDelta;
/** Flaky rate metric */
flakyRate?: MetricDelta;
/** Average test duration metric */
averageTestDuration?: MetricDelta;
/** 95th percentile test duration metric */
p95TestDuration?: MetricDelta;
/** Number of runs this test was executed in */
executedInRuns?: number;
/** Custom metadata */
extra?: Record<string, unknown>;
}
/**
* Metric with current value, baseline, and change
*
* @group Insights
*/
export interface MetricDelta {
/** Current value */
current?: number;
/** Baseline value for comparison */
baseline?: number;
/** Change from baseline (current - baseline) */
change?: number;
}
/**
* Reference to a baseline report
*
* @group Core Types
*/
export interface Baseline {
/** Report ID of the baseline report */
reportId: string;
/** Timestamp of the baseline report */
timestamp?: string;
/** Source description (e.g., 'main-branch', 'previous-run') */
source?: string;
/** Build number of the baseline */
buildNumber?: number;
/** Build name of the baseline */
buildName?: string;
/** Build URL of the baseline */
buildUrl?: string;
/** Git commit of the baseline */
commit?: string;
/** Custom metadata */
extra?: Record<string, unknown>;
}
// ============================================================================
// Utility Types
// ============================================================================
/**
* Result of schema validation
*
* @group Validation Options
*/
export interface ValidationResult {
/** Whether the report is valid */
valid: boolean;
/** Array of validation errors */
errors: ValidationErrorDetail[];
}
/**
* Details of a validation error
*
* @group Validation Options
*/
export interface ValidationErrorDetail {
/** Human-readable error message */
message: string;
/** JSON path to the error location */
path: string;
/** JSON Schema keyword that failed */
keyword: string;
}
/**
* Options for merging reports
*
* @group Merge Options
*/
export interface MergeOptions {
/** Remove duplicate tests by ID */
deduplicateTests?: boolean;
/** Recalculate summary from merged tests */
mergeSummary?: boolean;
/** Strategy for handling environments */
preserveEnvironment?: "first" | "last" | "merge";
}
/**
* Criteria for filtering and finding tests.
*
* @group Query & Filter Options
*/
export interface FilterCriteria {
/** Filter by test ID (UUID) */
id?: string;
/** Filter by test name */
name?: string;
/** Filter by status */
status?: TestStatus | TestStatus[];
/** Filter by tags */
tags?: string | string[];
/** Filter by suite */
suite?: string | string[];
/** Filter by flaky flag */
flaky?: boolean;
/** Filter by browser */
browser?: string;
/** Filter by device */
device?: string;
}
/**
* Options for insights calculation
*
* @group Insights Options
*/
export interface InsightsOptions {
/** Baseline report for comparison */
baseline?: CTRFReport;
/** Number of historical reports to analyze */
window?: number;
}
/**
* Options for ReportBuilder
*
* @group Builder Options
*/
export interface ReportBuilderOptions {
/** Automatically generate report ID */
autoGenerateId?: boolean;
/** Automatically set timestamp */
autoTimestamp?: boolean;
}
/**
* Options for TestBuilder
*
* @group Builder Options
*/
export interface TestBuilderOptions {
/** Automatically generate test ID */
autoGenerateId?: boolean;
}
/**
* Options for calculating summary
*
* @group Core Options
*/
export interface SummaryOptions {
/** Start timestamp */
start?: number;
/** Stop timestamp */
stop?: number;
}
/**
* Options for parsing JSON
*
* @group Core Options
*/
export interface ParseOptions {
/** Validate after parsing */
validate?: boolean;
}
/**
* Options for stringifying to JSON
*
* @group Core Options
*/
export interface StringifyOptions {
/** Pretty print with indentation */
pretty?: boolean;
/** Number of spaces for indentation (default: 2) */
indent?: number;
}
/**
* Options for validation
*
* @group Validation Options
*/
export interface ValidateOptions {
/** Specific spec version to validate against */
specVersion?: string;
}