/** * Shared Test Context Builder * =========================== * Provides standardized helper functions for building test contexts across all language emitters. * This ensures consistency in how tests are generated from @sample decorators. */ import { TypeNode, TestExample, BaseTestContext } from "../ir/ast.js"; /** * Options for building test context - language-specific transformations. */ export interface TestContextOptions { /** Transform property name to target language casing (e.g., PascalCase, snake_case) */ renderKey: (key: string) => string; /** Render boolean value as language-specific literal (e.g., "True"/"False" for Python) */ renderBoolean: (val: boolean) => string; /** Escape string for use in language-specific string literal */ escapeString: (str: string) => string; /** Get string delimiter based on content (e.g., '"' or '"""' for multiline) */ getDelimiter: (str: string) => string; /** Escape JSON for embedding in test template (optional - for languages that need it) */ escapeJsonForTemplate?: (json: string) => string; /** Escape YAML for embedding in test template (optional - for languages that need it) */ escapeYamlForTemplate?: (yaml: string) => string; /** Use YAML block literals for multiline strings instead of quoted folding. */ yamlMultilineStyle?: "block-literal"; /** Minimum encoded length at which double-quoted multiline values may be folded. */ yamlDoubleQuotedMinMultiLineLength?: number; /** Default scalar values for each type (used when @sample doesn't provide example) */ scalarValues: Record; /** Type mapper for scalar types */ typeMapper: Record; /** * Render an enum assertion value for a closed enum field. * Called with (enumName, rawStringValue, fieldName). * If provided and returns non-null, overrides default string/bool/number rendering. * The returned value+delimiter replace the default. */ renderEnumValue?: (enumName: string, rawValue: string, fieldName: string, isOpenEnum?: boolean) => { value: string; delimiter: string; } | null; /** Include scalar samples for complex properties that support scalar coercion. */ includeCoercedComplexValues?: boolean; } /** * Resolves a declared type name to its node. Supplied by each language driver from the * `TypeRegistry` it already builds, so synthesis can follow a property whose own `.type` * back-reference was left unresolved by `resolveModel`'s cycle prevention (only the first * property of a given element type gets one). */ export type TypeResolver = (name: string) => TypeNode | undefined; /** * Add payloads for required complex properties the `@sample` combinations left out. * * `buildExamples` derives a payload from `@sample` decorators alone, so a required complex * property that declares none is silently dropped — and the generated validation then * rejects the very payload the generator produced. * * Exported because C# renders its conversion tests through its own driver rather than * `buildBaseTestContext`; it must complete payloads through this same helper so every * backend's generated fixtures stay in agreement. */ export declare function withRequiredComplexSamples(sample: Record, node: TypeNode, resolveType: TypeResolver): Record; export declare function buildExampleSamples(node: TypeNode, resolveType: TypeResolver): Record[]; /** * Build a standardized test context from a TypeNode. * All language emitters should use this to ensure consistent test generation. */ export declare function buildBaseTestContext(node: TypeNode, packageName: string | undefined, options: TestContextOptions, resolveType?: TypeResolver): BaseTestContext; /** * Project a test example onto the shape a load → save → load round-trip can * actually reproduce: `save()` omits `@sensitive("save")` fields, so a reloaded * instance never carries them. Drops their validations and removes their keys * from the raw sample (so structured-validation passes skip them too). The * original example is returned untouched when the node has no save-withheld * field. Use this at every reload/round-trip validation site; the load-side * (`instance`) validations must keep asserting these fields. */ export declare function postSaveExample(example: TestExample, node: TypeNode): TestExample; /** * A single provider wire-name assertion the generated conversion test should make: * source field `fieldName` is renamed to `wireName` for `provider`. */ export interface WireTestMapping { fieldName: string; provider: string; wireName: string; } /** * Derive the provider wire-mapping assertions a generated conversion test should make for * a `@sample` payload. Shared by every language backend so the emitted `toWire`/`fromWire` * coverage is uniform (issue #328). * * The fixture generator synthesizes required-only payloads — optional fields are deliberately * omitted (see `synthesizeCompleteComplexSample`). `toWire` only emits a wire key when its * source field was populated, so the presence assertions are restricted to fields the fixture * actually carries. Asserting a wire field whose optional source was never set would produce a * test that fails against the very payload the generator built beside it. */ export declare function wireTestMappings(node: TypeNode, sample: Record | undefined): WireTestMapping[]; /** The distinct providers referenced by a set of wire mappings, in first-seen order. */ export declare function wireTestProviders(mappings: WireTestMapping[]): string[]; /** * C# test context options. */ export declare const csharpTestOptions: TestContextOptions; /** * Python test context options. */ export declare const pythonTestOptions: TestContextOptions; /** * TypeScript test context options. */ export declare const typescriptTestOptions: TestContextOptions; /** * Rust test context options. */ export declare const rustTestOptions: TestContextOptions; /** * Swift test context options. */ export declare const swiftTestOptions: TestContextOptions; /** * Go test context options. */ export declare const goTestOptions: TestContextOptions;