Hello all! :wave: We currently define our API resp...
# general
d
Hello all! 👋 We currently define our API response models using Zod schemas, and we’re duplicating the same structure again in Pact matchers. For example, instead of defining a response in Pact like: account: { email: MatchersV3.string('user@automated.testing')} we already have an Account object defined in a Zod schema that describes the same fields, types, and nullability. Is there a recommended way to reuse or derive Pact contracts (or matchers) from existing Zod schemas, so we don’t have to redefine the same response objects in Pact and risk schema drift? Or is the expected approach to define the response shape explicitly in Pact and treat the contract as the single source of truth? Many thanks! :)
j
This is an interesting and somewhat subtle point 😅 We don't currently have a programmatic adapter to convert Zod schemas to Pact matchers, though it’s certainly feasible. I’ve seen similar adapters built for libraries like TypeBox; however, there is a risk in doing so that's worth highlighting: You can quickly devolve from contract testing to schema testing. The core value of Pact is that it is consumer-driven: the consumers should only define the specific fields they actually "consume" to provide the provider with maximum flexibility. If you blindly reuse the full Zod schema, you inadvertently turn our contract tests into Schema Tests. Say for example your schema contains 20 fields, but your consumer only uses 2 of them. If you blindly use the full schema, your provider will think that all 20 fields are required. This can be an issue for example if you are looking to deprecate a field. If the consumer defines their needs precisely, the Provider can see that no one is using the old field and safely remove it. If the consumer blindly uses the Zod schema (which includes the deprecated field), the can-i-deploy check will fail, blocking the Provider from cleaning up their API even if the consumer doesn't actually need that data. So ultimately, while we are tempted to keep everything DRY, the duplication here can be good, and act as a buffer to ensure that the Consumer is only asserting what they strictly require. A possible use-case here could be if the consumer is maintaining their own Zod schema that is strictly what they need (as opposed to, for example, a shared package containing the fully schema). In that case, you might benefit from a Zod-to-Pact adapter 🙂
💯 1
If you do end up creating a Zod-to-Pact adapter, please feel free to share your work here 😄
v
Also consider optional values. Say field
a
and
b
are optional according to the schema. Is the consumer expecting both to be specified, or both unspecified? Only
a
? Only
b
? If
a
then
b
also? If
a
, then not
b
? If
b
then
a
also? If
b
, then not
a
? The permutations are impossible to capture in a schema. And this is only 2 optionals. Then you factor in provider states... The number of combinations is exponential. Similar arguments can be made for arrays and polymorphic schemas (
oneOf
,
anyOf
).
👌 2
m
cc @Murat Ozcan, I believe you’ve been doing some playing in this space
m
I will follow up when we can open source the wrapper lib ; it dogfoods the pact utilities in the lib with a sample backend and frontend that use zod maybe I could add something like this in there
thankyou 2
m
no probs, thought you might enjoy the convo!
m
The lib is still going through compliance team, it's close But I can share the docs. You can check out the new feature there https://seontechnologies.github.io/pactjs-utils/zod-to-pact/ Once the lib is released, you can review in depth, see it being used in real tests, and make feature requests. This turned out very nice , thanks for the request @Diana G --- I'm also adding this to the BMad Test Architect, so if you're using that, and have pactjs-utils installed, it will know how to use the library
thankyou 1
d
Thank you all for your comments and feedback , I am learning a lot! I have shared this with our developers and it has started a great conversation. They are now looking at ensuring that we only add to our Zod schemas what the frontend actually needs, rather than copying everything the backend returns. Really appreciate the help! - will look into the docs, this is great! thanks @Murat Ozcan 😃
smooth parrot 2
m
np it will be a thin wrapper over Pact TS, in the style of playwright-utils which we open sourced previously just helpers, utils, that make DX easier
thankyou 1