test(agent-bff): drive a generated client through list, count, form and execute - #1828
Conversation
|
Coverage Impact This PR will not change total coverage. 🚦 See full report on Qlty Cloud »🛟 Help
|
c01807b to
e242dc6
Compare
…nd execute Emits the document through the CLI command, runs @hey-api/openapi-ts on it, and drives the generated client against the real data and action middlewares over HTTP, so a 2xx proves the documented paths, fields and operator enums are sufficient to construct the call. The filter operator is read from the emitted enum rather than hardcoded, and a negative control asserts an operator the document leaves out is rejected with 400 - without it a permissive stub would keep the check green. Fixes PRD-687 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ing it A failing step now throws with what the tool said: the emission carries the CLI stderr it silenced, and the codegen carries its own output plus the artifact it never wrote. The exit status alone was not enough - this codegen reports a missing input while exiting 0. Also bounds the codegen child, since spawnSync blocks the event loop and the beforeAll deadline could never fire, and awaits the server close so the port cannot leak into the next suite. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
e242dc6 to
90b37ef
Compare
Tonours
left a comment
There was a problem hiding this comment.
Second pass on the branch head. Five findings: one blocking (the emission-failure message is always empty), two tests that cannot fail, one latent coupling and one gitignore placement.
Both were vacuous. The encoding one passed on a raw document because undici percent-encodes client-side, so the fixture now carries an action named "Facture 50/50": raw, its path splits into segments no route matches. The enum one compared the document against itself, so it now asserts the literal before filtering the generated types. Also captures the CLI stderr before restoring the spy, since mockRestore clears mock.calls and the failure message was always empty, and clears NODE_OPTIONS for the codegen child so an inherited Node warning cannot fail an assertion about the document. The ignored path for the generated client moves to the package, next to how datasource-sql and agent-testing ignore their own test artifacts.
Tonours
left a comment
There was a problem hiding this comment.
All five findings are addressed. I verified the two decorative tests now bite, by mutation rather than by reading the diff:
segmentreturningnameunchanged:should reach an action whose name carries the path separatorgoes red (14 passed, 1 failed). TheFacture 50/50fixture is what gives it teeth.operator: { type: 'string', enum: operators }down to a bare{ type: 'string' }:should carry the documented operator set into the generated typesnow goes red too, along with the two operator tests (12 passed, 3 failed). It stayed green before the literal assertion.
The other three read clean: written is captured before mockRestore(), NODE_OPTIONS: '' isolates the child's output from the runner's flags, and the ignore rule moved into packages/agent-bff/.gitignore with the root entry gone.
Package suite 1099/1099 green locally, CI green on 1bf8e77.

What
Proves the dynamic OpenAPI document is correct enough for codegen, not just schema-valid: a client generated from it can actually call list, count, action form and action execute.
The test:
dispatchCli(['openapi', '--output', …]), the body offorest-bff openapi) from a fixture schema and fixture capabilities;@hey-api/openapi-tson that file, as a consumer would from the command line;createClientseam), asserting a 2xx and the exact response body for each of the six operations.One fixture feeds both the document and the runtime read-model. Two sources would let the test go green while the document described a surface the runtime does not have.
Why the operator check has teeth
The filter operator is read from the emitted enum (
components.schemas.FilterLeaf_users-1.properties.operator.enum) and injected into the call, instead of being hardcoded — so the assertion follows the document rather than a human's memory of it.A negative control sends an operator the document leaves out and asserts
400 invalid_filter_operator. Without it, a permissive stub (or a regression that stopped validating) would keep the check green. The fixture reports a single capability operator (equal→Equal) so the out-of-set operator lands unambiguously on 400 rather than on 422field_not_filterableor 500mapping_error.What it found
Nothing broken. Worth recording, since these were the risks:
Générer la facture→G%C3%A9n%C3%A9rer%20la%20facture);anyOffilter tree becomes a clean recursive TS union, and the operator enum reaches the generated types as a string literal;notis dropped by the codegen — a tooling quirk, not a document defect: the union already encodes the leaf/branch exclusivity structurally, and the runtime 400 stays documented in prose. The document is unchanged.Notes
@hey-api/openapi-tsoveropenapi-generator-cli: the document is OpenAPI 3.1, and openapi-generator converts 3.1 → 3.0 internally, which would make "document defect vs tooling quirk" undecidable on exactly the constructs at risk. It also avoids a Java toolchain and a jar download inside a CI test.X-Forest-Bff-Keyscheme, and the test asserts the credential arrives under that header.test/openapi/.generated/, wiped before and after the run. ESLint ignores dot-directories by default, so no lint config change was needed.Fixes PRD-687
🤖 Generated with Claude Code
Note
Add generated-client test suite for
agent-bffOpenAPI operations@hey-api/openapi-tsto generate a TypeScript client, then drives the client against an in-memory Koa server through list, count, form, and execute flows.@hey-api/openapi-ts0.99.0 to package.json and ignores the.generatedoutput directory in .gitignore.Changes since #1828 opened
beforeAllhook in the OpenAPI generated client test to capture stderr before spy restoration and clear inherited Node options during codegen [1bf8e77]test/openapi/.generatedfrom root.gitignoretopackages/agent-bff/.gitignore[1bf8e77]Macroscope summarized 90b37ef.