Menu

API Reference

@kovojs/test

Generated from 13 public subpaths — 83 exports, 22 documented. Do not edit by hand.

@kovojs/test#

Test harness: PGlite-backed databases, db verification against the touch graph, and mutation/property testing.

Source: packages/test/src/index.ts

No public exports are declared by this subpath.

@kovojs/test/assertions#

Mutation failure assertions and optimistic property testing helpers.

Source: packages/test/src/assertions.ts

Functions#

assertMutationError#

Assert that a mutation result is a typed failure with the expected code (and, optionally, payload), returning the typed payload for further assertions. Throws with a descriptive message on mismatch (SPEC §10.3).

Parameter Type Description
mutation MutationDefinition<Key, InputSchema, Errors, Request, Value> The mutation whose result is being checked (for typing and messages).
result MutationResult<Value> The MutationResult to assert against.
expected MutationErrorExpectation<Errors, Code> The expected error code, or { code, payload }.
(returns) InferSchema<Errors[Code]> The typed error payload.
ts
function assertMutationError<
  const Key extends string,
  InputSchema extends Schema<unknown>,
  Errors extends Record<string, Schema<unknown>>,
  Request,
  Value,
  const Code extends Extract<keyof Errors, string>,
>(
  mutation: MutationDefinition<Key, InputSchema, Errors, Request, Value>,
  result: MutationResult<Value>,
  expected: MutationErrorExpectation<Errors, Code>,
): InferSchema<Errors[Code]>;

propertyTest#

Property-check that an optimistic prediction matches the eventual server result across many cases. For each case it runs predict and the real apply, projects both with shape, and throws on the first divergence — proving the optimistic transform is sound (SPEC §10.4).

Parameter Type Description
options PropertyTestOptions<State, Input, ClientShape> The predict, apply, cases, and optional shape projection.
(returns) PropertyTestResult A PropertyTestResult with the number of cases run.
ts
function propertyTest<State, Input, ClientShape = State>(
  options: PropertyTestOptions<State, Input, ClientShape>,
): PropertyTestResult;

Example

ts
import { propertyTest } from '@kovojs/test/assertions';

type Cart = { count: number };

const result = propertyTest<Cart, { quantity: number }>({
  apply: (state, input) => ({ count: state.count + input.quantity }),
  predict: (state, input) => ({ count: state.count + input.quantity }),
  cases: [{ state: { count: 0 }, input: { quantity: 2 } }],
});
// result.cases === 1

Types & interfaces#

MutationErrorExpectation#

An expected mutation failure: a code, or a code with an expected payload.

ts
type MutationErrorExpectation<
  Errors extends Record<string, Schema<unknown>>,
  Code extends Extract<keyof Errors, string>,
> =
  | Code
  | {
      code: Code;
      payload?: InferSchema<Errors[Code]>;
    };

PropertyCase#

One property-test case: an initial state and the mutation input to apply.

ts
interface PropertyCase<State, Input> {
  input: Input;
  state: State;
}

PropertyTestOptions#

Options for propertyTest: the optimistic predict, the eventual apply, the cases, and an optional shape projection.

ts
interface PropertyTestOptions<State, Input, ClientShape = unknown> {
  apply: (state: State, input: Input) => State;
  cases: Iterable<PropertyCase<State, Input>>;
  predict: (state: State, input: Input) => ClientShape;
  shape?: (state: State) => ClientShape;
}

PropertyTestResult#

The result of propertyTest: how many cases ran.

ts
interface PropertyTestResult {
  cases: number;
}

@kovojs/test/headers#

Header helpers for app scenario tests.

Source: packages/test/src/headers.ts

Functions#

headerValues#

Undocumented.

ts
function headerValues(source: HeaderSource, name: string): string[];

setCookieValues#

Undocumented.

ts
function setCookieValues(source: HeaderSource): string[];

cookiePair#

Undocumented.

ts
function cookiePair(setCookie: string | undefined): string;

firstSetCookiePair#

Undocumented.

ts
function firstSetCookiePair(source: HeaderSource): string;

enhancedMutationHeaders#

