Repository navigation
Generate Python payload types from a schema derived from shared - #421
Merged
Merged
Conversation
Every adapter sends Record<uid, SuiteStats>[] under the suites scope, but the type said Record<string, unknown>[], so nothing derived from it could describe a suite frame. The app's two fixtures build fragments, which the app reads as such, and are cast at the one place they enter a TraceLog.
An adapter that cannot import shared has had to retype its payloads by hand. scripts/wire-schema.ts reads WsPayloadFor and the new TraceExportPayloadFor with the TypeScript compiler and writes one JSON Schema per scope to wire-schema.json, mapping Date to its ISO string and Error to SerializedError as they cross the socket. A vitest test fails when the committed copy is stale, so the schema cannot drift from src. Refs #299
… frame types.py hand-mirrored shared and nothing checked the mirror; no mypy runs over this package, so a TypedDict alone enforces nothing. gen_contract.py now renders wire-schema.json into _wire_types.py, and the eight per-file fake transports become one RecordingTransport that validates each frame against the schema before recording it. That check found real drift, fixed here: null sent for callSource, metadata.url, and an in-flight request's status and endTime, and for an unfinished suite's state, where shared types each as absent; and a native viewport without offsetLeft, offsetTop and scale, which now carries 0, 0, 1 as core's fromWindow sends. Every reader uses ?., ?? or truthiness, so absent reads as null did. ElementScripts is renamed to shared's ElementScriptsResponse. Refs #299
The drift step now diffs _wire_types.py beside _contract.py, and the workflow triggers on packages/shared/wire-schema.json, since the tests read it and a schema change can turn them red.
|
…he send
RecordingTransport raised AssertionError from send_json, but the adapter's
best-effort senders catch every exception, so a bad frame was swallowed
wherever the test only checked the sender's return value. Violations are
now collected and fail the owning test at cleanup, outside those except
blocks. That surfaced two invalid fixtures, corrected here: an action
snapshot of {"a": 1} and a replaced row with no command or args.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #299
The Python adapter hand-mirrored shared's payload types in
types.py, and nothing checked the mirror: no mypy runs over the package, so the TypedDicts documented the contract without enforcing it. They had already drifted.What changes
packages/shared/scripts/wire-schema.tsreadsWsPayloadForand a newTraceExportPayloadForwith the TypeScript compiler and writes one JSON Schema per wire scope topackages/shared/wire-schema.json. Scope names and payloads come from shared's existing maps, not a hand list. On the wire aDateis its ISO string and anErroritsSerializedError, and the schema says so.packages/shared/tests/wire-schema.test.tsfails when the committed copy is stale, so the Node CI job guards it.gen_contract.pyrenders the schema into_wire_types.py(36 TypedDicts; required and optional keys split across a base class becausetyping.Requiredneeds 3.11).types.pyre-exports them in place of 151 hand-written lines. The existing drift step diffs the new file too.RecordingTransportthat checks each frame against the schema before recording it. Any test that sends anything now fails on an undeclared field, a missing required one, or a null where shared expects the key to be absent.TraceLog.suitesis tightened fromRecord<string, unknown>[]toRecord<string, SuiteStats>[], which is what every adapter sends, so suite frames are covered too.Drift the check found, fixed here
callSource(commands, tests)nullwhen unknownmetadata.urlnullwhen unknownstatus,endTimenullstatenullviewport{width, height}offsetLeft: 0, offsetTop: 0, scale: 1, as core'sfromWindowsendsEvery reader of those fields in the app, backend and trace uses
?.,??, truthiness or atypeofcheck, so absent reads the same asnulldid.ElementScriptsis renamed to shared'sElementScriptsResponse; the change fragment isminorfor that reason.Verification
pnpm test(2506 tests),pnpm lint,pnpm typecheck,pnpm build: green.Not verified against a live browser: the change is to payload shapes, and each reader of the changed fields was checked in code instead.