# Testing API reference

> Exports of @gramforge/testing.

Source: https://gramforge.n.yatsyk.com/docs/testing/jsdoc

## Functions

### assertRoundtripOk

Assert a roundtrip decoded `ok` and reconstructed a payload deep-equal to
`expected`. Throws a descriptive `Error` on any other decode outcome or a
value mismatch.

```ts
<TPayload extends Record<string, unknown>>(roundtrip: CallbackRoundtrip<TPayload>, expected: TPayload): void
```

### assertSurvivesBothPaths

Assert one payload survives the COMPACT path and another survives the
SPILLOVER (pointer) path — both decoding `ok` and equal to their input.

The caller supplies a small payload known to fit inline and a large payload
known to overflow the 64-byte budget; this proves both codec branches are
lossless. A mis-sized payload (compact that spills, or spillover that fits)
throws, surfacing the test's wrong assumption rather than passing silently.

```ts
<TPayload extends Record<string, unknown>, TActions extends Record<string, AnyActionDef>>(namespace: CallbackNamespace<TActions>, actionKey: keyof TActions & string, payloads: { readonly compact: TPayload; readonly spillover: TPayload; }, deps: CallbackTestDeps): Promise<void>
```

### callbackWireFormat

Classify a `callback_data` string by its version prefix.

```ts
callbackWireFormat(callbackData: string): CallbackWireFormat
```

### createCallbackTestDeps

Build a deterministic {@link CallbackTestDeps}: fresh fake store + fixed
secret + fixed clock + default TTL. Any field can be overridden.

```ts
createCallbackTestDeps(overrides?: Partial<CallbackTestDeps>): CallbackTestDeps
```

### createFakePointerStore

Create a fresh in-memory {@link FakePointerStore}.

```ts
createFakePointerStore(): FakePointerStore
```

### describeDecodeResult

Human-readable one-line description of any decode result (exhaustive).

```ts
<TPayload>(result: CallbackDecodeResult<TPayload>): string
```

### fixedNow

A constant clock returning `ms` (defaults to {@link FIXED_NOW_MS}).

```ts
fixedNow(ms?: number): () => number
```

### jsonDeepEqual

Recursive structural equality over JSON values (key-order-insensitive).

```ts
jsonDeepEqual(a: unknown, b: unknown): boolean
```

### roundtripCallback

Encode `payload` for `actionKey` in `namespace`, then decode the resulting
`callback_data` back — returning the wire string, the format it used, and the
`CallbackDecodeResult` for assertion.

```ts
<TPayload extends Record<string, unknown>, TActions extends Record<string, AnyActionDef>>(namespace: CallbackNamespace<TActions>, actionKey: keyof TActions & string, payload: TPayload, deps: CallbackTestDeps): Promise<CallbackRoundtrip<TPayload>>
```

### toDecodeDeps

Derive the decode-side deps (single-secret list) from the test deps.

```ts
toDecodeDeps(deps: CallbackTestDeps): CallbackDecodeDeps
```

### snapshotEntities

Snapshot the DEFAULT `{ text, entities }` render of a message, with entities
sorted into a stable order. Prefer this over snapshotting `toEntities`
directly so snapshots don't churn on walk-order changes.

```ts
snapshotEntities(message: MessageText | CaptionText): EntitiesSnapshot
```

### snapshotHtml

Snapshot the Telegram-HTML render of a message (a stable string).

```ts
snapshotHtml(message: MessageText | CaptionText): string
```

### snapshotMarkdown

Snapshot the MarkdownV2 (fallback) render of a message (a stable string).

```ts
snapshotMarkdown(message: MessageText | CaptionText): string
```

### assertUtf16Length

Assert the UTF-16 rendered length of `nodes` equals `expected`. Throws a
descriptive `Error` on mismatch (framework-agnostic — no vitest import), so
it works under any runner or a bare `node`.

```ts
assertUtf16Length(nodes: readonly RichTextNode[], expected: number): void
```

### fixtureNodes

Wrap a fixture's raw string in a single text node for renderer input.

```ts
fixtureNodes(fixture: UnicodeFixture): readonly RichTextNode[]
```

### unicodeFixtures

The Unicode fixture bank (function form, for parameterized-test ergonomics).

```ts
unicodeFixtures(): readonly UnicodeFixture[]
```

## Types

### CallbackTestDeps

The combined encode-side deps a roundtrip needs. Structurally identical to
core's `CallbackEncodeDeps`; {@link toDecodeDeps} derives the decode-side
shape (a single-secret list) from it.

```ts
type CallbackTestDeps = CallbackEncodeDeps
```

### CallbackWireFormat

Which of the codec's two wire formats a `callback_data` string uses.

```ts
type CallbackWireFormat = "compact" | "pointer" | "unknown"
```

## Interfaces

### CallbackRoundtrip

The full result of encoding then decoding a payload.

```ts
interface CallbackRoundtrip
```

- `callbackData: string` — The `callback_data` string the encoder produced.
- `wireFormat: CallbackWireFormat` — Which wire format the encoder chose (compact vs pointer spillover).
- `result: CallbackDecodeResult<TPayload>` — The decode outcome to assert against.

### FakePointerStore

An in-memory {@link PointerStore} with test-only inspection (`size`, `has`).
Non-durable, non-evicting — the same caveats as core's in-memory store.

```ts
interface FakePointerStore
```

- `size: () => number` — Number of envelopes currently held.
- `has: (token: CallbackToken) => boolean` — Whether a token currently resolves.

### EntitiesSnapshot

A stable, JSON-serializable projection of `toEntities` output.

```ts
interface EntitiesSnapshot
```

- `text: string`
- `entities: readonly MessageEntity[]`

### UnicodeFixture

A single Unicode edge case with its documented lengths in both units.

```ts
interface UnicodeFixture
```

- `label: string` — Short stable identifier for the case.
- `text: string` — The raw string under test.
- `utf16Length: number` — `text.length` — UTF-16 code units, the unit Telegram counts.
- `codePointLength: number` — `[...text].length` — Unicode code points (grapheme-ish, not clusters).

## Constants

### moduleId

```ts
const moduleId: "testing"
```

### DEFAULT_CALLBACK_TTL_MS

Default pointer TTL used by {@link createCallbackTestDeps} (24h).

```ts
const DEFAULT_CALLBACK_TTL_MS: number
```

### FIXED_HMAC_SECRET

A fixed 32-byte HMAC secret — deterministic pointer signatures across runs.

```ts
const FIXED_HMAC_SECRET: Uint8Array<ArrayBufferLike>
```

### FIXED_NOW_MS

A fixed wall-clock instant (epoch ms) for reproducible TTL/expiry tests.

```ts
const FIXED_NOW_MS: number
```

### UNICODE_FIXTURES

A cross-section of Unicode length hazards: plain ASCII, BMP CJK, an astral
emoji (surrogate pair), an emoji + skin-tone modifier, a ZWJ family sequence,
decomposed combining marks, and a regional-indicator flag pair.

```ts
const UNICODE_FIXTURES: readonly UnicodeFixture[]
```