Build the enhanced-mutation request headers used by app scenario tests (SPEC.md §9.1).

ts
function enhancedMutationHeaders(
  options: EnhancedMutationHeaderOptions = {},
): Record<string, string>;

Types & interfaces#

HeaderRecord#

Undocumented.

ts
type HeaderRecord = Record<string, string | string[] | undefined>;

HeaderSource#

Undocumented.

ts
type HeaderSource = Headers | HeaderRecord | undefined;

EnhancedMutationTarget#

Structured mutation target selection for enhanced scenario requests.

ts
interface EnhancedMutationTarget {
  queries?: readonly string[] | string;
  target: string;
}

EnhancedMutationLiveTarget#

Structured live-target descriptor for enhanced scenario requests.

ts
interface EnhancedMutationLiveTarget {
  component: string;
  props?: Record<string, unknown>;
  target: string;
}

EnhancedMutationHeaderOptions#

Options for {@link enhancedMutationHeaders}; targets follow the mutation wire protocol in SPEC.md §9.1.

ts
interface EnhancedMutationHeaderOptions {
  formTarget?: string;
  liveTargets?: readonly (EnhancedMutationLiveTarget | string)[] | string;
  targets?: readonly (EnhancedMutationTarget | string)[] | string;
}

@kovojs/test/harness#

Database-backed mutation, query, page, and verification harness.

Source: packages/test/src/harness.ts

Functions#

createKovoTestHarness#

Create a test harness around a database: run mutations and queries, load pages, and—when given a touch graph and verification config—verify that writes only touch the domains their mutations declared (SPEC §10.1, §11).

Parameter Type Description
options KovoTestHarnessOptions<Db> The db plus optional pages, request stub, touch graph, and verification config.
(returns) KovoTestContext<Db> A KovoTestContext with exec/query/page helpers.
ts
function createKovoTestHarness<Db>(
  options: KovoTestHarnessOptions<Db>,
): KovoTestContext<Db>;

Types & interfaces#

KovoTestContext#

The context a Kovo test receives: the db, and helpers to exec mutations, run querys, load a page, and read verification diagnostics.

ts
interface KovoTestContext<Db = unknown> {
  db: Db;
  dbHandle(): Db;
  exec: <
    InputSchema extends Schema<unknown>,
    Errors extends Record<string, Schema<unknown>>,
    Request extends { db: unknown },
    Value,
  >(
    mutation: MutationDefinition<string, InputSchema, Errors, Request, Value>,
    input: unknown,
    options?: KovoTestExecOptions<Request>,
  ) => Promise<MutationResult<Value>>;
  page: (path: string) => Promise<PageAssertion>;
  query: (query: QueryDefinition, input?: unknown) => Promise<unknown>;
  verificationDiagnostics(): readonly DbVerificationDiagnostic[];
}

KovoTestRequest#

Undocumented.

ts
interface KovoTestRequest<Db> {
  db: Db;
}

KovoTestHarnessOptions#

Options for createKovoTestHarness: the db, optional pages, request stub, touch graph, and verification config.

ts
interface KovoTestHarnessOptions<Db> {
  db: Db;
  pages?: Record<string, string | (() => string | Promise<string>)>;
  request?: Record<string, unknown>;
  touchGraph?: CoreGraph.TouchGraph;
  verification?: DbVerificationConfig;
}

KovoTestExecOptions#

Options for a single exec of a mutation inside the harness.

ts
type KovoTestExecOptions<Request> = HarnessMutationOptions<Request>;

@kovojs/test/harness-operations#

Lower-level harness operations used by test harness adapters.

Source: packages/test/src/harness-operations.ts

Functions#

executeHarnessMutation#

Undocumented.

ts
async function executeHarnessMutation<
  InputSchema extends Schema<unknown>,
  Errors extends Record<string, Schema<unknown>>,
  Request extends { db: unknown },
  Value,
>(
  mutation: MutationDefinition<string, InputSchema, Errors, Request, Value>,
  input: unknown,
  db: Request['db'],
  requestFixture: Record<string, unknown> | undefined,
  verifier: HarnessOperationVerifier | null,
  options?: HarnessMutationOptions<Request>,
): Promise<MutationResult<Value>>;

