Skip to main content

API Reference

API reference for the batch runner, scenario runner, configuration, assertions, and reporters in @powerduck/openapi-cli. The exports listed below are available from the package root.

Exports overview​

ExportKindDescription
runTestsfunctionRun all collected operations and return a TestReport
resolveConfigfunctionResolve a CliConfig from args / config file / defaults
loadSpecasync functionLoad and dereference a spec from a local path or remote URL
isRemoteSpecfunctionWhether a spec path starts with http(s)://
DEFAULT_CONFIGconstBuilt-in default values
runDeclarativeAssertionsfunctionEvaluate an array of DeclarativeAssertion against a response
extractAssertionsfunctionPull x-tests declarative assertions from an operation
extractPostmanScriptsfunctionPull the Postman test script string from an operation
resolveJsonPathfunctionMinimal JSONPath resolver (dot notation + array indices)
generateJsonReportfunctionWrite report.json to disk, returning the file path
generateCliReportfunctionBuild the colored CLI report string (without printing)
printCliReportfunctionPrint the CLI report to stdout and return the string
generateHtmlReportfunctionWrite report.html to disk, returning the file path
CliArgstypeShape of the CLI/config resolution input
DeclarativeAssertiontypeOne declarative assertion object
CliConfigtypeThe central configuration interface
TestReporttypeThe full report returned by runTests
TestResulttypeOne operation's test outcome
TestSummarytypeAggregate pass/fail counts
AssertionResulttypeOne assertion outcome
ReportFormattype"json" | "cli" | "html"
ProtocolNametype"http" | "sse" | "websocket" | "graphql" | "grpc" | "mcp"
TestStatustype"passed" | "failed" | "skipped" | "error"
AuthConfigtypeAuthentication configuration
TlsConfigtypeTLS / certificate configuration
FilterConfigtypeOperation filter
collectOperationsfunctionCollect operations with the batch filter applied
executeStepasync functionExecute one operation with per-step overrides
buildSummaryfunctionCalculate counts and pass rate from test results
formatAssertionErrorfunctionConvert an assertion error to readable text
buildImplicitAssertionsfunctionBuild protocol-specific default assertions
runScenarioasync functionRun ordered steps with shared variables and data-driven iterations
resolveStepsfunctionResolve all scenario references before sending requests
applyExtractsfunctionExtract response values into string variables
stepReffunctionNormalize a step reference
ScenarioDefinition, ScenarioStep, ScenarioStepRequest, ScenarioExtracttypesScenario input and extraction definitions
ScenarioStatus, ScenarioStepResult, ScenarioEvent, ScenarioEventType, ScenarioReport, RunScenarioOptionstypesScenario results, live events, and execution options

runTests​

runTests(config: CliConfig): Promise<TestReport>

Loads the spec with loadSpec, collects operations (honoring config.filter), executes them with bounded concurrency (min(config.concurrency ?? 5, queue.length)), runs declarative and Postman assertions, adds implicit protocol assertions when no user assertions exist, sorts results by path then method, and returns a TestReport.

The returned TestReport has shape:

interface TestReport {
summary: TestSummary;
results: TestResult[];
config: CliConfig;
generatedAt: string; // ISO timestamp
version: string; // runner version string
}

resolveConfig​

resolveConfig(args: CliArgs): CliConfig

Merges args (CLI flags), an optional JSON config file (args.config), and DEFAULT_CONFIG. Loads the resolved envFile if present, then expands ${ENV_VAR} references in serverUrl, proxy, header values, auth.token, and variable values. Throws "No OpenAPI spec path provided..." when no spec is given, and Invalid proxy URL: <url> when proxy is unparseable.

CliArgs mirrors the CLI flags:

interface CliArgs {
spec?: string;
server?: string;
output?: string;
format?: string;
method?: string;
path?: string;
tag?: string;
operationId?: string;
concurrency?: number;
timeout?: number;
proxy?: string;
ca?: string;
cert?: string;
key?: string;
insecure?: boolean;
header?: string[];
bearer?: string;
variable?: string[];
config?: string;
env?: string;
failOnError?: boolean;
grpcReflection?: boolean;
grpcProto?: string[];
mcpTransport?: string;
mcpCommand?: string;
mcpArgs?: string;
mcpCwd?: string;
}

loadSpec​

loadSpec(config: CliConfig): Promise<unknown>

Reads config.specPath. If isRemoteSpec is true, it fetches over HTTP(S) (following up to 5 redirects, enforcing config.timeout, with User-Agent: @powerduck/openapi-cli); otherwise it reads the local file. The body is parsed as JSON and must be an object with a paths object. Internal $refs are then best-effort dereferenced; failures leave the spec untouched.

isRemoteSpec​

isRemoteSpec(specPath: string): boolean

