pact-ruby
pact-ruby copied to clipboard
Feat/provider params
This allows the provider state to change some values in the request before the interaction is replayed. It's related to the pull request I made in the pact-support repository, here: https://github.com/pact-foundation/pact-support/pull/57.
I'd love to know what you think about doing this. We've been using my fork where I work, and have been finding it to be a great way of handling IDs in URLs, and also authorization headers.
This is fantastic, and I'm glad it's working for you, but I am unable to merge this into the main codebase because it doesn't conform to the pact-specification. Pact is about more than just the Ruby codebase - in fact, the Ruby user group is one of the smaller communities. Keeping the implementations in sync is important for interoperability.
I'd like to get something like this into the next pact spec version however. @uglyog is this a "thing" in v3 or v4? Is this what generators do?
This is awesome.
Yes, this has overlap with the generators. What we could do, is define a specific generator that can replace the values from what is setup in the provider state. That way we do not have to introduce any new elements to the pact file format, just define the generator. See https://github.com/pact-foundation/pact-specification/tree/version-3#introduce-example-generators for more info.
I might try spike out an implementation in Pact-JVM.
I must admit that was my first impression. It's even better than a usual generator, though, because it means we can support any type of value or logic behind creating that value, instead of relying on a fixed set of them.
For example, the Date generator might not work if the time must be something in the past or future, within a specific period. This would give the user flexibility over how its created.
+1
Oh, right. I thought generators allowed you to put in your own values. So, yes, we really want this.
I've been doing a dirty hack with my HAL pacts, where I put a placeholder URL in on the consumer side, that I then replace with the real URL when I run the verification. This allows my consumer tests not to have to "know" what the real provider URLs are, ensuring the intent of hypermedia is actually fulfilled. I want to put this properly into the pact spec, and imagine it would be similar to the above solution.
Thanks for the feedback! I'm so glad to hear that there is interest in adding this capability. I figured that it would need to be added to the spec, but I wasn't sure how to go about doing that.
Would this be something in version 3, or version 4? If it's done as a new type of generator, does that mean it could be in version 3?
Generators are V3. @bethesque we could try use the generators from the Rust implementation. We should just be able to create a Gem where you pass the body and the generator hash, and get a new body back.
Hey @tucker-m for your contributions, this was a very cool feature
Thanks for this, sorry for the delay.
So this relates to https://github.com/pact-foundation/pact-support/pull/57
so is this basically supported by v3 with generators? (and this can be closed?)
Ok so been digging a bit further, this was introduced into the spec in v4
https://github.com/pact-foundation/pact-specification/tree/version-4?tab=readme-ov-file#supported-generators
Generator | Attributes | Description | Example JSON |
---|---|---|---|
ProviderState | V4 | {"expression": "/api/user/${id}", "type": "ProviderState"} | Generates a value that is looked up from the provider state context using the given expression |
bit of a cookie trail here https://github.com/pact-foundation/pact-reference/issues/116 which was linked in the pact v4 rfc
so we would need the matching rules to change from
"path": "/food_item/5",
"headers": {
"Authorization": "Bearer faketoken"
},
"matchingRules": {
"$.path": {
"match": "provider_param",
"fill_string": "/food_item/:{id}"
},
"$.headers.Authorization": {
"match": "provider_param",
"fill_string": "Bearer :{auth_token}"
}
}
to be
"path": "/food_item/5",
"headers": {
"Authorization": "Bearer faketoken"
},
"matchingRules": {
"$.path": {
"type": "ProviderState"
"expression": "/food_item/${id}"
},
"$.headers.Authorization": {
"type": "ProviderState"
"expression": "Bearer ${auth_token}"
}
}
We would need to scope the matcher/generator to V4 (it isn't listed in the V3 matcher spec).
I'll check what the pact_ffi library does if it is told to process a v3 spec, and we provide this matcher.
See additional comments here in the associated change for pact-support
https://github.com/pact-foundation/pact-support/pull/57#issuecomment-2289150032
Will convert to a draft and pick up a continuation of this for progress towards https://github.com/pact-foundation/pact-ruby/issues/319