Skip to content

feat(scripting): field coverage tests for zod schemas#692

Open
yahgwai wants to merge 31 commits intofeat/zod-scriptingfrom
feat/schema-coverage
Open

feat(scripting): field coverage tests for zod schemas#692
yahgwai wants to merge 31 commits intofeat/zod-scriptingfrom
feat/schema-coverage

Conversation

@yahgwai
Copy link
Copy Markdown
Contributor

@yahgwai yahgwai commented Apr 10, 2026

Tests to make sure that every input field of the schema causes some discernible effect in the sdk function(s) that are called. Basically a check for dead schema fields - especially useful when writing new schemas for scripts that tie multiple sdk functions together

yahgwai added 28 commits April 9, 2026 15:44
Detects dead schema fields by mutating each field's value and verifying
the transform output changes. Values are generated from the schema type.
Includes test for getValidators schema.
…ansactionRequest

Tests nested object fields (coreContracts.upgradeExecutor,
coreContracts.sequencerInbox) alongside flat fields and hex schema.
Exports are needed for schema coverage testing. The runScript call
remains as a top-level side effect for direct execution.
Simplified assertSchemaCoverage API to take a single schema (with
transform baked in via .transform()). Added tuple, array, and never
type support to the value generator.

The coverage test caught a real bug: createRollup example was not
passing parentChainId to findChain when constructing the public client.
assertSchemaCoverage now accepts an optional execute function for full
pipeline testing. When provided, it mocks the SDK function and compares
its call args across two runs, catching fields that survive the
transform but get overwritten in the script body.

The createRollup example test now exercises the full pipeline.
Added Proxy-based tracked objects that record all method calls into a
shared sideEffects array. When execute is provided, assertSchemaCoverage
runs the full pipeline (parse + execute) and compares all side effects
across mutations, not just transform outputs.

transferOwnership example now exercises the full execute function with
mocked SDK functions, viem methods, and client interactions. Uses the
override mechanism for nativeToken (conditional branch on zero/non-zero).
Replace separate testTracker.ts module with a vi.hoisted() inline
registry. All mock functions (fn, fnSync, trackedObject) are created
in one place and shared with vi.mock factories via hoisting.

Tracked objects now return valid hex strings instead of embedding names
in hex positions.
Remove unused sdkFunction parameter. Make execute required -- callers
compose schema.parse + SDK function into a single execute function via
withTransform/withExecute helpers. Remove the two-path branching
(transform-only vs full pipeline) since all tests now go through
mocks.
Each test now inlines the schema.parse + SDK call as a simple lambda.
No helpers needed.
Execute now receives parsed output directly. Tuple results (from simple
schema transforms) are auto-spread into the execute function. No more
wrapper lambdas needed -- callers just pass the SDK function or execute.
Make assertSchemaCoverage generic so override functions receive and
return z.input<T> instead of Record<string, unknown>.
Optional/nullable fields are now skipped in auto-generation (tested
via overrides instead) to avoid refine conflicts. The keyset field
uses an override to set AnyTrust context.

Caught another parentChainId bug -- deployNewChain was not passing
it to findChain, same issue as createRollup.
Provide required chainId and InitialChainOwner fields in the keyset
override's chainConfig object.
Add coverage for getKeysets, getBatchPosters, isAnyTrust,
prepareKeysetHash, prepareKeyset, prepareChainConfig,
setAnyTrustFastConfirmer, upgradeExecutorPrepareTransactionRequest,
setValidKeyset, createRollupFetchCoreContracts,
createRollupFetchTransactionHash.

Optional/nullable fields are now skipped from auto-generation to
avoid refine conflicts (tested via overrides instead).

16 total tests, all passing.
Add coverage for fetchDecimals, fetchAllowance,
upgradeExecutorFetchPrivilegedAccounts, getBridgeUiConfig,
isTokenBridgeDeployed, createRollupGetRetryablesFees,
createSafePrepareTransactionRequest, and all 4 customFeeToken schemas.