loadHarnessPage#

Undocumented.

ts
async function loadHarnessPage(
  pages: Record<string, string | (() => string | Promise<string>)> | undefined,
  path: string,
): Promise<PageAssertion>;

executeHarnessQuery#

Undocumented.

ts
async function executeHarnessQuery<Db>(
  query: QueryDefinition,
  input: unknown,
  db: Db,
  requestFixture: Record<string, unknown> | undefined,
  verifier: HarnessOperationVerifier | null,
): Promise<unknown>;

Types & interfaces#

HarnessOperationVerifier#

Undocumented.

ts
interface HarnessOperationVerifier {
  assertCoveredOperations(observed: readonly ObservedDbOperation[], touchGraphKey?: string): void;
  assertReadsCoveredOperations(
    observed: readonly ObservedDbOperation[],
    domains: readonly string[],
  ): void;
  capture<T>(
    callback: () => T | Promise<T>,
  ): Promise<{ observed: readonly ObservedDbOperation[]; result: T }>;
}

HarnessMutationOptions#

Undocumented.

ts
interface HarnessMutationOptions<Request> {
  csrf?: CsrfValidationOptions<Request>;
  request?: Partial<Omit<Request, 'db'>>;
  touchGraphKey?: string;
}

@kovojs/test/html-fragment#

HTML and Kovo fragment fact extractors for scenario assertions.

Source: packages/test/src/html-fragment.ts

Functions#

fragmentHtml#

Undocumented.

ts
function fragmentHtml(html: string, target: string): string;

htmlElementCount#

Undocumented.

ts
function htmlElementCount(html: string, selector: HtmlElementSelector = {}): number;

htmlElementFacts#

Undocumented.

ts
function htmlElementFacts(
  html: string,
  selector: HtmlElementSelector = {},
): HtmlElementFact[];

htmlJsonScriptFacts#

Undocumented.

ts
function htmlJsonScriptFacts(
  html: string,
  attrs: Record<string, string | true> = { type: 'application/json' },
): HtmlJsonScriptFact[];

htmlDocumentFacts#

Undocumented.

ts
function htmlDocumentFacts(html: string): HtmlDocumentFact;

htmlDocumentRegions#

Undocumented.

ts
function htmlDocumentRegions(html: string): HtmlDocumentRegions;

htmlMainMarkerFact#

Undocumented.

ts
function htmlMainMarkerFact(
  html: string,
  attribute = 'data-kovo-check-export',
): HtmlMainMarkerFact;

htmlLinkHrefs#

Undocumented.

ts
function htmlLinkHrefs(html: string, attrs: Record<string, string | true> = {}): string[];

kovoQueryFacts#

Undocumented.

ts
function kovoQueryFacts(html: string, name?: string): KovoQueryFact[];

kovoFragmentFacts#

Undocumented.

ts
function kovoFragmentFacts(html: string, target?: string): KovoFragmentFact[];

kovoResponseBodyFact#

Undocumented.

ts
function kovoResponseBodyFact(html: string): KovoResponseBodyFact;

kovoQueryJsonValues#

Undocumented.

ts
function kovoQueryJsonValues(html: string, name: string): unknown[];

documentQueryScriptBehaviorFact#

Undocumented.

ts
function documentQueryScriptBehaviorFact(
  renderedDocument: string,
  options: {
    queryName: string;
    renderedDocumentQueryScript: string;
    renderedQueryScript: string;
  },
): DocumentQueryScriptBehaviorFact;

htmlFormFacts#

Undocumented.

ts
function htmlFormFacts(html: string): HtmlFormFact[];

htmlFormActions#

Undocumented.

ts
function htmlFormActions(html: string): string[];

htmlFormFields#

Undocumented.

ts
function htmlFormFields(html: string, name?: string): HtmlFormFieldFact[];

htmlFormFieldsByName#

Undocumented.

ts
function htmlFormFieldsByName(
  form: HtmlFormFact | undefined,
): Record<string, HtmlFormFieldFact>;

htmlKeyFacts#

Undocumented.

ts
function htmlKeyFacts(html: string, key?: string): HtmlKeyFact[];

htmlKeyValues#

Undocumented.

ts
function htmlKeyValues(html: string): string[];

htmlKeyTextMap#

Undocumented.

ts
function htmlKeyTextMap(html: string): Record<string, string>;

htmlTextContent#

Undocumented.

ts
function htmlTextContent(html: string): string;

Types & interfaces#

HtmlElementFact#

Undocumented.

ts
interface HtmlElementFact {
  attrs: Record<string, string>;
  html: string;
  innerHtml: string;
  tag: string;
}

HtmlElementSelector#

Undocumented.

ts
interface HtmlElementSelector {
  attrs?: Record<string, string | true>;
  tag?: string;
}

HtmlJsonScriptFact#

Undocumented.

ts
interface HtmlJsonScriptFact {
  attrs: Record<string, string>;
  html: string;
  json: unknown;
  rawJson: string;
}

HtmlDocumentFact#

Undocumented.

ts
interface HtmlDocumentFact {
  bodyAttrs: Record<string, string>;
  jsonScripts: HtmlJsonScriptFact[];
  links: HtmlElementFact[];
  metas: HtmlElementFact[];
  text: string;
  title: string;
}

HtmlDocumentRegions#

Undocumented.

ts
interface HtmlDocumentRegions {
  body: HtmlElementFact;
  head: HtmlElementFact;
  html: HtmlElementFact;
}

HtmlMainMarkerFact#

Undocumented.

ts
interface HtmlMainMarkerFact {
  attribute: string;
  mainCount: number;
  marker: string | undefined;
}

KovoQueryFact#

Undocumented.

ts
interface KovoQueryFact {
  attrs: Record<string, string>;
  html: string;
  json: unknown;
  name: string;
  rawJson: string;
  tag: string;
}

KovoFragmentFact#

Undocumented.

ts
interface KovoFragmentFact {
  attrs: Record<string, string>;
  html: string;
  innerHtml: string;
  stylesheetHrefs: string[];
  target: string;
}

KovoResponseBodyFact#

Undocumented.

ts
interface KovoResponseBodyFact {
  fragmentTargets: string[];
  fragments: KovoFragmentFact[];
  keyValues: string[];
  queries: KovoQueryFact[];
  queryJsonByName: Record<string, unknown[]>;
  queryNames: string[];
  stylesheetHrefsByTarget: Record<string, string[]>;
}

DocumentQueryScriptBehaviorFact#

Undocumented.

ts
interface DocumentQueryScriptBehaviorFact {
  bodyElements: HtmlElementFact[];
  bodyQueryScripts: Array<Pick<KovoQueryFact, 'attrs' | 'rawJson'>>;
  documentQueryScripts: Array<Pick<KovoQueryFact, 'attrs' | 'rawJson'>>;
  headQueryScripts: Array<Pick<KovoQueryFact, 'attrs' | 'rawJson'>>;
  renderedDocumentQueryScript: string;
  renderedQueryScript: string;
}

HtmlFormFieldFact#

Undocumented.

ts
interface HtmlFormFieldFact {
  attrs: Record<string, string>;
  html: string;
  name: string;
  tag: string;
  type: string;
  value: string;
}

HtmlFormFact#

Undocumented.

ts
interface HtmlFormFact {
  action: string;
  attrs: Record<string, string>;
  fields: HtmlFormFieldFact[];
  html: string;
  innerHtml: string;
  method: string;
}

HtmlKeyFact#

Undocumented.

ts
interface HtmlKeyFact {
  attrs: Record<string, string>;
  html: string;
  innerHtml: string;
  key: string;
  tag: string;
  text: string;
}

@kovojs/test/page#

Rendered page assertion helpers.

Source: packages/test/src/page.ts

Functions#

createPageAssertion#

Undocumented.

ts
function createPageAssertion(html: string): PageAssertion;

Types & interfaces#

PageAssertion#

Undocumented.

ts
interface PageAssertion {
  fragment(target: string): string;
  html: string;
}

@kovojs/test/pglite#

PGlite-backed test database helpers.

Source: packages/test/src/pglite.ts

Functions#

createPgliteTestDb#

Spin up an ephemeral in-process Postgres (PGlite) for tests, returning a handle with SQL and row helpers. No external database required.

Parameter Type Description
options PGliteOptions PGlite options (e.g. data directory; defaults to in-memory).
(returns) Promise<PgliteTestDb> A ready PgliteTestDb.
ts
async function createPgliteTestDb(options: PGliteOptions = {}): Promise<PgliteTestDb>;

Types & interfaces#

PgliteTestDb#

A PGlite-backed test database handle: exec/query/sql SQL helpers plus read/write and close.

ts
interface PgliteTestDb {
  close(): Promise<void>;
  exec(statement: string): Promise<Results[]>;
  pglite: PGlite;
  query<Row extends Record<string, unknown> = Record<string, unknown>>(
    statement: string,
    params?: readonly unknown[],
  ): Promise<Row[]>;
  read<Row extends Record<string, unknown> = Record<string, unknown>>(
    table: string,
  ): Promise<Row[]>;
  sql<Row extends Record<string, unknown> = Record<string, unknown>>(
    statement: string,
    params?: readonly unknown[],
  ): Promise<Row[]>;
  write(table: string, value: Record<string, unknown>): Promise<void>;
}

@kovojs/test/sql-observer#

SQL observation helpers for database verification.

Source: packages/test/src/sql-observer.ts

Functions#

observeSqlStatementArgument#

Undocumented.

ts
function observeSqlStatementArgument(
  statement: unknown,
  config: DbVerificationConfig,
  recorder: ObservationRecorder,
): void;

observeSqlStatementIfString#

Undocumented.

ts
function observeSqlStatementIfString(
  statement: unknown,
  config: DbVerificationConfig,
  recorder: ObservationRecorder,
): void;

sqlStatementText#

Undocumented.

ts
function sqlStatementText(statement: unknown): string | undefined;

@kovojs/test/test-case#

Named Kovo test case registration helpers.

Source: packages/test/src/test-case.ts

Functions#

kovoTest#

Define a Kovo test case: builds a harness from options, passes its context to fn, and (optionally) registers the case with a test runner like vitest's it.

Parameter Type Description
name string The test name.
fn (ctx: KovoTestContext<Db>) => void | Promise<void> The test body, receiving the harness context.
options KovoTestHarnessOptions<Db> Harness options (db, pages, verification, …).
runner KovoTestRunner Optional test-runner registration function.
(returns) KovoTestCase A KovoTestCase.
ts
function kovoTest<Db>(
  name: string,
  fn: (ctx: KovoTestContext<Db>) => void | Promise<void>,
  options: KovoTestHarnessOptions<Db>,
  runner?: KovoTestRunner,
): KovoTestCase;

Types & interfaces#

KovoTestRunner#

A test-runner adapter (e.g. vitest's it) kovoTest can register cases with.

ts
type KovoTestRunner = (name: string, run: () => Promise<void>) => unknown;

KovoTestCase#

A registered Kovo test case: its name and a run that builds the harness and runs the body.

ts
interface KovoTestCase {
  name: string;
  run: () => Promise<void>;
}

@kovojs/test/verifier#

Touch-graph database verifier.

Source: packages/test/src/verifier.ts

Functions#

createDbVerifier#

Create a database verifier from a touch graph: wrap a db to record its operations, then assert that every write is covered by the domains its mutation declared, and every read by its query's read set (SPEC §10.1, §11).

Parameter Type Description
touchGraph CoreGraph.TouchGraph The compiled touch graph to verify against.
config DbVerificationConfig Verification configuration (which tables/domains to observe).
(returns) DbVerifier A DbVerifier.
ts
function createDbVerifier(
  touchGraph: CoreGraph.TouchGraph,
  config: DbVerificationConfig,
): DbVerifier;

Types & interfaces#

DbObservationOptions#

Undocumented.

ts
interface DbObservationOptions {
  branch?: string;
  rowKey?: string;
}

DbVerificationConfig#

Undocumented.

ts
interface DbVerificationConfig {
  domainByTable: Record<string, string>;
  exemptTables?: readonly string[];
  keyByTable?: Record<string, string>;
}

ObservedDbOperation#

Undocumented.

ts
interface ObservedDbOperation {
  branch: string | undefined;
  domain: string | undefined;
  kind: 'read' | 'write';
  mutationRead: boolean | undefined;
  rowKey: string | undefined;
  sql: string | undefined;
  table: string;
}

DbVerifier#

Wraps a database to record operations and assert each write is covered by the touch graph.

ts
interface DbVerifier {
  assertCovered(touchGraphKey?: string): void;
  assertCoveredOperations(observed: readonly ObservedDbOperation[], touchGraphKey?: string): void;
  assertCoveredSince(start: number, touchGraphKey?: string): void;
  assertReadsCovered(domains: readonly string[]): void;
  assertReadsCoveredOperations(
    observed: readonly ObservedDbOperation[],
    domains: readonly string[],
  ): void;
  assertReadsCoveredSince(start: number, domains: readonly string[]): void;
  capture<T>(
    callback: () => T | Promise<T>,
  ): Promise<{ observed: readonly ObservedDbOperation[]; result: T }>;
  diagnostics(): DbVerificationDiagnostic[];
  observed: readonly ObservedDbOperation[];
  wrap<Db>(db: Db): Db;
}

@kovojs/test/verifier-diagnostics#

Verifier diagnostic facts and messages.

Source: packages/test/src/verifier-diagnostics.ts

Functions#

diagnosticsForObservations#

Undocumented.

ts
function diagnosticsForObservations(
  observed: readonly ObservedDbOperation[],
  touchGraph: CoreGraph.TouchGraph,
): DbVerificationDiagnostic[];

assertObservedWritesCovered#

Undocumented.

ts
function assertObservedWritesCovered(
  observed: readonly ObservedDbOperation[],
  touchGraph: CoreGraph.TouchGraph,
  config: DbVerificationConfig,
  touchGraphKey?: string,
): void;

assertObservedReadsCovered#

Undocumented.

ts
function assertObservedReadsCovered(
  observed: readonly ObservedDbOperation[],
  domains: readonly string[],
  config: DbVerificationConfig,
): void;

diagnosticMessage#

Undocumented.

ts
function diagnosticMessage(code: DiagnosticCode, detail: string): string;

Types & interfaces#

DiagnosticCode#

The string-literal union of every KV### diagnostic code the framework can emit.

ts
type DiagnosticCode =
  | 'KV201'
  | 'KV210'
  | 'KV211'
  | 'KV212'
  | 'KV220'
  | 'KV221'
  | 'KV222'
  | 'KV223'
  | 'KV224'
  | 'KV225'
  | 'KV226'
  | 'KV227'
  | 'KV228'
  | 'KV230'
  | 'KV231'
  | 'KV232'
  | 'KV233'
  | 'KV234'
  | 'KV235'
  | 'KV236'
  | 'KV237'
  | 'KV238'
  | 'KV239'
  | 'KV240'
  | 'KV241'
  | 'KV242'
  | 'KV301'
  | 'KV302'
  | 'KV303'
  | 'KV304'
  | 'KV310'
  | 'KV311'
  | 'KV320'
  | 'KV330'
  | 'KV402'
  | 'KV403'
  | 'KV404'
  | 'KV405'
  | 'KV406'
// … truncated (5 more lines); see the package source for the full declaration.

DbVerificationDiagnostic#

Undocumented.

ts
interface DbVerificationDiagnostic {
  branch?: string;
  code: DiagnosticCode;
  domain: string;
  message: string;
  severity: DiagnosticSeverity;
  site?: string;
}

@kovojs/test/verifier-sql#

SQL parser helpers used by verifier instrumentation.

Source: packages/test/src/verifier-sql.ts

Functions#

parseSqlOperations#

Undocumented.

ts
function parseSqlOperations(statement: string): ParsedSqlOperation[];

Types & interfaces#

ParsedSqlOperation#

Undocumented.

ts
type ParsedSqlOperation = Pick<
  ObservedDbOperation,
  'kind' | 'mutationRead' | 'rowKey' | 'table'
>;