Returns true when the trimmed specPath matches /^https?:\/\//i.

DEFAULT_CONFIG​

const DEFAULT_CONFIG = {
outputDir: "./openapi-cli-report",
formats: ["json", "cli", "html"],
concurrency: 5,
timeout: 30000,
failOnError: true,
grpcReflection: true,
mcpTransport: "streamable-http",
};

Assertion engine​

runDeclarativeAssertions​

runDeclarativeAssertions(
assertions: DeclarativeAssertion[],
ctx: { status?: number; headers?: Record<string,string>; body?: unknown; bodyText?: string; durationMs: number },
): AssertionResult[]

Evaluates every declarative assertion against a response context. Errors during evaluation are captured as a failed AssertionResult.

extractAssertions​

extractAssertions(operation: any, pathItem?: any): DeclarativeAssertion[]

Collects x-tests arrays from both the path item and the operation (path-item first, then operation), keeping only entries that are objects with both name and assert.

extractPostmanScripts​

extractPostmanScripts(operation: any): string | undefined

Returns the string at operation["x-postman-scripts"].test, if present.

resolveJsonPath​

resolveJsonPath(obj: unknown, path: string): unknown

Minimal resolver supporting leading $. or $, dot notation, and numeric array indices (e.g. $.data.items[0].id). Returns undefined when a segment does not exist.

DeclarativeAssertion​

interface DeclarativeAssertion {
name: string;
assert: "status" | "header" | "bodyContains" | "jsonPath" | "responseTime" | "bodyEquals";
value?: number; // assert=status
key?: string; // assert=header
contains?: string; // assert=header / bodyContains
path?: string; // assert=jsonPath
equals?: unknown; // assert=jsonPath
exists?: boolean; // assert=jsonPath
max?: number; // assert=responseTime
body?: string; // assert=bodyEquals
}

Reporters​

generateJsonReport​

generateJsonReport(report: TestReport, outputDir: string): string

The report may contain request headers, bodies, variables, and authentication settings; redact sensitive values before sharing or persisting it.

Creates outputDir (recursively) and writes report.json as JSON.stringify(report, null, 2). Returns the absolute file path.

generateCliReport​

generateCliReport(report: TestReport): string

Builds the colored, ANSI-escape CLI report string (header, summary bar, progress bar, per-result rows, assertion details) without printing it.

printCliReport​

printCliReport(report: TestReport): string

Calls generateCliReport, prints the result with console.log, and returns the string.

generateHtmlReport​

generateHtmlReport(report: TestReport, outputDir: string): string

Creates outputDir and writes a self-contained report.html (summary strip, progress bar, filter buttons, expandable rows, light/dark mode). Returns the file path.

Result types​

TestResult​

interface TestResult {
operationId: string;
path: string;
method: string;
protocol: ProtocolName | string;
status: TestStatus;
durationMs: number;
request?: {
method?: string;
url?: string;
headers?: Record<string, string>;
body?: unknown;
target?: string;
};
response?: {
status?: number;
statusText?: string;
contentType?: string;
sizeBytes?: number;
body?: unknown;
text?: string;
headers?: Record<string, string>;
events?: unknown[];
streaming?: boolean;
};
assertions?: AssertionResult[];
error?: string;
timestamp: string;
}

TestSummary​

interface TestSummary {
total: number;
passed: number;
failed: number;
errors: number;
skipped: number;
durationMs: number;
passRate: number; // rounded to one decimal
}

AssertionResult​

interface AssertionResult {
name: string;
passed: boolean;
error?: string;
}

Scenario runner​

runScenario​

runScenario(definition: ScenarioDefinition, options: RunScenarioOptions): Promise<ScenarioReport>

Runs steps in order with a shared variable scope per scenario iteration. It resolves all operation references before execution and ignores the batch filter, so any operation in the spec may be targeted. Variables start from config and scenario values; extracted values become available to later steps. stopOnFailure defaults to true. options.signal cancels the run and remaining steps are reported as skipped; exceptions from onEvent listeners do not abort execution.

Scenario-level data runs the whole sequence with a fresh scope per row. iterations can request additional repetitions; the effective count is the greater of the declared count and row count, with a maximum of 1000. Step-level request.data repeats that step and only the last execution's extracts persist into the shared scope.

Scenario types​

The following declarations describe scenario inputs and outputs. ScenarioDataRow and ScenarioIterations are supporting shapes shown here for clarity; they are not named exports from the package root. Their shapes are available through the public interfaces.

import type { RequestValues } from "@powerduck/openapi-request";

interface ScenarioExtract {
name: string;
from: "body" | "header" | "status";
path?: string;
key?: string;
}

type ScenarioDataRow = Record<string, string>;