27 total tests, all passing. getDefaults deferred to Stage 3 (needs
union support in generator).
Add coverage for createRollupPrepareTransactionRequest (default),
createRollup (default), createTokenBridge,
createTokenBridgePrepareTransactionRequest,
createTokenBridgePrepareSetWethGatewayTransactionRequest,
prepareDeploymentParamsConfigV21, prepareDeploymentParamsConfigV32,
prepareNodeConfig, feeRouterDeployRewardDistributor,
feeRouterDeployChildToParentRewardRouter, getDefaults.

Added support for union types, z.null(), and nonoptional (from
.required()) in the schema walker and value generator.

38 total tests, all passing.
Tests cover both schemas and examples, so they belong at the
scripting level rather than inside schemas/.
generateForType now throws with a clear message when it encounters
an unhandled zod type, instead of silently producing an invalid value.

Added section comments to the test file explaining the ordering:
1. Mock registry (vi.hoisted), 2. Module mocks, 3. Imports, 4. Tests.
Consumers can import createMockRegistry, viemTransformsMocks, and
assertSchemaCoverage to test their own schema coverage. The registry
must be inlined in vi.hoisted() due to vitest limitations, but the
canonical implementation lives in testing.ts.
…ation

vi.mock and vi.hoisted in an imported file get hoisted into the
importing test file's scope. This means testing.ts can own the
registry, all vi.mock calls, and the vi.hoisted block. The test file
just imports { mocks, assertSchemaCoverage } and writes tests.

No more duplicated registry between testing.ts and the test file.
A second test file imports { mocks, assertSchemaCoverage } from
testing.ts and adds its own vi.mock for a custom SDK function. Both
tests pass, proving the pattern works for consumers without vi.hoisted
duplication.
Single file for all test infrastructure: mock registry, vi.mock
setup, schema walker, value generator, and assertSchemaCoverage.
Consumers import { mocks, assertSchemaCoverage } from one place.

Fixed consumer test to use createRollupGetCallValue with proper types
instead of sequencerInboxReadContract with as any cast.
- Fix stale usage comment (referenced ./testing instead of ./schemaCoverage)
- Build base fixture once outside the loop instead of per-leaf
- Pre-compute leaf path keys to avoid repeated join('.')
- Remove unnecessary export on getSchemaLeaves (internal only)
… unions

createRollupPrepareTransactionRequest and createRollup have different
params schemas per version (v2.1 has extraChallengeTimeBlocks/
genesisBlockNum, v3.2 has feeTokenPricer/customOsp/bufferConfig/etc).
Testing only the default variant missed version-specific fields.

42 total tests, all passing.
@yahgwai yahgwai requested review from douglance and spsjvc April 10, 2026 13:54
yahgwai added 2 commits April 10, 2026 14:56
- Fix missing findChain in deployNewChain toWalletClient call (same
  bug class as the toPublicClient fix already applied)
- Throw if assertSchemaCoverage finds zero testable fields (prevents
  silently passing on misconfigured schemas)
- Fix misleading vi.mock hoisting comment
- Change generateChainId mock to use registry for consistency
- Document that optional fields are excluded from automatic testing
  and must use overrides
@yahgwai yahgwai force-pushed the feat/schema-coverage branch from fbd9986 to 6d131b9 Compare April 10, 2026 14:11
@yahgwai yahgwai changed the title Feat/schema coverage feat: schema coverage tests for zod schemas Apr 10, 2026
@yahgwai yahgwai changed the title feat: schema coverage tests for zod schemas feat: field coverage tests for zod schemas Apr 10, 2026
Run prettier on schemaCoverage files. Add eslint-disable for
no-explicit-any in schemaCoverage.ts -- the file introspects zod
internals and uses Proxy-based mocks that require any.
@yahgwai yahgwai changed the title feat: field coverage tests for zod schemas feat(scripting): field coverage tests for zod schemas Apr 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant