Skip to content

feat(sdk-generator): emit SSE contract tests in the contract-tests backend (TS + Python) - #47

Merged
calvin-archastro merged 2 commits into
mainfrom
feat/sdk-sse-contract-tests
Jun 30, 2026
Merged

feat(sdk-generator): emit SSE contract tests in the contract-tests backend (TS + Python)#47
calvin-archastro merged 2 commits into
mainfrom
feat/sdk-sse-contract-tests

Conversation

@calvin-archastro

Copy link
Copy Markdown
Contributor

What changed

Follow-up to #43 (merged). #43 landed SSE method emission, typed events, the channel-harness SSE support, and the sample contract-test loop — but the contract-tests backend that the SDK repos regenerate from (--lang contract-tests-ts/py) still skipped streaming ops, so SDK regens shipped the generated stream() methods with no contract test. This wires SSE coverage into generateContractTests itself, for both backends.

  • method-chain-builder: add buildStreamCalls — the streaming inverse of buildMethodCalls, sharing the resource walk so streaming ops get the same SDK accessor chains (client.v1.ai.chat.completions.stream).
  • TypeScript__tests__/contract/streams/<resource>.contract.test.ts: construct PlatformClient against the harness, registerStreamScenario with autoEmit (the harness synthesizes contract-valid event payloads, resolving $refs — no SDK-side fixtures needed), iterate stream(), assert the event order; plus a non-2xx → ApiError case.
  • Pythontests/contract/streams/test_<resource>.py: same shape over AsyncPlatformClient.stream().
  • Both gated by the existing opt-in (ARCHASTRO_RUN_CHANNEL_CONTRACT_TESTS): excluded from the default run, and the harness subprocess boots when the spec has channels or streams.
sequenceDiagram
    participant T as generated streams test
    participant H as harness control API
    participant C as PlatformClient.stream()
    participant S as harness SSE endpoint
    T->>H: registerStreamScenario(autoEmit each event)
    T->>C: for await ev of client.v1.ai.chat.completions.stream(input)
    C->>S: POST text/event-stream
    S-->>C: event frames (synthesized, contract-valid)
    C-->>T: {event, data} ... assert event order
Loading

Scope

Generator-only (archastro-openapi). No runtime/SDK changes here.

Risk

Low. Additive: a new builder function + new emitted files behind the existing opt-in gate. The default contract-test run (REST, Prism-backed) is unchanged. Generator suite 299 (incl. 3 new tests covering TS + Python emission + the gating).

Testing

  • Generator suite: 299 pass, tsc clean.
  • Verified against the real public spec + archastro-js config: emits streams/ai.contract.test.ts (client.v1.ai.chat.completions.stream(...), autoEmit ×6, assert order, 402→ApiError) and tests/contract/streams/test_ai.py (async equivalent).

Runs green once deps land (unchanged from #43's follow-ups)

These tests are opt-in (excluded by default), so they don't affect CI. To execute:

calvin-archastro and others added 2 commits June 29, 2026 20:01
…ckend (TS + Python)

Previously emitStreamContractTestFile was only wired into the channel-harness
sample — so SDK regens (contract-tests-ts/py) shipped the generated stream()
methods with no contract test. Wire SSE coverage into generateContractTests
itself, for both backends.

- method-chain-builder: add buildStreamCalls (the streaming inverse of
  buildMethodCalls), sharing the resource walk so streaming ops get the same
  accessor chains (client.v1.ai.chat.completions.stream).
- typescript-emitter: emit __tests__/contract/streams/<resource>.contract.test.ts
  — construct PlatformClient pointed at the harness, registerStreamScenario with
  autoEmit (harness synthesizes contract-valid event payloads, resolving $refs),
  iterate stream(), assert event order; plus a non-2xx -> ApiError case.
- python-emitter: emit tests/contract/streams/test_<resource>.py — same shape
  over AsyncPlatformClient.stream().
- Both gated by the existing opt-in env (ARCHASTRO_RUN_CHANNEL_CONTRACT_TESTS):
  excluded from the default test run + the harness subprocess boots when the
  spec has channels OR streams.

These run green once their deps land: runtime streamSSE/stream_sse
(archastro-js #34 / archastro-python #28) and registerStreamScenario on the
harness client (TS: shipped in this PR's channel-harness; Python: phx_channel
harness.py). Generator suite 299; channel-harness 63.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…bumped)

The v0.6.0 release bumped @archastro/sdk-generator, but channel-harness still
pinned ^0.5.0 — which 0.6.0 doesn't satisfy — so a fresh `npm ci` pulled the
published 0.5.6 (pre-SSE-contract-test exports, missing emitResourceFile)
instead of linking the workspace, breaking the pretest. Bump to ^0.6.0 and
`npm dedupe` so it links the workspace 0.6.0 (minimal lockfile change).

Note: this caret keeps drifting whenever sdk-generator's version bumps — the
release process should bump this dependency in lockstep (the two packages are
co-released). Verified: npm ci links the workspace, cold Node 20 run is green
(channel-harness 63, sdk-generator 299).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@calvin-archastro
calvin-archastro merged commit d31a71b into main Jun 30, 2026
2 checks passed
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