interface ScenarioStepRequest {
values?: RequestValues;
serverUrl?: string;
extract?: ScenarioExtract[];
assertions?: DeclarativeAssertion[];
data?: ScenarioDataRow[];
}

interface ScenarioStep {
ref?: string;
method?: string;
path?: string;
name?: string;
request?: ScenarioStepRequest;
skip?: boolean;
}

interface ScenarioDefinition {
name: string;
description?: string;
steps: ScenarioStep[];
variables?: Record<string, string>;
stopOnFailure?: boolean;
data?: ScenarioDataRow[];
iterations?: number;
}

type ScenarioStatus = "passed" | "failed" | "error" | "cancelled";

interface ScenarioStepResult extends TestResult {
index: number;
ref: string;
name?: string;
scenarioIteration?: number;
scenarioIterations?: number;
stepIteration?: number;
stepIterations?: number;
extracted?: Record<string, string>;
variablesAfter?: Record<string, string>;
notRun?: boolean;
notRunReason?: string;
}

type ScenarioEventType =
| "scenario:start"
| "step:start"
| "step:finish"
| "step:skip"
| "scenario:finish"
| "scenario:cancel";

interface ScenarioEvent {
type: ScenarioEventType;
scenario: string;
stepIndex?: number;
step?: ScenarioStepResult;
status?: ScenarioStatus;
message?: string;
scenarioIteration?: number;
scenarioIterations?: number;
stepIteration?: number;
stepIterations?: number;
}

interface ScenarioIterations {
scenarioCount: number;
stepCounts: number[];
}

interface ScenarioReport {
name: string;
description?: string;
status: ScenarioStatus;
summary: TestSummary;
steps: ScenarioStepResult[];
variables: Record<string, string>;
iterations?: ScenarioIterations;
config: CliConfig;
startedAt: string;
durationMs: number;
generatedAt: string;
version: string;
}

interface RunScenarioOptions {
config: CliConfig;
spec?: unknown;
onEvent?: (event: ScenarioEvent) => void;
signal?: AbortSignal;
}

stepRef and resolveSteps​

stepRef(step: ScenarioStep): string
resolveSteps(definition: ScenarioDefinition, operations: OperationInfo[]): ResolvedStep[]

stepRef prefers an explicit method and path, otherwise normalizes ref while preserving a bare operationId. resolveSteps returns entries containing step, op, and the normalized ref; it throws if any reference cannot be found, including skipped steps.

applyExtracts​

applyExtracts(extracts: ScenarioExtract[] | undefined, response: TestResult["response"]): Record<string, string>

Reads body values via JSONPath, headers case-insensitively, or the response status. Missing and null values are omitted; other values are converted to strings, with objects serialized as JSON.

Runner helpers​

The helper signatures use supporting types that are not named root exports. Infer them from the public functions instead of importing internal files:

import { collectOperations, executeStep, resolveSteps } from "@powerduck/openapi-cli";

type OperationInfo = ReturnType<typeof collectOperations>[number];
type StepExecutionOptions = Parameters<typeof executeStep>[2];
type StepExecution = Awaited<ReturnType<typeof executeStep>>;
type ResolvedStep = ReturnType<typeof resolveSteps>[number];

collectOperations​

collectOperations(spec: any, config: CliConfig): OperationInfo[]

Collects standard and additional operations, assigns an operationId fallback, infers each protocol, and applies config.filter. Each entry contains path, method, operation, pathItem, operationId, and protocol.

executeStep​

executeStep(client: ReturnType<typeof createClient>, op: OperationInfo, options: StepExecutionOptions): Promise<StepExecution>

The client comes from createClient in @powerduck/openapi-request. Options require config and spec, with optional signal, variables, values, serverUrl, and extraAssertions. The result contains result, normalized response, optional request, and the script-produced variable scope env. Batch and scenario runners share this execution path.

buildSummary​

buildSummary(results: TestResult[], durationMs: number): TestSummary

Counts passed, failed, error, and skipped results. The pass rate is passed divided by total, rounded to one decimal place; an empty result set has a rate of zero.

formatAssertionError​

formatAssertionError(error: unknown): string | undefined

Returns a readable message from a string, Error, message or msg field, then falls back to serialization. Falsy input yields undefined.

buildImplicitAssertions​

buildImplicitAssertions(protocol: string, response: TestResult["response"]): AssertionResult[]

Builds the checks listed under Implicit assertions. Unknown protocols produce no implicit checks.

Implicit assertions​

When an operation defines neither x-tests nor a Postman script, the runner adds one protocol-specific implicit assertion:

ProtocolImplicit check
http, sseHTTP status is 2xx
graphqlHTTP status 2xx and no non-empty top-level errors array
grpcgRPC status code is 0 (OK)
mcpJSON-RPC response has result and no error
websocketConnection reached open with no error event