import './assert_dev_env.js';
/**
 * Error reachability coverage tracking.
 *
 * Tracks which declared error statuses (and specific error codes) are
 * actually exercised in tests. `ErrorCoverageCollector` records status
 * codes (optionally with body `error` codes) observed during test runs,
 * then `assert_error_coverage` compares against declared error schemas
 * to find uncovered error paths — reporting per-code when the declared
 * schema is a literal or enum, per-status otherwise.
 *
 * @module
 */
import { z } from 'zod';
import type { RouteSpec } from '../http/route_spec.js';
/**
 * Extract declared error code values from an error response schema.
 *
 * Recognizes schemas shaped like `z.object({error: z.literal(...)})` or
 * `z.object({error: z.enum([...])})` (incl. `looseObject`/`strictObject`).
 * Returns the set of declared code values, or `null` if the schema doesn't
 * expose a literal/enum `error` field (e.g., bare `ApiError` with `z.string()`).
 *
 * Used by coverage reporting to split a single declared status into per-code
 * rows when the route's error schema names specific codes.
 */
export declare const extract_declared_error_codes: (schema: z.ZodType) => Array<string> | null;
/** Uncovered entry — either a status-level row (no `code`) or a specific-code row. */
export interface UncoveredEntry {
    method: string;
    path: string;
    status: number;
    /** Declared code value missing, when the status's error schema names specific codes. */
    code?: string;
}
/** Options controlling which routes/statuses are considered for coverage. */
export interface CoverageFilterOptions {
    /** Routes to skip, in `'METHOD /path'` format. */
    ignore_routes?: Array<string>;
    /** HTTP status codes to skip. */
    ignore_statuses?: Array<number>;
}
/**
 * Tracks which route × status (and route × status × code) combinations have
 * been exercised in tests.
 *
 * Use `record()` to log an observed status (optionally with the body's `error`
 * code), or `assert_and_record()` to combine response validation with tracking
 * (auto-extracts `body.error` from the response when present).
 * After all tests, call `uncovered()` to find declared error paths never
 * exercised.
 *
 * An observation recorded without a code still satisfies "any-code" coverage
 * requirements for the same status — i.e., if a caller records just the status,
 * all declared codes for that status are considered covered. Per-code tracking
 * is additive: callers who know the body's `error` value should pass it to get
 * precise per-code gap reporting on routes with literal/enum error schemas.
 */
export declare class ErrorCoverageCollector {
    /**
     * Observed keys: `"METHOD /spec-path:STATUS"` or `"METHOD /spec-path:STATUS:CODE"`.
     *
     * Both shapes coexist — the code-less key marks the status as covered at any
     * code; a code-bearing key adds per-code precision.
     */
    readonly observed: Set<string>;
    /**
     * Record an observed error status (optionally with the body's `error` code) for a route.
     *
     * Resolves the concrete request path back to the spec template path
     * (e.g., `/api/accounts/abc` → `/api/accounts/:id`). When `code` is provided,
     * it is stored alongside the status for per-code coverage tracking.
     *
     * @param path - request path (may be concrete)
     * @param code - observed body `error` code (pass when the route's error
     *   schema declares specific codes via `z.literal` or `z.enum`)
     * @mutates `this.observed` - adds the resolved `"METHOD /spec-path:STATUS"`
     *   key (and the `:CODE` variant when `code` is provided).
     */
    record(route_specs: Array<RouteSpec>, method: string, path: string, status: number, code?: string): void;
    /**
     * Validate a response against its route spec and record the status.
     *
     * Wraps `assert_response_matches_spec` and records the status code. For
     * error responses, auto-extracts `body.error` from the JSON body (via a
     * cloned response, so the original stream stays usable) and records it
     * for per-code coverage. Pass an explicit `code` to override the
     * auto-extracted value or when the body was already consumed.
     *
     * @param code - observed body `error` code (override; if omitted and the
     *   response body is a JSON object with a string `error` field, that value
     *   is auto-extracted)
     * @mutates `this.observed` - via `record` after `assert_response_matches_spec`
     *   succeeds.
     * @throws Error if the response body fails the route spec's declared
     *   schemas (propagated from `assert_response_matches_spec`).
     */
    assert_and_record(route_specs: Array<RouteSpec>, method: string, path: string, response: Response, code?: string): Promise<void>;
    /**
     * Find declared error paths that were never observed.
     *
     * Computes the declared set from `merge_error_schemas` for each route spec.
     * For statuses whose error schema names specific codes (via `z.literal` or
     * `z.enum`), reports per-code rows; otherwise reports one row per status.
     * A status-only observation (no code) satisfies all declared codes for that
     * status — the "any-code" rule.
     */
    uncovered(route_specs: Array<RouteSpec>, options?: CoverageFilterOptions): Array<UncoveredEntry>;
}
/**
 * Default minimum error coverage threshold for the standard integration
 * and admin test suites. Conservative — not all error paths are exercisable
 * in the composable suites. Consumers should increase as their test suites mature.
 */
export declare const DEFAULT_INTEGRATION_ERROR_COVERAGE = 0.2;
/** Options for `assert_error_coverage`. */
export interface ErrorCoverageOptions extends CoverageFilterOptions {
    /** Minimum coverage ratio (0–1). Default `0` (informational only). */
    min_coverage?: number;
}
/**
 * Assert error coverage meets a minimum threshold.
 *
 * Computes the ratio of exercised error paths to total declared error paths.
 * For routes whose status error schema names specific codes (`z.literal` or
 * `z.enum`), each declared code counts as one coverage path; for schemas
 * without declared codes (`ApiError`/`z.string()`), the status counts as one
 * path. A status-only observation covers all declared codes for that status
 * (the "any-code" rule).
 *
 * When `min_coverage` is 0 (default), logs coverage info without failing.
 * When > 0, fails if coverage is below the threshold.
 *
 * @throws AssertionError if `min_coverage > 0` and the covered/total ratio
 *   falls below the threshold — the failure message lists every uncovered
 *   route + status (+ code).
 */
export declare const assert_error_coverage: (collector: ErrorCoverageCollector, route_specs: Array<RouteSpec>, options?: ErrorCoverageOptions) => void;
//# sourceMappingURL=error_coverage.d.ts.map